blob: dfe7fe111e6c4e9573ad59d5e13933d00b29f74f [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)
Eric Fiseliera49c64f2017-01-24 12:26:01 +000028#include <assert.h>
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +000029#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
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +000064#define _LIBCPP_NULL_THREAD 0U
65
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000066typedef pthread_t __libcpp_thread_t;
67
68// Thrad Local Storage
69typedef pthread_key_t __libcpp_tls_key;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +000070
71#define _LIBCPP_TLS_DESTRUCTOR_CC
72#else
73// Mutex
74typedef SRWLOCK __libcpp_mutex_t;
75#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT
76
77typedef CRITICAL_SECTION __libcpp_recursive_mutex_t;
78
79// Condition Variable
80typedef CONDITION_VARIABLE __libcpp_condvar_t;
81#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT
82
83// Execute Once
84typedef INIT_ONCE __libcpp_exec_once_flag;
85#define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
86
87// Thread ID
88typedef DWORD __libcpp_thread_id;
89
90// Thread
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +000091#define _LIBCPP_NULL_THREAD 0U
92
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +000093typedef HANDLE __libcpp_thread_t;
94
95// Thread Local Storage
96typedef DWORD __libcpp_tls_key;
97
98#define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000099#endif
100
101// Mutex
102_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000103int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
104
105_LIBCPP_THREAD_ABI_VISIBILITY
106int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
107
108_LIBCPP_THREAD_ABI_VISIBILITY
Eric Fiselier30d12e32017-01-14 10:27:12 +0000109bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000110
111_LIBCPP_THREAD_ABI_VISIBILITY
112int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
113
114_LIBCPP_THREAD_ABI_VISIBILITY
115int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000116
117_LIBCPP_THREAD_ABI_VISIBILITY
118int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
119
120_LIBCPP_THREAD_ABI_VISIBILITY
Eric Fiselier30d12e32017-01-14 10:27:12 +0000121bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000122
123_LIBCPP_THREAD_ABI_VISIBILITY
124int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
125
126_LIBCPP_THREAD_ABI_VISIBILITY
127int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
128
129// Condition variable
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000130_LIBCPP_THREAD_ABI_VISIBILITY
131int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000132
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000133_LIBCPP_THREAD_ABI_VISIBILITY
134int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000135
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000136_LIBCPP_THREAD_ABI_VISIBILITY
137int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000138
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000139_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000140int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
141 timespec *__ts);
142
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000143_LIBCPP_THREAD_ABI_VISIBILITY
144int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
145
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000146// Execute once
147_LIBCPP_THREAD_ABI_VISIBILITY
148int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
149 void (*init_routine)(void));
150
151// Thread id
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000152_LIBCPP_THREAD_ABI_VISIBILITY
153bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000154
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000155_LIBCPP_THREAD_ABI_VISIBILITY
156bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
157
158// Thread
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000159_LIBCPP_THREAD_ABI_VISIBILITY
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +0000160bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
161
162_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000163int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
164 void *__arg);
165
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000166_LIBCPP_THREAD_ABI_VISIBILITY
167__libcpp_thread_id __libcpp_thread_get_current_id();
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000168
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000169_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000170__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
171
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000172_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000173int __libcpp_thread_join(__libcpp_thread_t *__t);
174
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000175_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000176int __libcpp_thread_detach(__libcpp_thread_t *__t);
177
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000178_LIBCPP_THREAD_ABI_VISIBILITY
179void __libcpp_thread_yield();
180
181// Thread local storage
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000182_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000183int __libcpp_tls_create(__libcpp_tls_key* __key,
184 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000185
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000186_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000187void *__libcpp_tls_get(__libcpp_tls_key __key);
188
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000189_LIBCPP_THREAD_ABI_VISIBILITY
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000190int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000191
Eric Fiselier66134e82017-01-06 20:05:40 +0000192#if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
193 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
194
195#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000196
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000197int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000198{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000199 pthread_mutexattr_t attr;
200 int __ec = pthread_mutexattr_init(&attr);
201 if (__ec)
202 return __ec;
203 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
204 if (__ec) {
205 pthread_mutexattr_destroy(&attr);
206 return __ec;
207 }
208 __ec = pthread_mutex_init(__m, &attr);
209 if (__ec) {
210 pthread_mutexattr_destroy(&attr);
211 return __ec;
212 }
213 __ec = pthread_mutexattr_destroy(&attr);
214 if (__ec) {
215 pthread_mutex_destroy(__m);
216 return __ec;
217 }
218 return 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000219}
220
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000221int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
222{
223 return pthread_mutex_lock(__m);
224}
225
Eric Fiselier30d12e32017-01-14 10:27:12 +0000226bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000227{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000228 return pthread_mutex_trylock(__m) == 0;
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000229}
230
231int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
232{
233 return pthread_mutex_unlock(__m);
234}
235
236int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
237{
238 return pthread_mutex_destroy(__m);
239}
240
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000241int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000242{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000243 return pthread_mutex_lock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000244}
245
Eric Fiselier30d12e32017-01-14 10:27:12 +0000246bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000247{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000248 return pthread_mutex_trylock(__m) == 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000249}
250
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000251int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000252{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000253 return pthread_mutex_unlock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000254}
255
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000256int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000257{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000258 return pthread_mutex_destroy(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000259}
260
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000261// Condition Variable
262int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000263{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000264 return pthread_cond_signal(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000265}
266
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000267int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000268{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000269 return pthread_cond_broadcast(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000270}
271
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000272int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000273{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000274 return pthread_cond_wait(__cv, __m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000275}
276
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000277int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
278 timespec *__ts)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000279{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000280 return pthread_cond_timedwait(__cv, __m, __ts);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000281}
282
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000283int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000284{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000285 return pthread_cond_destroy(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000286}
287
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000288// Execute once
289int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
290 void (*init_routine)(void)) {
291 return pthread_once(flag, init_routine);
292}
293
294// Thread id
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000295// Returns non-zero if the thread ids are equal, otherwise 0
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000296bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
297{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000298 return pthread_equal(t1, t2) != 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000299}
300
301// Returns non-zero if t1 < t2, otherwise 0
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000302bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
303{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000304 return t1 < t2;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000305}
306
307// Thread
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +0000308bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
309 return *__t == 0;
310}
311
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
Eric Fiselier30d12e32017-01-14 10:27:12 +0000374bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000375{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000376 return TryEnterCriticalSection(__m) != 0;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000377}
378
379int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
380{
381 LeaveCriticalSection(__m);
382 return 0;
383}
384
385int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
386{
Saleem Abdulrasool1d324082017-01-10 04:18:47 +0000387 DeleteCriticalSection(__m);
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000388 return 0;
389}
390
391int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
392{
393 AcquireSRWLockExclusive(__m);
394 return 0;
395}
396
Eric Fiselier30d12e32017-01-14 10:27:12 +0000397bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000398{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000399 return TryAcquireSRWLockExclusive(__m) != 0;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000400}
401
402int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
403{
404 ReleaseSRWLockExclusive(__m);
405 return 0;
406}
407
408int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
409{
410 static_cast<void>(__m);
411 return 0;
412}
413
414// Condition Variable
415int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
416{
417 WakeConditionVariable(__cv);
418 return 0;
419}
420
421int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
422{
423 WakeAllConditionVariable(__cv);
424 return 0;
425}
426
427int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
428{
429 SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
430 return 0;
431}
432
433int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
434 timespec *__ts)
435{
436 using namespace _VSTD::chrono;
437
438 auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
439 auto abstime =
440 system_clock::time_point(duration_cast<system_clock::duration>(duration));
441 auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
442
443 if (!SleepConditionVariableSRW(__cv, __m,
444 timeout_ms.count() > 0 ? timeout_ms.count()
445 : 0,
446 0))
447 return GetLastError();
448 return 0;
449}
450
451int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
452{
453 static_cast<void>(__cv);
454 return 0;
455}
456
457// Execute Once
458static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
459__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
460 PVOID *__context)
461{
462 static_cast<void>(__init_once);
463 static_cast<void>(__context);
464
465 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
466 init_routine();
467 return TRUE;
468}
469
470int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
471 void (*__init_routine)(void))
472{
473 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
474 reinterpret_cast<void *>(__init_routine), NULL))
475 return GetLastError();
476 return 0;
477}
478
479// Thread ID
480bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
481 __libcpp_thread_id __rhs)
482{
483 return __lhs == __rhs;
484}
485
486bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
487{
488 return __lhs < __rhs;
489}
490
491// Thread
492struct __libcpp_beginthreadex_thunk_data
493{
494 void *(*__func)(void *);
495 void *__arg;
496};
497
Eric Fiselier543e83b2017-01-14 20:19:00 +0000498static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI
Eric Fiselier433a3972017-01-14 19:11:07 +0000499__libcpp_beginthreadex_thunk(void *__raw_data)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000500{
Eric Fiselier433a3972017-01-14 19:11:07 +0000501 auto *__data =
502 static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data);
503 auto *__func = __data->__func;
504 void *__arg = __data->__arg;
505 delete __data;
Eric Fiselier543e83b2017-01-14 20:19:00 +0000506 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg)));
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000507}
508
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +0000509bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
510 return *__t == 0;
511}
512
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000513int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
514 void *__arg)
515{
Eric Fiselier433a3972017-01-14 19:11:07 +0000516 auto *__data = new __libcpp_beginthreadex_thunk_data;
517 __data->__func = __func;
518 __data->__arg = __arg;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000519
Eric Fiselier543e83b2017-01-14 20:19:00 +0000520 *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
521 __libcpp_beginthreadex_thunk,
522 __data, 0, nullptr));
523
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000524 if (*__t)
525 return 0;
526 return GetLastError();
527}
528
529__libcpp_thread_id __libcpp_thread_get_current_id()
530{
531 return GetCurrentThreadId();
532}
533
534__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
535{
536 return GetThreadId(*__t);
537}
538
539int __libcpp_thread_join(__libcpp_thread_t *__t)
540{
541 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
542 return GetLastError();
543 if (!CloseHandle(*__t))
544 return GetLastError();
545 return 0;
546}
547
548int __libcpp_thread_detach(__libcpp_thread_t *__t)
549{
550 if (!CloseHandle(*__t))
551 return GetLastError();
552 return 0;
553}
554
555void __libcpp_thread_yield()
556{
557 SwitchToThread();
558}
559
560// Thread Local Storage
561int __libcpp_tls_create(__libcpp_tls_key* __key,
562 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
563{
564 *__key = FlsAlloc(__at_exit);
565 if (*__key == FLS_OUT_OF_INDEXES)
566 return GetLastError();
567 return 0;
568}
569
570void *__libcpp_tls_get(__libcpp_tls_key __key)
571{
572 return FlsGetValue(__key);
573}
574
575int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
576{
577 if (!FlsSetValue(__key, __p))
578 return GetLastError();
579 return 0;
580}
581
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000582#endif // _LIBCPP_HAS_THREAD_API_PTHREAD
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000583
Eric Fiselier66134e82017-01-06 20:05:40 +0000584#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
585
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000586_LIBCPP_END_NAMESPACE_STD
587
Eric Fiselier66134e82017-01-06 20:05:40 +0000588#endif // !_LIBCPP_HAS_NO_THREADS
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000589
590#endif // _LIBCPP_THREADING_SUPPORT