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