blob: 53a956ed9809e943af08a346b9eb7bea52bac6c0 [file] [log] [blame]
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +00001// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// The LLVM Compiler Infrastructure
5//
6// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_THREADING_SUPPORT
12#define _LIBCPP_THREADING_SUPPORT
13
14#include <__config>
15
16#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
17#pragma GCC system_header
18#endif
19
Asiri Rathnayake040945b2016-09-11 21:46:40 +000020#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
Eric Fiselier66134e82017-01-06 20:05:40 +000021# include <__external_threading>
22#elif !defined(_LIBCPP_HAS_NO_THREADS)
23
24#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
25# include <pthread.h>
26# include <sched.h>
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +000027#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +000028#include <Windows.h>
29#include <process.h>
30#include <fibersapi.h>
31
32#include <chrono>
Eric Fiselier66134e82017-01-06 20:05:40 +000033#endif
34
35#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
36 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
Asiri Rathnayake040945b2016-09-11 21:46:40 +000037#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
38#else
39#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
40#endif
41
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
186// Thread local storage
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000187_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000188int __libcpp_tls_create(__libcpp_tls_key* __key,
189 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000190
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000191_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000192void *__libcpp_tls_get(__libcpp_tls_key __key);
193
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000194_LIBCPP_THREAD_ABI_VISIBILITY
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000195int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000196
Eric Fiselier66134e82017-01-06 20:05:40 +0000197#if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
198 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
199
200#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000201
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000202int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000203{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000204 pthread_mutexattr_t attr;
205 int __ec = pthread_mutexattr_init(&attr);
206 if (__ec)
207 return __ec;
208 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
209 if (__ec) {
210 pthread_mutexattr_destroy(&attr);
211 return __ec;
212 }
213 __ec = pthread_mutex_init(__m, &attr);
214 if (__ec) {
215 pthread_mutexattr_destroy(&attr);
216 return __ec;
217 }
218 __ec = pthread_mutexattr_destroy(&attr);
219 if (__ec) {
220 pthread_mutex_destroy(__m);
221 return __ec;
222 }
223 return 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000224}
225
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000226int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
227{
228 return pthread_mutex_lock(__m);
229}
230
Eric Fiselier30d12e32017-01-14 10:27:12 +0000231bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000232{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000233 return pthread_mutex_trylock(__m) == 0;
Saleem Abdulrasool3451a652017-01-05 17:54:45 +0000234}
235
236int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
237{
238 return pthread_mutex_unlock(__m);
239}
240
241int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
242{
243 return pthread_mutex_destroy(__m);
244}
245
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000246int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000247{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000248 return pthread_mutex_lock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000249}
250
Eric Fiselier30d12e32017-01-14 10:27:12 +0000251bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000252{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000253 return pthread_mutex_trylock(__m) == 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000254}
255
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000256int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000257{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000258 return pthread_mutex_unlock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000259}
260
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000261int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000262{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000263 return pthread_mutex_destroy(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000264}
265
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000266// Condition Variable
267int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000268{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000269 return pthread_cond_signal(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000270}
271
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000272int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000273{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000274 return pthread_cond_broadcast(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000275}
276
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000277int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000278{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000279 return pthread_cond_wait(__cv, __m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000280}
281
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000282int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
283 timespec *__ts)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000284{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000285 return pthread_cond_timedwait(__cv, __m, __ts);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000286}
287
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000288int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000289{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000290 return pthread_cond_destroy(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000291}
292
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000293// Execute once
294int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
295 void (*init_routine)(void)) {
296 return pthread_once(flag, init_routine);
297}
298
299// Thread id
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000300// Returns non-zero if the thread ids are equal, otherwise 0
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000301bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
302{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000303 return pthread_equal(t1, t2) != 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000304}
305
306// Returns non-zero if t1 < t2, otherwise 0
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000307bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
308{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000309 return t1 < t2;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000310}
311
312// Thread
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +0000313bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
314 return *__t == 0;
315}
316
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000317int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
318 void *__arg)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000319{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000320 return pthread_create(__t, 0, __func, __arg);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000321}
322
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000323__libcpp_thread_id __libcpp_thread_get_current_id()
324{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000325 return pthread_self();
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000326}
327
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000328__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000329{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000330 return *__t;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000331}
332
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000333int __libcpp_thread_join(__libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000334{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000335 return pthread_join(*__t, 0);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000336}
337
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000338int __libcpp_thread_detach(__libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000339{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000340 return pthread_detach(*__t);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000341}
342
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000343void __libcpp_thread_yield()
344{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000345 sched_yield();
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000346}
347
348// Thread local storage
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000349int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000350{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000351 return pthread_key_create(__key, __at_exit);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000352}
353
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000354void *__libcpp_tls_get(__libcpp_tls_key __key)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000355{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000356 return pthread_getspecific(__key);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000357}
358
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000359int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000360{
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000361 return pthread_setspecific(__key, __p);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000362}
363
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000364#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
365
366// Mutex
367int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
368{
369 InitializeCriticalSection(__m);
370 return 0;
371}
372
373int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
374{
375 EnterCriticalSection(__m);
376 return 0;
377}
378
Eric Fiselier30d12e32017-01-14 10:27:12 +0000379bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000380{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000381 return TryEnterCriticalSection(__m) != 0;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000382}
383
384int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
385{
386 LeaveCriticalSection(__m);
387 return 0;
388}
389
390int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
391{
Saleem Abdulrasool1d324082017-01-10 04:18:47 +0000392 DeleteCriticalSection(__m);
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000393 return 0;
394}
395
396int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
397{
398 AcquireSRWLockExclusive(__m);
399 return 0;
400}
401
Eric Fiselier30d12e32017-01-14 10:27:12 +0000402bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000403{
Eric Fiselier30d12e32017-01-14 10:27:12 +0000404 return TryAcquireSRWLockExclusive(__m) != 0;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000405}
406
407int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
408{
409 ReleaseSRWLockExclusive(__m);
410 return 0;
411}
412
413int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
414{
415 static_cast<void>(__m);
416 return 0;
417}
418
419// Condition Variable
420int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
421{
422 WakeConditionVariable(__cv);
423 return 0;
424}
425
426int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
427{
428 WakeAllConditionVariable(__cv);
429 return 0;
430}
431
432int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
433{
434 SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
435 return 0;
436}
437
438int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
439 timespec *__ts)
440{
441 using namespace _VSTD::chrono;
442
443 auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
444 auto abstime =
445 system_clock::time_point(duration_cast<system_clock::duration>(duration));
446 auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
447
448 if (!SleepConditionVariableSRW(__cv, __m,
449 timeout_ms.count() > 0 ? timeout_ms.count()
450 : 0,
451 0))
452 return GetLastError();
453 return 0;
454}
455
456int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
457{
458 static_cast<void>(__cv);
459 return 0;
460}
461
462// Execute Once
463static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
464__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
465 PVOID *__context)
466{
467 static_cast<void>(__init_once);
468 static_cast<void>(__context);
469
470 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
471 init_routine();
472 return TRUE;
473}
474
475int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
476 void (*__init_routine)(void))
477{
478 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
479 reinterpret_cast<void *>(__init_routine), NULL))
480 return GetLastError();
481 return 0;
482}
483
484// Thread ID
485bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
486 __libcpp_thread_id __rhs)
487{
488 return __lhs == __rhs;
489}
490
491bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
492{
493 return __lhs < __rhs;
494}
495
496// Thread
497struct __libcpp_beginthreadex_thunk_data
498{
499 void *(*__func)(void *);
500 void *__arg;
501};
502
Eric Fiselier543e83b2017-01-14 20:19:00 +0000503static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI
Eric Fiselier433a3972017-01-14 19:11:07 +0000504__libcpp_beginthreadex_thunk(void *__raw_data)
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000505{
Eric Fiselier433a3972017-01-14 19:11:07 +0000506 auto *__data =
507 static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data);
508 auto *__func = __data->__func;
509 void *__arg = __data->__arg;
510 delete __data;
Eric Fiselier543e83b2017-01-14 20:19:00 +0000511 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg)));
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000512}
513
Asiri Rathnayakea1d7d2f2017-01-16 12:19:54 +0000514bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
515 return *__t == 0;
516}
517
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000518int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
519 void *__arg)
520{
Eric Fiselier433a3972017-01-14 19:11:07 +0000521 auto *__data = new __libcpp_beginthreadex_thunk_data;
522 __data->__func = __func;
523 __data->__arg = __arg;
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000524
Eric Fiselier543e83b2017-01-14 20:19:00 +0000525 *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
526 __libcpp_beginthreadex_thunk,
527 __data, 0, nullptr));
528
Saleem Abdulrasool678eadd2017-01-07 03:07:45 +0000529 if (*__t)
530 return 0;
531 return GetLastError();
532}
533
534__libcpp_thread_id __libcpp_thread_get_current_id()
535{
536 return GetCurrentThreadId();
537}
538
539__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
540{
541 return GetThreadId(*__t);
542}
543
544int __libcpp_thread_join(__libcpp_thread_t *__t)
545{
546 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
547 return GetLastError();
548 if (!CloseHandle(*__t))
549 return GetLastError();
550 return 0;
551}
552
553int __libcpp_thread_detach(__libcpp_thread_t *__t)
554{
555 if (!CloseHandle(*__t))
556 return GetLastError();
557 return 0;
558}
559
560void __libcpp_thread_yield()
561{
562 SwitchToThread();
563}
564
565// Thread Local Storage
566int __libcpp_tls_create(__libcpp_tls_key* __key,
567 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
568{
569 *__key = FlsAlloc(__at_exit);
570 if (*__key == FLS_OUT_OF_INDEXES)
571 return GetLastError();
572 return 0;
573}
574
575void *__libcpp_tls_get(__libcpp_tls_key __key)
576{
577 return FlsGetValue(__key);
578}
579
580int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
581{
582 if (!FlsSetValue(__key, __p))
583 return GetLastError();
584 return 0;
585}
586
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000587#endif // _LIBCPP_HAS_THREAD_API_PTHREAD
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000588
Eric Fiselier66134e82017-01-06 20:05:40 +0000589#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
590
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000591_LIBCPP_END_NAMESPACE_STD
592
Eric Fiselier66134e82017-01-06 20:05:40 +0000593#endif // !_LIBCPP_HAS_NO_THREADS
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000594
595#endif // _LIBCPP_THREADING_SUPPORT