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_THREAD_ABI_VISIBILITY
282  bool operator()(chrono::nanoseconds __elapsed) const;
283};
284
285inline _LIBCPP_INLINE_VISIBILITY
286bool __libcpp_timed_backoff_policy::operator()(chrono::nanoseconds __elapsed) const
287{
288    if(__elapsed > chrono::milliseconds(128))
289        __libcpp_thread_sleep_for(chrono::milliseconds(8));
290    else if(__elapsed > chrono::microseconds(64))
291        __libcpp_thread_sleep_for(__elapsed / 2);
292    else if(__elapsed > chrono::microseconds(4))
293      __libcpp_thread_yield();
294    else
295      ; // poll
296    return false;
297}
298
299static _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64;
300
301template<class _Fn, class _BFn>
302_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
303bool __libcpp_thread_poll_with_backoff(
304  _Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero())
305{
306    auto const __start = chrono::high_resolution_clock::now();
307    for(int __count = 0;;) {
308      if(__f())
309        return true; // _Fn completion means success
310      if(__count < __libcpp_polling_count) {
311        __count += 1;
312        continue;
313      }
314      chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start;
315      if(__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed)
316          return false; // timeout failure
317      if(__bf(__elapsed))
318        return false; // _BFn completion means failure
319    }
320}
321
322#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
323     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL))
324
325
326namespace __thread_detail {
327
328inline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns)
329{
330  using namespace chrono;
331  seconds __s = duration_cast<seconds>(__ns);
332  __libcpp_timespec_t __ts;
333  typedef decltype(__ts.tv_sec) __ts_sec;
334  const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
335
336  if (__s.count() < __ts_sec_max)
337  {
338    __ts.tv_sec = static_cast<__ts_sec>(__s.count());
339    __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
340  }
341  else
342  {
343    __ts.tv_sec = __ts_sec_max;
344    __ts.tv_nsec = 999999999; // (10^9 - 1)
345  }
346
347  return __ts;
348}
349
350}
351
352#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
353
354int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
355{
356  pthread_mutexattr_t attr;
357  int __ec = pthread_mutexattr_init(&attr);
358  if (__ec)
359    return __ec;
360  __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
361  if (__ec) {
362    pthread_mutexattr_destroy(&attr);
363    return __ec;
364  }
365  __ec = pthread_mutex_init(__m, &attr);
366  if (__ec) {
367    pthread_mutexattr_destroy(&attr);
368    return __ec;
369  }
370  __ec = pthread_mutexattr_destroy(&attr);
371  if (__ec) {
372    pthread_mutex_destroy(__m);
373    return __ec;
374  }
375  return 0;
376}
377
378int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
379{
380  return pthread_mutex_lock(__m);
381}
382
383bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
384{
385  return pthread_mutex_trylock(__m) == 0;
386}
387
388int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
389{
390  return pthread_mutex_unlock(__m);
391}
392
393int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
394{
395  return pthread_mutex_destroy(__m);
396}
397
398int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
399{
400  return pthread_mutex_lock(__m);
401}
402
403bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
404{
405  return pthread_mutex_trylock(__m) == 0;
406}
407
408int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
409{
410  return pthread_mutex_unlock(__m);
411}
412
413int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
414{
415  return pthread_mutex_destroy(__m);
416}
417
418// Condition Variable
419int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
420{
421  return pthread_cond_signal(__cv);
422}
423
424int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
425{
426  return pthread_cond_broadcast(__cv);
427}
428
429int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
430{
431  return pthread_cond_wait(__cv, __m);
432}
433
434int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
435                               __libcpp_timespec_t *__ts)
436{
437  return pthread_cond_timedwait(__cv, __m, __ts);
438}
439
440int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
441{
442  return pthread_cond_destroy(__cv);
443}
444
445#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
446
447// Semaphore
448bool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init)
449{
450    return sem_init(__sem, 0, __init) == 0;
451}
452
453bool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem)
454{
455    return sem_destroy(__sem) == 0;
456}
457
458bool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem)
459{
460    return sem_post(__sem) == 0;
461}
462
463bool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem)
464{
465    return sem_wait(__sem) == 0;
466}
467
468bool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns)
469{
470    auto const __abs_time = chrono::system_clock::now().time_since_epoch() + __ns;
471    __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__abs_time);
472    return sem_timedwait(__sem, &__ts) == 0;
473}
474
475#endif //_LIBCPP_NO_NATIVE_SEMAPHORES
476
477// Execute once
478int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
479                          void (*init_routine)()) {
480  return pthread_once(flag, init_routine);
481}
482
483// Thread id
484// Returns non-zero if the thread ids are equal, otherwise 0
485bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
486{
487  return pthread_equal(t1, t2) != 0;
488}
489
490// Returns non-zero if t1 < t2, otherwise 0
491bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
492{
493  return t1 < t2;
494}
495
496// Thread
497bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
498  return *__t == 0;
499}
500
501int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
502                           void *__arg)
503{
504  return pthread_create(__t, 0, __func, __arg);
505}
506
507__libcpp_thread_id __libcpp_thread_get_current_id()
508{
509  return pthread_self();
510}
511
512__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
513{
514  return *__t;
515}
516
517int __libcpp_thread_join(__libcpp_thread_t *__t)
518{
519  return pthread_join(*__t, 0);
520}
521
522int __libcpp_thread_detach(__libcpp_thread_t *__t)
523{
524  return pthread_detach(*__t);
525}
526
527void __libcpp_thread_yield()
528{
529  sched_yield();
530}
531
532void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
533{
534   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
535   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
536}
537
538// Thread local storage
539int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
540{
541  return pthread_key_create(__key, __at_exit);
542}
543
544void *__libcpp_tls_get(__libcpp_tls_key __key)
545{
546  return pthread_getspecific(__key);
547}
548
549int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
550{
551    return pthread_setspecific(__key, __p);
552}
553
554#elif defined(_LIBCPP_HAS_THREAD_API_C11)
555
556int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
557{
558  return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
559}
560
561int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
562{
563  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
564}
565
566bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
567{
568  return mtx_trylock(__m) == thrd_success;
569}
570
571int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
572{
573  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
574}
575
576int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
577{
578  mtx_destroy(__m);
579  return 0;
580}
581
582int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
583{
584  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
585}
586
587bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
588{
589  return mtx_trylock(__m) == thrd_success;
590}
591
592int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
593{
594  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
595}
596
597int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
598{
599  mtx_destroy(__m);
600  return 0;
601}
602
603// Condition Variable
604int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
605{
606  return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
607}
608
609int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
610{
611  return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
612}
613
614int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
615{
616  return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
617}
618
619int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
620                               timespec *__ts)
621{
622  int __ec = cnd_timedwait(__cv, __m, __ts);
623  return __ec == thrd_timedout ? ETIMEDOUT : __ec;
624}
625
626int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
627{
628  cnd_destroy(__cv);
629  return 0;
630}
631
632// Execute once
633int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
634                          void (*init_routine)(void)) {
635  ::call_once(flag, init_routine);
636  return 0;
637}
638
639// Thread id
640// Returns non-zero if the thread ids are equal, otherwise 0
641bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
642{
643  return thrd_equal(t1, t2) != 0;
644}
645
646// Returns non-zero if t1 < t2, otherwise 0
647bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
648{
649  return t1 < t2;
650}
651
652// Thread
653bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
654  return *__t == 0;
655}
656
657int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
658                           void *__arg)
659{
660  int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
661  return __ec == thrd_nomem ? ENOMEM : __ec;
662}
663
664__libcpp_thread_id __libcpp_thread_get_current_id()
665{
666  return thrd_current();
667}
668
669__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
670{
671  return *__t;
672}
673
674int __libcpp_thread_join(__libcpp_thread_t *__t)
675{
676  return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
677}
678
679int __libcpp_thread_detach(__libcpp_thread_t *__t)
680{
681  return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
682}
683
684void __libcpp_thread_yield()
685{
686  thrd_yield();
687}
688
689void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
690{
691   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
692  thrd_sleep(&__ts, nullptr);
693}
694
695// Thread local storage
696int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
697{
698  return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
699}
700
701void *__libcpp_tls_get(__libcpp_tls_key __key)
702{
703  return tss_get(__key);
704}
705
706int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
707{
708  return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
709}
710
711#endif
712
713
714#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
715
716class _LIBCPP_TYPE_VIS thread;
717class _LIBCPP_TYPE_VIS __thread_id;
718
719namespace this_thread
720{
721
722_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
723
724}  // this_thread
725
726template<> struct hash<__thread_id>;
727
728class _LIBCPP_TEMPLATE_VIS __thread_id
729{
730    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
731    // NULL is the no-thread value on Darwin.  Someone needs to check
732    // on other platforms.  We assume 0 works everywhere for now.
733    __libcpp_thread_id __id_;
734
735public:
736    _LIBCPP_INLINE_VISIBILITY
737    __thread_id() _NOEXCEPT : __id_(0) {}
738
739    friend _LIBCPP_INLINE_VISIBILITY
740        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
741        { // don't pass id==0 to underlying routines
742        if (__x.__id_ == 0) return __y.__id_ == 0;
743        if (__y.__id_ == 0) return false;
744        return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
745        }
746    friend _LIBCPP_INLINE_VISIBILITY
747        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
748        {return !(__x == __y);}
749    friend _LIBCPP_INLINE_VISIBILITY
750        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
751        { // id==0 is always less than any other thread_id
752        if (__x.__id_ == 0) return __y.__id_ != 0;
753        if (__y.__id_ == 0) return false;
754        return  __libcpp_thread_id_less(__x.__id_, __y.__id_);
755        }
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   __y < __x ;}
762    friend _LIBCPP_INLINE_VISIBILITY
763        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
764        {return !(__x < __y);}
765
766    _LIBCPP_INLINE_VISIBILITY
767    void __reset() { __id_ = 0; }
768
769    template<class _CharT, class _Traits>
770    friend
771    _LIBCPP_INLINE_VISIBILITY
772    basic_ostream<_CharT, _Traits>&
773    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
774
775private:
776    _LIBCPP_INLINE_VISIBILITY
777    __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
778
779    friend __thread_id this_thread::get_id() _NOEXCEPT;
780    friend class _LIBCPP_TYPE_VIS thread;
781    friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
782};
783
784namespace this_thread
785{
786
787inline _LIBCPP_INLINE_VISIBILITY
788__thread_id
789get_id() _NOEXCEPT
790{
791    return __libcpp_thread_get_current_id();
792}
793
794}  // this_thread
795
796#endif // !_LIBCPP_HAS_NO_THREADS
797
798_LIBCPP_END_NAMESPACE_STD
799
800_LIBCPP_POP_MACROS
801
802#endif // _LIBCPP_THREADING_SUPPORT
803