blob: b2c3b1fc6376142f280e85d5ca1f43ffedd57838 [file] [log] [blame]
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +00001// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// The LLVM Compiler Infrastructure
5//
6// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_THREADING_SUPPORT
12#define _LIBCPP_THREADING_SUPPORT
13
14#include <__config>
15
16#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
17#pragma GCC system_header
18#endif
19
Asiri Rathnayake040945b2016-09-11 21:46:40 +000020#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
Eric Fiselier66134e82017-01-06 20:05:40 +000021# include <__external_threading>
22#elif !defined(_LIBCPP_HAS_NO_THREADS)
23
24#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
25# include <pthread.h>
26# include <sched.h>
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +000027#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
28#include <assert.h>
29#include <Windows.h>
30#include <process.h>
31#include <fibersapi.h>
32
33#include <chrono>
Eric Fiselier66134e82017-01-06 20:05:40 +000034#endif
35
36#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
37 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
Asiri Rathnayake040945b2016-09-11 21:46:40 +000038#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
39#else
40#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
41#endif
42
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000043_LIBCPP_BEGIN_NAMESPACE_STD
44
Eric Fiselier66134e82017-01-06 20:05:40 +000045#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000046// Mutex
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000047typedef pthread_mutex_t __libcpp_mutex_t;
Asiri Rathnayake040945b2016-09-11 21:46:40 +000048#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000049
Saleem Abdulrasool3451a652017-01-05 17:54:45 +000050typedef pthread_mutex_t __libcpp_recursive_mutex_t;
51
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000052// Condition Variable
Asiri Rathnayake040945b2016-09-11 21:46:40 +000053typedef pthread_cond_t __libcpp_condvar_t;
54#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000055
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +000056// Execute once
57typedef pthread_once_t __libcpp_exec_once_flag;
58#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
59
60// Thread id
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000061typedef pthread_t __libcpp_thread_id;
62
63// Thread
64typedef pthread_t __libcpp_thread_t;
65
66// Thrad Local Storage
67typedef pthread_key_t __libcpp_tls_key;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +000068
69#define _LIBCPP_TLS_DESTRUCTOR_CC
70#else
71// Mutex
72typedef SRWLOCK __libcpp_mutex_t;
73#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT
74
75typedef CRITICAL_SECTION __libcpp_recursive_mutex_t;
76
77// Condition Variable
78typedef CONDITION_VARIABLE __libcpp_condvar_t;
79#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT
80
81// Execute Once
82typedef INIT_ONCE __libcpp_exec_once_flag;
83#define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
84
85// Thread ID
86typedef DWORD __libcpp_thread_id;
87
88// Thread
89typedef HANDLE __libcpp_thread_t;
90
91// Thread Local Storage
92typedef DWORD __libcpp_tls_key;
93
94#define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000095#endif
96
97// Mutex
98_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool3451a652017-01-05 17:54:45 +000099int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
100
101_LIBCPP_THREAD_ABI_VISIBILITY
102int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
103
104_LIBCPP_THREAD_ABI_VISIBILITY
105int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
106
107_LIBCPP_THREAD_ABI_VISIBILITY
108int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
109
110_LIBCPP_THREAD_ABI_VISIBILITY
111int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000112
113_LIBCPP_THREAD_ABI_VISIBILITY
114int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
115
116_LIBCPP_THREAD_ABI_VISIBILITY
117int __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
118
119_LIBCPP_THREAD_ABI_VISIBILITY
120int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
121
122_LIBCPP_THREAD_ABI_VISIBILITY
123int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
124
125// Condition variable
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000126_LIBCPP_THREAD_ABI_VISIBILITY
127int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000128
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000129_LIBCPP_THREAD_ABI_VISIBILITY
130int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000131
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000132_LIBCPP_THREAD_ABI_VISIBILITY
133int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000134
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000135_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000136int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
137 timespec *__ts);
138
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000139_LIBCPP_THREAD_ABI_VISIBILITY
140int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
141
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000142// Execute once
143_LIBCPP_THREAD_ABI_VISIBILITY
144int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
145 void (*init_routine)(void));
146
147// Thread id
148#if defined(__APPLE__) && !defined(__arm__)
149_LIBCPP_THREAD_ABI_VISIBILITY
150mach_port_t __libcpp_thread_get_port();
151#endif
152
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000153_LIBCPP_THREAD_ABI_VISIBILITY
154bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000155
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000156_LIBCPP_THREAD_ABI_VISIBILITY
157bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
158
159// Thread
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000160_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000161int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
162 void *__arg);
163
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000164_LIBCPP_THREAD_ABI_VISIBILITY
165__libcpp_thread_id __libcpp_thread_get_current_id();
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000166
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000167_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000168__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
169
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000170_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000171int __libcpp_thread_join(__libcpp_thread_t *__t);
172
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000173_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000174int __libcpp_thread_detach(__libcpp_thread_t *__t);
175
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000176_LIBCPP_THREAD_ABI_VISIBILITY
177void __libcpp_thread_yield();
178
179// Thread local storage
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000180_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000181int __libcpp_tls_create(__libcpp_tls_key* __key,
182 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000183
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000184_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000185void *__libcpp_tls_get(__libcpp_tls_key __key);
186
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000187_LIBCPP_THREAD_ABI_VISIBILITY
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000188int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000189
Eric Fiselier66134e82017-01-06 20:05:40 +0000190#if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
191 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
192
193#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000194
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000195int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000196{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000197 pthread_mutexattr_t attr;
198 int __ec = pthread_mutexattr_init(&attr);
199 if (__ec)
200 return __ec;
201 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
202 if (__ec) {
203 pthread_mutexattr_destroy(&attr);
204 return __ec;
205 }
206 __ec = pthread_mutex_init(__m, &attr);
207 if (__ec) {
208 pthread_mutexattr_destroy(&attr);
209 return __ec;
210 }
211 __ec = pthread_mutexattr_destroy(&attr);
212 if (__ec) {
213 pthread_mutex_destroy(__m);
214 return __ec;
215 }
216 return 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000217}
218
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000219int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
220{
221 return pthread_mutex_lock(__m);
222}
223
224int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
225{
226 return pthread_mutex_trylock(__m);
227}
228
229int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
230{
231 return pthread_mutex_unlock(__m);
232}
233
234int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
235{
236 return pthread_mutex_destroy(__m);
237}
238
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000239int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000240{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000241 return pthread_mutex_lock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000242}
243
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000244int __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000245{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000246 return pthread_mutex_trylock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000247}
248
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000249int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000250{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000251 return pthread_mutex_unlock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000252}
253
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000254int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000255{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000256 return pthread_mutex_destroy(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000257}
258
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000259// Condition Variable
260int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000261{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000262 return pthread_cond_signal(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000263}
264
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000265int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000266{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000267 return pthread_cond_broadcast(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000268}
269
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000270int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000271{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000272 return pthread_cond_wait(__cv, __m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000273}
274
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000275int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
276 timespec *__ts)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000277{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000278 return pthread_cond_timedwait(__cv, __m, __ts);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000279}
280
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000281int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000282{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000283 return pthread_cond_destroy(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000284}
285
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000286// Execute once
287int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
288 void (*init_routine)(void)) {
289 return pthread_once(flag, init_routine);
290}
291
292// Thread id
293#if defined(__APPLE__) && !defined(__arm__)
294mach_port_t __libcpp_thread_get_port() {
295 return pthread_mach_thread_np(pthread_self());
296}
297#endif
298
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000299// Returns non-zero if the thread ids are equal, otherwise 0
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000300bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
301{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000302 return pthread_equal(t1, t2) != 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000303}
304
305// Returns non-zero if t1 < t2, otherwise 0
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000306bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
307{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000308 return t1 < t2;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000309}
310
311// Thread
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000312int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
313 void *__arg)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000314{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000315 return pthread_create(__t, 0, __func, __arg);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000316}
317
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000318__libcpp_thread_id __libcpp_thread_get_current_id()
319{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000320 return pthread_self();
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000321}
322
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000323__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000324{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000325 return *__t;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000326}
327
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000328int __libcpp_thread_join(__libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000329{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000330 return pthread_join(*__t, 0);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000331}
332
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000333int __libcpp_thread_detach(__libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000334{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000335 return pthread_detach(*__t);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000336}
337
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000338void __libcpp_thread_yield()
339{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000340 sched_yield();
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000341}
342
343// Thread local storage
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000344int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000345{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000346 return pthread_key_create(__key, __at_exit);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000347}
348
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000349void *__libcpp_tls_get(__libcpp_tls_key __key)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000350{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000351 return pthread_getspecific(__key);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000352}
353
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000354int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000355{
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000356 return pthread_setspecific(__key, __p);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000357}
358
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000359#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
360
361// Mutex
362int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
363{
364 InitializeCriticalSection(__m);
365 return 0;
366}
367
368int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
369{
370 EnterCriticalSection(__m);
371 return 0;
372}
373
374int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
375{
376 TryEnterCriticalSection(__m);
377 return 0;
378}
379
380int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
381{
382 LeaveCriticalSection(__m);
383 return 0;
384}
385
386int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
387{
388 static_cast<void>(__m);
389 return 0;
390}
391
392int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
393{
394 AcquireSRWLockExclusive(__m);
395 return 0;
396}
397
398int __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
399{
400 TryAcquireSRWLockExclusive(__m);
401 return 0;
402}
403
404int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
405{
406 ReleaseSRWLockExclusive(__m);
407 return 0;
408}
409
410int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
411{
412 static_cast<void>(__m);
413 return 0;
414}
415
416// Condition Variable
417int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
418{
419 WakeConditionVariable(__cv);
420 return 0;
421}
422
423int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
424{
425 WakeAllConditionVariable(__cv);
426 return 0;
427}
428
429int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
430{
431 SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
432 return 0;
433}
434
435int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
436 timespec *__ts)
437{
438 using namespace _VSTD::chrono;
439
440 auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
441 auto abstime =
442 system_clock::time_point(duration_cast<system_clock::duration>(duration));
443 auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
444
445 if (!SleepConditionVariableSRW(__cv, __m,
446 timeout_ms.count() > 0 ? timeout_ms.count()
447 : 0,
448 0))
449 return GetLastError();
450 return 0;
451}
452
453int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
454{
455 static_cast<void>(__cv);
456 return 0;
457}
458
459// Execute Once
460static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
461__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
462 PVOID *__context)
463{
464 static_cast<void>(__init_once);
465 static_cast<void>(__context);
466
467 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
468 init_routine();
469 return TRUE;
470}
471
472int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
473 void (*__init_routine)(void))
474{
475 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
476 reinterpret_cast<void *>(__init_routine), NULL))
477 return GetLastError();
478 return 0;
479}
480
481// Thread ID
482bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
483 __libcpp_thread_id __rhs)
484{
485 return __lhs == __rhs;
486}
487
488bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
489{
490 return __lhs < __rhs;
491}
492
493// Thread
494struct __libcpp_beginthreadex_thunk_data
495{
496 void *(*__func)(void *);
497 void *__arg;
498};
499
500static inline _LIBCPP_ALWAYS_INLINE unsigned int WINAPI
501__libcpp_beginthreadex_thunk(void *__data)
502{
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));
507}
508
509int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
510 void *__arg)
511{
512 auto *data = new __libcpp_beginthreadex_thunk_data;
513 data->__func = __func;
514 data->__arg = __arg;
515
516 *__t = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0,
517 __libcpp_beginthreadex_thunk,
518 data, 0, NULL));
519 if (*__t)
520 return 0;
521 return GetLastError();
522}
523
524__libcpp_thread_id __libcpp_thread_get_current_id()
525{
526 return GetCurrentThreadId();
527}
528
529__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
530{
531 return GetThreadId(*__t);
532}
533
534int __libcpp_thread_join(__libcpp_thread_t *__t)
535{
536 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
537 return GetLastError();
538 if (!CloseHandle(*__t))
539 return GetLastError();
540 return 0;
541}
542
543int __libcpp_thread_detach(__libcpp_thread_t *__t)
544{
545 if (!CloseHandle(*__t))
546 return GetLastError();
547 return 0;
548}
549
550void __libcpp_thread_yield()
551{
552 SwitchToThread();
553}
554
555// Thread Local Storage
556int __libcpp_tls_create(__libcpp_tls_key* __key,
557 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
558{
559 *__key = FlsAlloc(__at_exit);
560 if (*__key == FLS_OUT_OF_INDEXES)
561 return GetLastError();
562 return 0;
563}
564
565void *__libcpp_tls_get(__libcpp_tls_key __key)
566{
567 return FlsGetValue(__key);
568}
569
570int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
571{
572 if (!FlsSetValue(__key, __p))
573 return GetLastError();
574 return 0;
575}
576
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000577#endif // _LIBCPP_HAS_THREAD_API_PTHREAD
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000578
Eric Fiselier66134e82017-01-06 20:05:40 +0000579#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
580
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000581_LIBCPP_END_NAMESPACE_STD
582
Eric Fiselier66134e82017-01-06 20:05:40 +0000583#endif // !_LIBCPP_HAS_NO_THREADS
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000584
585#endif // _LIBCPP_THREADING_SUPPORT