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