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