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