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