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