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