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>
33 #include <__undef_min_max>
36 #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
37 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
38 #define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
40 #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
43 #if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
44 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
46 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
49 _LIBCPP_BEGIN_NAMESPACE_STD
51 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
53 typedef pthread_mutex_t __libcpp_mutex_t;
54 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
56 typedef pthread_mutex_t __libcpp_recursive_mutex_t;
59 typedef pthread_cond_t __libcpp_condvar_t;
60 #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
63 typedef pthread_once_t __libcpp_exec_once_flag;
64 #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
67 typedef pthread_t __libcpp_thread_id;
70 #define _LIBCPP_NULL_THREAD 0U
72 typedef pthread_t __libcpp_thread_t;
74 // Thrad Local Storage
75 typedef pthread_key_t __libcpp_tls_key;
77 #define _LIBCPP_TLS_DESTRUCTOR_CC
80 typedef SRWLOCK __libcpp_mutex_t;
81 #define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT
83 typedef CRITICAL_SECTION __libcpp_recursive_mutex_t;
86 typedef CONDITION_VARIABLE __libcpp_condvar_t;
87 #define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT
90 typedef INIT_ONCE __libcpp_exec_once_flag;
91 #define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
94 typedef DWORD __libcpp_thread_id;
97 #define _LIBCPP_NULL_THREAD 0U
99 typedef HANDLE __libcpp_thread_t;
101 // Thread Local Storage
102 typedef DWORD __libcpp_tls_key;
104 #define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI
108 _LIBCPP_THREAD_ABI_VISIBILITY
109 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
111 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
112 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
114 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
115 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
117 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
118 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
120 _LIBCPP_THREAD_ABI_VISIBILITY
121 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
123 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
124 int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
126 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
127 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
129 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
130 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
132 _LIBCPP_THREAD_ABI_VISIBILITY
133 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
135 // Condition variable
136 _LIBCPP_THREAD_ABI_VISIBILITY
137 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
139 _LIBCPP_THREAD_ABI_VISIBILITY
140 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
142 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
143 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
145 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
146 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
149 _LIBCPP_THREAD_ABI_VISIBILITY
150 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
153 _LIBCPP_THREAD_ABI_VISIBILITY
154 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
155 void (*init_routine)(void));
158 _LIBCPP_THREAD_ABI_VISIBILITY
159 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
161 _LIBCPP_THREAD_ABI_VISIBILITY
162 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
165 _LIBCPP_THREAD_ABI_VISIBILITY
166 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
168 _LIBCPP_THREAD_ABI_VISIBILITY
169 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
172 _LIBCPP_THREAD_ABI_VISIBILITY
173 __libcpp_thread_id __libcpp_thread_get_current_id();
175 _LIBCPP_THREAD_ABI_VISIBILITY
176 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
178 _LIBCPP_THREAD_ABI_VISIBILITY
179 int __libcpp_thread_join(__libcpp_thread_t *__t);
181 _LIBCPP_THREAD_ABI_VISIBILITY
182 int __libcpp_thread_detach(__libcpp_thread_t *__t);
184 _LIBCPP_THREAD_ABI_VISIBILITY
185 void __libcpp_thread_yield();
187 _LIBCPP_THREAD_ABI_VISIBILITY
188 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
190 // Thread local storage
191 _LIBCPP_THREAD_ABI_VISIBILITY
192 int __libcpp_tls_create(__libcpp_tls_key* __key,
193 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
195 _LIBCPP_THREAD_ABI_VISIBILITY
196 void *__libcpp_tls_get(__libcpp_tls_key __key);
198 _LIBCPP_THREAD_ABI_VISIBILITY
199 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
201 #if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
202 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
204 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
206 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
208 pthread_mutexattr_t attr;
209 int __ec = pthread_mutexattr_init(&attr);
212 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
214 pthread_mutexattr_destroy(&attr);
217 __ec = pthread_mutex_init(__m, &attr);
219 pthread_mutexattr_destroy(&attr);
222 __ec = pthread_mutexattr_destroy(&attr);
224 pthread_mutex_destroy(__m);
230 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
232 return pthread_mutex_lock(__m);
235 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
237 return pthread_mutex_trylock(__m) == 0;
240 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
242 return pthread_mutex_unlock(__m);
245 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
247 return pthread_mutex_destroy(__m);
250 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
252 return pthread_mutex_lock(__m);
255 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
257 return pthread_mutex_trylock(__m) == 0;
260 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
262 return pthread_mutex_unlock(__m);
265 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
267 return pthread_mutex_destroy(__m);
270 // Condition Variable
271 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
273 return pthread_cond_signal(__cv);
276 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
278 return pthread_cond_broadcast(__cv);
281 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
283 return pthread_cond_wait(__cv, __m);
286 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
289 return pthread_cond_timedwait(__cv, __m, __ts);
292 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
294 return pthread_cond_destroy(__cv);
298 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
299 void (*init_routine)(void)) {
300 return pthread_once(flag, init_routine);
304 // Returns non-zero if the thread ids are equal, otherwise 0
305 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
307 return pthread_equal(t1, t2) != 0;
310 // Returns non-zero if t1 < t2, otherwise 0
311 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
317 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
321 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
324 return pthread_create(__t, 0, __func, __arg);
327 __libcpp_thread_id __libcpp_thread_get_current_id()
329 return pthread_self();
332 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
337 int __libcpp_thread_join(__libcpp_thread_t *__t)
339 return pthread_join(*__t, 0);
342 int __libcpp_thread_detach(__libcpp_thread_t *__t)
344 return pthread_detach(*__t);
347 void __libcpp_thread_yield()
352 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
354 using namespace chrono;
355 seconds __s = duration_cast<seconds>(__ns);
357 typedef decltype(__ts.tv_sec) ts_sec;
358 _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max();
360 if (__s.count() < __ts_sec_max)
362 __ts.tv_sec = static_cast<ts_sec>(__s.count());
363 __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
367 __ts.tv_sec = __ts_sec_max;
368 __ts.tv_nsec = 999999999; // (10^9 - 1)
371 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
374 // Thread local storage
375 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
377 return pthread_key_create(__key, __at_exit);
380 void *__libcpp_tls_get(__libcpp_tls_key __key)
382 return pthread_getspecific(__key);
385 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
387 return pthread_setspecific(__key, __p);
390 #elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
393 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
395 InitializeCriticalSection(__m);
399 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
401 EnterCriticalSection(__m);
405 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
407 return TryEnterCriticalSection(__m) != 0;
410 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
412 LeaveCriticalSection(__m);
416 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
418 DeleteCriticalSection(__m);
422 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
424 AcquireSRWLockExclusive(__m);
428 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
430 return TryAcquireSRWLockExclusive(__m) != 0;
433 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
435 ReleaseSRWLockExclusive(__m);
439 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
441 static_cast<void>(__m);
445 // Condition Variable
446 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
448 WakeConditionVariable(__cv);
452 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
454 WakeAllConditionVariable(__cv);
458 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
460 SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
464 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
467 using namespace _VSTD::chrono;
469 auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
471 system_clock::time_point(duration_cast<system_clock::duration>(duration));
472 auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
474 if (!SleepConditionVariableSRW(__cv, __m,
475 timeout_ms.count() > 0 ? timeout_ms.count()
479 auto __ec = GetLastError();
480 return __ec == ERROR_TIMEOUT ? ETIMEDOUT : __ec;
485 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
487 static_cast<void>(__cv);
492 static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
493 __libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
496 static_cast<void>(__init_once);
497 static_cast<void>(__context);
499 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
504 int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
505 void (*__init_routine)(void))
507 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
508 reinterpret_cast<void *>(__init_routine), NULL))
509 return GetLastError();
514 bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
515 __libcpp_thread_id __rhs)
517 return __lhs == __rhs;
520 bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
522 return __lhs < __rhs;
526 struct __libcpp_beginthreadex_thunk_data
528 void *(*__func)(void *);
532 static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI
533 __libcpp_beginthreadex_thunk(void *__raw_data)
536 static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data);
537 auto *__func = __data->__func;
538 void *__arg = __data->__arg;
540 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg)));
543 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
547 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
550 auto *__data = new __libcpp_beginthreadex_thunk_data;
551 __data->__func = __func;
552 __data->__arg = __arg;
554 *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
555 __libcpp_beginthreadex_thunk,
556 __data, 0, nullptr));
560 return GetLastError();
563 __libcpp_thread_id __libcpp_thread_get_current_id()
565 return GetCurrentThreadId();
568 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
570 return GetThreadId(*__t);
573 int __libcpp_thread_join(__libcpp_thread_t *__t)
575 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
576 return GetLastError();
577 if (!CloseHandle(*__t))
578 return GetLastError();
582 int __libcpp_thread_detach(__libcpp_thread_t *__t)
584 if (!CloseHandle(*__t))
585 return GetLastError();
589 void __libcpp_thread_yield()
594 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
596 using namespace chrono;
597 // round-up to the nearest milisecond
599 duration_cast<milliseconds>(__ns + chrono::nanoseconds(999999));
600 // FIXME(compnerd) this should be an alertable sleep (WFSO or SleepEx)
604 // Thread Local Storage
605 int __libcpp_tls_create(__libcpp_tls_key* __key,
606 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
608 *__key = FlsAlloc(__at_exit);
609 if (*__key == FLS_OUT_OF_INDEXES)
610 return GetLastError();
614 void *__libcpp_tls_get(__libcpp_tls_key __key)
616 return FlsGetValue(__key);
619 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
621 if (!FlsSetValue(__key, __p))
622 return GetLastError();
626 #endif // _LIBCPP_HAS_THREAD_API_PTHREAD
628 #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
630 _LIBCPP_END_NAMESPACE_STD
632 #endif // !_LIBCPP_HAS_NO_THREADS
634 #endif // _LIBCPP_THREADING_SUPPORT