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
16 #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
17 #pragma GCC system_header
20 #if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
21 # include <__external_threading>
22 #elif !defined(_LIBCPP_HAS_NO_THREADS)
24 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
27 #elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
31 #include <fibersapi.h>
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 typedef pthread_t __libcpp_thread_t;
72 // Thrad Local Storage
73 typedef pthread_key_t __libcpp_tls_key;
75 #define _LIBCPP_TLS_DESTRUCTOR_CC
78 typedef SRWLOCK __libcpp_mutex_t;
79 #define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT
81 typedef CRITICAL_SECTION __libcpp_recursive_mutex_t;
84 typedef CONDITION_VARIABLE __libcpp_condvar_t;
85 #define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT
88 typedef INIT_ONCE __libcpp_exec_once_flag;
89 #define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
92 typedef DWORD __libcpp_thread_id;
95 typedef HANDLE __libcpp_thread_t;
97 // Thread Local Storage
98 typedef DWORD __libcpp_tls_key;
100 #define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI
104 _LIBCPP_THREAD_ABI_VISIBILITY
105 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
107 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
108 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
110 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
111 int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
113 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
114 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
116 _LIBCPP_THREAD_ABI_VISIBILITY
117 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
119 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
120 int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
122 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
123 int __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
125 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
126 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
128 _LIBCPP_THREAD_ABI_VISIBILITY
129 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
131 // Condition variable
132 _LIBCPP_THREAD_ABI_VISIBILITY
133 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
135 _LIBCPP_THREAD_ABI_VISIBILITY
136 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
138 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
139 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
141 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
142 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
145 _LIBCPP_THREAD_ABI_VISIBILITY
146 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
149 _LIBCPP_THREAD_ABI_VISIBILITY
150 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
151 void (*init_routine)(void));
154 #if defined(__APPLE__) && !defined(__arm__)
155 _LIBCPP_THREAD_ABI_VISIBILITY
156 mach_port_t __libcpp_thread_get_port();
159 _LIBCPP_THREAD_ABI_VISIBILITY
160 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
162 _LIBCPP_THREAD_ABI_VISIBILITY
163 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
166 _LIBCPP_THREAD_ABI_VISIBILITY
167 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
170 _LIBCPP_THREAD_ABI_VISIBILITY
171 __libcpp_thread_id __libcpp_thread_get_current_id();
173 _LIBCPP_THREAD_ABI_VISIBILITY
174 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
176 _LIBCPP_THREAD_ABI_VISIBILITY
177 int __libcpp_thread_join(__libcpp_thread_t *__t);
179 _LIBCPP_THREAD_ABI_VISIBILITY
180 int __libcpp_thread_detach(__libcpp_thread_t *__t);
182 _LIBCPP_THREAD_ABI_VISIBILITY
183 void __libcpp_thread_yield();
185 // Thread local storage
186 _LIBCPP_THREAD_ABI_VISIBILITY
187 int __libcpp_tls_create(__libcpp_tls_key* __key,
188 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
190 _LIBCPP_THREAD_ABI_VISIBILITY
191 void *__libcpp_tls_get(__libcpp_tls_key __key);
193 _LIBCPP_THREAD_ABI_VISIBILITY
194 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
196 #if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
197 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
199 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
201 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
203 pthread_mutexattr_t attr;
204 int __ec = pthread_mutexattr_init(&attr);
207 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
209 pthread_mutexattr_destroy(&attr);
212 __ec = pthread_mutex_init(__m, &attr);
214 pthread_mutexattr_destroy(&attr);
217 __ec = pthread_mutexattr_destroy(&attr);
219 pthread_mutex_destroy(__m);
225 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
227 return pthread_mutex_lock(__m);
230 int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
232 return pthread_mutex_trylock(__m);
235 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
237 return pthread_mutex_unlock(__m);
240 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
242 return pthread_mutex_destroy(__m);
245 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
247 return pthread_mutex_lock(__m);
250 int __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
252 return pthread_mutex_trylock(__m);
255 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
257 return pthread_mutex_unlock(__m);
260 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
262 return pthread_mutex_destroy(__m);
265 // Condition Variable
266 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
268 return pthread_cond_signal(__cv);
271 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
273 return pthread_cond_broadcast(__cv);
276 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
278 return pthread_cond_wait(__cv, __m);
281 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
284 return pthread_cond_timedwait(__cv, __m, __ts);
287 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
289 return pthread_cond_destroy(__cv);
293 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
294 void (*init_routine)(void)) {
295 return pthread_once(flag, init_routine);
299 #if defined(__APPLE__) && !defined(__arm__)
300 mach_port_t __libcpp_thread_get_port() {
301 return pthread_mach_thread_np(pthread_self());
305 // Returns non-zero if the thread ids are equal, otherwise 0
306 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
308 return pthread_equal(t1, t2) != 0;
311 // Returns non-zero if t1 < t2, otherwise 0
312 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
318 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
321 return pthread_create(__t, 0, __func, __arg);
324 __libcpp_thread_id __libcpp_thread_get_current_id()
326 return pthread_self();
329 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
334 int __libcpp_thread_join(__libcpp_thread_t *__t)
336 return pthread_join(*__t, 0);
339 int __libcpp_thread_detach(__libcpp_thread_t *__t)
341 return pthread_detach(*__t);
344 void __libcpp_thread_yield()
349 // Thread local storage
350 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
352 return pthread_key_create(__key, __at_exit);
355 void *__libcpp_tls_get(__libcpp_tls_key __key)
357 return pthread_getspecific(__key);
360 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
362 return pthread_setspecific(__key, __p);
365 #elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
368 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
370 InitializeCriticalSection(__m);
374 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
376 EnterCriticalSection(__m);
380 int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
382 TryEnterCriticalSection(__m);
386 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
388 LeaveCriticalSection(__m);
392 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
394 DeleteCriticalSection(__m);
398 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
400 AcquireSRWLockExclusive(__m);
404 int __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
406 TryAcquireSRWLockExclusive(__m);
410 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
412 ReleaseSRWLockExclusive(__m);
416 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
418 static_cast<void>(__m);
422 // Condition Variable
423 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
425 WakeConditionVariable(__cv);
429 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
431 WakeAllConditionVariable(__cv);
435 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
437 SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
441 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
444 using namespace _VSTD::chrono;
446 auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
448 system_clock::time_point(duration_cast<system_clock::duration>(duration));
449 auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
451 if (!SleepConditionVariableSRW(__cv, __m,
452 timeout_ms.count() > 0 ? timeout_ms.count()
455 return GetLastError();
459 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
461 static_cast<void>(__cv);
466 static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
467 __libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
470 static_cast<void>(__init_once);
471 static_cast<void>(__context);
473 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
478 int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
479 void (*__init_routine)(void))
481 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
482 reinterpret_cast<void *>(__init_routine), NULL))
483 return GetLastError();
488 bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
489 __libcpp_thread_id __rhs)
491 return __lhs == __rhs;
494 bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
496 return __lhs < __rhs;
500 struct __libcpp_beginthreadex_thunk_data
502 void *(*__func)(void *);
506 static inline _LIBCPP_ALWAYS_INLINE unsigned int WINAPI
507 __libcpp_beginthreadex_thunk(void *__data)
509 __libcpp_beginthreadex_thunk_data data =
510 *reinterpret_cast<__libcpp_beginthreadex_thunk_data *>(__data);
511 delete reinterpret_cast<__libcpp_beginthreadex_thunk_data *>(__data);
512 return reinterpret_cast<unsigned int>(data.__func(data.__arg));
515 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
518 auto *data = new __libcpp_beginthreadex_thunk_data;
519 data->__func = __func;
522 *__t = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0,
523 __libcpp_beginthreadex_thunk,
527 return GetLastError();
530 __libcpp_thread_id __libcpp_thread_get_current_id()
532 return GetCurrentThreadId();
535 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
537 return GetThreadId(*__t);
540 int __libcpp_thread_join(__libcpp_thread_t *__t)
542 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
543 return GetLastError();
544 if (!CloseHandle(*__t))
545 return GetLastError();
549 int __libcpp_thread_detach(__libcpp_thread_t *__t)
551 if (!CloseHandle(*__t))
552 return GetLastError();
556 void __libcpp_thread_yield()
561 // Thread Local Storage
562 int __libcpp_tls_create(__libcpp_tls_key* __key,
563 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
565 *__key = FlsAlloc(__at_exit);
566 if (*__key == FLS_OUT_OF_INDEXES)
567 return GetLastError();
571 void *__libcpp_tls_get(__libcpp_tls_key __key)
573 return FlsGetValue(__key);
576 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
578 if (!FlsSetValue(__key, __p))
579 return GetLastError();
583 #endif // _LIBCPP_HAS_THREAD_API_PTHREAD
585 #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
587 _LIBCPP_END_NAMESPACE_STD
589 #endif // !_LIBCPP_HAS_NO_THREADS
591 #endif // _LIBCPP_THREADING_SUPPORT