blob: b1eaf25ae8a4318071d6f1660fc382eb9c7d970b [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
20#ifndef _LIBCPP_HAS_NO_THREADS
21
Asiri Rathnayake4f2c83f2016-10-14 13:56:58 +000022#ifndef __libcpp_has_include
23 #ifndef __has_include
24 #define __libcpp_has_include(x) 0
25 #else
26 #define __libcpp_has_include(x) __has_include(x)
27 #endif
Asiri Rathnayakef6600b72016-09-13 09:32:32 +000028#endif
29
Asiri Rathnayake4f2c83f2016-10-14 13:56:58 +000030#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) && \
Asiri Rathnayakee29d9ff2017-01-03 11:32:31 +000031 !__libcpp_has_include(<__external_threading>)
32// If the <__external_threading> header is absent, build libc++ against a
33// pthread-oriented thread api but leave out its implementation. This setup
34// allows building+testing of an externally-threaded library variant (on any
35// platform that supports pthreads). Here, an 'externally-threaded' library
36// variant is one where the implementation of the libc++ thread api is provided
37// as a separate library.
38#define _LIBCPP_HAS_THREAD_API_EXTERNAL_PTHREAD
39#endif
40
41#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) && \
Asiri Rathnayake4f2c83f2016-10-14 13:56:58 +000042 __libcpp_has_include(<__external_threading>)
43#include <__external_threading>
44#else
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000045
Asiri Rathnayakee29d9ff2017-01-03 11:32:31 +000046#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) || \
47 defined(_LIBCPP_HAS_THREAD_API_EXTERNAL_PTHREAD)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000048#include <pthread.h>
49#include <sched.h>
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000050#endif
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000051
Asiri Rathnayake040945b2016-09-11 21:46:40 +000052#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
53#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
54#else
55#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
56#endif
57
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000058_LIBCPP_BEGIN_NAMESPACE_STD
59
Asiri Rathnayakee29d9ff2017-01-03 11:32:31 +000060#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) || \
61 defined(_LIBCPP_HAS_THREAD_API_EXTERNAL_PTHREAD)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000062// Mutex
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000063typedef pthread_mutex_t __libcpp_mutex_t;
Asiri Rathnayake040945b2016-09-11 21:46:40 +000064#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +000065
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000066// Condition Variable
Asiri Rathnayake040945b2016-09-11 21:46:40 +000067typedef pthread_cond_t __libcpp_condvar_t;
68#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000069
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +000070// Execute once
71typedef pthread_once_t __libcpp_exec_once_flag;
72#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
73
74// Thread id
Saleem Abdulrasool1d192372017-01-03 02:00:31 +000075typedef pthread_t __libcpp_thread_id;
76
77// Thread
78typedef pthread_t __libcpp_thread_t;
79
80// Thrad Local Storage
81typedef pthread_key_t __libcpp_tls_key;
82#endif
83
84// Mutex
85_LIBCPP_THREAD_ABI_VISIBILITY
86int __libcpp_recursive_mutex_init(__libcpp_mutex_t *__m);
87
88_LIBCPP_THREAD_ABI_VISIBILITY
89int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
90
91_LIBCPP_THREAD_ABI_VISIBILITY
92int __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
93
94_LIBCPP_THREAD_ABI_VISIBILITY
95int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
96
97_LIBCPP_THREAD_ABI_VISIBILITY
98int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
99
100// Condition variable
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000101_LIBCPP_THREAD_ABI_VISIBILITY
102int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000103
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000104_LIBCPP_THREAD_ABI_VISIBILITY
105int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000106
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000107_LIBCPP_THREAD_ABI_VISIBILITY
108int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000109
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000110_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000111int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
112 timespec *__ts);
113
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000114_LIBCPP_THREAD_ABI_VISIBILITY
115int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
116
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000117// Execute once
118_LIBCPP_THREAD_ABI_VISIBILITY
119int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
120 void (*init_routine)(void));
121
122// Thread id
123#if defined(__APPLE__) && !defined(__arm__)
124_LIBCPP_THREAD_ABI_VISIBILITY
125mach_port_t __libcpp_thread_get_port();
126#endif
127
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000128_LIBCPP_THREAD_ABI_VISIBILITY
129bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000130
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000131_LIBCPP_THREAD_ABI_VISIBILITY
132bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
133
134// Thread
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000135_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000136int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
137 void *__arg);
138
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000139_LIBCPP_THREAD_ABI_VISIBILITY
140__libcpp_thread_id __libcpp_thread_get_current_id();
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000141
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000142_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000143__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
144
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000145_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000146int __libcpp_thread_join(__libcpp_thread_t *__t);
147
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000148_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000149int __libcpp_thread_detach(__libcpp_thread_t *__t);
150
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000151_LIBCPP_THREAD_ABI_VISIBILITY
152void __libcpp_thread_yield();
153
154// Thread local storage
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000155_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000156int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *));
157
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000158_LIBCPP_THREAD_ABI_VISIBILITY
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000159void *__libcpp_tls_get(__libcpp_tls_key __key);
160
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000161_LIBCPP_THREAD_ABI_VISIBILITY
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000162int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000163
Asiri Rathnayakee29d9ff2017-01-03 11:32:31 +0000164#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) || \
165 defined(_LIBCPP_BUILDING_THREAD_API_EXTERNAL_PTHREAD)
Asiri Rathnayake040945b2016-09-11 21:46:40 +0000166
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000167int __libcpp_recursive_mutex_init(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000168{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000169 pthread_mutexattr_t attr;
170 int __ec = pthread_mutexattr_init(&attr);
171 if (__ec)
172 return __ec;
173 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
174 if (__ec) {
175 pthread_mutexattr_destroy(&attr);
176 return __ec;
177 }
178 __ec = pthread_mutex_init(__m, &attr);
179 if (__ec) {
180 pthread_mutexattr_destroy(&attr);
181 return __ec;
182 }
183 __ec = pthread_mutexattr_destroy(&attr);
184 if (__ec) {
185 pthread_mutex_destroy(__m);
186 return __ec;
187 }
188 return 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000189}
190
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000191int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000192{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000193 return pthread_mutex_lock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000194}
195
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000196int __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000197{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000198 return pthread_mutex_trylock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000199}
200
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000201int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000202{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000203 return pthread_mutex_unlock(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000204}
205
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000206int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000207{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000208 return pthread_mutex_destroy(__m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000209}
210
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000211// Condition Variable
212int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000213{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000214 return pthread_cond_signal(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000215}
216
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000217int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000218{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000219 return pthread_cond_broadcast(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000220}
221
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000222int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000223{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000224 return pthread_cond_wait(__cv, __m);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000225}
226
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000227int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
228 timespec *__ts)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000229{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000230 return pthread_cond_timedwait(__cv, __m, __ts);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000231}
232
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000233int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000234{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000235 return pthread_cond_destroy(__cv);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000236}
237
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000238// Execute once
239int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
240 void (*init_routine)(void)) {
241 return pthread_once(flag, init_routine);
242}
243
244// Thread id
245#if defined(__APPLE__) && !defined(__arm__)
246mach_port_t __libcpp_thread_get_port() {
247 return pthread_mach_thread_np(pthread_self());
248}
249#endif
250
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000251// Returns non-zero if the thread ids are equal, otherwise 0
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000252bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
253{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000254 return pthread_equal(t1, t2) != 0;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000255}
256
257// Returns non-zero if t1 < t2, otherwise 0
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000258bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
259{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000260 return t1 < t2;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000261}
262
263// Thread
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000264int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
265 void *__arg)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000266{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000267 return pthread_create(__t, 0, __func, __arg);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000268}
269
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000270__libcpp_thread_id __libcpp_thread_get_current_id()
271{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000272 return pthread_self();
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000273}
274
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000275__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000276{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000277 return *__t;
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000278}
279
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000280int __libcpp_thread_join(__libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000281{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000282 return pthread_join(*__t, 0);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000283}
284
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000285int __libcpp_thread_detach(__libcpp_thread_t *__t)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000286{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000287 return pthread_detach(*__t);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000288}
289
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000290void __libcpp_thread_yield()
291{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000292 sched_yield();
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000293}
294
295// Thread local storage
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000296int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000297{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000298 return pthread_key_create(__key, __at_exit);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000299}
300
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000301void *__libcpp_tls_get(__libcpp_tls_key __key)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000302{
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000303 return pthread_getspecific(__key);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000304}
305
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000306int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000307{
Asiri Rathnayakee262e7b2017-01-03 12:59:50 +0000308 return pthread_setspecific(__key, __p);
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000309}
310
Saleem Abdulrasool1d192372017-01-03 02:00:31 +0000311#endif // _LIBCPP_HAS_THREAD_API_PTHREAD
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000312
313_LIBCPP_END_NAMESPACE_STD
314
Asiri Rathnayake4f2c83f2016-10-14 13:56:58 +0000315#endif // !_LIBCPP_HAS_THREAD_API_EXTERNAL || !__libcpp_has_include(<__external_threading>)
Asiri Rathnayake7250d332016-10-14 13:00:07 +0000316
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000317#endif // _LIBCPP_HAS_NO_THREADS
318
319#endif // _LIBCPP_THREADING_SUPPORT