xref: /netbsd-src/external/apache2/llvm/dist/libcxx/include/__threading_support (revision 4d6fc14bc9b0c5bf3e30be318c143ee82cadd108)
1*4d6fc14bSjoerg// -*- C++ -*-
2*4d6fc14bSjoerg//===----------------------------------------------------------------------===//
3*4d6fc14bSjoerg//
4*4d6fc14bSjoerg// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*4d6fc14bSjoerg// See https://llvm.org/LICENSE.txt for license information.
6*4d6fc14bSjoerg// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*4d6fc14bSjoerg//
8*4d6fc14bSjoerg//===----------------------------------------------------------------------===//
9*4d6fc14bSjoerg
10*4d6fc14bSjoerg#ifndef _LIBCPP_THREADING_SUPPORT
11*4d6fc14bSjoerg#define _LIBCPP_THREADING_SUPPORT
12*4d6fc14bSjoerg
13*4d6fc14bSjoerg#include <__config>
14*4d6fc14bSjoerg#include <__availability>
15*4d6fc14bSjoerg#include <chrono>
16*4d6fc14bSjoerg#include <iosfwd>
17*4d6fc14bSjoerg#include <errno.h>
18*4d6fc14bSjoerg#include <limits>
19*4d6fc14bSjoerg
20*4d6fc14bSjoerg#ifdef __MVS__
21*4d6fc14bSjoerg# include <__support/ibm/nanosleep.h>
22*4d6fc14bSjoerg#endif
23*4d6fc14bSjoerg
24*4d6fc14bSjoerg#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
25*4d6fc14bSjoerg#pragma GCC system_header
26*4d6fc14bSjoerg#endif
27*4d6fc14bSjoerg
28*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
29*4d6fc14bSjoerg# include <__external_threading>
30*4d6fc14bSjoerg#elif !defined(_LIBCPP_HAS_NO_THREADS)
31*4d6fc14bSjoerg
32*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
33*4d6fc14bSjoerg# include <pthread.h>
34*4d6fc14bSjoerg# include <sched.h>
35*4d6fc14bSjoerg# if defined(__APPLE__) || defined(__MVS__)
36*4d6fc14bSjoerg#  define _LIBCPP_NO_NATIVE_SEMAPHORES
37*4d6fc14bSjoerg# endif
38*4d6fc14bSjoerg# ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
39*4d6fc14bSjoerg# include <semaphore.h>
40*4d6fc14bSjoerg# endif
41*4d6fc14bSjoerg#elif defined(_LIBCPP_HAS_THREAD_API_C11)
42*4d6fc14bSjoerg# include <threads.h>
43*4d6fc14bSjoerg#endif
44*4d6fc14bSjoerg
45*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
46*4d6fc14bSjoerg    defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \
47*4d6fc14bSjoerg    defined(_LIBCPP_HAS_THREAD_API_WIN32)
48*4d6fc14bSjoerg#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
49*4d6fc14bSjoerg#else
50*4d6fc14bSjoerg#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
51*4d6fc14bSjoerg#endif
52*4d6fc14bSjoerg
53*4d6fc14bSjoerg#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
54*4d6fc14bSjoerg#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
55*4d6fc14bSjoerg#else
56*4d6fc14bSjoerg#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
57*4d6fc14bSjoerg#endif
58*4d6fc14bSjoerg
59*4d6fc14bSjoergtypedef ::timespec __libcpp_timespec_t;
60*4d6fc14bSjoerg#endif // !defined(_LIBCPP_HAS_NO_THREADS)
61*4d6fc14bSjoerg
62*4d6fc14bSjoerg_LIBCPP_PUSH_MACROS
63*4d6fc14bSjoerg#include <__undef_macros>
64*4d6fc14bSjoerg
65*4d6fc14bSjoerg_LIBCPP_BEGIN_NAMESPACE_STD
66*4d6fc14bSjoerg
67*4d6fc14bSjoerg#if !defined(_LIBCPP_HAS_NO_THREADS)
68*4d6fc14bSjoerg
69*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
70*4d6fc14bSjoerg// Mutex
71*4d6fc14bSjoergtypedef pthread_mutex_t __libcpp_mutex_t;
72*4d6fc14bSjoerg#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
73*4d6fc14bSjoerg
74*4d6fc14bSjoergtypedef pthread_mutex_t __libcpp_recursive_mutex_t;
75*4d6fc14bSjoerg
76*4d6fc14bSjoerg// Condition Variable
77*4d6fc14bSjoergtypedef pthread_cond_t __libcpp_condvar_t;
78*4d6fc14bSjoerg#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
79*4d6fc14bSjoerg
80*4d6fc14bSjoerg#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
81*4d6fc14bSjoerg// Semaphore
82*4d6fc14bSjoergtypedef sem_t __libcpp_semaphore_t;
83*4d6fc14bSjoerg# define _LIBCPP_SEMAPHORE_MAX SEM_VALUE_MAX
84*4d6fc14bSjoerg#endif
85*4d6fc14bSjoerg
86*4d6fc14bSjoerg// Execute once
87*4d6fc14bSjoergtypedef pthread_once_t __libcpp_exec_once_flag;
88*4d6fc14bSjoerg#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
89*4d6fc14bSjoerg
90*4d6fc14bSjoerg// Thread id
91*4d6fc14bSjoerg#if defined(__MVS__)
92*4d6fc14bSjoerg  typedef unsigned long long __libcpp_thread_id;
93*4d6fc14bSjoerg#else
94*4d6fc14bSjoerg  typedef pthread_t __libcpp_thread_id;
95*4d6fc14bSjoerg#endif
96*4d6fc14bSjoerg
97*4d6fc14bSjoerg// Thread
98*4d6fc14bSjoerg#define _LIBCPP_NULL_THREAD ((__libcpp_thread_t()))
99*4d6fc14bSjoergtypedef pthread_t __libcpp_thread_t;
100*4d6fc14bSjoerg
101*4d6fc14bSjoerg// Thread Local Storage
102*4d6fc14bSjoergtypedef pthread_key_t __libcpp_tls_key;
103*4d6fc14bSjoerg
104*4d6fc14bSjoerg#define _LIBCPP_TLS_DESTRUCTOR_CC
105*4d6fc14bSjoerg#elif defined(_LIBCPP_HAS_THREAD_API_C11)
106*4d6fc14bSjoerg// Mutex
107*4d6fc14bSjoergtypedef mtx_t __libcpp_mutex_t;
108*4d6fc14bSjoerg// mtx_t is a struct so using {} for initialization is valid.
109*4d6fc14bSjoerg#define _LIBCPP_MUTEX_INITIALIZER {}
110*4d6fc14bSjoerg
111*4d6fc14bSjoergtypedef mtx_t __libcpp_recursive_mutex_t;
112*4d6fc14bSjoerg
113*4d6fc14bSjoerg// Condition Variable
114*4d6fc14bSjoergtypedef cnd_t __libcpp_condvar_t;
115*4d6fc14bSjoerg// cnd_t is a struct so using {} for initialization is valid.
116*4d6fc14bSjoerg#define _LIBCPP_CONDVAR_INITIALIZER {}
117*4d6fc14bSjoerg
118*4d6fc14bSjoerg// Execute once
119*4d6fc14bSjoergtypedef once_flag __libcpp_exec_once_flag;
120*4d6fc14bSjoerg#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT
121*4d6fc14bSjoerg
122*4d6fc14bSjoerg// Thread id
123*4d6fc14bSjoergtypedef thrd_t __libcpp_thread_id;
124*4d6fc14bSjoerg
125*4d6fc14bSjoerg// Thread
126*4d6fc14bSjoerg#define _LIBCPP_NULL_THREAD 0U
127*4d6fc14bSjoerg
128*4d6fc14bSjoergtypedef thrd_t __libcpp_thread_t;
129*4d6fc14bSjoerg
130*4d6fc14bSjoerg// Thread Local Storage
131*4d6fc14bSjoergtypedef tss_t __libcpp_tls_key;
132*4d6fc14bSjoerg
133*4d6fc14bSjoerg#define _LIBCPP_TLS_DESTRUCTOR_CC
134*4d6fc14bSjoerg#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
135*4d6fc14bSjoerg// Mutex
136*4d6fc14bSjoergtypedef void* __libcpp_mutex_t;
137*4d6fc14bSjoerg#define _LIBCPP_MUTEX_INITIALIZER 0
138*4d6fc14bSjoerg
139*4d6fc14bSjoerg#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
140*4d6fc14bSjoergtypedef void* __libcpp_recursive_mutex_t[6];
141*4d6fc14bSjoerg#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
142*4d6fc14bSjoergtypedef void* __libcpp_recursive_mutex_t[5];
143*4d6fc14bSjoerg#else
144*4d6fc14bSjoerg# error Unsupported architecture
145*4d6fc14bSjoerg#endif
146*4d6fc14bSjoerg
147*4d6fc14bSjoerg// Condition Variable
148*4d6fc14bSjoergtypedef void* __libcpp_condvar_t;
149*4d6fc14bSjoerg#define _LIBCPP_CONDVAR_INITIALIZER 0
150*4d6fc14bSjoerg
151*4d6fc14bSjoerg// Semaphore
152*4d6fc14bSjoergtypedef void* __libcpp_semaphore_t;
153*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_THREAD_API_WIN32)
154*4d6fc14bSjoerg# define _LIBCPP_SEMAPHORE_MAX (::std::numeric_limits<long>::max())
155*4d6fc14bSjoerg#endif
156*4d6fc14bSjoerg
157*4d6fc14bSjoerg// Execute Once
158*4d6fc14bSjoergtypedef void* __libcpp_exec_once_flag;
159*4d6fc14bSjoerg#define _LIBCPP_EXEC_ONCE_INITIALIZER 0
160*4d6fc14bSjoerg
161*4d6fc14bSjoerg// Thread ID
162*4d6fc14bSjoergtypedef long __libcpp_thread_id;
163*4d6fc14bSjoerg
164*4d6fc14bSjoerg// Thread
165*4d6fc14bSjoerg#define _LIBCPP_NULL_THREAD 0U
166*4d6fc14bSjoerg
167*4d6fc14bSjoergtypedef void* __libcpp_thread_t;
168*4d6fc14bSjoerg
169*4d6fc14bSjoerg// Thread Local Storage
170*4d6fc14bSjoergtypedef long __libcpp_tls_key;
171*4d6fc14bSjoerg
172*4d6fc14bSjoerg#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
173*4d6fc14bSjoerg#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
174*4d6fc14bSjoerg
175*4d6fc14bSjoerg#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
176*4d6fc14bSjoerg// Mutex
177*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
178*4d6fc14bSjoergint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
179*4d6fc14bSjoerg
180*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
181*4d6fc14bSjoergint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
182*4d6fc14bSjoerg
183*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
184*4d6fc14bSjoergbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
185*4d6fc14bSjoerg
186*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
187*4d6fc14bSjoergint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
188*4d6fc14bSjoerg
189*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
190*4d6fc14bSjoergint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
191*4d6fc14bSjoerg
192*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
193*4d6fc14bSjoergint __libcpp_mutex_lock(__libcpp_mutex_t *__m);
194*4d6fc14bSjoerg
195*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
196*4d6fc14bSjoergbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
197*4d6fc14bSjoerg
198*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
199*4d6fc14bSjoergint __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
200*4d6fc14bSjoerg
201*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
202*4d6fc14bSjoergint __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
203*4d6fc14bSjoerg
204*4d6fc14bSjoerg// Condition variable
205*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
206*4d6fc14bSjoergint __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
207*4d6fc14bSjoerg
208*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
209*4d6fc14bSjoergint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
210*4d6fc14bSjoerg
211*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
212*4d6fc14bSjoergint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
213*4d6fc14bSjoerg
214*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
215*4d6fc14bSjoergint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
216*4d6fc14bSjoerg                               __libcpp_timespec_t *__ts);
217*4d6fc14bSjoerg
218*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
219*4d6fc14bSjoergint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
220*4d6fc14bSjoerg
221*4d6fc14bSjoerg#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
222*4d6fc14bSjoerg
223*4d6fc14bSjoerg// Semaphore
224*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
225*4d6fc14bSjoergbool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init);
226*4d6fc14bSjoerg
227*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
228*4d6fc14bSjoergbool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem);
229*4d6fc14bSjoerg
230*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
231*4d6fc14bSjoergbool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem);
232*4d6fc14bSjoerg
233*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
234*4d6fc14bSjoergbool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem);
235*4d6fc14bSjoerg
236*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
237*4d6fc14bSjoergbool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns);
238*4d6fc14bSjoerg
239*4d6fc14bSjoerg#endif // _LIBCPP_NO_NATIVE_SEMAPHORES
240*4d6fc14bSjoerg
241*4d6fc14bSjoerg// Execute once
242*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
243*4d6fc14bSjoergint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
244*4d6fc14bSjoerg                          void (*init_routine)());
245*4d6fc14bSjoerg
246*4d6fc14bSjoerg// Thread id
247*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
248*4d6fc14bSjoergbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
249*4d6fc14bSjoerg
250*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
251*4d6fc14bSjoergbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
252*4d6fc14bSjoerg
253*4d6fc14bSjoerg// Thread
254*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
255*4d6fc14bSjoergbool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
256*4d6fc14bSjoerg
257*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
258*4d6fc14bSjoergint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
259*4d6fc14bSjoerg                           void *__arg);
260*4d6fc14bSjoerg
261*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
262*4d6fc14bSjoerg__libcpp_thread_id __libcpp_thread_get_current_id();
263*4d6fc14bSjoerg
264*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
265*4d6fc14bSjoerg__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
266*4d6fc14bSjoerg
267*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
268*4d6fc14bSjoergint __libcpp_thread_join(__libcpp_thread_t *__t);
269*4d6fc14bSjoerg
270*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
271*4d6fc14bSjoergint __libcpp_thread_detach(__libcpp_thread_t *__t);
272*4d6fc14bSjoerg
273*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
274*4d6fc14bSjoergvoid __libcpp_thread_yield();
275*4d6fc14bSjoerg
276*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
277*4d6fc14bSjoergvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
278*4d6fc14bSjoerg
279*4d6fc14bSjoerg// Thread local storage
280*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
281*4d6fc14bSjoergint __libcpp_tls_create(__libcpp_tls_key* __key,
282*4d6fc14bSjoerg                        void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
283*4d6fc14bSjoerg
284*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
285*4d6fc14bSjoergvoid *__libcpp_tls_get(__libcpp_tls_key __key);
286*4d6fc14bSjoerg
287*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY
288*4d6fc14bSjoergint __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
289*4d6fc14bSjoerg
290*4d6fc14bSjoerg#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
291*4d6fc14bSjoerg
292*4d6fc14bSjoergstruct __libcpp_timed_backoff_policy {
293*4d6fc14bSjoerg  _LIBCPP_INLINE_VISIBILITY
294*4d6fc14bSjoerg  bool operator()(chrono::nanoseconds __elapsed) const
295*4d6fc14bSjoerg  {
296*4d6fc14bSjoerg      if(__elapsed > chrono::milliseconds(128))
297*4d6fc14bSjoerg          __libcpp_thread_sleep_for(chrono::milliseconds(8));
298*4d6fc14bSjoerg      else if(__elapsed > chrono::microseconds(64))
299*4d6fc14bSjoerg          __libcpp_thread_sleep_for(__elapsed / 2);
300*4d6fc14bSjoerg      else if(__elapsed > chrono::microseconds(4))
301*4d6fc14bSjoerg        __libcpp_thread_yield();
302*4d6fc14bSjoerg      else
303*4d6fc14bSjoerg        {} // poll
304*4d6fc14bSjoerg      return false;
305*4d6fc14bSjoerg  }
306*4d6fc14bSjoerg};
307*4d6fc14bSjoerg
308*4d6fc14bSjoergstatic _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64;
309*4d6fc14bSjoerg
310*4d6fc14bSjoergtemplate<class _Fn, class _BFn>
311*4d6fc14bSjoerg_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
312*4d6fc14bSjoergbool __libcpp_thread_poll_with_backoff(
313*4d6fc14bSjoerg  _Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero())
314*4d6fc14bSjoerg{
315*4d6fc14bSjoerg    auto const __start = chrono::high_resolution_clock::now();
316*4d6fc14bSjoerg    for(int __count = 0;;) {
317*4d6fc14bSjoerg      if(__f())
318*4d6fc14bSjoerg        return true; // _Fn completion means success
319*4d6fc14bSjoerg      if(__count < __libcpp_polling_count) {
320*4d6fc14bSjoerg        __count += 1;
321*4d6fc14bSjoerg        continue;
322*4d6fc14bSjoerg      }
323*4d6fc14bSjoerg      chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start;
324*4d6fc14bSjoerg      if(__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed)
325*4d6fc14bSjoerg          return false; // timeout failure
326*4d6fc14bSjoerg      if(__bf(__elapsed))
327*4d6fc14bSjoerg        return false; // _BFn completion means failure
328*4d6fc14bSjoerg    }
329*4d6fc14bSjoerg}
330*4d6fc14bSjoerg
331*4d6fc14bSjoerg#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
332*4d6fc14bSjoerg     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL))
333*4d6fc14bSjoerg
334*4d6fc14bSjoerg
335*4d6fc14bSjoergnamespace __thread_detail {
336*4d6fc14bSjoerg
337*4d6fc14bSjoerginline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns)
338*4d6fc14bSjoerg{
339*4d6fc14bSjoerg  using namespace chrono;
340*4d6fc14bSjoerg  seconds __s = duration_cast<seconds>(__ns);
341*4d6fc14bSjoerg  __libcpp_timespec_t __ts;
342*4d6fc14bSjoerg  typedef decltype(__ts.tv_sec) __ts_sec;
343*4d6fc14bSjoerg  const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
344*4d6fc14bSjoerg
345*4d6fc14bSjoerg  if (__s.count() < __ts_sec_max)
346*4d6fc14bSjoerg  {
347*4d6fc14bSjoerg    __ts.tv_sec = static_cast<__ts_sec>(__s.count());
348*4d6fc14bSjoerg    __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
349*4d6fc14bSjoerg  }
350*4d6fc14bSjoerg  else
351*4d6fc14bSjoerg  {
352*4d6fc14bSjoerg    __ts.tv_sec = __ts_sec_max;
353*4d6fc14bSjoerg    __ts.tv_nsec = 999999999; // (10^9 - 1)
354*4d6fc14bSjoerg  }
355*4d6fc14bSjoerg
356*4d6fc14bSjoerg  return __ts;
357*4d6fc14bSjoerg}
358*4d6fc14bSjoerg
359*4d6fc14bSjoerg}
360*4d6fc14bSjoerg
361*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
362*4d6fc14bSjoerg
363*4d6fc14bSjoergint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
364*4d6fc14bSjoerg{
365*4d6fc14bSjoerg  pthread_mutexattr_t attr;
366*4d6fc14bSjoerg  int __ec = pthread_mutexattr_init(&attr);
367*4d6fc14bSjoerg  if (__ec)
368*4d6fc14bSjoerg    return __ec;
369*4d6fc14bSjoerg  __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
370*4d6fc14bSjoerg  if (__ec) {
371*4d6fc14bSjoerg    pthread_mutexattr_destroy(&attr);
372*4d6fc14bSjoerg    return __ec;
373*4d6fc14bSjoerg  }
374*4d6fc14bSjoerg  __ec = pthread_mutex_init(__m, &attr);
375*4d6fc14bSjoerg  if (__ec) {
376*4d6fc14bSjoerg    pthread_mutexattr_destroy(&attr);
377*4d6fc14bSjoerg    return __ec;
378*4d6fc14bSjoerg  }
379*4d6fc14bSjoerg  __ec = pthread_mutexattr_destroy(&attr);
380*4d6fc14bSjoerg  if (__ec) {
381*4d6fc14bSjoerg    pthread_mutex_destroy(__m);
382*4d6fc14bSjoerg    return __ec;
383*4d6fc14bSjoerg  }
384*4d6fc14bSjoerg  return 0;
385*4d6fc14bSjoerg}
386*4d6fc14bSjoerg
387*4d6fc14bSjoergint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
388*4d6fc14bSjoerg{
389*4d6fc14bSjoerg  return pthread_mutex_lock(__m);
390*4d6fc14bSjoerg}
391*4d6fc14bSjoerg
392*4d6fc14bSjoergbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
393*4d6fc14bSjoerg{
394*4d6fc14bSjoerg  return pthread_mutex_trylock(__m) == 0;
395*4d6fc14bSjoerg}
396*4d6fc14bSjoerg
397*4d6fc14bSjoergint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
398*4d6fc14bSjoerg{
399*4d6fc14bSjoerg  return pthread_mutex_unlock(__m);
400*4d6fc14bSjoerg}
401*4d6fc14bSjoerg
402*4d6fc14bSjoergint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
403*4d6fc14bSjoerg{
404*4d6fc14bSjoerg  return pthread_mutex_destroy(__m);
405*4d6fc14bSjoerg}
406*4d6fc14bSjoerg
407*4d6fc14bSjoergint __libcpp_mutex_lock(__libcpp_mutex_t *__m)
408*4d6fc14bSjoerg{
409*4d6fc14bSjoerg  return pthread_mutex_lock(__m);
410*4d6fc14bSjoerg}
411*4d6fc14bSjoerg
412*4d6fc14bSjoergbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
413*4d6fc14bSjoerg{
414*4d6fc14bSjoerg  return pthread_mutex_trylock(__m) == 0;
415*4d6fc14bSjoerg}
416*4d6fc14bSjoerg
417*4d6fc14bSjoergint __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
418*4d6fc14bSjoerg{
419*4d6fc14bSjoerg  return pthread_mutex_unlock(__m);
420*4d6fc14bSjoerg}
421*4d6fc14bSjoerg
422*4d6fc14bSjoergint __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
423*4d6fc14bSjoerg{
424*4d6fc14bSjoerg  return pthread_mutex_destroy(__m);
425*4d6fc14bSjoerg}
426*4d6fc14bSjoerg
427*4d6fc14bSjoerg// Condition Variable
428*4d6fc14bSjoergint __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
429*4d6fc14bSjoerg{
430*4d6fc14bSjoerg  return pthread_cond_signal(__cv);
431*4d6fc14bSjoerg}
432*4d6fc14bSjoerg
433*4d6fc14bSjoergint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
434*4d6fc14bSjoerg{
435*4d6fc14bSjoerg  return pthread_cond_broadcast(__cv);
436*4d6fc14bSjoerg}
437*4d6fc14bSjoerg
438*4d6fc14bSjoergint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
439*4d6fc14bSjoerg{
440*4d6fc14bSjoerg  return pthread_cond_wait(__cv, __m);
441*4d6fc14bSjoerg}
442*4d6fc14bSjoerg
443*4d6fc14bSjoergint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
444*4d6fc14bSjoerg                               __libcpp_timespec_t *__ts)
445*4d6fc14bSjoerg{
446*4d6fc14bSjoerg  return pthread_cond_timedwait(__cv, __m, __ts);
447*4d6fc14bSjoerg}
448*4d6fc14bSjoerg
449*4d6fc14bSjoergint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
450*4d6fc14bSjoerg{
451*4d6fc14bSjoerg  return pthread_cond_destroy(__cv);
452*4d6fc14bSjoerg}
453*4d6fc14bSjoerg
454*4d6fc14bSjoerg#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
455*4d6fc14bSjoerg
456*4d6fc14bSjoerg// Semaphore
457*4d6fc14bSjoergbool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init)
458*4d6fc14bSjoerg{
459*4d6fc14bSjoerg    return sem_init(__sem, 0, __init) == 0;
460*4d6fc14bSjoerg}
461*4d6fc14bSjoerg
462*4d6fc14bSjoergbool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem)
463*4d6fc14bSjoerg{
464*4d6fc14bSjoerg    return sem_destroy(__sem) == 0;
465*4d6fc14bSjoerg}
466*4d6fc14bSjoerg
467*4d6fc14bSjoergbool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem)
468*4d6fc14bSjoerg{
469*4d6fc14bSjoerg    return sem_post(__sem) == 0;
470*4d6fc14bSjoerg}
471*4d6fc14bSjoerg
472*4d6fc14bSjoergbool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem)
473*4d6fc14bSjoerg{
474*4d6fc14bSjoerg    return sem_wait(__sem) == 0;
475*4d6fc14bSjoerg}
476*4d6fc14bSjoerg
477*4d6fc14bSjoergbool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns)
478*4d6fc14bSjoerg{
479*4d6fc14bSjoerg    auto const __abs_time = chrono::system_clock::now().time_since_epoch() + __ns;
480*4d6fc14bSjoerg    __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__abs_time);
481*4d6fc14bSjoerg    return sem_timedwait(__sem, &__ts) == 0;
482*4d6fc14bSjoerg}
483*4d6fc14bSjoerg
484*4d6fc14bSjoerg#endif //_LIBCPP_NO_NATIVE_SEMAPHORES
485*4d6fc14bSjoerg
486*4d6fc14bSjoerg// Execute once
487*4d6fc14bSjoergint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
488*4d6fc14bSjoerg                          void (*init_routine)()) {
489*4d6fc14bSjoerg  return pthread_once(flag, init_routine);
490*4d6fc14bSjoerg}
491*4d6fc14bSjoerg
492*4d6fc14bSjoerg// Thread id
493*4d6fc14bSjoerg// Returns non-zero if the thread ids are equal, otherwise 0
494*4d6fc14bSjoergbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
495*4d6fc14bSjoerg{
496*4d6fc14bSjoerg  return t1 == t2;
497*4d6fc14bSjoerg}
498*4d6fc14bSjoerg
499*4d6fc14bSjoerg// Returns non-zero if t1 < t2, otherwise 0
500*4d6fc14bSjoergbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
501*4d6fc14bSjoerg{
502*4d6fc14bSjoerg  return t1 < t2;
503*4d6fc14bSjoerg}
504*4d6fc14bSjoerg
505*4d6fc14bSjoerg// Thread
506*4d6fc14bSjoergbool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
507*4d6fc14bSjoerg  return __libcpp_thread_get_id(__t) == 0;
508*4d6fc14bSjoerg}
509*4d6fc14bSjoerg
510*4d6fc14bSjoergint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
511*4d6fc14bSjoerg                           void *__arg)
512*4d6fc14bSjoerg{
513*4d6fc14bSjoerg  return pthread_create(__t, nullptr, __func, __arg);
514*4d6fc14bSjoerg}
515*4d6fc14bSjoerg
516*4d6fc14bSjoerg__libcpp_thread_id __libcpp_thread_get_current_id()
517*4d6fc14bSjoerg{
518*4d6fc14bSjoerg  const __libcpp_thread_t thread = pthread_self();
519*4d6fc14bSjoerg  return __libcpp_thread_get_id(&thread);
520*4d6fc14bSjoerg}
521*4d6fc14bSjoerg
522*4d6fc14bSjoerg__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
523*4d6fc14bSjoerg{
524*4d6fc14bSjoerg#if defined(__MVS__)
525*4d6fc14bSjoerg  return __t->__;
526*4d6fc14bSjoerg#else
527*4d6fc14bSjoerg  return *__t;
528*4d6fc14bSjoerg#endif
529*4d6fc14bSjoerg}
530*4d6fc14bSjoerg
531*4d6fc14bSjoergint __libcpp_thread_join(__libcpp_thread_t *__t)
532*4d6fc14bSjoerg{
533*4d6fc14bSjoerg  return pthread_join(*__t, nullptr);
534*4d6fc14bSjoerg}
535*4d6fc14bSjoerg
536*4d6fc14bSjoergint __libcpp_thread_detach(__libcpp_thread_t *__t)
537*4d6fc14bSjoerg{
538*4d6fc14bSjoerg  return pthread_detach(*__t);
539*4d6fc14bSjoerg}
540*4d6fc14bSjoerg
541*4d6fc14bSjoergvoid __libcpp_thread_yield()
542*4d6fc14bSjoerg{
543*4d6fc14bSjoerg  sched_yield();
544*4d6fc14bSjoerg}
545*4d6fc14bSjoerg
546*4d6fc14bSjoergvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
547*4d6fc14bSjoerg{
548*4d6fc14bSjoerg   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
549*4d6fc14bSjoerg   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
550*4d6fc14bSjoerg}
551*4d6fc14bSjoerg
552*4d6fc14bSjoerg// Thread local storage
553*4d6fc14bSjoergint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
554*4d6fc14bSjoerg{
555*4d6fc14bSjoerg  return pthread_key_create(__key, __at_exit);
556*4d6fc14bSjoerg}
557*4d6fc14bSjoerg
558*4d6fc14bSjoergvoid *__libcpp_tls_get(__libcpp_tls_key __key)
559*4d6fc14bSjoerg{
560*4d6fc14bSjoerg  return pthread_getspecific(__key);
561*4d6fc14bSjoerg}
562*4d6fc14bSjoerg
563*4d6fc14bSjoergint __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
564*4d6fc14bSjoerg{
565*4d6fc14bSjoerg    return pthread_setspecific(__key, __p);
566*4d6fc14bSjoerg}
567*4d6fc14bSjoerg
568*4d6fc14bSjoerg#elif defined(_LIBCPP_HAS_THREAD_API_C11)
569*4d6fc14bSjoerg
570*4d6fc14bSjoergint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
571*4d6fc14bSjoerg{
572*4d6fc14bSjoerg  return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
573*4d6fc14bSjoerg}
574*4d6fc14bSjoerg
575*4d6fc14bSjoergint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
576*4d6fc14bSjoerg{
577*4d6fc14bSjoerg  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
578*4d6fc14bSjoerg}
579*4d6fc14bSjoerg
580*4d6fc14bSjoergbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
581*4d6fc14bSjoerg{
582*4d6fc14bSjoerg  return mtx_trylock(__m) == thrd_success;
583*4d6fc14bSjoerg}
584*4d6fc14bSjoerg
585*4d6fc14bSjoergint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
586*4d6fc14bSjoerg{
587*4d6fc14bSjoerg  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
588*4d6fc14bSjoerg}
589*4d6fc14bSjoerg
590*4d6fc14bSjoergint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
591*4d6fc14bSjoerg{
592*4d6fc14bSjoerg  mtx_destroy(__m);
593*4d6fc14bSjoerg  return 0;
594*4d6fc14bSjoerg}
595*4d6fc14bSjoerg
596*4d6fc14bSjoergint __libcpp_mutex_lock(__libcpp_mutex_t *__m)
597*4d6fc14bSjoerg{
598*4d6fc14bSjoerg  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
599*4d6fc14bSjoerg}
600*4d6fc14bSjoerg
601*4d6fc14bSjoergbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
602*4d6fc14bSjoerg{
603*4d6fc14bSjoerg  return mtx_trylock(__m) == thrd_success;
604*4d6fc14bSjoerg}
605*4d6fc14bSjoerg
606*4d6fc14bSjoergint __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
607*4d6fc14bSjoerg{
608*4d6fc14bSjoerg  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
609*4d6fc14bSjoerg}
610*4d6fc14bSjoerg
611*4d6fc14bSjoergint __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
612*4d6fc14bSjoerg{
613*4d6fc14bSjoerg  mtx_destroy(__m);
614*4d6fc14bSjoerg  return 0;
615*4d6fc14bSjoerg}
616*4d6fc14bSjoerg
617*4d6fc14bSjoerg// Condition Variable
618*4d6fc14bSjoergint __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
619*4d6fc14bSjoerg{
620*4d6fc14bSjoerg  return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
621*4d6fc14bSjoerg}
622*4d6fc14bSjoerg
623*4d6fc14bSjoergint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
624*4d6fc14bSjoerg{
625*4d6fc14bSjoerg  return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
626*4d6fc14bSjoerg}
627*4d6fc14bSjoerg
628*4d6fc14bSjoergint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
629*4d6fc14bSjoerg{
630*4d6fc14bSjoerg  return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
631*4d6fc14bSjoerg}
632*4d6fc14bSjoerg
633*4d6fc14bSjoergint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
634*4d6fc14bSjoerg                               timespec *__ts)
635*4d6fc14bSjoerg{
636*4d6fc14bSjoerg  int __ec = cnd_timedwait(__cv, __m, __ts);
637*4d6fc14bSjoerg  return __ec == thrd_timedout ? ETIMEDOUT : __ec;
638*4d6fc14bSjoerg}
639*4d6fc14bSjoerg
640*4d6fc14bSjoergint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
641*4d6fc14bSjoerg{
642*4d6fc14bSjoerg  cnd_destroy(__cv);
643*4d6fc14bSjoerg  return 0;
644*4d6fc14bSjoerg}
645*4d6fc14bSjoerg
646*4d6fc14bSjoerg// Execute once
647*4d6fc14bSjoergint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
648*4d6fc14bSjoerg                          void (*init_routine)(void)) {
649*4d6fc14bSjoerg  ::call_once(flag, init_routine);
650*4d6fc14bSjoerg  return 0;
651*4d6fc14bSjoerg}
652*4d6fc14bSjoerg
653*4d6fc14bSjoerg// Thread id
654*4d6fc14bSjoerg// Returns non-zero if the thread ids are equal, otherwise 0
655*4d6fc14bSjoergbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
656*4d6fc14bSjoerg{
657*4d6fc14bSjoerg  return thrd_equal(t1, t2) != 0;
658*4d6fc14bSjoerg}
659*4d6fc14bSjoerg
660*4d6fc14bSjoerg// Returns non-zero if t1 < t2, otherwise 0
661*4d6fc14bSjoergbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
662*4d6fc14bSjoerg{
663*4d6fc14bSjoerg  return t1 < t2;
664*4d6fc14bSjoerg}
665*4d6fc14bSjoerg
666*4d6fc14bSjoerg// Thread
667*4d6fc14bSjoergbool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
668*4d6fc14bSjoerg  return __libcpp_thread_get_id(__t) == 0;
669*4d6fc14bSjoerg}
670*4d6fc14bSjoerg
671*4d6fc14bSjoergint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
672*4d6fc14bSjoerg                           void *__arg)
673*4d6fc14bSjoerg{
674*4d6fc14bSjoerg  int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
675*4d6fc14bSjoerg  return __ec == thrd_nomem ? ENOMEM : __ec;
676*4d6fc14bSjoerg}
677*4d6fc14bSjoerg
678*4d6fc14bSjoerg__libcpp_thread_id __libcpp_thread_get_current_id()
679*4d6fc14bSjoerg{
680*4d6fc14bSjoerg  return thrd_current();
681*4d6fc14bSjoerg}
682*4d6fc14bSjoerg
683*4d6fc14bSjoerg__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
684*4d6fc14bSjoerg{
685*4d6fc14bSjoerg  return *__t;
686*4d6fc14bSjoerg}
687*4d6fc14bSjoerg
688*4d6fc14bSjoergint __libcpp_thread_join(__libcpp_thread_t *__t)
689*4d6fc14bSjoerg{
690*4d6fc14bSjoerg  return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
691*4d6fc14bSjoerg}
692*4d6fc14bSjoerg
693*4d6fc14bSjoergint __libcpp_thread_detach(__libcpp_thread_t *__t)
694*4d6fc14bSjoerg{
695*4d6fc14bSjoerg  return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
696*4d6fc14bSjoerg}
697*4d6fc14bSjoerg
698*4d6fc14bSjoergvoid __libcpp_thread_yield()
699*4d6fc14bSjoerg{
700*4d6fc14bSjoerg  thrd_yield();
701*4d6fc14bSjoerg}
702*4d6fc14bSjoerg
703*4d6fc14bSjoergvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
704*4d6fc14bSjoerg{
705*4d6fc14bSjoerg   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
706*4d6fc14bSjoerg  thrd_sleep(&__ts, nullptr);
707*4d6fc14bSjoerg}
708*4d6fc14bSjoerg
709*4d6fc14bSjoerg// Thread local storage
710*4d6fc14bSjoergint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
711*4d6fc14bSjoerg{
712*4d6fc14bSjoerg  return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
713*4d6fc14bSjoerg}
714*4d6fc14bSjoerg
715*4d6fc14bSjoergvoid *__libcpp_tls_get(__libcpp_tls_key __key)
716*4d6fc14bSjoerg{
717*4d6fc14bSjoerg  return tss_get(__key);
718*4d6fc14bSjoerg}
719*4d6fc14bSjoerg
720*4d6fc14bSjoergint __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
721*4d6fc14bSjoerg{
722*4d6fc14bSjoerg  return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
723*4d6fc14bSjoerg}
724*4d6fc14bSjoerg
725*4d6fc14bSjoerg#endif
726*4d6fc14bSjoerg
727*4d6fc14bSjoerg
728*4d6fc14bSjoerg#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
729*4d6fc14bSjoerg
730*4d6fc14bSjoergclass _LIBCPP_TYPE_VIS thread;
731*4d6fc14bSjoergclass _LIBCPP_TYPE_VIS __thread_id;
732*4d6fc14bSjoerg
733*4d6fc14bSjoergnamespace this_thread
734*4d6fc14bSjoerg{
735*4d6fc14bSjoerg
736*4d6fc14bSjoerg_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
737*4d6fc14bSjoerg
738*4d6fc14bSjoerg}  // this_thread
739*4d6fc14bSjoerg
740*4d6fc14bSjoergtemplate<> struct hash<__thread_id>;
741*4d6fc14bSjoerg
742*4d6fc14bSjoergclass _LIBCPP_TEMPLATE_VIS __thread_id
743*4d6fc14bSjoerg{
744*4d6fc14bSjoerg    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
745*4d6fc14bSjoerg    // NULL is the no-thread value on Darwin.  Someone needs to check
746*4d6fc14bSjoerg    // on other platforms.  We assume 0 works everywhere for now.
747*4d6fc14bSjoerg    __libcpp_thread_id __id_;
748*4d6fc14bSjoerg
749*4d6fc14bSjoergpublic:
750*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
751*4d6fc14bSjoerg    __thread_id() _NOEXCEPT : __id_(0) {}
752*4d6fc14bSjoerg
753*4d6fc14bSjoerg    friend _LIBCPP_INLINE_VISIBILITY
754*4d6fc14bSjoerg        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
755*4d6fc14bSjoerg        { // don't pass id==0 to underlying routines
756*4d6fc14bSjoerg        if (__x.__id_ == 0) return __y.__id_ == 0;
757*4d6fc14bSjoerg        if (__y.__id_ == 0) return false;
758*4d6fc14bSjoerg        return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
759*4d6fc14bSjoerg        }
760*4d6fc14bSjoerg    friend _LIBCPP_INLINE_VISIBILITY
761*4d6fc14bSjoerg        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
762*4d6fc14bSjoerg        {return !(__x == __y);}
763*4d6fc14bSjoerg    friend _LIBCPP_INLINE_VISIBILITY
764*4d6fc14bSjoerg        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
765*4d6fc14bSjoerg        { // id==0 is always less than any other thread_id
766*4d6fc14bSjoerg        if (__x.__id_ == 0) return __y.__id_ != 0;
767*4d6fc14bSjoerg        if (__y.__id_ == 0) return false;
768*4d6fc14bSjoerg        return  __libcpp_thread_id_less(__x.__id_, __y.__id_);
769*4d6fc14bSjoerg        }
770*4d6fc14bSjoerg    friend _LIBCPP_INLINE_VISIBILITY
771*4d6fc14bSjoerg        bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
772*4d6fc14bSjoerg        {return !(__y < __x);}
773*4d6fc14bSjoerg    friend _LIBCPP_INLINE_VISIBILITY
774*4d6fc14bSjoerg        bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
775*4d6fc14bSjoerg        {return   __y < __x ;}
776*4d6fc14bSjoerg    friend _LIBCPP_INLINE_VISIBILITY
777*4d6fc14bSjoerg        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
778*4d6fc14bSjoerg        {return !(__x < __y);}
779*4d6fc14bSjoerg
780*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
781*4d6fc14bSjoerg    void __reset() { __id_ = 0; }
782*4d6fc14bSjoerg
783*4d6fc14bSjoerg    template<class _CharT, class _Traits>
784*4d6fc14bSjoerg    friend
785*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
786*4d6fc14bSjoerg    basic_ostream<_CharT, _Traits>&
787*4d6fc14bSjoerg    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
788*4d6fc14bSjoerg
789*4d6fc14bSjoergprivate:
790*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
791*4d6fc14bSjoerg    __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
792*4d6fc14bSjoerg
793*4d6fc14bSjoerg    friend __thread_id this_thread::get_id() _NOEXCEPT;
794*4d6fc14bSjoerg    friend class _LIBCPP_TYPE_VIS thread;
795*4d6fc14bSjoerg    friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
796*4d6fc14bSjoerg};
797*4d6fc14bSjoerg
798*4d6fc14bSjoergnamespace this_thread
799*4d6fc14bSjoerg{
800*4d6fc14bSjoerg
801*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY
802*4d6fc14bSjoerg__thread_id
803*4d6fc14bSjoergget_id() _NOEXCEPT
804*4d6fc14bSjoerg{
805*4d6fc14bSjoerg    return __libcpp_thread_get_current_id();
806*4d6fc14bSjoerg}
807*4d6fc14bSjoerg
808*4d6fc14bSjoerg}  // this_thread
809*4d6fc14bSjoerg
810*4d6fc14bSjoerg#endif // !_LIBCPP_HAS_NO_THREADS
811*4d6fc14bSjoerg
812*4d6fc14bSjoerg_LIBCPP_END_NAMESPACE_STD
813*4d6fc14bSjoerg
814*4d6fc14bSjoerg_LIBCPP_POP_MACROS
815*4d6fc14bSjoerg
816*4d6fc14bSjoerg#endif // _LIBCPP_THREADING_SUPPORT
817