2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP_THREADING_SUPPORT
11 #define _LIBCPP_THREADING_SUPPORT
18 #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
19 #pragma GCC system_header
22 #if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
23 # include <__external_threading>
24 #elif !defined(_LIBCPP_HAS_NO_THREADS)
26 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
29 #elif defined(_LIBCPP_HAS_THREAD_API_C11)
33 #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
34 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \
35 defined(_LIBCPP_HAS_THREAD_API_WIN32)
36 #define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
38 #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
41 #if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
42 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
44 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
47 typedef ::timespec __libcpp_timespec_t;
48 #endif // !defined(_LIBCPP_HAS_NO_THREADS)
51 #include <__undef_macros>
53 _LIBCPP_BEGIN_NAMESPACE_STD
55 #if !defined(_LIBCPP_HAS_NO_THREADS)
57 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
59 typedef pthread_mutex_t __libcpp_mutex_t;
60 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
62 typedef pthread_mutex_t __libcpp_recursive_mutex_t;
65 typedef pthread_cond_t __libcpp_condvar_t;
66 #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
69 typedef pthread_once_t __libcpp_exec_once_flag;
70 #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
73 typedef pthread_t __libcpp_thread_id;
76 #define _LIBCPP_NULL_THREAD 0U
78 typedef pthread_t __libcpp_thread_t;
80 // Thread Local Storage
81 typedef pthread_key_t __libcpp_tls_key;
83 #define _LIBCPP_TLS_DESTRUCTOR_CC
84 #elif defined(_LIBCPP_HAS_THREAD_API_C11)
86 typedef mtx_t __libcpp_mutex_t;
87 // mtx_t is a struct so using {} for initialization is valid.
88 #define _LIBCPP_MUTEX_INITIALIZER {}
90 typedef mtx_t __libcpp_recursive_mutex_t;
93 typedef cnd_t __libcpp_condvar_t;
94 // cnd_t is a struct so using {} for initialization is valid.
95 #define _LIBCPP_CONDVAR_INITIALIZER {}
98 typedef once_flag __libcpp_exec_once_flag;
99 #define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT
102 typedef thrd_t __libcpp_thread_id;
105 #define _LIBCPP_NULL_THREAD 0U
107 typedef thrd_t __libcpp_thread_t;
109 // Thread Local Storage
110 typedef tss_t __libcpp_tls_key;
112 #define _LIBCPP_TLS_DESTRUCTOR_CC
113 #elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
115 typedef void* __libcpp_mutex_t;
116 #define _LIBCPP_MUTEX_INITIALIZER 0
118 #if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
119 typedef void* __libcpp_recursive_mutex_t[6];
120 #elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
121 typedef void* __libcpp_recursive_mutex_t[5];
123 # error Unsupported architecture
126 // Condition Variable
127 typedef void* __libcpp_condvar_t;
128 #define _LIBCPP_CONDVAR_INITIALIZER 0
131 typedef void* __libcpp_exec_once_flag;
132 #define _LIBCPP_EXEC_ONCE_INITIALIZER 0
135 typedef long __libcpp_thread_id;
138 #define _LIBCPP_NULL_THREAD 0U
140 typedef void* __libcpp_thread_t;
142 // Thread Local Storage
143 typedef long __libcpp_tls_key;
145 #define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
146 #endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
148 #if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
150 _LIBCPP_THREAD_ABI_VISIBILITY
151 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
153 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
154 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
156 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
157 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
159 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
160 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
162 _LIBCPP_THREAD_ABI_VISIBILITY
163 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
165 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
166 int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
168 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
169 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
171 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
172 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
174 _LIBCPP_THREAD_ABI_VISIBILITY
175 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
177 // Condition variable
178 _LIBCPP_THREAD_ABI_VISIBILITY
179 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
181 _LIBCPP_THREAD_ABI_VISIBILITY
182 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
184 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
185 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
187 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
188 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
189 __libcpp_timespec_t *__ts);
191 _LIBCPP_THREAD_ABI_VISIBILITY
192 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
195 _LIBCPP_THREAD_ABI_VISIBILITY
196 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
197 void (*init_routine)());
200 _LIBCPP_THREAD_ABI_VISIBILITY
201 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
203 _LIBCPP_THREAD_ABI_VISIBILITY
204 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
207 _LIBCPP_THREAD_ABI_VISIBILITY
208 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
210 _LIBCPP_THREAD_ABI_VISIBILITY
211 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
214 _LIBCPP_THREAD_ABI_VISIBILITY
215 __libcpp_thread_id __libcpp_thread_get_current_id();
217 _LIBCPP_THREAD_ABI_VISIBILITY
218 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
220 _LIBCPP_THREAD_ABI_VISIBILITY
221 int __libcpp_thread_join(__libcpp_thread_t *__t);
223 _LIBCPP_THREAD_ABI_VISIBILITY
224 int __libcpp_thread_detach(__libcpp_thread_t *__t);
226 _LIBCPP_THREAD_ABI_VISIBILITY
227 void __libcpp_thread_yield();
229 _LIBCPP_THREAD_ABI_VISIBILITY
230 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
232 // Thread local storage
233 _LIBCPP_THREAD_ABI_VISIBILITY
234 int __libcpp_tls_create(__libcpp_tls_key* __key,
235 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
237 _LIBCPP_THREAD_ABI_VISIBILITY
238 void *__libcpp_tls_get(__libcpp_tls_key __key);
240 _LIBCPP_THREAD_ABI_VISIBILITY
241 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
243 #endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
245 #if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
246 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL))
248 namespace __thread_detail {
250 inline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns)
252 using namespace chrono;
253 seconds __s = duration_cast<seconds>(__ns);
254 __libcpp_timespec_t __ts;
255 typedef decltype(__ts.tv_sec) __ts_sec;
256 const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
258 if (__s.count() < __ts_sec_max)
260 __ts.tv_sec = static_cast<__ts_sec>(__s.count());
261 __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
265 __ts.tv_sec = __ts_sec_max;
266 __ts.tv_nsec = 999999999; // (10^9 - 1)
274 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
276 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
278 pthread_mutexattr_t attr;
279 int __ec = pthread_mutexattr_init(&attr);
282 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
284 pthread_mutexattr_destroy(&attr);
287 __ec = pthread_mutex_init(__m, &attr);
289 pthread_mutexattr_destroy(&attr);
292 __ec = pthread_mutexattr_destroy(&attr);
294 pthread_mutex_destroy(__m);
300 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
302 return pthread_mutex_lock(__m);
305 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
307 return pthread_mutex_trylock(__m) == 0;
310 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
312 return pthread_mutex_unlock(__m);
315 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
317 return pthread_mutex_destroy(__m);
320 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
322 return pthread_mutex_lock(__m);
325 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
327 return pthread_mutex_trylock(__m) == 0;
330 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
332 return pthread_mutex_unlock(__m);
335 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
337 return pthread_mutex_destroy(__m);
340 // Condition Variable
341 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
343 return pthread_cond_signal(__cv);
346 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
348 return pthread_cond_broadcast(__cv);
351 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
353 return pthread_cond_wait(__cv, __m);
356 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
357 __libcpp_timespec_t *__ts)
359 return pthread_cond_timedwait(__cv, __m, __ts);
362 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
364 return pthread_cond_destroy(__cv);
368 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
369 void (*init_routine)()) {
370 return pthread_once(flag, init_routine);
374 // Returns non-zero if the thread ids are equal, otherwise 0
375 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
377 return pthread_equal(t1, t2) != 0;
380 // Returns non-zero if t1 < t2, otherwise 0
381 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
387 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
391 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
394 return pthread_create(__t, 0, __func, __arg);
397 __libcpp_thread_id __libcpp_thread_get_current_id()
399 return pthread_self();
402 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
407 int __libcpp_thread_join(__libcpp_thread_t *__t)
409 return pthread_join(*__t, 0);
412 int __libcpp_thread_detach(__libcpp_thread_t *__t)
414 return pthread_detach(*__t);
417 void __libcpp_thread_yield()
422 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
424 __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
425 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
428 // Thread local storage
429 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
431 return pthread_key_create(__key, __at_exit);
434 void *__libcpp_tls_get(__libcpp_tls_key __key)
436 return pthread_getspecific(__key);
439 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
441 return pthread_setspecific(__key, __p);
444 #elif defined(_LIBCPP_HAS_THREAD_API_C11)
446 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
448 return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
451 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
453 return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
456 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
458 return mtx_trylock(__m) == thrd_success;
461 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
463 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
466 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
472 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
474 return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
477 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
479 return mtx_trylock(__m) == thrd_success;
482 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
484 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
487 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
493 // Condition Variable
494 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
496 return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
499 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
501 return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
504 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
506 return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
509 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
512 int __ec = cnd_timedwait(__cv, __m, __ts);
513 return __ec == thrd_timedout ? ETIMEDOUT : __ec;
516 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
523 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
524 void (*init_routine)(void)) {
525 ::call_once(flag, init_routine);
530 // Returns non-zero if the thread ids are equal, otherwise 0
531 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
533 return thrd_equal(t1, t2) != 0;
536 // Returns non-zero if t1 < t2, otherwise 0
537 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
543 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
547 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
550 int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
551 return __ec == thrd_nomem ? ENOMEM : __ec;
554 __libcpp_thread_id __libcpp_thread_get_current_id()
556 return thrd_current();
559 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
564 int __libcpp_thread_join(__libcpp_thread_t *__t)
566 return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
569 int __libcpp_thread_detach(__libcpp_thread_t *__t)
571 return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
574 void __libcpp_thread_yield()
579 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
581 __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
582 thrd_sleep(&__ts, nullptr);
585 // Thread local storage
586 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
588 return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
591 void *__libcpp_tls_get(__libcpp_tls_key __key)
593 return tss_get(__key);
596 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
598 return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
603 #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
605 class _LIBCPP_TYPE_VIS thread;
606 class _LIBCPP_TYPE_VIS __thread_id;
608 namespace this_thread
611 _LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
615 template<> struct hash<__thread_id>;
617 class _LIBCPP_TEMPLATE_VIS __thread_id
619 // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
620 // NULL is the no-thread value on Darwin. Someone needs to check
621 // on other platforms. We assume 0 works everywhere for now.
622 __libcpp_thread_id __id_;
625 _LIBCPP_INLINE_VISIBILITY
626 __thread_id() _NOEXCEPT : __id_(0) {}
628 friend _LIBCPP_INLINE_VISIBILITY
629 bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
630 { // don't pass id==0 to underlying routines
631 if (__x.__id_ == 0) return __y.__id_ == 0;
632 if (__y.__id_ == 0) return false;
633 return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
635 friend _LIBCPP_INLINE_VISIBILITY
636 bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
637 {return !(__x == __y);}
638 friend _LIBCPP_INLINE_VISIBILITY
639 bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
640 { // id==0 is always less than any other thread_id
641 if (__x.__id_ == 0) return __y.__id_ != 0;
642 if (__y.__id_ == 0) return false;
643 return __libcpp_thread_id_less(__x.__id_, __y.__id_);
645 friend _LIBCPP_INLINE_VISIBILITY
646 bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
647 {return !(__y < __x);}
648 friend _LIBCPP_INLINE_VISIBILITY
649 bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
651 friend _LIBCPP_INLINE_VISIBILITY
652 bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
653 {return !(__x < __y);}
655 _LIBCPP_INLINE_VISIBILITY
656 void __reset() { __id_ = 0; }
658 template<class _CharT, class _Traits>
660 _LIBCPP_INLINE_VISIBILITY
661 basic_ostream<_CharT, _Traits>&
662 operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
665 _LIBCPP_INLINE_VISIBILITY
666 __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
668 friend __thread_id this_thread::get_id() _NOEXCEPT;
669 friend class _LIBCPP_TYPE_VIS thread;
670 friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
673 namespace this_thread
676 inline _LIBCPP_INLINE_VISIBILITY
680 return __libcpp_thread_get_current_id();
685 #endif // !_LIBCPP_HAS_NO_THREADS
687 _LIBCPP_END_NAMESPACE_STD
691 #endif // _LIBCPP_THREADING_SUPPORT