blob: d049c9193d989c203fb98709ce39537d68b46ccd [file] [log] [blame]
Asiri Rathnayakec7e42392016-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 Rathnayake8c2bf452016-09-11 21:46:40 +000020#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
Eric Fiselier00f6bea2017-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 Abdulrasool6d7d0be2017-01-07 03:07:45 +000027#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
Eric Fiselierf9e7bf32017-01-24 12:26:01 +000028#include <assert.h>
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +000029#include <Windows.h>
30#include <process.h>
31#include <fibersapi.h>
32
33#include <chrono>
Eric Fiselier00f6bea2017-01-06 20:05:40 +000034#endif
35
36#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
37 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
Asiri Rathnayake8c2bf452016-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
Dimitry Andric83dca5c2017-01-26 18:37:18 +000043#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
44#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
45#else
46#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
47#endif
48
Asiri Rathnayakec7e42392016-05-06 14:06:29 +000049_LIBCPP_BEGIN_NAMESPACE_STD
50
Eric Fiselier00f6bea2017-01-06 20:05:40 +000051#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +000052// Mutex
Asiri Rathnayakec7e42392016-05-06 14:06:29 +000053typedef pthread_mutex_t __libcpp_mutex_t;
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +000054#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
Asiri Rathnayakec7e42392016-05-06 14:06:29 +000055
Saleem Abdulrasool58a0dce2017-01-05 17:54:45 +000056typedef pthread_mutex_t __libcpp_recursive_mutex_t;
57
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +000058// Condition Variable
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +000059typedef pthread_cond_t __libcpp_condvar_t;
60#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +000061
Asiri Rathnayake205d7d32017-01-03 12:59:50 +000062// Execute once
63typedef pthread_once_t __libcpp_exec_once_flag;
64#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
65
66// Thread id
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +000067typedef pthread_t __libcpp_thread_id;
68
69// Thread
Asiri Rathnayakeaf762e912017-01-16 12:19:54 +000070#define _LIBCPP_NULL_THREAD 0U
71
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +000072typedef pthread_t __libcpp_thread_t;
73
74// Thrad Local Storage
75typedef pthread_key_t __libcpp_tls_key;
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +000076
77#define _LIBCPP_TLS_DESTRUCTOR_CC
78#else
79// Mutex
80typedef SRWLOCK __libcpp_mutex_t;
81#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT
82
83typedef CRITICAL_SECTION __libcpp_recursive_mutex_t;
84
85// Condition Variable
86typedef CONDITION_VARIABLE __libcpp_condvar_t;
87#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT
88
89// Execute Once
90typedef INIT_ONCE __libcpp_exec_once_flag;
91#define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
92
93// Thread ID
94typedef DWORD __libcpp_thread_id;
95
96// Thread
Asiri Rathnayakeaf762e912017-01-16 12:19:54 +000097#define _LIBCPP_NULL_THREAD 0U
98
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +000099typedef HANDLE __libcpp_thread_t;
100
101// Thread Local Storage
102typedef DWORD __libcpp_tls_key;
103
104#define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000105#endif
106
107// Mutex
108_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool58a0dce2017-01-05 17:54:45 +0000109int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
110
Dimitry Andric83dca5c2017-01-26 18:37:18 +0000111_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool58a0dce2017-01-05 17:54:45 +0000112int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
113
Dimitry Andric83dca5c2017-01-26 18:37:18 +0000114_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Eric Fiselier08e14772017-01-14 10:27:12 +0000115bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
Saleem Abdulrasool58a0dce2017-01-05 17:54:45 +0000116
Dimitry Andric83dca5c2017-01-26 18:37:18 +0000117_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool58a0dce2017-01-05 17:54:45 +0000118int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
119
120_LIBCPP_THREAD_ABI_VISIBILITY
121int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000122
Dimitry Andric83dca5c2017-01-26 18:37:18 +0000123_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000124int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
125
Dimitry Andric83dca5c2017-01-26 18:37:18 +0000126_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Eric Fiselier08e14772017-01-14 10:27:12 +0000127bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000128
Dimitry Andric83dca5c2017-01-26 18:37:18 +0000129_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000130int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
131
132_LIBCPP_THREAD_ABI_VISIBILITY
133int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
134
135// Condition variable
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000136_LIBCPP_THREAD_ABI_VISIBILITY
137int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000138
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000139_LIBCPP_THREAD_ABI_VISIBILITY
140int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000141
Dimitry Andric83dca5c2017-01-26 18:37:18 +0000142_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000143int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000144
Dimitry Andric83dca5c2017-01-26 18:37:18 +0000145_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000146int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
147 timespec *__ts);
148
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000149_LIBCPP_THREAD_ABI_VISIBILITY
150int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
151
Asiri Rathnayake205d7d32017-01-03 12:59:50 +0000152// Execute once
153_LIBCPP_THREAD_ABI_VISIBILITY
154int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
155 void (*init_routine)(void));
156
157// Thread id
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000158_LIBCPP_THREAD_ABI_VISIBILITY
159bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000160
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000161_LIBCPP_THREAD_ABI_VISIBILITY
162bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
163
164// Thread
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000165_LIBCPP_THREAD_ABI_VISIBILITY
Asiri Rathnayakeaf762e912017-01-16 12:19:54 +0000166bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
167
168_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000169int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
170 void *__arg);
171
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000172_LIBCPP_THREAD_ABI_VISIBILITY
173__libcpp_thread_id __libcpp_thread_get_current_id();
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000174
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000175_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000176__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
177
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000178_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000179int __libcpp_thread_join(__libcpp_thread_t *__t);
180
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000181_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000182int __libcpp_thread_detach(__libcpp_thread_t *__t);
183
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000184_LIBCPP_THREAD_ABI_VISIBILITY
185void __libcpp_thread_yield();
186
187// Thread local storage
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000188_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +0000189int __libcpp_tls_create(__libcpp_tls_key* __key,
190 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000191
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000192_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000193void *__libcpp_tls_get(__libcpp_tls_key __key);
194
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000195_LIBCPP_THREAD_ABI_VISIBILITY
Asiri Rathnayake205d7d32017-01-03 12:59:50 +0000196int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000197
Eric Fiselier00f6bea2017-01-06 20:05:40 +0000198#if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
199 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
200
201#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
Asiri Rathnayake8c2bf452016-09-11 21:46:40 +0000202
Saleem Abdulrasool58a0dce2017-01-05 17:54:45 +0000203int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000204{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000205 pthread_mutexattr_t attr;
206 int __ec = pthread_mutexattr_init(&attr);
207 if (__ec)
208 return __ec;
209 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
210 if (__ec) {
211 pthread_mutexattr_destroy(&attr);
212 return __ec;
213 }
214 __ec = pthread_mutex_init(__m, &attr);
215 if (__ec) {
216 pthread_mutexattr_destroy(&attr);
217 return __ec;
218 }
219 __ec = pthread_mutexattr_destroy(&attr);
220 if (__ec) {
221 pthread_mutex_destroy(__m);
222 return __ec;
223 }
224 return 0;
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000225}
226
Saleem Abdulrasool58a0dce2017-01-05 17:54:45 +0000227int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
228{
229 return pthread_mutex_lock(__m);
230}
231
Eric Fiselier08e14772017-01-14 10:27:12 +0000232bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
Saleem Abdulrasool58a0dce2017-01-05 17:54:45 +0000233{
Eric Fiselier08e14772017-01-14 10:27:12 +0000234 return pthread_mutex_trylock(__m) == 0;
Saleem Abdulrasool58a0dce2017-01-05 17:54:45 +0000235}
236
237int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
238{
239 return pthread_mutex_unlock(__m);
240}
241
242int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
243{
244 return pthread_mutex_destroy(__m);
245}
246
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000247int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000248{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000249 return pthread_mutex_lock(__m);
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000250}
251
Eric Fiselier08e14772017-01-14 10:27:12 +0000252bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000253{
Eric Fiselier08e14772017-01-14 10:27:12 +0000254 return pthread_mutex_trylock(__m) == 0;
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000255}
256
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000257int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000258{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000259 return pthread_mutex_unlock(__m);
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000260}
261
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000262int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000263{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000264 return pthread_mutex_destroy(__m);
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000265}
266
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000267// Condition Variable
268int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000269{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000270 return pthread_cond_signal(__cv);
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000271}
272
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000273int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000274{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000275 return pthread_cond_broadcast(__cv);
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000276}
277
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000278int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000279{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000280 return pthread_cond_wait(__cv, __m);
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000281}
282
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000283int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
284 timespec *__ts)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000285{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000286 return pthread_cond_timedwait(__cv, __m, __ts);
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000287}
288
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000289int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000290{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000291 return pthread_cond_destroy(__cv);
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000292}
293
Asiri Rathnayake205d7d32017-01-03 12:59:50 +0000294// Execute once
295int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
296 void (*init_routine)(void)) {
297 return pthread_once(flag, init_routine);
298}
299
300// Thread id
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000301// Returns non-zero if the thread ids are equal, otherwise 0
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000302bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
303{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000304 return pthread_equal(t1, t2) != 0;
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000305}
306
307// Returns non-zero if t1 < t2, otherwise 0
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000308bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
309{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000310 return t1 < t2;
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000311}
312
313// Thread
Asiri Rathnayakeaf762e912017-01-16 12:19:54 +0000314bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
315 return *__t == 0;
316}
317
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000318int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
319 void *__arg)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000320{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000321 return pthread_create(__t, 0, __func, __arg);
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000322}
323
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000324__libcpp_thread_id __libcpp_thread_get_current_id()
325{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000326 return pthread_self();
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000327}
328
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000329__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000330{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000331 return *__t;
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000332}
333
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000334int __libcpp_thread_join(__libcpp_thread_t *__t)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000335{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000336 return pthread_join(*__t, 0);
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000337}
338
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000339int __libcpp_thread_detach(__libcpp_thread_t *__t)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000340{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000341 return pthread_detach(*__t);
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000342}
343
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000344void __libcpp_thread_yield()
345{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000346 sched_yield();
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000347}
348
349// Thread local storage
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000350int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000351{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000352 return pthread_key_create(__key, __at_exit);
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000353}
354
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000355void *__libcpp_tls_get(__libcpp_tls_key __key)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000356{
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000357 return pthread_getspecific(__key);
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000358}
359
Asiri Rathnayake205d7d32017-01-03 12:59:50 +0000360int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000361{
Asiri Rathnayake205d7d32017-01-03 12:59:50 +0000362 return pthread_setspecific(__key, __p);
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000363}
364
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +0000365#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
366
367// Mutex
368int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
369{
370 InitializeCriticalSection(__m);
371 return 0;
372}
373
374int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
375{
376 EnterCriticalSection(__m);
377 return 0;
378}
379
Eric Fiselier08e14772017-01-14 10:27:12 +0000380bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +0000381{
Eric Fiselier08e14772017-01-14 10:27:12 +0000382 return TryEnterCriticalSection(__m) != 0;
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +0000383}
384
385int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
386{
387 LeaveCriticalSection(__m);
388 return 0;
389}
390
391int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
392{
Saleem Abdulrasool4ec493b2017-01-10 04:18:47 +0000393 DeleteCriticalSection(__m);
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +0000394 return 0;
395}
396
397int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
398{
399 AcquireSRWLockExclusive(__m);
400 return 0;
401}
402
Eric Fiselier08e14772017-01-14 10:27:12 +0000403bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +0000404{
Eric Fiselier08e14772017-01-14 10:27:12 +0000405 return TryAcquireSRWLockExclusive(__m) != 0;
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +0000406}
407
408int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
409{
410 ReleaseSRWLockExclusive(__m);
411 return 0;
412}
413
414int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
415{
416 static_cast<void>(__m);
417 return 0;
418}
419
420// Condition Variable
421int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
422{
423 WakeConditionVariable(__cv);
424 return 0;
425}
426
427int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
428{
429 WakeAllConditionVariable(__cv);
430 return 0;
431}
432
433int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
434{
435 SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
436 return 0;
437}
438
439int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
440 timespec *__ts)
441{
442 using namespace _VSTD::chrono;
443
444 auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
445 auto abstime =
446 system_clock::time_point(duration_cast<system_clock::duration>(duration));
447 auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
448
449 if (!SleepConditionVariableSRW(__cv, __m,
450 timeout_ms.count() > 0 ? timeout_ms.count()
451 : 0,
452 0))
453 return GetLastError();
454 return 0;
455}
456
457int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
458{
459 static_cast<void>(__cv);
460 return 0;
461}
462
463// Execute Once
464static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
465__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
466 PVOID *__context)
467{
468 static_cast<void>(__init_once);
469 static_cast<void>(__context);
470
471 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
472 init_routine();
473 return TRUE;
474}
475
476int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
477 void (*__init_routine)(void))
478{
479 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
480 reinterpret_cast<void *>(__init_routine), NULL))
481 return GetLastError();
482 return 0;
483}
484
485// Thread ID
486bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
487 __libcpp_thread_id __rhs)
488{
489 return __lhs == __rhs;
490}
491
492bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
493{
494 return __lhs < __rhs;
495}
496
497// Thread
498struct __libcpp_beginthreadex_thunk_data
499{
500 void *(*__func)(void *);
501 void *__arg;
502};
503
Eric Fiselierd75a9d22017-01-14 20:19:00 +0000504static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI
Eric Fiselier6f38b6a2017-01-14 19:11:07 +0000505__libcpp_beginthreadex_thunk(void *__raw_data)
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +0000506{
Eric Fiselier6f38b6a2017-01-14 19:11:07 +0000507 auto *__data =
508 static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data);
509 auto *__func = __data->__func;
510 void *__arg = __data->__arg;
511 delete __data;
Eric Fiselierd75a9d22017-01-14 20:19:00 +0000512 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg)));
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +0000513}
514
Asiri Rathnayakeaf762e912017-01-16 12:19:54 +0000515bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
516 return *__t == 0;
517}
518
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +0000519int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
520 void *__arg)
521{
Eric Fiselier6f38b6a2017-01-14 19:11:07 +0000522 auto *__data = new __libcpp_beginthreadex_thunk_data;
523 __data->__func = __func;
524 __data->__arg = __arg;
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +0000525
Eric Fiselierd75a9d22017-01-14 20:19:00 +0000526 *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
527 __libcpp_beginthreadex_thunk,
528 __data, 0, nullptr));
529
Saleem Abdulrasool6d7d0be2017-01-07 03:07:45 +0000530 if (*__t)
531 return 0;
532 return GetLastError();
533}
534
535__libcpp_thread_id __libcpp_thread_get_current_id()
536{
537 return GetCurrentThreadId();
538}
539
540__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
541{
542 return GetThreadId(*__t);
543}
544
545int __libcpp_thread_join(__libcpp_thread_t *__t)
546{
547 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
548 return GetLastError();
549 if (!CloseHandle(*__t))
550 return GetLastError();
551 return 0;
552}
553
554int __libcpp_thread_detach(__libcpp_thread_t *__t)
555{
556 if (!CloseHandle(*__t))
557 return GetLastError();
558 return 0;
559}
560
561void __libcpp_thread_yield()
562{
563 SwitchToThread();
564}
565
566// Thread Local Storage
567int __libcpp_tls_create(__libcpp_tls_key* __key,
568 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
569{
570 *__key = FlsAlloc(__at_exit);
571 if (*__key == FLS_OUT_OF_INDEXES)
572 return GetLastError();
573 return 0;
574}
575
576void *__libcpp_tls_get(__libcpp_tls_key __key)
577{
578 return FlsGetValue(__key);
579}
580
581int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
582{
583 if (!FlsSetValue(__key, __p))
584 return GetLastError();
585 return 0;
586}
587
Saleem Abdulrasool790e10f2017-01-03 02:00:31 +0000588#endif // _LIBCPP_HAS_THREAD_API_PTHREAD
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000589
Eric Fiselier00f6bea2017-01-06 20:05:40 +0000590#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
591
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000592_LIBCPP_END_NAMESPACE_STD
593
Eric Fiselier00f6bea2017-01-06 20:05:40 +0000594#endif // !_LIBCPP_HAS_NO_THREADS
Asiri Rathnayakec7e42392016-05-06 14:06:29 +0000595
596#endif // _LIBCPP_THREADING_SUPPORT