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