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