1// -*- 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
22// These checks are carefully arranged so as not to trigger a gcc pre-processor
23// defect which causes it to fail to parse the __has_include check below, the
24// redundancy is intentional.
25#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
26#if !defined(__clang__) && (_GNUC_VER < 500)
27#include <__external_threading>
28#define _LIBCPP_EXTERNAL_THREADING
29#elif !defined(__has_include) || __has_include(<__external_threading>)
30#include <__external_threading>
31#define _LIBCPP_EXTERNAL_THREADING
32#endif
33#endif
34
35#if !defined(_LIBCPP_EXTERNAL_THREADING)
36#include <pthread.h>
37#include <sched.h>
38#endif
39
40#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
41#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
42#else
43#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
44#endif
45
46_LIBCPP_BEGIN_NAMESPACE_STD
47
48// Mutex
49typedef pthread_mutex_t __libcpp_mutex_t;
50#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
51
52_LIBCPP_THREAD_ABI_VISIBILITY
53int __libcpp_recursive_mutex_init(__libcpp_mutex_t* __m);
54_LIBCPP_THREAD_ABI_VISIBILITY
55int __libcpp_mutex_lock(__libcpp_mutex_t* __m);
56_LIBCPP_THREAD_ABI_VISIBILITY
57int __libcpp_mutex_trylock(__libcpp_mutex_t* __m);
58_LIBCPP_THREAD_ABI_VISIBILITY
59int __libcpp_mutex_unlock(__libcpp_mutex_t* __m);
60_LIBCPP_THREAD_ABI_VISIBILITY
61int __libcpp_mutex_destroy(__libcpp_mutex_t* __m);
62
63// Condition variable
64typedef pthread_cond_t __libcpp_condvar_t;
65#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
66_LIBCPP_THREAD_ABI_VISIBILITY
67int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
68_LIBCPP_THREAD_ABI_VISIBILITY
69int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
70_LIBCPP_THREAD_ABI_VISIBILITY
71int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
72_LIBCPP_THREAD_ABI_VISIBILITY
73int __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts);
74_LIBCPP_THREAD_ABI_VISIBILITY
75int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
76
77// Thread id
78typedef pthread_t __libcpp_thread_id;
79_LIBCPP_THREAD_ABI_VISIBILITY
80bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
81_LIBCPP_THREAD_ABI_VISIBILITY
82bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
83
84// Thread
85typedef pthread_t __libcpp_thread_t;
86_LIBCPP_THREAD_ABI_VISIBILITY
87int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg);
88_LIBCPP_THREAD_ABI_VISIBILITY
89__libcpp_thread_id __libcpp_thread_get_current_id();
90_LIBCPP_THREAD_ABI_VISIBILITY
91__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t);
92_LIBCPP_THREAD_ABI_VISIBILITY
93int __libcpp_thread_join(__libcpp_thread_t* __t);
94_LIBCPP_THREAD_ABI_VISIBILITY
95int __libcpp_thread_detach(__libcpp_thread_t* __t);
96_LIBCPP_THREAD_ABI_VISIBILITY
97void __libcpp_thread_yield();
98
99// Thread local storage
100typedef pthread_key_t __libcpp_tls_key;
101_LIBCPP_THREAD_ABI_VISIBILITY
102int __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*));
103_LIBCPP_THREAD_ABI_VISIBILITY
104void* __libcpp_tls_get(__libcpp_tls_key __key);
105_LIBCPP_THREAD_ABI_VISIBILITY
106void __libcpp_tls_set(__libcpp_tls_key __key, void* __p);
107
108#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) || defined(_LIBCPP_BUILDING_EXTERNAL_THREADS)
109
110int __libcpp_recursive_mutex_init(__libcpp_mutex_t* __m)
111{
112    pthread_mutexattr_t attr;
113    int __ec = pthread_mutexattr_init(&attr);
114    if (__ec) return __ec;
115    __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
116    if (__ec)
117    {
118        pthread_mutexattr_destroy(&attr);
119        return __ec;
120    }
121    __ec = pthread_mutex_init(__m, &attr);
122    if (__ec)
123    {
124        pthread_mutexattr_destroy(&attr);
125        return __ec;
126    }
127    __ec = pthread_mutexattr_destroy(&attr);
128    if (__ec)
129    {
130        pthread_mutex_destroy(__m);
131        return __ec;
132    }
133    return 0;
134}
135
136int __libcpp_mutex_lock(__libcpp_mutex_t* __m)
137{
138    return pthread_mutex_lock(__m);
139}
140
141int __libcpp_mutex_trylock(__libcpp_mutex_t* __m)
142{
143    return pthread_mutex_trylock(__m);
144}
145
146int __libcpp_mutex_unlock(__libcpp_mutex_t* __m)
147{
148    return pthread_mutex_unlock(__m);
149}
150
151int __libcpp_mutex_destroy(__libcpp_mutex_t* __m)
152{
153    return pthread_mutex_destroy(__m);
154}
155
156// Condition variable
157int __libcpp_condvar_signal(__libcpp_condvar_t* __cv)
158{
159    return pthread_cond_signal(__cv);
160}
161
162int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv)
163{
164    return pthread_cond_broadcast(__cv);
165}
166
167int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m)
168{
169    return pthread_cond_wait(__cv, __m);
170}
171
172int __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts)
173{
174    return pthread_cond_timedwait(__cv, __m, __ts);
175}
176
177int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv)
178{
179    return pthread_cond_destroy(__cv);
180}
181
182// Returns non-zero if the thread ids are equal, otherwise 0
183bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
184{
185    return pthread_equal(t1, t2) != 0;
186}
187
188// Returns non-zero if t1 < t2, otherwise 0
189bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
190{
191    return t1 < t2;
192}
193
194// Thread
195int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg)
196{
197    return pthread_create(__t, 0, __func, __arg);
198}
199
200__libcpp_thread_id __libcpp_thread_get_current_id()
201{
202    return pthread_self();
203}
204
205__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t)
206{
207    return *__t;
208}
209
210int __libcpp_thread_join(__libcpp_thread_t* __t)
211{
212    return pthread_join(*__t, 0);
213}
214
215int __libcpp_thread_detach(__libcpp_thread_t* __t)
216{
217    return pthread_detach(*__t);
218}
219
220void __libcpp_thread_yield()
221{
222    sched_yield();
223}
224
225// Thread local storage
226int __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*))
227{
228    return pthread_key_create(__key, __at_exit);
229}
230
231void* __libcpp_tls_get(__libcpp_tls_key __key)
232{
233    return pthread_getspecific(__key);
234}
235
236void __libcpp_tls_set(__libcpp_tls_key __key, void* __p)
237{
238    pthread_setspecific(__key, __p);
239}
240
241#endif // _LIBCPP_HAS_THREAD_API_PTHREAD || _LIBCPP_BUILDING_EXTERNAL_THREADS
242
243_LIBCPP_END_NAMESPACE_STD
244
245#endif // _LIBCPP_HAS_NO_THREADS
246
247#endif // _LIBCPP_THREADING_SUPPORT
248