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