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