1c7e4239fSAsiri Rathnayake// -*- C++ -*-
2c7e4239fSAsiri Rathnayake//===----------------------------------------------------------------------===//
3c7e4239fSAsiri Rathnayake//
457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information.
657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7c7e4239fSAsiri Rathnayake//
8c7e4239fSAsiri Rathnayake//===----------------------------------------------------------------------===//
9c7e4239fSAsiri Rathnayake
10c7e4239fSAsiri Rathnayake#ifndef _LIBCPP_THREADING_SUPPORT
11c7e4239fSAsiri Rathnayake#define _LIBCPP_THREADING_SUPPORT
12c7e4239fSAsiri Rathnayake
132eadbc86SLouis Dionne#include <__availability>
14bfbd73f8SArthur O'Dwyer#include <__config>
1592832e48SLouis Dionne#include <__thread/poll_with_backoff.h>
1654a987e1SAsiri Rathnayake#include <chrono>
1754a987e1SAsiri Rathnayake#include <errno.h>
18bfbd73f8SArthur O'Dwyer#include <iosfwd>
191773eec6SMartin Storsjö#include <limits>
20c7e4239fSAsiri Rathnayake
216a8099e0SZbigniew Sarbinowski#ifdef __MVS__
22b5175681SLouis Dionne# include <__support/ibm/nanosleep.h>
236a8099e0SZbigniew Sarbinowski#endif
246a8099e0SZbigniew Sarbinowski
25c7e4239fSAsiri Rathnayake#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
26c7e4239fSAsiri Rathnayake#pragma GCC system_header
27c7e4239fSAsiri Rathnayake#endif
28c7e4239fSAsiri Rathnayake
2900f6beaeSEric Fiselier#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
303cf2f7bcSAsiri Rathnayake# include <__external_threading>
3100f6beaeSEric Fiselier#elif !defined(_LIBCPP_HAS_NO_THREADS)
32790e10f6SSaleem Abdulrasool
33db757ba7SLouis Dionne#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
34db757ba7SLouis Dionne# include <pthread.h>
35db757ba7SLouis Dionne# include <sched.h>
36ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11)
37ab9aefeeSPetr Hosek# include <threads.h>
38790e10f6SSaleem Abdulrasool#endif
39c7e4239fSAsiri Rathnayake
402a129dc3SPeter Collingbourne#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
412a129dc3SPeter Collingbourne    defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \
422a129dc3SPeter Collingbourne    defined(_LIBCPP_HAS_THREAD_API_WIN32)
432a129dc3SPeter Collingbourne#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
442a129dc3SPeter Collingbourne#else
452a129dc3SPeter Collingbourne#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
462a129dc3SPeter Collingbourne#endif
472a129dc3SPeter Collingbourne
4883dca5c3SDimitry Andric#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
4983dca5c3SDimitry Andric#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
5083dca5c3SDimitry Andric#else
5183dca5c3SDimitry Andric#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
5283dca5c3SDimitry Andric#endif
5383dca5c3SDimitry Andric
54696630eaSMarshall Clowtypedef ::timespec __libcpp_timespec_t;
55696630eaSMarshall Clow#endif // !defined(_LIBCPP_HAS_NO_THREADS)
56696630eaSMarshall Clow
57696630eaSMarshall Clow_LIBCPP_PUSH_MACROS
58696630eaSMarshall Clow#include <__undef_macros>
59696630eaSMarshall Clow
60c7e4239fSAsiri Rathnayake_LIBCPP_BEGIN_NAMESPACE_STD
61c7e4239fSAsiri Rathnayake
62696630eaSMarshall Clow#if !defined(_LIBCPP_HAS_NO_THREADS)
63696630eaSMarshall Clow
642a129dc3SPeter Collingbourne#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
65c7e4239fSAsiri Rathnayake// Mutex
66c7e4239fSAsiri Rathnayaketypedef pthread_mutex_t __libcpp_mutex_t;
678c2bf45dSAsiri Rathnayake#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
68c7e4239fSAsiri Rathnayake
6958a0dceeSSaleem Abdulrasooltypedef pthread_mutex_t __libcpp_recursive_mutex_t;
7058a0dceeSSaleem Abdulrasool
71790e10f6SSaleem Abdulrasool// Condition Variable
72790e10f6SSaleem Abdulrasooltypedef pthread_cond_t __libcpp_condvar_t;
73790e10f6SSaleem Abdulrasool#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
74790e10f6SSaleem Abdulrasool
75205d7d3fSAsiri Rathnayake// Execute once
76205d7d3fSAsiri Rathnayaketypedef pthread_once_t __libcpp_exec_once_flag;
77205d7d3fSAsiri Rathnayake#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
78205d7d3fSAsiri Rathnayake
79205d7d3fSAsiri Rathnayake// Thread id
80e6c89a49SZbigniew Sarbinowski#if defined(__MVS__)
81e6c89a49SZbigniew Sarbinowski  typedef unsigned long long __libcpp_thread_id;
82e6c89a49SZbigniew Sarbinowski#else
83790e10f6SSaleem Abdulrasool  typedef pthread_t __libcpp_thread_id;
84e6c89a49SZbigniew Sarbinowski#endif
85790e10f6SSaleem Abdulrasool
86790e10f6SSaleem Abdulrasool// Thread
87e6c89a49SZbigniew Sarbinowski#define _LIBCPP_NULL_THREAD ((__libcpp_thread_t()))
88790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_t;
89790e10f6SSaleem Abdulrasool
90cac6d217SFangrui Song// Thread Local Storage
91790e10f6SSaleem Abdulrasooltypedef pthread_key_t __libcpp_tls_key;
926d7d0becSSaleem Abdulrasool
936d7d0becSSaleem Abdulrasool#define _LIBCPP_TLS_DESTRUCTOR_CC
94ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11)
95ab9aefeeSPetr Hosek// Mutex
96ab9aefeeSPetr Hosektypedef mtx_t __libcpp_mutex_t;
97ab9aefeeSPetr Hosek// mtx_t is a struct so using {} for initialization is valid.
98ab9aefeeSPetr Hosek#define _LIBCPP_MUTEX_INITIALIZER {}
99ab9aefeeSPetr Hosek
100ab9aefeeSPetr Hosektypedef mtx_t __libcpp_recursive_mutex_t;
101ab9aefeeSPetr Hosek
102ab9aefeeSPetr Hosek// Condition Variable
103ab9aefeeSPetr Hosektypedef cnd_t __libcpp_condvar_t;
104ab9aefeeSPetr Hosek// cnd_t is a struct so using {} for initialization is valid.
105ab9aefeeSPetr Hosek#define _LIBCPP_CONDVAR_INITIALIZER {}
106ab9aefeeSPetr Hosek
107ab9aefeeSPetr Hosek// Execute once
108ab9aefeeSPetr Hosektypedef once_flag __libcpp_exec_once_flag;
109ab9aefeeSPetr Hosek#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT
110ab9aefeeSPetr Hosek
111ab9aefeeSPetr Hosek// Thread id
112ab9aefeeSPetr Hosektypedef thrd_t __libcpp_thread_id;
113ab9aefeeSPetr Hosek
114ab9aefeeSPetr Hosek// Thread
115ab9aefeeSPetr Hosek#define _LIBCPP_NULL_THREAD 0U
116ab9aefeeSPetr Hosek
117ab9aefeeSPetr Hosektypedef thrd_t __libcpp_thread_t;
118ab9aefeeSPetr Hosek
119ab9aefeeSPetr Hosek// Thread Local Storage
120ab9aefeeSPetr Hosektypedef tss_t __libcpp_tls_key;
121ab9aefeeSPetr Hosek
122ab9aefeeSPetr Hosek#define _LIBCPP_TLS_DESTRUCTOR_CC
123e2b200b7SDavid Spickett#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
124ac15ae6dSPeter Collingbourne// Mutex
125ac15ae6dSPeter Collingbournetypedef void* __libcpp_mutex_t;
126ac15ae6dSPeter Collingbourne#define _LIBCPP_MUTEX_INITIALIZER 0
127ac15ae6dSPeter Collingbourne
128ac15ae6dSPeter Collingbourne#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
129ac15ae6dSPeter Collingbournetypedef void* __libcpp_recursive_mutex_t[6];
130ac15ae6dSPeter Collingbourne#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
131ac15ae6dSPeter Collingbournetypedef void* __libcpp_recursive_mutex_t[5];
132ac15ae6dSPeter Collingbourne#else
133ac15ae6dSPeter Collingbourne# error Unsupported architecture
134ac15ae6dSPeter Collingbourne#endif
1356d7d0becSSaleem Abdulrasool
1366d7d0becSSaleem Abdulrasool// Condition Variable
137ac15ae6dSPeter Collingbournetypedef void* __libcpp_condvar_t;
138ac15ae6dSPeter Collingbourne#define _LIBCPP_CONDVAR_INITIALIZER 0
1396d7d0becSSaleem Abdulrasool
1406d7d0becSSaleem Abdulrasool// Execute Once
141ac15ae6dSPeter Collingbournetypedef void* __libcpp_exec_once_flag;
142ac15ae6dSPeter Collingbourne#define _LIBCPP_EXEC_ONCE_INITIALIZER 0
1436d7d0becSSaleem Abdulrasool
1446d7d0becSSaleem Abdulrasool// Thread ID
145ac15ae6dSPeter Collingbournetypedef long __libcpp_thread_id;
1466d7d0becSSaleem Abdulrasool
1476d7d0becSSaleem Abdulrasool// Thread
148af762e91SAsiri Rathnayake#define _LIBCPP_NULL_THREAD 0U
149af762e91SAsiri Rathnayake
150ac15ae6dSPeter Collingbournetypedef void* __libcpp_thread_t;
1516d7d0becSSaleem Abdulrasool
1526d7d0becSSaleem Abdulrasool// Thread Local Storage
153ac15ae6dSPeter Collingbournetypedef long __libcpp_tls_key;
1546d7d0becSSaleem Abdulrasool
155ac15ae6dSPeter Collingbourne#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
156e2b200b7SDavid Spickett#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
157790e10f6SSaleem Abdulrasool
158e2b200b7SDavid Spickett#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
159790e10f6SSaleem Abdulrasool// Mutex
1608c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
16158a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
16258a0dceeSSaleem Abdulrasool
16383dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
16458a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
16558a0dceeSSaleem Abdulrasool
16683dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
16708e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
16858a0dceeSSaleem Abdulrasool
16983dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
17058a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
17158a0dceeSSaleem Abdulrasool
17258a0dceeSSaleem Abdulrasool_LIBCPP_THREAD_ABI_VISIBILITY
17358a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
174790e10f6SSaleem Abdulrasool
17583dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
1768c2bf45dSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m);
177790e10f6SSaleem Abdulrasool
17883dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
17908e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
180790e10f6SSaleem Abdulrasool
18183dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
1828c2bf45dSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
183790e10f6SSaleem Abdulrasool
1848c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1858c2bf45dSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
1868c2bf45dSAsiri Rathnayake
1878c2bf45dSAsiri Rathnayake// Condition variable
1888c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1898c2bf45dSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
190790e10f6SSaleem Abdulrasool
1918c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1928c2bf45dSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
193790e10f6SSaleem Abdulrasool
19483dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
1958c2bf45dSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
196790e10f6SSaleem Abdulrasool
19783dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
198790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
199cfdc7f0dSMikhail Maltsev                               __libcpp_timespec_t *__ts);
200790e10f6SSaleem Abdulrasool
2018c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2028c2bf45dSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
2038c2bf45dSAsiri Rathnayake
204205d7d3fSAsiri Rathnayake// Execute once
205205d7d3fSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
206205d7d3fSAsiri Rathnayakeint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
2074603460aSBruce Mitchener                          void (*init_routine)());
208205d7d3fSAsiri Rathnayake
209205d7d3fSAsiri Rathnayake// Thread id
2108c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2118c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
212790e10f6SSaleem Abdulrasool
2138c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2148c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
2158c2bf45dSAsiri Rathnayake
2168c2bf45dSAsiri Rathnayake// Thread
2178c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
218af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
219af762e91SAsiri Rathnayake
220af762e91SAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
221790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
222790e10f6SSaleem Abdulrasool                           void *__arg);
223790e10f6SSaleem Abdulrasool
2248c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2258c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id();
226790e10f6SSaleem Abdulrasool
2278c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2288c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
229790e10f6SSaleem Abdulrasool
2308c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2318c2bf45dSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t);
232790e10f6SSaleem Abdulrasool
2338c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2348c2bf45dSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t);
235790e10f6SSaleem Abdulrasool
2368c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2378c2bf45dSAsiri Rathnayakevoid __libcpp_thread_yield();
2388c2bf45dSAsiri Rathnayake
23954a987e1SAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2409e8a082dSJoerg Sonnenbergervoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
24154a987e1SAsiri Rathnayake
2428c2bf45dSAsiri Rathnayake// Thread local storage
2438c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2446d7d0becSSaleem Abdulrasoolint __libcpp_tls_create(__libcpp_tls_key* __key,
2456d7d0becSSaleem Abdulrasool                        void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
246790e10f6SSaleem Abdulrasool
2478c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2488c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key);
249790e10f6SSaleem Abdulrasool
2508c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
251205d7d3fSAsiri Rathnayakeint __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
2528c2bf45dSAsiri Rathnayake
253e2b200b7SDavid Spickett#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
254e2b200b7SDavid Spickett
25514aef536SMikhail Maltsevstruct __libcpp_timed_backoff_policy {
25621a1a263SLouis Dionne  _LIBCPP_INLINE_VISIBILITY
25721a1a263SLouis Dionne  bool operator()(chrono::nanoseconds __elapsed) const
2583411a1a9SDavid Nicuesa  {
2593411a1a9SDavid Nicuesa      if(__elapsed > chrono::milliseconds(128))
2603411a1a9SDavid Nicuesa          __libcpp_thread_sleep_for(chrono::milliseconds(8));
2613411a1a9SDavid Nicuesa      else if(__elapsed > chrono::microseconds(64))
2623411a1a9SDavid Nicuesa          __libcpp_thread_sleep_for(__elapsed / 2);
2633411a1a9SDavid Nicuesa      else if(__elapsed > chrono::microseconds(4))
2643411a1a9SDavid Nicuesa        __libcpp_thread_yield();
2653411a1a9SDavid Nicuesa      else
266d2acf229SMarek Kurdej        {} // poll
2673411a1a9SDavid Nicuesa      return false;
2683411a1a9SDavid Nicuesa  }
26921a1a263SLouis Dionne};
2703411a1a9SDavid Nicuesa
2713411a1a9SDavid Nicuesa#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
2723411a1a9SDavid Nicuesa     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL))
2733411a1a9SDavid Nicuesa
27414aef536SMikhail Maltsev
275ab9aefeeSPetr Hoseknamespace __thread_detail {
276ab9aefeeSPetr Hosek
277ab9aefeeSPetr Hosekinline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns)
278ab9aefeeSPetr Hosek{
279ab9aefeeSPetr Hosek  using namespace chrono;
280ab9aefeeSPetr Hosek  seconds __s = duration_cast<seconds>(__ns);
281ab9aefeeSPetr Hosek  __libcpp_timespec_t __ts;
282ab9aefeeSPetr Hosek  typedef decltype(__ts.tv_sec) __ts_sec;
283ab9aefeeSPetr Hosek  const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
284ab9aefeeSPetr Hosek
285ab9aefeeSPetr Hosek  if (__s.count() < __ts_sec_max)
286ab9aefeeSPetr Hosek  {
287ab9aefeeSPetr Hosek    __ts.tv_sec = static_cast<__ts_sec>(__s.count());
288ab9aefeeSPetr Hosek    __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
289ab9aefeeSPetr Hosek  }
290ab9aefeeSPetr Hosek  else
291ab9aefeeSPetr Hosek  {
292ab9aefeeSPetr Hosek    __ts.tv_sec = __ts_sec_max;
293ab9aefeeSPetr Hosek    __ts.tv_nsec = 999999999; // (10^9 - 1)
294ab9aefeeSPetr Hosek  }
295ab9aefeeSPetr Hosek
296ab9aefeeSPetr Hosek  return __ts;
297ab9aefeeSPetr Hosek}
298ab9aefeeSPetr Hosek
299*d2b0df35SNikolas Klauser} // namespace __thread_detail
300ab9aefeeSPetr Hosek
301ab9aefeeSPetr Hosek#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
3028c2bf45dSAsiri Rathnayake
30358a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
304c7e4239fSAsiri Rathnayake{
305c7e4239fSAsiri Rathnayake  pthread_mutexattr_t attr;
306c7e4239fSAsiri Rathnayake  int __ec = pthread_mutexattr_init(&attr);
307c7e4239fSAsiri Rathnayake  if (__ec)
308790e10f6SSaleem Abdulrasool    return __ec;
309790e10f6SSaleem Abdulrasool  __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
310790e10f6SSaleem Abdulrasool  if (__ec) {
311c7e4239fSAsiri Rathnayake    pthread_mutexattr_destroy(&attr);
312c7e4239fSAsiri Rathnayake    return __ec;
313c7e4239fSAsiri Rathnayake  }
314c7e4239fSAsiri Rathnayake  __ec = pthread_mutex_init(__m, &attr);
315790e10f6SSaleem Abdulrasool  if (__ec) {
316c7e4239fSAsiri Rathnayake    pthread_mutexattr_destroy(&attr);
317c7e4239fSAsiri Rathnayake    return __ec;
318c7e4239fSAsiri Rathnayake  }
319c7e4239fSAsiri Rathnayake  __ec = pthread_mutexattr_destroy(&attr);
320790e10f6SSaleem Abdulrasool  if (__ec) {
321c7e4239fSAsiri Rathnayake    pthread_mutex_destroy(__m);
322c7e4239fSAsiri Rathnayake    return __ec;
323c7e4239fSAsiri Rathnayake  }
324c7e4239fSAsiri Rathnayake  return 0;
325c7e4239fSAsiri Rathnayake}
326c7e4239fSAsiri Rathnayake
32758a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
32858a0dceeSSaleem Abdulrasool{
32958a0dceeSSaleem Abdulrasool  return pthread_mutex_lock(__m);
33058a0dceeSSaleem Abdulrasool}
33158a0dceeSSaleem Abdulrasool
33208e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
33358a0dceeSSaleem Abdulrasool{
33408e1477cSEric Fiselier  return pthread_mutex_trylock(__m) == 0;
33558a0dceeSSaleem Abdulrasool}
33658a0dceeSSaleem Abdulrasool
337ebfadd82SColin Finckint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
33858a0dceeSSaleem Abdulrasool{
33958a0dceeSSaleem Abdulrasool  return pthread_mutex_unlock(__m);
34058a0dceeSSaleem Abdulrasool}
34158a0dceeSSaleem Abdulrasool
34258a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
34358a0dceeSSaleem Abdulrasool{
34458a0dceeSSaleem Abdulrasool  return pthread_mutex_destroy(__m);
34558a0dceeSSaleem Abdulrasool}
34658a0dceeSSaleem Abdulrasool
347c7e4239fSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m)
348c7e4239fSAsiri Rathnayake{
349c7e4239fSAsiri Rathnayake  return pthread_mutex_lock(__m);
350c7e4239fSAsiri Rathnayake}
351c7e4239fSAsiri Rathnayake
35208e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
353c7e4239fSAsiri Rathnayake{
35408e1477cSEric Fiselier  return pthread_mutex_trylock(__m) == 0;
355c7e4239fSAsiri Rathnayake}
356c7e4239fSAsiri Rathnayake
357c7e4239fSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
358c7e4239fSAsiri Rathnayake{
359c7e4239fSAsiri Rathnayake  return pthread_mutex_unlock(__m);
360c7e4239fSAsiri Rathnayake}
361c7e4239fSAsiri Rathnayake
362c7e4239fSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
363c7e4239fSAsiri Rathnayake{
364c7e4239fSAsiri Rathnayake  return pthread_mutex_destroy(__m);
365c7e4239fSAsiri Rathnayake}
366c7e4239fSAsiri Rathnayake
367790e10f6SSaleem Abdulrasool// Condition Variable
368c7e4239fSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
369c7e4239fSAsiri Rathnayake{
370c7e4239fSAsiri Rathnayake  return pthread_cond_signal(__cv);
371c7e4239fSAsiri Rathnayake}
372c7e4239fSAsiri Rathnayake
373c7e4239fSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
374c7e4239fSAsiri Rathnayake{
375c7e4239fSAsiri Rathnayake  return pthread_cond_broadcast(__cv);
376c7e4239fSAsiri Rathnayake}
377c7e4239fSAsiri Rathnayake
378c7e4239fSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
379c7e4239fSAsiri Rathnayake{
380c7e4239fSAsiri Rathnayake  return pthread_cond_wait(__cv, __m);
381c7e4239fSAsiri Rathnayake}
382c7e4239fSAsiri Rathnayake
383790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
384cfdc7f0dSMikhail Maltsev                               __libcpp_timespec_t *__ts)
385c7e4239fSAsiri Rathnayake{
386c7e4239fSAsiri Rathnayake  return pthread_cond_timedwait(__cv, __m, __ts);
387c7e4239fSAsiri Rathnayake}
388c7e4239fSAsiri Rathnayake
389c7e4239fSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
390c7e4239fSAsiri Rathnayake{
391c7e4239fSAsiri Rathnayake  return pthread_cond_destroy(__cv);
392c7e4239fSAsiri Rathnayake}
393c7e4239fSAsiri Rathnayake
394205d7d3fSAsiri Rathnayake// Execute once
395205d7d3fSAsiri Rathnayakeint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
3964603460aSBruce Mitchener                          void (*init_routine)()) {
397205d7d3fSAsiri Rathnayake  return pthread_once(flag, init_routine);
398205d7d3fSAsiri Rathnayake}
399205d7d3fSAsiri Rathnayake
400205d7d3fSAsiri Rathnayake// Thread id
401c7e4239fSAsiri Rathnayake// Returns non-zero if the thread ids are equal, otherwise 0
402c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
403c7e4239fSAsiri Rathnayake{
404e6c89a49SZbigniew Sarbinowski  return t1 == t2;
405c7e4239fSAsiri Rathnayake}
406c7e4239fSAsiri Rathnayake
407c7e4239fSAsiri Rathnayake// Returns non-zero if t1 < t2, otherwise 0
408c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
409c7e4239fSAsiri Rathnayake{
410c7e4239fSAsiri Rathnayake  return t1 < t2;
411c7e4239fSAsiri Rathnayake}
412c7e4239fSAsiri Rathnayake
413c7e4239fSAsiri Rathnayake// Thread
414af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
41548fcce1aSZbigniew Sarbinowski  return __libcpp_thread_get_id(__t) == 0;
416af762e91SAsiri Rathnayake}
417af762e91SAsiri Rathnayake
418790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
419790e10f6SSaleem Abdulrasool                           void *__arg)
420c7e4239fSAsiri Rathnayake{
421527a7fdfSBruce Mitchener  return pthread_create(__t, nullptr, __func, __arg);
422c7e4239fSAsiri Rathnayake}
423c7e4239fSAsiri Rathnayake
424c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id()
425c7e4239fSAsiri Rathnayake{
426e6c89a49SZbigniew Sarbinowski  const __libcpp_thread_t thread = pthread_self();
427e6c89a49SZbigniew Sarbinowski  return __libcpp_thread_get_id(&thread);
428c7e4239fSAsiri Rathnayake}
429c7e4239fSAsiri Rathnayake
430c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
431c7e4239fSAsiri Rathnayake{
432e6c89a49SZbigniew Sarbinowski#if defined(__MVS__)
433e6c89a49SZbigniew Sarbinowski  return __t->__;
434e6c89a49SZbigniew Sarbinowski#else
435c7e4239fSAsiri Rathnayake  return *__t;
436e6c89a49SZbigniew Sarbinowski#endif
437c7e4239fSAsiri Rathnayake}
438c7e4239fSAsiri Rathnayake
439c7e4239fSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t)
440c7e4239fSAsiri Rathnayake{
441527a7fdfSBruce Mitchener  return pthread_join(*__t, nullptr);
442c7e4239fSAsiri Rathnayake}
443c7e4239fSAsiri Rathnayake
444c7e4239fSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t)
445c7e4239fSAsiri Rathnayake{
446c7e4239fSAsiri Rathnayake  return pthread_detach(*__t);
447c7e4239fSAsiri Rathnayake}
448c7e4239fSAsiri Rathnayake
449c7e4239fSAsiri Rathnayakevoid __libcpp_thread_yield()
450c7e4239fSAsiri Rathnayake{
451c7e4239fSAsiri Rathnayake  sched_yield();
452c7e4239fSAsiri Rathnayake}
453c7e4239fSAsiri Rathnayake
45454a987e1SAsiri Rathnayakevoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
45554a987e1SAsiri Rathnayake{
456ab9aefeeSPetr Hosek   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
45754a987e1SAsiri Rathnayake   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
45854a987e1SAsiri Rathnayake}
45954a987e1SAsiri Rathnayake
460c7e4239fSAsiri Rathnayake// Thread local storage
4618c2bf45dSAsiri Rathnayakeint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
462c7e4239fSAsiri Rathnayake{
463c7e4239fSAsiri Rathnayake  return pthread_key_create(__key, __at_exit);
464c7e4239fSAsiri Rathnayake}
465c7e4239fSAsiri Rathnayake
4668c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key)
467c7e4239fSAsiri Rathnayake{
468c7e4239fSAsiri Rathnayake  return pthread_getspecific(__key);
469c7e4239fSAsiri Rathnayake}
470c7e4239fSAsiri Rathnayake
471205d7d3fSAsiri Rathnayakeint __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
472c7e4239fSAsiri Rathnayake{
473205d7d3fSAsiri Rathnayake    return pthread_setspecific(__key, __p);
474c7e4239fSAsiri Rathnayake}
475c7e4239fSAsiri Rathnayake
476ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11)
477ab9aefeeSPetr Hosek
478ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
479ab9aefeeSPetr Hosek{
4803481e5d7SPetr Hosek  return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
481ab9aefeeSPetr Hosek}
482ab9aefeeSPetr Hosek
483ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
484ab9aefeeSPetr Hosek{
485ab9aefeeSPetr Hosek  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
486ab9aefeeSPetr Hosek}
487ab9aefeeSPetr Hosek
488ab9aefeeSPetr Hosekbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
489ab9aefeeSPetr Hosek{
490ab9aefeeSPetr Hosek  return mtx_trylock(__m) == thrd_success;
491ab9aefeeSPetr Hosek}
492ab9aefeeSPetr Hosek
493ebfadd82SColin Finckint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
494ab9aefeeSPetr Hosek{
495ab9aefeeSPetr Hosek  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
496ab9aefeeSPetr Hosek}
497ab9aefeeSPetr Hosek
498ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
499ab9aefeeSPetr Hosek{
500ab9aefeeSPetr Hosek  mtx_destroy(__m);
501ab9aefeeSPetr Hosek  return 0;
502ab9aefeeSPetr Hosek}
503ab9aefeeSPetr Hosek
504ab9aefeeSPetr Hosekint __libcpp_mutex_lock(__libcpp_mutex_t *__m)
505ab9aefeeSPetr Hosek{
506ab9aefeeSPetr Hosek  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
507ab9aefeeSPetr Hosek}
508ab9aefeeSPetr Hosek
509ab9aefeeSPetr Hosekbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
510ab9aefeeSPetr Hosek{
511ab9aefeeSPetr Hosek  return mtx_trylock(__m) == thrd_success;
512ab9aefeeSPetr Hosek}
513ab9aefeeSPetr Hosek
514ab9aefeeSPetr Hosekint __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
515ab9aefeeSPetr Hosek{
516ab9aefeeSPetr Hosek  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
517ab9aefeeSPetr Hosek}
518ab9aefeeSPetr Hosek
519ab9aefeeSPetr Hosekint __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
520ab9aefeeSPetr Hosek{
521ab9aefeeSPetr Hosek  mtx_destroy(__m);
522ab9aefeeSPetr Hosek  return 0;
523ab9aefeeSPetr Hosek}
524ab9aefeeSPetr Hosek
525ab9aefeeSPetr Hosek// Condition Variable
526ab9aefeeSPetr Hosekint __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
527ab9aefeeSPetr Hosek{
528ab9aefeeSPetr Hosek  return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
529ab9aefeeSPetr Hosek}
530ab9aefeeSPetr Hosek
531ab9aefeeSPetr Hosekint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
532ab9aefeeSPetr Hosek{
533ab9aefeeSPetr Hosek  return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
534ab9aefeeSPetr Hosek}
535ab9aefeeSPetr Hosek
536ab9aefeeSPetr Hosekint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
537ab9aefeeSPetr Hosek{
538ab9aefeeSPetr Hosek  return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
539ab9aefeeSPetr Hosek}
540ab9aefeeSPetr Hosek
541ab9aefeeSPetr Hosekint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
542ab9aefeeSPetr Hosek                               timespec *__ts)
543ab9aefeeSPetr Hosek{
544ab9aefeeSPetr Hosek  int __ec = cnd_timedwait(__cv, __m, __ts);
545ab9aefeeSPetr Hosek  return __ec == thrd_timedout ? ETIMEDOUT : __ec;
546ab9aefeeSPetr Hosek}
547ab9aefeeSPetr Hosek
548ab9aefeeSPetr Hosekint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
549ab9aefeeSPetr Hosek{
550ab9aefeeSPetr Hosek  cnd_destroy(__cv);
551ab9aefeeSPetr Hosek  return 0;
552ab9aefeeSPetr Hosek}
553ab9aefeeSPetr Hosek
554ab9aefeeSPetr Hosek// Execute once
555ab9aefeeSPetr Hosekint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
556ab9aefeeSPetr Hosek                          void (*init_routine)(void)) {
557ab9aefeeSPetr Hosek  ::call_once(flag, init_routine);
558ab9aefeeSPetr Hosek  return 0;
559ab9aefeeSPetr Hosek}
560ab9aefeeSPetr Hosek
561ab9aefeeSPetr Hosek// Thread id
562ab9aefeeSPetr Hosek// Returns non-zero if the thread ids are equal, otherwise 0
563ab9aefeeSPetr Hosekbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
564ab9aefeeSPetr Hosek{
565ab9aefeeSPetr Hosek  return thrd_equal(t1, t2) != 0;
566ab9aefeeSPetr Hosek}
567ab9aefeeSPetr Hosek
568ab9aefeeSPetr Hosek// Returns non-zero if t1 < t2, otherwise 0
569ab9aefeeSPetr Hosekbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
570ab9aefeeSPetr Hosek{
571ab9aefeeSPetr Hosek  return t1 < t2;
572ab9aefeeSPetr Hosek}
573ab9aefeeSPetr Hosek
574ab9aefeeSPetr Hosek// Thread
575ab9aefeeSPetr Hosekbool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
576e6c89a49SZbigniew Sarbinowski  return __libcpp_thread_get_id(__t) == 0;
577ab9aefeeSPetr Hosek}
578ab9aefeeSPetr Hosek
579ab9aefeeSPetr Hosekint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
580ab9aefeeSPetr Hosek                           void *__arg)
581ab9aefeeSPetr Hosek{
582ab9aefeeSPetr Hosek  int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
583ab9aefeeSPetr Hosek  return __ec == thrd_nomem ? ENOMEM : __ec;
584ab9aefeeSPetr Hosek}
585ab9aefeeSPetr Hosek
586ab9aefeeSPetr Hosek__libcpp_thread_id __libcpp_thread_get_current_id()
587ab9aefeeSPetr Hosek{
588ab9aefeeSPetr Hosek  return thrd_current();
589ab9aefeeSPetr Hosek}
590ab9aefeeSPetr Hosek
591ab9aefeeSPetr Hosek__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
592ab9aefeeSPetr Hosek{
593ab9aefeeSPetr Hosek  return *__t;
594ab9aefeeSPetr Hosek}
595ab9aefeeSPetr Hosek
596ab9aefeeSPetr Hosekint __libcpp_thread_join(__libcpp_thread_t *__t)
597ab9aefeeSPetr Hosek{
598ab9aefeeSPetr Hosek  return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
599ab9aefeeSPetr Hosek}
600ab9aefeeSPetr Hosek
601ab9aefeeSPetr Hosekint __libcpp_thread_detach(__libcpp_thread_t *__t)
602ab9aefeeSPetr Hosek{
603ab9aefeeSPetr Hosek  return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
604ab9aefeeSPetr Hosek}
605ab9aefeeSPetr Hosek
606ab9aefeeSPetr Hosekvoid __libcpp_thread_yield()
607ab9aefeeSPetr Hosek{
608ab9aefeeSPetr Hosek  thrd_yield();
609ab9aefeeSPetr Hosek}
610ab9aefeeSPetr Hosek
611ab9aefeeSPetr Hosekvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
612ab9aefeeSPetr Hosek{
613ab9aefeeSPetr Hosek   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
614ab9aefeeSPetr Hosek  thrd_sleep(&__ts, nullptr);
615ab9aefeeSPetr Hosek}
616ab9aefeeSPetr Hosek
617ab9aefeeSPetr Hosek// Thread local storage
618ab9aefeeSPetr Hosekint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
619ab9aefeeSPetr Hosek{
620ab9aefeeSPetr Hosek  return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
621ab9aefeeSPetr Hosek}
622ab9aefeeSPetr Hosek
623ab9aefeeSPetr Hosekvoid *__libcpp_tls_get(__libcpp_tls_key __key)
624ab9aefeeSPetr Hosek{
625ab9aefeeSPetr Hosek  return tss_get(__key);
626ab9aefeeSPetr Hosek}
627ab9aefeeSPetr Hosek
628ab9aefeeSPetr Hosekint __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
629ab9aefeeSPetr Hosek{
630ab9aefeeSPetr Hosek  return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
631ab9aefeeSPetr Hosek}
632ab9aefeeSPetr Hosek
633ab9aefeeSPetr Hosek#endif
634ab9aefeeSPetr Hosek
635e3add3e5SMartin Storsjö
63600f6beaeSEric Fiselier#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
63700f6beaeSEric Fiselier
6382b1d4254SMarshall Clowclass _LIBCPP_TYPE_VIS thread;
6392b1d4254SMarshall Clowclass _LIBCPP_TYPE_VIS __thread_id;
6402b1d4254SMarshall Clow
6412b1d4254SMarshall Clownamespace this_thread
6422b1d4254SMarshall Clow{
6432b1d4254SMarshall Clow
6442b1d4254SMarshall Clow_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
6452b1d4254SMarshall Clow
646*d2b0df35SNikolas Klauser} // namespace this_thread
6472b1d4254SMarshall Clow
6482b1d4254SMarshall Clowtemplate<> struct hash<__thread_id>;
6492b1d4254SMarshall Clow
6502b1d4254SMarshall Clowclass _LIBCPP_TEMPLATE_VIS __thread_id
6512b1d4254SMarshall Clow{
6522b1d4254SMarshall Clow    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
6532b1d4254SMarshall Clow    // NULL is the no-thread value on Darwin.  Someone needs to check
6542b1d4254SMarshall Clow    // on other platforms.  We assume 0 works everywhere for now.
6552b1d4254SMarshall Clow    __libcpp_thread_id __id_;
6562b1d4254SMarshall Clow
6572b1d4254SMarshall Clowpublic:
6582b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
6592b1d4254SMarshall Clow    __thread_id() _NOEXCEPT : __id_(0) {}
6602b1d4254SMarshall Clow
6612b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
6622b1d4254SMarshall Clow        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
6632e80d01fSMarshall Clow        { // don't pass id==0 to underlying routines
6642e80d01fSMarshall Clow        if (__x.__id_ == 0) return __y.__id_ == 0;
6652e80d01fSMarshall Clow        if (__y.__id_ == 0) return false;
6662e80d01fSMarshall Clow        return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
6672e80d01fSMarshall Clow        }
6682b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
6692b1d4254SMarshall Clow        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
6702b1d4254SMarshall Clow        {return !(__x == __y);}
6712b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
6722b1d4254SMarshall Clow        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
6732e80d01fSMarshall Clow        { // id==0 is always less than any other thread_id
6742e80d01fSMarshall Clow        if (__x.__id_ == 0) return __y.__id_ != 0;
6752e80d01fSMarshall Clow        if (__y.__id_ == 0) return false;
6762e80d01fSMarshall Clow        return  __libcpp_thread_id_less(__x.__id_, __y.__id_);
6772e80d01fSMarshall Clow        }
6782b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
6792b1d4254SMarshall Clow        bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
6802b1d4254SMarshall Clow        {return !(__y < __x);}
6812b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
6822b1d4254SMarshall Clow        bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
6832b1d4254SMarshall Clow        {return   __y < __x ;}
6842b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
6852b1d4254SMarshall Clow        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
6862b1d4254SMarshall Clow        {return !(__x < __y);}
6872b1d4254SMarshall Clow
6882b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
6892e80d01fSMarshall Clow    void __reset() { __id_ = 0; }
6902b1d4254SMarshall Clow
6912b1d4254SMarshall Clow    template<class _CharT, class _Traits>
6922b1d4254SMarshall Clow    friend
6932b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
6942b1d4254SMarshall Clow    basic_ostream<_CharT, _Traits>&
6952b1d4254SMarshall Clow    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
6962b1d4254SMarshall Clow
6972b1d4254SMarshall Clowprivate:
6982b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
6992b1d4254SMarshall Clow    __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
7002b1d4254SMarshall Clow
7012b1d4254SMarshall Clow    friend __thread_id this_thread::get_id() _NOEXCEPT;
7022b1d4254SMarshall Clow    friend class _LIBCPP_TYPE_VIS thread;
7032b1d4254SMarshall Clow    friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
7042b1d4254SMarshall Clow};
7052b1d4254SMarshall Clow
7062b1d4254SMarshall Clownamespace this_thread
7072b1d4254SMarshall Clow{
7082b1d4254SMarshall Clow
7092b1d4254SMarshall Clowinline _LIBCPP_INLINE_VISIBILITY
7102b1d4254SMarshall Clow__thread_id
7112b1d4254SMarshall Clowget_id() _NOEXCEPT
7122b1d4254SMarshall Clow{
7132b1d4254SMarshall Clow    return __libcpp_thread_get_current_id();
7142b1d4254SMarshall Clow}
7152b1d4254SMarshall Clow
716*d2b0df35SNikolas Klauser} // namespace this_thread
7172b1d4254SMarshall Clow
718696630eaSMarshall Clow#endif // !_LIBCPP_HAS_NO_THREADS
719696630eaSMarshall Clow
720c7e4239fSAsiri Rathnayake_LIBCPP_END_NAMESPACE_STD
721c7e4239fSAsiri Rathnayake
722a016efb1SEric Fiselier_LIBCPP_POP_MACROS
723a016efb1SEric Fiselier
724c7e4239fSAsiri Rathnayake#endif // _LIBCPP_THREADING_SUPPORT
725