blob: ac0544dfb368cf9e7bb3126b27a63aad6efcb0d0 [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 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
Dimitry Andric362353a2017-01-26 18:37:18 +000042#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
43#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
44#else
45#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
46#endif
47
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000048_LIBCPP_BEGIN_NAMESPACE_STD
49
Eric Fiselier66134e82017-01-06 20:05:40 +000050#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000051// Mutex
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000052typedef pthread_mutex_t __libcpp_mutex_t;
Asiri Rathnayake040945b2016-09-11 21:46:40 +000053#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000054
Saleem Abdulrasool3451a652017-01-05 17:54:45 +000055typedef pthread_mutex_t __libcpp_recursive_mutex_t;
56
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000057// Condition Variable
Asiri Rathnayake040945b2016-09-11 21:46:40 +000058typedef pthread_cond_t __libcpp_condvar_t;
59#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000060
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +000061// Execute once
62typedef pthread_once_t __libcpp_exec_once_flag;
63#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
64
65// Thread id
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000066typedef pthread_t __libcpp_thread_id;
67
68// Thread
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +000069#define _LIBCPP_NULL_THREAD 0U
70
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000071typedef pthread_t __libcpp_thread_t;
72
73// Thrad Local Storage
74typedef pthread_key_t __libcpp_tls_key;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +000075
76#define _LIBCPP_TLS_DESTRUCTOR_CC
77#else
78// Mutex
79typedef SRWLOCK __libcpp_mutex_t;
80#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT
81
82typedef CRITICAL_SECTION __libcpp_recursive_mutex_t;
83
84// Condition Variable
85typedef CONDITION_VARIABLE __libcpp_condvar_t;
86#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT
87
88// Execute Once
89typedef INIT_ONCE __libcpp_exec_once_flag;
90#define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
91
92// Thread ID
93typedef DWORD __libcpp_thread_id;
94
95// Thread
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +000096#define _LIBCPP_NULL_THREAD 0U
97
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +000098typedef HANDLE __libcpp_thread_t;
99
100// Thread Local Storage
101typedef DWORD __libcpp_tls_key;
102
103#define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000104#endif
105
106// Mutex
107_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000108int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
109
Dimitry Andric362353a2017-01-26 18:37:18 +0000110_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000111int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
112
Dimitry Andric362353a2017-01-26 18:37:18 +0000113_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Eric Fiselier30d12e32017-01-14 10:27:12 +0000114bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000115
Dimitry Andric362353a2017-01-26 18:37:18 +0000116_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000117int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
118
119_LIBCPP_THREAD_ABI_VISIBILITY
120int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000121
Dimitry Andric362353a2017-01-26 18:37:18 +0000122_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000123int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
124
Dimitry Andric362353a2017-01-26 18:37:18 +0000125_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Eric Fiselier30d12e32017-01-14 10:27:12 +0000126bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000127
Dimitry Andric362353a2017-01-26 18:37:18 +0000128_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000129int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
130
131_LIBCPP_THREAD_ABI_VISIBILITY
132int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
133
134// Condition variable
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000135_LIBCPP_THREAD_ABI_VISIBILITY
136int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000137
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000138_LIBCPP_THREAD_ABI_VISIBILITY
139int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000140
Dimitry Andric362353a2017-01-26 18:37:18 +0000141_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000142int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000143
Dimitry Andric362353a2017-01-26 18:37:18 +0000144_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000145int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
146 timespec *__ts);
147
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000148_LIBCPP_THREAD_ABI_VISIBILITY
149int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
150
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000151// Execute once
152_LIBCPP_THREAD_ABI_VISIBILITY
153int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
154 void (*init_routine)(void));
155
156// Thread id
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000157_LIBCPP_THREAD_ABI_VISIBILITY
158bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000159
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000160_LIBCPP_THREAD_ABI_VISIBILITY
161bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
162
163// Thread
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000164_LIBCPP_THREAD_ABI_VISIBILITY
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +0000165bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
166
167_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000168int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
169 void *__arg);
170
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000171_LIBCPP_THREAD_ABI_VISIBILITY
172__libcpp_thread_id __libcpp_thread_get_current_id();
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000173
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000174_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000175__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
176
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000177_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000178int __libcpp_thread_join(__libcpp_thread_t *__t);
179
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000180_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000181int __libcpp_thread_detach(__libcpp_thread_t *__t);
182
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000183_LIBCPP_THREAD_ABI_VISIBILITY
184void __libcpp_thread_yield();
185
Asiri Rathnayake1b939612017-02-09 09:31:41 +0000186_LIBCPP_THREAD_ABI_VISIBILITY
187void __libcpp_thread_sleep_for(const chrono::nanoseconds& ns);
188
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000189// Thread local storage
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000190_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000191int __libcpp_tls_create(__libcpp_tls_key* __key,
192 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000193
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000194_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000195void *__libcpp_tls_get(__libcpp_tls_key __key);
196
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000197_LIBCPP_THREAD_ABI_VISIBILITY
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000198int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000199
Eric Fiselier66134e82017-01-06 20:05:40 +0000200#if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
201 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
202
203#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000204
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000205int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000206{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000207 pthread_mutexattr_t attr;
208 int __ec = pthread_mutexattr_init(&attr);
209 if (__ec)
210 return __ec;
211 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
212 if (__ec) {
213 pthread_mutexattr_destroy(&attr);
214 return __ec;
215 }
216 __ec = pthread_mutex_init(__m, &attr);
217 if (__ec) {
218 pthread_mutexattr_destroy(&attr);
219 return __ec;
220 }
221 __ec = pthread_mutexattr_destroy(&attr);
222 if (__ec) {
223 pthread_mutex_destroy(__m);
224 return __ec;
225 }
226 return 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000227}
228
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000229int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
230{
231 return pthread_mutex_lock(__m);
232}
233
Eric Fiselier30d12e32017-01-14 10:27:12 +0000234bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000235{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000236 return pthread_mutex_trylock(__m) == 0;
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000237}
238
239int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
240{
241 return pthread_mutex_unlock(__m);
242}
243
244int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
245{
246 return pthread_mutex_destroy(__m);
247}
248
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000249int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000250{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000251 return pthread_mutex_lock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000252}
253
Eric Fiselier30d12e32017-01-14 10:27:12 +0000254bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000255{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000256 return pthread_mutex_trylock(__m) == 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000257}
258
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000259int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000260{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000261 return pthread_mutex_unlock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000262}
263
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000264int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000265{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000266 return pthread_mutex_destroy(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000267}
268
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000269// Condition Variable
270int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000271{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000272 return pthread_cond_signal(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000273}
274
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000275int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000276{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000277 return pthread_cond_broadcast(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000278}
279
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000280int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000281{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000282 return pthread_cond_wait(__cv, __m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000283}
284
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000285int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
286 timespec *__ts)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000287{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000288 return pthread_cond_timedwait(__cv, __m, __ts);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000289}
290
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000291int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000292{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000293 return pthread_cond_destroy(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000294}
295
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000296// Execute once
297int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
298 void (*init_routine)(void)) {
299 return pthread_once(flag, init_routine);
300}
301
302// Thread id
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000303// Returns non-zero if the thread ids are equal, otherwise 0
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000304bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
305{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000306 return pthread_equal(t1, t2) != 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000307}
308
309// Returns non-zero if t1 < t2, otherwise 0
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000310bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
311{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000312 return t1 < t2;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000313}
314
315// Thread
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +0000316bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
317 return *__t == 0;
318}
319
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000320int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
321 void *__arg)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000322{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000323 return pthread_create(__t, 0, __func, __arg);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000324}
325
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000326__libcpp_thread_id __libcpp_thread_get_current_id()
327{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000328 return pthread_self();
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000329}
330
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000331__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000332{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000333 return *__t;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000334}
335
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000336int __libcpp_thread_join(__libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000337{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000338 return pthread_join(*__t, 0);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000339}
340
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000341int __libcpp_thread_detach(__libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000342{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000343 return pthread_detach(*__t);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000344}
345
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000346void __libcpp_thread_yield()
347{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000348 sched_yield();
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000349}
350
Asiri Rathnayake1b939612017-02-09 09:31:41 +0000351void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
352{
353 using namespace chrono;
354 seconds __s = duration_cast<seconds>(__ns);
355 timespec __ts;
356 typedef decltype(__ts.tv_sec) ts_sec;
357 _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max();
358
359 if (__s.count() < __ts_sec_max)
360 {
361 __ts.tv_sec = static_cast<ts_sec>(__s.count());
362 __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
363 }
364 else
365 {
366 __ts.tv_sec = __ts_sec_max;
367 __ts.tv_nsec = 999999999; // (10^9 - 1)
368 }
369
370 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
371}
372
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000373// Thread local storage
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000374int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000375{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000376 return pthread_key_create(__key, __at_exit);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000377}
378
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000379void *__libcpp_tls_get(__libcpp_tls_key __key)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000380{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000381 return pthread_getspecific(__key);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000382}
383
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000384int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000385{
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000386 return pthread_setspecific(__key, __p);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000387}
388
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000389#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
390
391// Mutex
392int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
393{
394 InitializeCriticalSection(__m);
395 return 0;
396}
397
398int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
399{
400 EnterCriticalSection(__m);
401 return 0;
402}
403
Eric Fiselier30d12e32017-01-14 10:27:12 +0000404bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000405{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000406 return TryEnterCriticalSection(__m) != 0;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000407}
408
409int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
410{
411 LeaveCriticalSection(__m);
412 return 0;
413}
414
415int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
416{
Saleem Abdulrasool1d324082017-01-10 04:18:47 +0000417 DeleteCriticalSection(__m);
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000418 return 0;
419}
420
421int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
422{
423 AcquireSRWLockExclusive(__m);
424 return 0;
425}
426
Eric Fiselier30d12e32017-01-14 10:27:12 +0000427bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000428{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000429 return TryAcquireSRWLockExclusive(__m) != 0;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000430}
431
432int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
433{
434 ReleaseSRWLockExclusive(__m);
435 return 0;
436}
437
438int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
439{
440 static_cast<void>(__m);
441 return 0;
442}
443
444// Condition Variable
445int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
446{
447 WakeConditionVariable(__cv);
448 return 0;
449}
450
451int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
452{
453 WakeAllConditionVariable(__cv);
454 return 0;
455}
456
457int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
458{
459 SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
460 return 0;
461}
462
463int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
464 timespec *__ts)
465{
466 using namespace _VSTD::chrono;
467
468 auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
469 auto abstime =
470 system_clock::time_point(duration_cast<system_clock::duration>(duration));
471 auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
472
473 if (!SleepConditionVariableSRW(__cv, __m,
474 timeout_ms.count() > 0 ? timeout_ms.count()
475 : 0,
476 0))
477 return GetLastError();
478 return 0;
479}
480
481int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
482{
483 static_cast<void>(__cv);
484 return 0;
485}
486
487// Execute Once
488static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
489__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
490 PVOID *__context)
491{
492 static_cast<void>(__init_once);
493 static_cast<void>(__context);
494
495 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
496 init_routine();
497 return TRUE;
498}
499
500int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
501 void (*__init_routine)(void))
502{
503 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
504 reinterpret_cast<void *>(__init_routine), NULL))
505 return GetLastError();
506 return 0;
507}
508
509// Thread ID
510bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
511 __libcpp_thread_id __rhs)
512{
513 return __lhs == __rhs;
514}
515
516bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
517{
518 return __lhs < __rhs;
519}
520
521// Thread
522struct __libcpp_beginthreadex_thunk_data
523{
524 void *(*__func)(void *);
525 void *__arg;
526};
527
Eric Fiselier543e83b2017-01-14 20:19:00 +0000528static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI
Eric Fiselier433a3972017-01-14 19:11:07 +0000529__libcpp_beginthreadex_thunk(void *__raw_data)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000530{
Eric Fiselier433a3972017-01-14 19:11:07 +0000531 auto *__data =
532 static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data);
533 auto *__func = __data->__func;
534 void *__arg = __data->__arg;
535 delete __data;
Eric Fiselier543e83b2017-01-14 20:19:00 +0000536 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg)));
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000537}
538
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +0000539bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
540 return *__t == 0;
541}
542
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000543int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
544 void *__arg)
545{
Eric Fiselier433a3972017-01-14 19:11:07 +0000546 auto *__data = new __libcpp_beginthreadex_thunk_data;
547 __data->__func = __func;
548 __data->__arg = __arg;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000549
Eric Fiselier543e83b2017-01-14 20:19:00 +0000550 *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
551 __libcpp_beginthreadex_thunk,
552 __data, 0, nullptr));
553
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000554 if (*__t)
555 return 0;
556 return GetLastError();
557}
558
559__libcpp_thread_id __libcpp_thread_get_current_id()
560{
561 return GetCurrentThreadId();
562}
563
564__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
565{
566 return GetThreadId(*__t);
567}
568
569int __libcpp_thread_join(__libcpp_thread_t *__t)
570{
571 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
572 return GetLastError();
573 if (!CloseHandle(*__t))
574 return GetLastError();
575 return 0;
576}
577
578int __libcpp_thread_detach(__libcpp_thread_t *__t)
579{
580 if (!CloseHandle(*__t))
581 return GetLastError();
582 return 0;
583}
584
585void __libcpp_thread_yield()
586{
587 SwitchToThread();
588}
589
Asiri Rathnayake1b939612017-02-09 09:31:41 +0000590void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
591{
592 using namespace chrono;
593 // round-up to the nearest milisecond
594 milliseconds __ms = duration_cast<milliseconds>(__ns + 999999);
595 Sleep(__ms.count());
596}
597
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000598// Thread Local Storage
599int __libcpp_tls_create(__libcpp_tls_key* __key,
600 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
601{
602 *__key = FlsAlloc(__at_exit);
603 if (*__key == FLS_OUT_OF_INDEXES)
604 return GetLastError();
605 return 0;
606}
607
608void *__libcpp_tls_get(__libcpp_tls_key __key)
609{
610 return FlsGetValue(__key);
611}
612
613int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
614{
615 if (!FlsSetValue(__key, __p))
616 return GetLastError();
617 return 0;
618}
619
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000620#endif // _LIBCPP_HAS_THREAD_API_PTHREAD
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000621
Eric Fiselier66134e82017-01-06 20:05:40 +0000622#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
623
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000624_LIBCPP_END_NAMESPACE_STD
625
Eric Fiselier66134e82017-01-06 20:05:40 +0000626#endif // !_LIBCPP_HAS_NO_THREADS
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000627
628#endif // _LIBCPP_THREADING_SUPPORT