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)
31 #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
32 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \
33 defined(_LIBCPP_HAS_THREAD_API_WIN32)
34 #define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
36 #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
39 #if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
40 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
42 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
45 typedef ::timespec __libcpp_timespec_t;
46 #endif // !defined(_LIBCPP_HAS_NO_THREADS)
49 #include <__undef_macros>
51 _LIBCPP_BEGIN_NAMESPACE_STD
53 #if !defined(_LIBCPP_HAS_NO_THREADS)
55 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
57 typedef pthread_mutex_t __libcpp_mutex_t;
58 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
60 typedef pthread_mutex_t __libcpp_recursive_mutex_t;
63 typedef pthread_cond_t __libcpp_condvar_t;
64 #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
67 typedef pthread_once_t __libcpp_exec_once_flag;
68 #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
71 typedef pthread_t __libcpp_thread_id;
74 #define _LIBCPP_NULL_THREAD 0U
76 typedef pthread_t __libcpp_thread_t;
78 // Thread Local Storage
79 typedef pthread_key_t __libcpp_tls_key;
81 #define _LIBCPP_TLS_DESTRUCTOR_CC
82 #elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
84 typedef void* __libcpp_mutex_t;
85 #define _LIBCPP_MUTEX_INITIALIZER 0
87 #if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
88 typedef void* __libcpp_recursive_mutex_t[6];
89 #elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
90 typedef void* __libcpp_recursive_mutex_t[5];
92 # error Unsupported architecture
96 typedef void* __libcpp_condvar_t;
97 #define _LIBCPP_CONDVAR_INITIALIZER 0
100 typedef void* __libcpp_exec_once_flag;
101 #define _LIBCPP_EXEC_ONCE_INITIALIZER 0
104 typedef long __libcpp_thread_id;
107 #define _LIBCPP_NULL_THREAD 0U
109 typedef void* __libcpp_thread_t;
111 // Thread Local Storage
112 typedef long __libcpp_tls_key;
114 #define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
115 #endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
117 #if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
119 _LIBCPP_THREAD_ABI_VISIBILITY
120 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
122 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
123 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
125 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
126 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
128 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
129 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
131 _LIBCPP_THREAD_ABI_VISIBILITY
132 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
134 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
135 int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
137 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
138 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
140 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
141 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
143 _LIBCPP_THREAD_ABI_VISIBILITY
144 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
146 // Condition variable
147 _LIBCPP_THREAD_ABI_VISIBILITY
148 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
150 _LIBCPP_THREAD_ABI_VISIBILITY
151 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
153 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
154 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
156 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
157 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
158 __libcpp_timespec_t *__ts);
160 _LIBCPP_THREAD_ABI_VISIBILITY
161 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
164 _LIBCPP_THREAD_ABI_VISIBILITY
165 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
166 void (*init_routine)());
169 _LIBCPP_THREAD_ABI_VISIBILITY
170 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
172 _LIBCPP_THREAD_ABI_VISIBILITY
173 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
176 _LIBCPP_THREAD_ABI_VISIBILITY
177 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
179 _LIBCPP_THREAD_ABI_VISIBILITY
180 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
183 _LIBCPP_THREAD_ABI_VISIBILITY
184 __libcpp_thread_id __libcpp_thread_get_current_id();
186 _LIBCPP_THREAD_ABI_VISIBILITY
187 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
189 _LIBCPP_THREAD_ABI_VISIBILITY
190 int __libcpp_thread_join(__libcpp_thread_t *__t);
192 _LIBCPP_THREAD_ABI_VISIBILITY
193 int __libcpp_thread_detach(__libcpp_thread_t *__t);
195 _LIBCPP_THREAD_ABI_VISIBILITY
196 void __libcpp_thread_yield();
198 _LIBCPP_THREAD_ABI_VISIBILITY
199 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
201 // Thread local storage
202 _LIBCPP_THREAD_ABI_VISIBILITY
203 int __libcpp_tls_create(__libcpp_tls_key* __key,
204 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
206 _LIBCPP_THREAD_ABI_VISIBILITY
207 void *__libcpp_tls_get(__libcpp_tls_key __key);
209 _LIBCPP_THREAD_ABI_VISIBILITY
210 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
212 #endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
214 #if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
215 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \
216 defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
218 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
220 pthread_mutexattr_t attr;
221 int __ec = pthread_mutexattr_init(&attr);
224 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
226 pthread_mutexattr_destroy(&attr);
229 __ec = pthread_mutex_init(__m, &attr);
231 pthread_mutexattr_destroy(&attr);
234 __ec = pthread_mutexattr_destroy(&attr);
236 pthread_mutex_destroy(__m);
242 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
244 return pthread_mutex_lock(__m);
247 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
249 return pthread_mutex_trylock(__m) == 0;
252 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
254 return pthread_mutex_unlock(__m);
257 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
259 return pthread_mutex_destroy(__m);
262 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
264 return pthread_mutex_lock(__m);
267 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
269 return pthread_mutex_trylock(__m) == 0;
272 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
274 return pthread_mutex_unlock(__m);
277 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
279 return pthread_mutex_destroy(__m);
282 // Condition Variable
283 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
285 return pthread_cond_signal(__cv);
288 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
290 return pthread_cond_broadcast(__cv);
293 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
295 return pthread_cond_wait(__cv, __m);
298 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
299 __libcpp_timespec_t *__ts)
301 return pthread_cond_timedwait(__cv, __m, __ts);
304 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
306 return pthread_cond_destroy(__cv);
310 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
311 void (*init_routine)()) {
312 return pthread_once(flag, init_routine);
316 // Returns non-zero if the thread ids are equal, otherwise 0
317 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
319 return pthread_equal(t1, t2) != 0;
322 // Returns non-zero if t1 < t2, otherwise 0
323 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
329 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
333 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
336 return pthread_create(__t, 0, __func, __arg);
339 __libcpp_thread_id __libcpp_thread_get_current_id()
341 return pthread_self();
344 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
349 int __libcpp_thread_join(__libcpp_thread_t *__t)
351 return pthread_join(*__t, 0);
354 int __libcpp_thread_detach(__libcpp_thread_t *__t)
356 return pthread_detach(*__t);
359 void __libcpp_thread_yield()
364 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
366 using namespace chrono;
367 seconds __s = duration_cast<seconds>(__ns);
368 __libcpp_timespec_t __ts;
369 typedef decltype(__ts.tv_sec) ts_sec;
370 _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max();
372 if (__s.count() < __ts_sec_max)
374 __ts.tv_sec = static_cast<ts_sec>(__s.count());
375 __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
379 __ts.tv_sec = __ts_sec_max;
380 __ts.tv_nsec = 999999999; // (10^9 - 1)
383 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
386 // Thread local storage
387 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
389 return pthread_key_create(__key, __at_exit);
392 void *__libcpp_tls_get(__libcpp_tls_key __key)
394 return pthread_getspecific(__key);
397 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
399 return pthread_setspecific(__key, __p);
402 #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
404 class _LIBCPP_TYPE_VIS thread;
405 class _LIBCPP_TYPE_VIS __thread_id;
407 namespace this_thread
410 _LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
414 template<> struct hash<__thread_id>;
416 class _LIBCPP_TEMPLATE_VIS __thread_id
418 // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
419 // NULL is the no-thread value on Darwin. Someone needs to check
420 // on other platforms. We assume 0 works everywhere for now.
421 __libcpp_thread_id __id_;
424 _LIBCPP_INLINE_VISIBILITY
425 __thread_id() _NOEXCEPT : __id_(0) {}
427 friend _LIBCPP_INLINE_VISIBILITY
428 bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
429 { // don't pass id==0 to underlying routines
430 if (__x.__id_ == 0) return __y.__id_ == 0;
431 if (__y.__id_ == 0) return false;
432 return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
434 friend _LIBCPP_INLINE_VISIBILITY
435 bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
436 {return !(__x == __y);}
437 friend _LIBCPP_INLINE_VISIBILITY
438 bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
439 { // id==0 is always less than any other thread_id
440 if (__x.__id_ == 0) return __y.__id_ != 0;
441 if (__y.__id_ == 0) return false;
442 return __libcpp_thread_id_less(__x.__id_, __y.__id_);
444 friend _LIBCPP_INLINE_VISIBILITY
445 bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
446 {return !(__y < __x);}
447 friend _LIBCPP_INLINE_VISIBILITY
448 bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
450 friend _LIBCPP_INLINE_VISIBILITY
451 bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
452 {return !(__x < __y);}
454 _LIBCPP_INLINE_VISIBILITY
455 void __reset() { __id_ = 0; }
457 template<class _CharT, class _Traits>
459 _LIBCPP_INLINE_VISIBILITY
460 basic_ostream<_CharT, _Traits>&
461 operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
464 _LIBCPP_INLINE_VISIBILITY
465 __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
467 friend __thread_id this_thread::get_id() _NOEXCEPT;
468 friend class _LIBCPP_TYPE_VIS thread;
469 friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
472 namespace this_thread
475 inline _LIBCPP_INLINE_VISIBILITY
479 return __libcpp_thread_get_current_id();
484 #endif // !_LIBCPP_HAS_NO_THREADS
486 _LIBCPP_END_NAMESPACE_STD
490 #endif // _LIBCPP_THREADING_SUPPORT