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 _LIBCPP_BEGIN_NAMESPACE_STD
45 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
47 typedef pthread_mutex_t __libcpp_mutex_t;
48 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
50 typedef pthread_mutex_t __libcpp_recursive_mutex_t;
53 typedef pthread_cond_t __libcpp_condvar_t;
54 #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
57 typedef pthread_once_t __libcpp_exec_once_flag;
58 #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
61 typedef pthread_t __libcpp_thread_id;
64 typedef pthread_t __libcpp_thread_t;
66 // Thrad Local Storage
67 typedef pthread_key_t __libcpp_tls_key;
69 #define _LIBCPP_TLS_DESTRUCTOR_CC
72 typedef SRWLOCK __libcpp_mutex_t;
73 #define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT
75 typedef CRITICAL_SECTION __libcpp_recursive_mutex_t;
78 typedef CONDITION_VARIABLE __libcpp_condvar_t;
79 #define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT
82 typedef INIT_ONCE __libcpp_exec_once_flag;
83 #define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
86 typedef DWORD __libcpp_thread_id;
89 typedef HANDLE __libcpp_thread_t;
91 // Thread Local Storage
92 typedef DWORD __libcpp_tls_key;
94 #define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI
98 _LIBCPP_THREAD_ABI_VISIBILITY
99 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
101 _LIBCPP_THREAD_ABI_VISIBILITY
102 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
104 _LIBCPP_THREAD_ABI_VISIBILITY
105 int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
107 _LIBCPP_THREAD_ABI_VISIBILITY
108 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
110 _LIBCPP_THREAD_ABI_VISIBILITY
111 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
113 _LIBCPP_THREAD_ABI_VISIBILITY
114 int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
116 _LIBCPP_THREAD_ABI_VISIBILITY
117 int __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
119 _LIBCPP_THREAD_ABI_VISIBILITY
120 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
122 _LIBCPP_THREAD_ABI_VISIBILITY
123 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
125 // Condition variable
126 _LIBCPP_THREAD_ABI_VISIBILITY
127 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
129 _LIBCPP_THREAD_ABI_VISIBILITY
130 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
132 _LIBCPP_THREAD_ABI_VISIBILITY
133 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
135 _LIBCPP_THREAD_ABI_VISIBILITY
136 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
139 _LIBCPP_THREAD_ABI_VISIBILITY
140 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
143 _LIBCPP_THREAD_ABI_VISIBILITY
144 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
145 void (*init_routine)(void));
148 #if defined(__APPLE__) && !defined(__arm__)
149 _LIBCPP_THREAD_ABI_VISIBILITY
150 mach_port_t __libcpp_thread_get_port();
153 _LIBCPP_THREAD_ABI_VISIBILITY
154 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
156 _LIBCPP_THREAD_ABI_VISIBILITY
157 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
160 _LIBCPP_THREAD_ABI_VISIBILITY
161 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
164 _LIBCPP_THREAD_ABI_VISIBILITY
165 __libcpp_thread_id __libcpp_thread_get_current_id();
167 _LIBCPP_THREAD_ABI_VISIBILITY
168 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
170 _LIBCPP_THREAD_ABI_VISIBILITY
171 int __libcpp_thread_join(__libcpp_thread_t *__t);
173 _LIBCPP_THREAD_ABI_VISIBILITY
174 int __libcpp_thread_detach(__libcpp_thread_t *__t);
176 _LIBCPP_THREAD_ABI_VISIBILITY
177 void __libcpp_thread_yield();
179 // Thread local storage
180 _LIBCPP_THREAD_ABI_VISIBILITY
181 int __libcpp_tls_create(__libcpp_tls_key* __key,
182 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
184 _LIBCPP_THREAD_ABI_VISIBILITY
185 void *__libcpp_tls_get(__libcpp_tls_key __key);
187 _LIBCPP_THREAD_ABI_VISIBILITY
188 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
190 #if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
191 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
193 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
195 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
197 pthread_mutexattr_t attr;
198 int __ec = pthread_mutexattr_init(&attr);
201 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
203 pthread_mutexattr_destroy(&attr);
206 __ec = pthread_mutex_init(__m, &attr);
208 pthread_mutexattr_destroy(&attr);
211 __ec = pthread_mutexattr_destroy(&attr);
213 pthread_mutex_destroy(__m);
219 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
221 return pthread_mutex_lock(__m);
224 int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
226 return pthread_mutex_trylock(__m);
229 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
231 return pthread_mutex_unlock(__m);
234 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
236 return pthread_mutex_destroy(__m);
239 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
241 return pthread_mutex_lock(__m);
244 int __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
246 return pthread_mutex_trylock(__m);
249 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
251 return pthread_mutex_unlock(__m);
254 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
256 return pthread_mutex_destroy(__m);
259 // Condition Variable
260 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
262 return pthread_cond_signal(__cv);
265 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
267 return pthread_cond_broadcast(__cv);
270 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
272 return pthread_cond_wait(__cv, __m);
275 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
278 return pthread_cond_timedwait(__cv, __m, __ts);
281 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
283 return pthread_cond_destroy(__cv);
287 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
288 void (*init_routine)(void)) {
289 return pthread_once(flag, init_routine);
293 #if defined(__APPLE__) && !defined(__arm__)
294 mach_port_t __libcpp_thread_get_port() {
295 return pthread_mach_thread_np(pthread_self());
299 // Returns non-zero if the thread ids are equal, otherwise 0
300 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
302 return pthread_equal(t1, t2) != 0;
305 // Returns non-zero if t1 < t2, otherwise 0
306 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
312 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
315 return pthread_create(__t, 0, __func, __arg);
318 __libcpp_thread_id __libcpp_thread_get_current_id()
320 return pthread_self();
323 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
328 int __libcpp_thread_join(__libcpp_thread_t *__t)
330 return pthread_join(*__t, 0);
333 int __libcpp_thread_detach(__libcpp_thread_t *__t)
335 return pthread_detach(*__t);
338 void __libcpp_thread_yield()
343 // Thread local storage
344 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
346 return pthread_key_create(__key, __at_exit);
349 void *__libcpp_tls_get(__libcpp_tls_key __key)
351 return pthread_getspecific(__key);
354 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
356 return pthread_setspecific(__key, __p);
359 #elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
362 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
364 InitializeCriticalSection(__m);
368 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
370 EnterCriticalSection(__m);
374 int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
376 TryEnterCriticalSection(__m);
380 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
382 LeaveCriticalSection(__m);
386 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
388 DeleteCriticalSection(__m);
392 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
394 AcquireSRWLockExclusive(__m);
398 int __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
400 TryAcquireSRWLockExclusive(__m);
404 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
406 ReleaseSRWLockExclusive(__m);
410 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
412 static_cast<void>(__m);
416 // Condition Variable
417 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
419 WakeConditionVariable(__cv);
423 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
425 WakeAllConditionVariable(__cv);
429 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
431 SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
435 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
438 using namespace _VSTD::chrono;
440 auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
442 system_clock::time_point(duration_cast<system_clock::duration>(duration));
443 auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
445 if (!SleepConditionVariableSRW(__cv, __m,
446 timeout_ms.count() > 0 ? timeout_ms.count()
449 return GetLastError();
453 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
455 static_cast<void>(__cv);
460 static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
461 __libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
464 static_cast<void>(__init_once);
465 static_cast<void>(__context);
467 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
472 int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
473 void (*__init_routine)(void))
475 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
476 reinterpret_cast<void *>(__init_routine), NULL))
477 return GetLastError();
482 bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
483 __libcpp_thread_id __rhs)
485 return __lhs == __rhs;
488 bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
490 return __lhs < __rhs;
494 struct __libcpp_beginthreadex_thunk_data
496 void *(*__func)(void *);
500 static inline _LIBCPP_ALWAYS_INLINE unsigned int WINAPI
501 __libcpp_beginthreadex_thunk(void *__data)
503 __libcpp_beginthreadex_thunk_data data =
504 *reinterpret_cast<__libcpp_beginthreadex_thunk_data *>(__data);
505 delete reinterpret_cast<__libcpp_beginthreadex_thunk_data *>(__data);
506 return reinterpret_cast<unsigned int>(data.__func(data.__arg));
509 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
512 auto *data = new __libcpp_beginthreadex_thunk_data;
513 data->__func = __func;
516 *__t = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0,
517 __libcpp_beginthreadex_thunk,
521 return GetLastError();
524 __libcpp_thread_id __libcpp_thread_get_current_id()
526 return GetCurrentThreadId();
529 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
531 return GetThreadId(*__t);
534 int __libcpp_thread_join(__libcpp_thread_t *__t)
536 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
537 return GetLastError();
538 if (!CloseHandle(*__t))
539 return GetLastError();
543 int __libcpp_thread_detach(__libcpp_thread_t *__t)
545 if (!CloseHandle(*__t))
546 return GetLastError();
550 void __libcpp_thread_yield()
555 // Thread Local Storage
556 int __libcpp_tls_create(__libcpp_tls_key* __key,
557 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
559 *__key = FlsAlloc(__at_exit);
560 if (*__key == FLS_OUT_OF_INDEXES)
561 return GetLastError();
565 void *__libcpp_tls_get(__libcpp_tls_key __key)
567 return FlsGetValue(__key);
570 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
572 if (!FlsSetValue(__key, __p))
573 return GetLastError();
577 #endif // _LIBCPP_HAS_THREAD_API_PTHREAD
579 #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
581 _LIBCPP_END_NAMESPACE_STD
583 #endif // !_LIBCPP_HAS_NO_THREADS
585 #endif // _LIBCPP_THREADING_SUPPORT