2 //===----------------------------------------------------------------------===//
4 // The LLVM Compiler Infrastructure
6 // This file is dual licensed under the MIT and the University of Illinois Open
7 // Source Licenses. See LICENSE.TXT for details.
9 //===----------------------------------------------------------------------===//
11 #ifndef _LIBCPP_THREADING_SUPPORT
12 #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_WIN32)
32 #include <fibersapi.h>
36 #include <__undef_macros>
39 #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
40 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
41 #define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
43 #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
46 #if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
47 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
49 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
52 _LIBCPP_BEGIN_NAMESPACE_STD
54 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
56 typedef pthread_mutex_t __libcpp_mutex_t;
57 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
59 typedef pthread_mutex_t __libcpp_recursive_mutex_t;
62 typedef pthread_cond_t __libcpp_condvar_t;
63 #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
66 typedef pthread_once_t __libcpp_exec_once_flag;
67 #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
70 typedef pthread_t __libcpp_thread_id;
73 #define _LIBCPP_NULL_THREAD 0U
75 typedef pthread_t __libcpp_thread_t;
77 // Thrad Local Storage
78 typedef pthread_key_t __libcpp_tls_key;
80 #define _LIBCPP_TLS_DESTRUCTOR_CC
83 typedef SRWLOCK __libcpp_mutex_t;
84 #define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT
86 typedef CRITICAL_SECTION __libcpp_recursive_mutex_t;
89 typedef CONDITION_VARIABLE __libcpp_condvar_t;
90 #define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT
93 typedef INIT_ONCE __libcpp_exec_once_flag;
94 #define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
97 typedef DWORD __libcpp_thread_id;
100 #define _LIBCPP_NULL_THREAD 0U
102 typedef HANDLE __libcpp_thread_t;
104 // Thread Local Storage
105 typedef DWORD __libcpp_tls_key;
107 #define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI
111 _LIBCPP_THREAD_ABI_VISIBILITY
112 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
114 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
115 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
117 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
118 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
120 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
121 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
123 _LIBCPP_THREAD_ABI_VISIBILITY
124 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
126 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
127 int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
129 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
130 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
132 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
133 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
135 _LIBCPP_THREAD_ABI_VISIBILITY
136 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
138 // Condition variable
139 _LIBCPP_THREAD_ABI_VISIBILITY
140 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
142 _LIBCPP_THREAD_ABI_VISIBILITY
143 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
145 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
146 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
148 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
149 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
152 _LIBCPP_THREAD_ABI_VISIBILITY
153 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
156 _LIBCPP_THREAD_ABI_VISIBILITY
157 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
158 void (*init_routine)(void));
161 _LIBCPP_THREAD_ABI_VISIBILITY
162 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
164 _LIBCPP_THREAD_ABI_VISIBILITY
165 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
168 _LIBCPP_THREAD_ABI_VISIBILITY
169 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
171 _LIBCPP_THREAD_ABI_VISIBILITY
172 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
175 _LIBCPP_THREAD_ABI_VISIBILITY
176 __libcpp_thread_id __libcpp_thread_get_current_id();
178 _LIBCPP_THREAD_ABI_VISIBILITY
179 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
181 _LIBCPP_THREAD_ABI_VISIBILITY
182 int __libcpp_thread_join(__libcpp_thread_t *__t);
184 _LIBCPP_THREAD_ABI_VISIBILITY
185 int __libcpp_thread_detach(__libcpp_thread_t *__t);
187 _LIBCPP_THREAD_ABI_VISIBILITY
188 void __libcpp_thread_yield();
190 _LIBCPP_THREAD_ABI_VISIBILITY
191 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
193 // Thread local storage
194 _LIBCPP_THREAD_ABI_VISIBILITY
195 int __libcpp_tls_create(__libcpp_tls_key* __key,
196 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
198 _LIBCPP_THREAD_ABI_VISIBILITY
199 void *__libcpp_tls_get(__libcpp_tls_key __key);
201 _LIBCPP_THREAD_ABI_VISIBILITY
202 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
204 #if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
205 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
207 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
209 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
211 pthread_mutexattr_t attr;
212 int __ec = pthread_mutexattr_init(&attr);
215 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
217 pthread_mutexattr_destroy(&attr);
220 __ec = pthread_mutex_init(__m, &attr);
222 pthread_mutexattr_destroy(&attr);
225 __ec = pthread_mutexattr_destroy(&attr);
227 pthread_mutex_destroy(__m);
233 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
235 return pthread_mutex_lock(__m);
238 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
240 return pthread_mutex_trylock(__m) == 0;
243 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
245 return pthread_mutex_unlock(__m);
248 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
250 return pthread_mutex_destroy(__m);
253 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
255 return pthread_mutex_lock(__m);
258 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
260 return pthread_mutex_trylock(__m) == 0;
263 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
265 return pthread_mutex_unlock(__m);
268 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
270 return pthread_mutex_destroy(__m);
273 // Condition Variable
274 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
276 return pthread_cond_signal(__cv);
279 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
281 return pthread_cond_broadcast(__cv);
284 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
286 return pthread_cond_wait(__cv, __m);
289 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
292 return pthread_cond_timedwait(__cv, __m, __ts);
295 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
297 return pthread_cond_destroy(__cv);
301 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
302 void (*init_routine)(void)) {
303 return pthread_once(flag, init_routine);
307 // Returns non-zero if the thread ids are equal, otherwise 0
308 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
310 return pthread_equal(t1, t2) != 0;
313 // Returns non-zero if t1 < t2, otherwise 0
314 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
320 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
324 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
327 return pthread_create(__t, 0, __func, __arg);
330 __libcpp_thread_id __libcpp_thread_get_current_id()
332 return pthread_self();
335 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
340 int __libcpp_thread_join(__libcpp_thread_t *__t)
342 return pthread_join(*__t, 0);
345 int __libcpp_thread_detach(__libcpp_thread_t *__t)
347 return pthread_detach(*__t);
350 void __libcpp_thread_yield()
355 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
357 using namespace chrono;
358 seconds __s = duration_cast<seconds>(__ns);
360 typedef decltype(__ts.tv_sec) ts_sec;
361 _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max();
363 if (__s.count() < __ts_sec_max)
365 __ts.tv_sec = static_cast<ts_sec>(__s.count());
366 __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
370 __ts.tv_sec = __ts_sec_max;
371 __ts.tv_nsec = 999999999; // (10^9 - 1)
374 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
377 // Thread local storage
378 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
380 return pthread_key_create(__key, __at_exit);
383 void *__libcpp_tls_get(__libcpp_tls_key __key)
385 return pthread_getspecific(__key);
388 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
390 return pthread_setspecific(__key, __p);
393 #elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
396 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
398 InitializeCriticalSection(__m);
402 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
404 EnterCriticalSection(__m);
408 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
410 return TryEnterCriticalSection(__m) != 0;
413 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
415 LeaveCriticalSection(__m);
419 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
421 DeleteCriticalSection(__m);
425 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
427 AcquireSRWLockExclusive(__m);
431 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
433 return TryAcquireSRWLockExclusive(__m) != 0;
436 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
438 ReleaseSRWLockExclusive(__m);
442 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
444 static_cast<void>(__m);
448 // Condition Variable
449 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
451 WakeConditionVariable(__cv);
455 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
457 WakeAllConditionVariable(__cv);
461 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
463 SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
467 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
470 using namespace _VSTD::chrono;
472 auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
474 system_clock::time_point(duration_cast<system_clock::duration>(duration));
475 auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
477 if (!SleepConditionVariableSRW(__cv, __m,
478 timeout_ms.count() > 0 ? timeout_ms.count()
482 auto __ec = GetLastError();
483 return __ec == ERROR_TIMEOUT ? ETIMEDOUT : __ec;
488 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
490 static_cast<void>(__cv);
495 static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
496 __libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
499 static_cast<void>(__init_once);
500 static_cast<void>(__context);
502 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
507 int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
508 void (*__init_routine)(void))
510 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
511 reinterpret_cast<void *>(__init_routine), NULL))
512 return GetLastError();
517 bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
518 __libcpp_thread_id __rhs)
520 return __lhs == __rhs;
523 bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
525 return __lhs < __rhs;
529 struct __libcpp_beginthreadex_thunk_data
531 void *(*__func)(void *);
535 static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI
536 __libcpp_beginthreadex_thunk(void *__raw_data)
539 static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data);
540 auto *__func = __data->__func;
541 void *__arg = __data->__arg;
543 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg)));
546 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
550 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
553 auto *__data = new __libcpp_beginthreadex_thunk_data;
554 __data->__func = __func;
555 __data->__arg = __arg;
557 *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
558 __libcpp_beginthreadex_thunk,
559 __data, 0, nullptr));
563 return GetLastError();
566 __libcpp_thread_id __libcpp_thread_get_current_id()
568 return GetCurrentThreadId();
571 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
573 return GetThreadId(*__t);
576 int __libcpp_thread_join(__libcpp_thread_t *__t)
578 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
579 return GetLastError();
580 if (!CloseHandle(*__t))
581 return GetLastError();
585 int __libcpp_thread_detach(__libcpp_thread_t *__t)
587 if (!CloseHandle(*__t))
588 return GetLastError();
592 void __libcpp_thread_yield()
597 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
599 using namespace chrono;
600 // round-up to the nearest milisecond
602 duration_cast<milliseconds>(__ns + chrono::nanoseconds(999999));
603 // FIXME(compnerd) this should be an alertable sleep (WFSO or SleepEx)
607 // Thread Local Storage
608 int __libcpp_tls_create(__libcpp_tls_key* __key,
609 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
611 *__key = FlsAlloc(__at_exit);
612 if (*__key == FLS_OUT_OF_INDEXES)
613 return GetLastError();
617 void *__libcpp_tls_get(__libcpp_tls_key __key)
619 return FlsGetValue(__key);
622 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
624 if (!FlsSetValue(__key, __p))
625 return GetLastError();
629 #endif // _LIBCPP_HAS_THREAD_API_PTHREAD
631 #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
633 _LIBCPP_END_NAMESPACE_STD
637 #endif // !_LIBCPP_HAS_NO_THREADS
639 #endif // _LIBCPP_THREADING_SUPPORT