blob: 385fff32b350c0d1873741e62b1ac17c76a2715c [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>
Asiri Rathnayake1b939612017-02-09 09:31:41 +000015#include <chrono>
16#include <errno.h>
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000017
18#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
19#pragma GCC system_header
20#endif
21
Asiri Rathnayake040945b2016-09-11 21:46:40 +000022#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
Eric Fiselier66134e82017-01-06 20:05:40 +000023# include <__external_threading>
24#elif !defined(_LIBCPP_HAS_NO_THREADS)
25
26#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
27# include <pthread.h>
28# include <sched.h>
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +000029#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +000030#include <Windows.h>
31#include <process.h>
32#include <fibersapi.h>
Eric Fiselier41af64a2017-05-10 20:57:45 +000033#include <__undef_min_max>
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
Dimitry Andric362353a2017-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 Rathnayake35ff03b2016-05-06 14:06:29 +000049_LIBCPP_BEGIN_NAMESPACE_STD
50
Eric Fiselier66134e82017-01-06 20:05:40 +000051#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000052// Mutex
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000053typedef pthread_mutex_t __libcpp_mutex_t;
Asiri Rathnayake040945b2016-09-11 21:46:40 +000054#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000055
Saleem Abdulrasool3451a652017-01-05 17:54:45 +000056typedef pthread_mutex_t __libcpp_recursive_mutex_t;
57
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000058// Condition Variable
Asiri Rathnayake040945b2016-09-11 21:46:40 +000059typedef pthread_cond_t __libcpp_condvar_t;
60#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000061
Asiri Rathnayakee262e7b2017-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 Abdulrasool1d192372017-01-03 02:00:31 +000067typedef pthread_t __libcpp_thread_id;
68
69// Thread
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +000070#define _LIBCPP_NULL_THREAD 0U
71
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000072typedef pthread_t __libcpp_thread_t;
73
74// Thrad Local Storage
75typedef pthread_key_t __libcpp_tls_key;
Saleem Abdulrasool678eadd2017-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 Rathnayakea1d7d2f2017-01-16 12:19:54 +000097#define _LIBCPP_NULL_THREAD 0U
98
Saleem Abdulrasool678eadd2017-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 Abdulrasool1d192372017-01-03 02:00:31 +0000105#endif
106
107// Mutex
108_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000109int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
110
Dimitry Andric362353a2017-01-26 18:37:18 +0000111_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000112int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
113
Dimitry Andric362353a2017-01-26 18:37:18 +0000114_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Eric Fiselier30d12e32017-01-14 10:27:12 +0000115bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000116
Dimitry Andric362353a2017-01-26 18:37:18 +0000117_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool3451a652017-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 Abdulrasool1d192372017-01-03 02:00:31 +0000122
Dimitry Andric362353a2017-01-26 18:37:18 +0000123_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000124int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
125
Dimitry Andric362353a2017-01-26 18:37:18 +0000126_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Eric Fiselier30d12e32017-01-14 10:27:12 +0000127bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000128
Dimitry Andric362353a2017-01-26 18:37:18 +0000129_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool1d192372017-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 Rathnayake040945b2016-09-11 21:46:40 +0000136_LIBCPP_THREAD_ABI_VISIBILITY
137int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000138
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000139_LIBCPP_THREAD_ABI_VISIBILITY
140int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000141
Dimitry Andric362353a2017-01-26 18:37:18 +0000142_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000143int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000144
Dimitry Andric362353a2017-01-26 18:37:18 +0000145_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000146int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
147 timespec *__ts);
148
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000149_LIBCPP_THREAD_ABI_VISIBILITY
150int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
151
Asiri Rathnayakee262e7b2017-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 Rathnayake040945b2016-09-11 21:46:40 +0000158_LIBCPP_THREAD_ABI_VISIBILITY
159bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000160
Asiri Rathnayake040945b2016-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 Rathnayake040945b2016-09-11 21:46:40 +0000165_LIBCPP_THREAD_ABI_VISIBILITY
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +0000166bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
167
168_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000169int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
170 void *__arg);
171
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000172_LIBCPP_THREAD_ABI_VISIBILITY
173__libcpp_thread_id __libcpp_thread_get_current_id();
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000174
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000175_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000176__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
177
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000178_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000179int __libcpp_thread_join(__libcpp_thread_t *__t);
180
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000181_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000182int __libcpp_thread_detach(__libcpp_thread_t *__t);
183
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000184_LIBCPP_THREAD_ABI_VISIBILITY
185void __libcpp_thread_yield();
186
Asiri Rathnayake1b939612017-02-09 09:31:41 +0000187_LIBCPP_THREAD_ABI_VISIBILITY
Joerg Sonnenberger5a0c9c32017-02-09 14:12:29 +0000188void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
Asiri Rathnayake1b939612017-02-09 09:31:41 +0000189
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000190// Thread local storage
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000191_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000192int __libcpp_tls_create(__libcpp_tls_key* __key,
193 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000194
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000195_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000196void *__libcpp_tls_get(__libcpp_tls_key __key);
197
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000198_LIBCPP_THREAD_ABI_VISIBILITY
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000199int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000200
Eric Fiselier66134e82017-01-06 20:05:40 +0000201#if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
202 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
203
204#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000205
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000206int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000207{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000208 pthread_mutexattr_t attr;
209 int __ec = pthread_mutexattr_init(&attr);
210 if (__ec)
211 return __ec;
212 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
213 if (__ec) {
214 pthread_mutexattr_destroy(&attr);
215 return __ec;
216 }
217 __ec = pthread_mutex_init(__m, &attr);
218 if (__ec) {
219 pthread_mutexattr_destroy(&attr);
220 return __ec;
221 }
222 __ec = pthread_mutexattr_destroy(&attr);
223 if (__ec) {
224 pthread_mutex_destroy(__m);
225 return __ec;
226 }
227 return 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000228}
229
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000230int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
231{
232 return pthread_mutex_lock(__m);
233}
234
Eric Fiselier30d12e32017-01-14 10:27:12 +0000235bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000236{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000237 return pthread_mutex_trylock(__m) == 0;
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000238}
239
240int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
241{
242 return pthread_mutex_unlock(__m);
243}
244
245int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
246{
247 return pthread_mutex_destroy(__m);
248}
249
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000250int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000251{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000252 return pthread_mutex_lock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000253}
254
Eric Fiselier30d12e32017-01-14 10:27:12 +0000255bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000256{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000257 return pthread_mutex_trylock(__m) == 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000258}
259
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000260int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000261{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000262 return pthread_mutex_unlock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000263}
264
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000265int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000266{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000267 return pthread_mutex_destroy(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000268}
269
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000270// Condition Variable
271int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000272{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000273 return pthread_cond_signal(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000274}
275
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000276int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000277{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000278 return pthread_cond_broadcast(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000279}
280
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000281int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000282{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000283 return pthread_cond_wait(__cv, __m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000284}
285
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000286int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
287 timespec *__ts)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000288{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000289 return pthread_cond_timedwait(__cv, __m, __ts);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000290}
291
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000292int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000293{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000294 return pthread_cond_destroy(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000295}
296
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000297// Execute once
298int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
299 void (*init_routine)(void)) {
300 return pthread_once(flag, init_routine);
301}
302
303// Thread id
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000304// Returns non-zero if the thread ids are equal, otherwise 0
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000305bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
306{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000307 return pthread_equal(t1, t2) != 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000308}
309
310// Returns non-zero if t1 < t2, otherwise 0
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000311bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
312{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000313 return t1 < t2;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000314}
315
316// Thread
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +0000317bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
318 return *__t == 0;
319}
320
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000321int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
322 void *__arg)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000323{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000324 return pthread_create(__t, 0, __func, __arg);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000325}
326
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000327__libcpp_thread_id __libcpp_thread_get_current_id()
328{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000329 return pthread_self();
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000330}
331
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000332__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000333{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000334 return *__t;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000335}
336
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000337int __libcpp_thread_join(__libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000338{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000339 return pthread_join(*__t, 0);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000340}
341
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000342int __libcpp_thread_detach(__libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000343{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000344 return pthread_detach(*__t);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000345}
346
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000347void __libcpp_thread_yield()
348{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000349 sched_yield();
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000350}
351
Asiri Rathnayake1b939612017-02-09 09:31:41 +0000352void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
353{
354 using namespace chrono;
355 seconds __s = duration_cast<seconds>(__ns);
356 timespec __ts;
357 typedef decltype(__ts.tv_sec) ts_sec;
358 _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max();
359
360 if (__s.count() < __ts_sec_max)
361 {
362 __ts.tv_sec = static_cast<ts_sec>(__s.count());
363 __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
364 }
365 else
366 {
367 __ts.tv_sec = __ts_sec_max;
368 __ts.tv_nsec = 999999999; // (10^9 - 1)
369 }
370
371 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
372}
373
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000374// Thread local storage
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000375int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000376{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000377 return pthread_key_create(__key, __at_exit);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000378}
379
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000380void *__libcpp_tls_get(__libcpp_tls_key __key)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000381{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000382 return pthread_getspecific(__key);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000383}
384
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000385int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000386{
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000387 return pthread_setspecific(__key, __p);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000388}
389
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000390#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
391
392// Mutex
393int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
394{
395 InitializeCriticalSection(__m);
396 return 0;
397}
398
399int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
400{
401 EnterCriticalSection(__m);
402 return 0;
403}
404
Eric Fiselier30d12e32017-01-14 10:27:12 +0000405bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000406{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000407 return TryEnterCriticalSection(__m) != 0;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000408}
409
410int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
411{
412 LeaveCriticalSection(__m);
413 return 0;
414}
415
416int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
417{
Saleem Abdulrasool1d324082017-01-10 04:18:47 +0000418 DeleteCriticalSection(__m);
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000419 return 0;
420}
421
422int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
423{
424 AcquireSRWLockExclusive(__m);
425 return 0;
426}
427
Eric Fiselier30d12e32017-01-14 10:27:12 +0000428bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000429{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000430 return TryAcquireSRWLockExclusive(__m) != 0;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000431}
432
433int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
434{
435 ReleaseSRWLockExclusive(__m);
436 return 0;
437}
438
439int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
440{
441 static_cast<void>(__m);
442 return 0;
443}
444
445// Condition Variable
446int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
447{
448 WakeConditionVariable(__cv);
449 return 0;
450}
451
452int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
453{
454 WakeAllConditionVariable(__cv);
455 return 0;
456}
457
458int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
459{
460 SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
461 return 0;
462}
463
464int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
465 timespec *__ts)
466{
467 using namespace _VSTD::chrono;
468
469 auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
470 auto abstime =
471 system_clock::time_point(duration_cast<system_clock::duration>(duration));
472 auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
473
474 if (!SleepConditionVariableSRW(__cv, __m,
475 timeout_ms.count() > 0 ? timeout_ms.count()
476 : 0,
477 0))
Eric Fiselier08fd3362017-05-05 21:31:22 +0000478 {
479 auto __ec = GetLastError();
480 return __ec == ERROR_TIMEOUT ? ETIMEDOUT : __ec;
481 }
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000482 return 0;
483}
484
485int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
486{
487 static_cast<void>(__cv);
488 return 0;
489}
490
491// Execute Once
492static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
493__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
494 PVOID *__context)
495{
496 static_cast<void>(__init_once);
497 static_cast<void>(__context);
498
499 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
500 init_routine();
501 return TRUE;
502}
503
504int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
505 void (*__init_routine)(void))
506{
507 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
508 reinterpret_cast<void *>(__init_routine), NULL))
509 return GetLastError();
510 return 0;
511}
512
513// Thread ID
514bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
515 __libcpp_thread_id __rhs)
516{
517 return __lhs == __rhs;
518}
519
520bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
521{
522 return __lhs < __rhs;
523}
524
525// Thread
526struct __libcpp_beginthreadex_thunk_data
527{
528 void *(*__func)(void *);
529 void *__arg;
530};
531
Eric Fiselier543e83b2017-01-14 20:19:00 +0000532static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI
Eric Fiselier433a3972017-01-14 19:11:07 +0000533__libcpp_beginthreadex_thunk(void *__raw_data)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000534{
Eric Fiselier433a3972017-01-14 19:11:07 +0000535 auto *__data =
536 static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data);
537 auto *__func = __data->__func;
538 void *__arg = __data->__arg;
539 delete __data;
Eric Fiselier543e83b2017-01-14 20:19:00 +0000540 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg)));
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000541}
542
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +0000543bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
544 return *__t == 0;
545}
546
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000547int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
548 void *__arg)
549{
Eric Fiselier433a3972017-01-14 19:11:07 +0000550 auto *__data = new __libcpp_beginthreadex_thunk_data;
551 __data->__func = __func;
552 __data->__arg = __arg;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000553
Eric Fiselier543e83b2017-01-14 20:19:00 +0000554 *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
555 __libcpp_beginthreadex_thunk,
556 __data, 0, nullptr));
557
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000558 if (*__t)
559 return 0;
560 return GetLastError();
561}
562
563__libcpp_thread_id __libcpp_thread_get_current_id()
564{
565 return GetCurrentThreadId();
566}
567
568__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
569{
570 return GetThreadId(*__t);
571}
572
573int __libcpp_thread_join(__libcpp_thread_t *__t)
574{
575 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
576 return GetLastError();
577 if (!CloseHandle(*__t))
578 return GetLastError();
579 return 0;
580}
581
582int __libcpp_thread_detach(__libcpp_thread_t *__t)
583{
584 if (!CloseHandle(*__t))
585 return GetLastError();
586 return 0;
587}
588
589void __libcpp_thread_yield()
590{
591 SwitchToThread();
592}
593
Asiri Rathnayake1b939612017-02-09 09:31:41 +0000594void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
595{
Saleem Abdulrasoole891cc82017-02-18 19:28:43 +0000596 using namespace chrono;
Asiri Rathnayake1b939612017-02-09 09:31:41 +0000597 // round-up to the nearest milisecond
Saleem Abdulrasool29e11422017-02-10 02:49:52 +0000598 milliseconds __ms =
599 duration_cast<milliseconds>(__ns + chrono::nanoseconds(999999));
Saleem Abdulrasoole891cc82017-02-18 19:28:43 +0000600 // FIXME(compnerd) this should be an alertable sleep (WFSO or SleepEx)
601 Sleep(__ms.count());
Asiri Rathnayake1b939612017-02-09 09:31:41 +0000602}
603
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000604// Thread Local Storage
605int __libcpp_tls_create(__libcpp_tls_key* __key,
606 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
607{
608 *__key = FlsAlloc(__at_exit);
609 if (*__key == FLS_OUT_OF_INDEXES)
610 return GetLastError();
611 return 0;
612}
613
614void *__libcpp_tls_get(__libcpp_tls_key __key)
615{
616 return FlsGetValue(__key);
617}
618
619int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
620{
621 if (!FlsSetValue(__key, __p))
622 return GetLastError();
623 return 0;
624}
625
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000626#endif // _LIBCPP_HAS_THREAD_API_PTHREAD
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000627
Eric Fiselier66134e82017-01-06 20:05:40 +0000628#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
629
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000630_LIBCPP_END_NAMESPACE_STD
631
Eric Fiselier66134e82017-01-06 20:05:40 +0000632#endif // !_LIBCPP_HAS_NO_THREADS
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000633
634#endif // _LIBCPP_THREADING_SUPPORT