blob: 35b61967edb64afff781e7faf2b71949ae72f0bf [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)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +000028#include <Windows.h>
29#include <process.h>
30#include <fibersapi.h>
31
32#include <chrono>
Eric Fiselier66134e82017-01-06 20:05:40 +000033#endif
34
35#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
36 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
Asiri Rathnayake040945b2016-09-11 21:46:40 +000037#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
38#else
39#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
40#endif
41
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000042_LIBCPP_BEGIN_NAMESPACE_STD
43
Eric Fiselier66134e82017-01-06 20:05:40 +000044#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000045// Mutex
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000046typedef pthread_mutex_t __libcpp_mutex_t;
Asiri Rathnayake040945b2016-09-11 21:46:40 +000047#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000048
Saleem Abdulrasool3451a652017-01-05 17:54:45 +000049typedef pthread_mutex_t __libcpp_recursive_mutex_t;
50
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000051// Condition Variable
Asiri Rathnayake040945b2016-09-11 21:46:40 +000052typedef pthread_cond_t __libcpp_condvar_t;
53#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000054
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +000055// Execute once
56typedef pthread_once_t __libcpp_exec_once_flag;
57#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
58
59// Thread id
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000060typedef pthread_t __libcpp_thread_id;
61
62// Thread
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +000063#define _LIBCPP_NULL_THREAD 0U
64
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000065typedef pthread_t __libcpp_thread_t;
66
67// Thrad Local Storage
68typedef pthread_key_t __libcpp_tls_key;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +000069
70#define _LIBCPP_TLS_DESTRUCTOR_CC
71#else
72// Mutex
73typedef SRWLOCK __libcpp_mutex_t;
74#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT
75
76typedef CRITICAL_SECTION __libcpp_recursive_mutex_t;
77
78// Condition Variable
79typedef CONDITION_VARIABLE __libcpp_condvar_t;
80#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT
81
82// Execute Once
83typedef INIT_ONCE __libcpp_exec_once_flag;
84#define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
85
86// Thread ID
87typedef DWORD __libcpp_thread_id;
88
89// Thread
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +000090#define _LIBCPP_NULL_THREAD 0U
91
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +000092typedef HANDLE __libcpp_thread_t;
93
94// Thread Local Storage
95typedef DWORD __libcpp_tls_key;
96
97#define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000098#endif
99
100// Mutex
101_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000102int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
103
104_LIBCPP_THREAD_ABI_VISIBILITY
105int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
106
107_LIBCPP_THREAD_ABI_VISIBILITY
Eric Fiselier30d12e32017-01-14 10:27:12 +0000108bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000109
110_LIBCPP_THREAD_ABI_VISIBILITY
111int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
112
113_LIBCPP_THREAD_ABI_VISIBILITY
114int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000115
116_LIBCPP_THREAD_ABI_VISIBILITY
117int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
118
119_LIBCPP_THREAD_ABI_VISIBILITY
Eric Fiselier30d12e32017-01-14 10:27:12 +0000120bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000121
122_LIBCPP_THREAD_ABI_VISIBILITY
123int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
124
125_LIBCPP_THREAD_ABI_VISIBILITY
126int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
127
128// Condition variable
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000129_LIBCPP_THREAD_ABI_VISIBILITY
130int __libcpp_condvar_signal(__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_broadcast(__libcpp_condvar_t* __cv);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000134
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000135_LIBCPP_THREAD_ABI_VISIBILITY
136int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000137
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000138_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000139int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
140 timespec *__ts);
141
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000142_LIBCPP_THREAD_ABI_VISIBILITY
143int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
144
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000145// Execute once
146_LIBCPP_THREAD_ABI_VISIBILITY
147int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
148 void (*init_routine)(void));
149
150// Thread id
151#if defined(__APPLE__) && !defined(__arm__)
152_LIBCPP_THREAD_ABI_VISIBILITY
153mach_port_t __libcpp_thread_get_port();
154#endif
155
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000156_LIBCPP_THREAD_ABI_VISIBILITY
157bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000158
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000159_LIBCPP_THREAD_ABI_VISIBILITY
160bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
161
162// Thread
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000163_LIBCPP_THREAD_ABI_VISIBILITY
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +0000164bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
165
166_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000167int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
168 void *__arg);
169
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000170_LIBCPP_THREAD_ABI_VISIBILITY
171__libcpp_thread_id __libcpp_thread_get_current_id();
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000172
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000173_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000174__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
175
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000176_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000177int __libcpp_thread_join(__libcpp_thread_t *__t);
178
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000179_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000180int __libcpp_thread_detach(__libcpp_thread_t *__t);
181
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000182_LIBCPP_THREAD_ABI_VISIBILITY
183void __libcpp_thread_yield();
184
185// Thread local storage
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000186_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000187int __libcpp_tls_create(__libcpp_tls_key* __key,
188 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000189
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000190_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000191void *__libcpp_tls_get(__libcpp_tls_key __key);
192
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000193_LIBCPP_THREAD_ABI_VISIBILITY
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000194int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000195
Eric Fiselier66134e82017-01-06 20:05:40 +0000196#if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
197 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
198
199#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000200
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000201int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000202{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000203 pthread_mutexattr_t attr;
204 int __ec = pthread_mutexattr_init(&attr);
205 if (__ec)
206 return __ec;
207 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
208 if (__ec) {
209 pthread_mutexattr_destroy(&attr);
210 return __ec;
211 }
212 __ec = pthread_mutex_init(__m, &attr);
213 if (__ec) {
214 pthread_mutexattr_destroy(&attr);
215 return __ec;
216 }
217 __ec = pthread_mutexattr_destroy(&attr);
218 if (__ec) {
219 pthread_mutex_destroy(__m);
220 return __ec;
221 }
222 return 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000223}
224
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000225int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
226{
227 return pthread_mutex_lock(__m);
228}
229
Eric Fiselier30d12e32017-01-14 10:27:12 +0000230bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000231{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000232 return pthread_mutex_trylock(__m) == 0;
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000233}
234
235int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
236{
237 return pthread_mutex_unlock(__m);
238}
239
240int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
241{
242 return pthread_mutex_destroy(__m);
243}
244
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000245int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000246{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000247 return pthread_mutex_lock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000248}
249
Eric Fiselier30d12e32017-01-14 10:27:12 +0000250bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000251{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000252 return pthread_mutex_trylock(__m) == 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000253}
254
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000255int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000256{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000257 return pthread_mutex_unlock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000258}
259
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000260int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000261{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000262 return pthread_mutex_destroy(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000263}
264
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000265// Condition Variable
266int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000267{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000268 return pthread_cond_signal(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000269}
270
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000271int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000272{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000273 return pthread_cond_broadcast(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000274}
275
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000276int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000277{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000278 return pthread_cond_wait(__cv, __m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000279}
280
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000281int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
282 timespec *__ts)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000283{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000284 return pthread_cond_timedwait(__cv, __m, __ts);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000285}
286
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000287int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000288{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000289 return pthread_cond_destroy(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000290}
291
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000292// Execute once
293int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
294 void (*init_routine)(void)) {
295 return pthread_once(flag, init_routine);
296}
297
298// Thread id
299#if defined(__APPLE__) && !defined(__arm__)
300mach_port_t __libcpp_thread_get_port() {
301 return pthread_mach_thread_np(pthread_self());
302}
303#endif
304
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000305// Returns non-zero if the thread ids are equal, otherwise 0
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000306bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
307{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000308 return pthread_equal(t1, t2) != 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000309}
310
311// Returns non-zero if t1 < t2, otherwise 0
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000312bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
313{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000314 return t1 < t2;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000315}
316
317// Thread
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +0000318bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
319 return *__t == 0;
320}
321
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000322int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
323 void *__arg)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000324{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000325 return pthread_create(__t, 0, __func, __arg);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000326}
327
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000328__libcpp_thread_id __libcpp_thread_get_current_id()
329{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000330 return pthread_self();
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000331}
332
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000333__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000334{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000335 return *__t;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000336}
337
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000338int __libcpp_thread_join(__libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000339{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000340 return pthread_join(*__t, 0);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000341}
342
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000343int __libcpp_thread_detach(__libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000344{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000345 return pthread_detach(*__t);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000346}
347
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000348void __libcpp_thread_yield()
349{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000350 sched_yield();
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000351}
352
353// Thread local storage
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000354int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000355{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000356 return pthread_key_create(__key, __at_exit);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000357}
358
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000359void *__libcpp_tls_get(__libcpp_tls_key __key)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000360{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000361 return pthread_getspecific(__key);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000362}
363
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000364int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000365{
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000366 return pthread_setspecific(__key, __p);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000367}
368
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000369#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
370
371// Mutex
372int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
373{
374 InitializeCriticalSection(__m);
375 return 0;
376}
377
378int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
379{
380 EnterCriticalSection(__m);
381 return 0;
382}
383
Eric Fiselier30d12e32017-01-14 10:27:12 +0000384bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000385{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000386 return TryEnterCriticalSection(__m) != 0;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000387}
388
389int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
390{
391 LeaveCriticalSection(__m);
392 return 0;
393}
394
395int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
396{
Saleem Abdulrasool1d324082017-01-10 04:18:47 +0000397 DeleteCriticalSection(__m);
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000398 return 0;
399}
400
401int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
402{
403 AcquireSRWLockExclusive(__m);
404 return 0;
405}
406
Eric Fiselier30d12e32017-01-14 10:27:12 +0000407bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000408{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000409 return TryAcquireSRWLockExclusive(__m) != 0;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000410}
411
412int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
413{
414 ReleaseSRWLockExclusive(__m);
415 return 0;
416}
417
418int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
419{
420 static_cast<void>(__m);
421 return 0;
422}
423
424// Condition Variable
425int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
426{
427 WakeConditionVariable(__cv);
428 return 0;
429}
430
431int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
432{
433 WakeAllConditionVariable(__cv);
434 return 0;
435}
436
437int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
438{
439 SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
440 return 0;
441}
442
443int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
444 timespec *__ts)
445{
446 using namespace _VSTD::chrono;
447
448 auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
449 auto abstime =
450 system_clock::time_point(duration_cast<system_clock::duration>(duration));
451 auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
452
453 if (!SleepConditionVariableSRW(__cv, __m,
454 timeout_ms.count() > 0 ? timeout_ms.count()
455 : 0,
456 0))
457 return GetLastError();
458 return 0;
459}
460
461int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
462{
463 static_cast<void>(__cv);
464 return 0;
465}
466
467// Execute Once
468static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
469__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
470 PVOID *__context)
471{
472 static_cast<void>(__init_once);
473 static_cast<void>(__context);
474
475 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
476 init_routine();
477 return TRUE;
478}
479
480int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
481 void (*__init_routine)(void))
482{
483 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
484 reinterpret_cast<void *>(__init_routine), NULL))
485 return GetLastError();
486 return 0;
487}
488
489// Thread ID
490bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
491 __libcpp_thread_id __rhs)
492{
493 return __lhs == __rhs;
494}
495
496bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
497{
498 return __lhs < __rhs;
499}
500
501// Thread
502struct __libcpp_beginthreadex_thunk_data
503{
504 void *(*__func)(void *);
505 void *__arg;
506};
507
Eric Fiselier543e83b2017-01-14 20:19:00 +0000508static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI
Eric Fiselier433a3972017-01-14 19:11:07 +0000509__libcpp_beginthreadex_thunk(void *__raw_data)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000510{
Eric Fiselier433a3972017-01-14 19:11:07 +0000511 auto *__data =
512 static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data);
513 auto *__func = __data->__func;
514 void *__arg = __data->__arg;
515 delete __data;
Eric Fiselier543e83b2017-01-14 20:19:00 +0000516 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg)));
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000517}
518
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +0000519bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
520 return *__t == 0;
521}
522
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000523int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
524 void *__arg)
525{
Eric Fiselier433a3972017-01-14 19:11:07 +0000526 auto *__data = new __libcpp_beginthreadex_thunk_data;
527 __data->__func = __func;
528 __data->__arg = __arg;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000529
Eric Fiselier543e83b2017-01-14 20:19:00 +0000530 *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
531 __libcpp_beginthreadex_thunk,
532 __data, 0, nullptr));
533
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000534 if (*__t)
535 return 0;
536 return GetLastError();
537}
538
539__libcpp_thread_id __libcpp_thread_get_current_id()
540{
541 return GetCurrentThreadId();
542}
543
544__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
545{
546 return GetThreadId(*__t);
547}
548
549int __libcpp_thread_join(__libcpp_thread_t *__t)
550{
551 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
552 return GetLastError();
553 if (!CloseHandle(*__t))
554 return GetLastError();
555 return 0;
556}
557
558int __libcpp_thread_detach(__libcpp_thread_t *__t)
559{
560 if (!CloseHandle(*__t))
561 return GetLastError();
562 return 0;
563}
564
565void __libcpp_thread_yield()
566{
567 SwitchToThread();
568}
569
570// Thread Local Storage
571int __libcpp_tls_create(__libcpp_tls_key* __key,
572 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
573{
574 *__key = FlsAlloc(__at_exit);
575 if (*__key == FLS_OUT_OF_INDEXES)
576 return GetLastError();
577 return 0;
578}
579
580void *__libcpp_tls_get(__libcpp_tls_key __key)
581{
582 return FlsGetValue(__key);
583}
584
585int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
586{
587 if (!FlsSetValue(__key, __p))
588 return GetLastError();
589 return 0;
590}
591
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000592#endif // _LIBCPP_HAS_THREAD_API_PTHREAD
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000593
Eric Fiselier66134e82017-01-06 20:05:40 +0000594#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
595
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000596_LIBCPP_END_NAMESPACE_STD
597
Eric Fiselier66134e82017-01-06 20:05:40 +0000598#endif // !_LIBCPP_HAS_NO_THREADS
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000599
600#endif // _LIBCPP_THREADING_SUPPORT