• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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#include <chrono>
16#include <errno.h>
17
18#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
19#pragma GCC system_header
20#endif
21
22#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
23# 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>
29#endif
30
31_LIBCPP_PUSH_MACROS
32#include <__undef_macros>
33
34#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
35    defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \
36    defined(_LIBCPP_HAS_THREAD_API_WIN32)
37#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
38#else
39#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
40#endif
41
42#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
48_LIBCPP_BEGIN_NAMESPACE_STD
49
50#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
51// Mutex
52typedef pthread_mutex_t __libcpp_mutex_t;
53#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
54
55typedef pthread_mutex_t __libcpp_recursive_mutex_t;
56
57// Condition Variable
58typedef pthread_cond_t __libcpp_condvar_t;
59#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
60
61// Execute once
62typedef pthread_once_t __libcpp_exec_once_flag;
63#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
64
65// Thread id
66typedef pthread_t __libcpp_thread_id;
67
68// Thread
69#define _LIBCPP_NULL_THREAD 0U
70
71typedef pthread_t __libcpp_thread_t;
72
73// Thread Local Storage
74typedef pthread_key_t __libcpp_tls_key;
75
76#define _LIBCPP_TLS_DESTRUCTOR_CC
77#else
78// Mutex
79typedef void* __libcpp_mutex_t;
80#define _LIBCPP_MUTEX_INITIALIZER 0
81
82#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
83typedef void* __libcpp_recursive_mutex_t[6];
84#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
85typedef void* __libcpp_recursive_mutex_t[5];
86#else
87# error Unsupported architecture
88#endif
89
90// Condition Variable
91typedef void* __libcpp_condvar_t;
92#define _LIBCPP_CONDVAR_INITIALIZER 0
93
94// Execute Once
95typedef void* __libcpp_exec_once_flag;
96#define _LIBCPP_EXEC_ONCE_INITIALIZER 0
97
98// Thread ID
99typedef long __libcpp_thread_id;
100
101// Thread
102#define _LIBCPP_NULL_THREAD 0U
103
104typedef void* __libcpp_thread_t;
105
106// Thread Local Storage
107typedef long __libcpp_tls_key;
108
109#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
110#endif
111
112// Mutex
113_LIBCPP_THREAD_ABI_VISIBILITY
114int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
115
116_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
117int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
118
119_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
120bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
121
122_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
123int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
124
125_LIBCPP_THREAD_ABI_VISIBILITY
126int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
127
128_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
129int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
130
131_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
132bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
133
134_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
135int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
136
137_LIBCPP_THREAD_ABI_VISIBILITY
138int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
139
140// Condition variable
141_LIBCPP_THREAD_ABI_VISIBILITY
142int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
143
144_LIBCPP_THREAD_ABI_VISIBILITY
145int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
146
147_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
148int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
149
150_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
151int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
152                               timespec *__ts);
153
154_LIBCPP_THREAD_ABI_VISIBILITY
155int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
156
157// Execute once
158_LIBCPP_THREAD_ABI_VISIBILITY
159int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
160                          void (*init_routine)(void));
161
162// Thread id
163_LIBCPP_THREAD_ABI_VISIBILITY
164bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
165
166_LIBCPP_THREAD_ABI_VISIBILITY
167bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
168
169// Thread
170_LIBCPP_THREAD_ABI_VISIBILITY
171bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
172
173_LIBCPP_THREAD_ABI_VISIBILITY
174int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
175                           void *__arg);
176
177_LIBCPP_THREAD_ABI_VISIBILITY
178__libcpp_thread_id __libcpp_thread_get_current_id();
179
180_LIBCPP_THREAD_ABI_VISIBILITY
181__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
182
183_LIBCPP_THREAD_ABI_VISIBILITY
184int __libcpp_thread_join(__libcpp_thread_t *__t);
185
186_LIBCPP_THREAD_ABI_VISIBILITY
187int __libcpp_thread_detach(__libcpp_thread_t *__t);
188
189_LIBCPP_THREAD_ABI_VISIBILITY
190void __libcpp_thread_yield();
191
192_LIBCPP_THREAD_ABI_VISIBILITY
193void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
194
195// Thread local storage
196_LIBCPP_THREAD_ABI_VISIBILITY
197int __libcpp_tls_create(__libcpp_tls_key* __key,
198                        void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
199
200_LIBCPP_THREAD_ABI_VISIBILITY
201void *__libcpp_tls_get(__libcpp_tls_key __key);
202
203_LIBCPP_THREAD_ABI_VISIBILITY
204int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
205
206#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
207     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \
208    defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
209
210int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
211{
212  pthread_mutexattr_t attr;
213  int __ec = pthread_mutexattr_init(&attr);
214  if (__ec)
215    return __ec;
216  __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
217  if (__ec) {
218    pthread_mutexattr_destroy(&attr);
219    return __ec;
220  }
221  __ec = pthread_mutex_init(__m, &attr);
222  if (__ec) {
223    pthread_mutexattr_destroy(&attr);
224    return __ec;
225  }
226  __ec = pthread_mutexattr_destroy(&attr);
227  if (__ec) {
228    pthread_mutex_destroy(__m);
229    return __ec;
230  }
231  return 0;
232}
233
234int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
235{
236  return pthread_mutex_lock(__m);
237}
238
239bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
240{
241  return pthread_mutex_trylock(__m) == 0;
242}
243
244int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
245{
246  return pthread_mutex_unlock(__m);
247}
248
249int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
250{
251  return pthread_mutex_destroy(__m);
252}
253
254int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
255{
256  return pthread_mutex_lock(__m);
257}
258
259bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
260{
261  return pthread_mutex_trylock(__m) == 0;
262}
263
264int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
265{
266  return pthread_mutex_unlock(__m);
267}
268
269int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
270{
271  return pthread_mutex_destroy(__m);
272}
273
274// Condition Variable
275int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
276{
277  return pthread_cond_signal(__cv);
278}
279
280int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
281{
282  return pthread_cond_broadcast(__cv);
283}
284
285int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
286{
287  return pthread_cond_wait(__cv, __m);
288}
289
290int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
291                               timespec *__ts)
292{
293  return pthread_cond_timedwait(__cv, __m, __ts);
294}
295
296int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
297{
298  return pthread_cond_destroy(__cv);
299}
300
301// Execute once
302int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
303                          void (*init_routine)(void)) {
304  return pthread_once(flag, init_routine);
305}
306
307// Thread id
308// Returns non-zero if the thread ids are equal, otherwise 0
309bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
310{
311  return pthread_equal(t1, t2) != 0;
312}
313
314// Returns non-zero if t1 < t2, otherwise 0
315bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
316{
317  return t1 < t2;
318}
319
320// Thread
321bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
322  return *__t == 0;
323}
324
325int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
326                           void *__arg)
327{
328  return pthread_create(__t, 0, __func, __arg);
329}
330
331__libcpp_thread_id __libcpp_thread_get_current_id()
332{
333  return pthread_self();
334}
335
336__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
337{
338  return *__t;
339}
340
341int __libcpp_thread_join(__libcpp_thread_t *__t)
342{
343  return pthread_join(*__t, 0);
344}
345
346int __libcpp_thread_detach(__libcpp_thread_t *__t)
347{
348  return pthread_detach(*__t);
349}
350
351void __libcpp_thread_yield()
352{
353  sched_yield();
354}
355
356void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
357{
358   using namespace chrono;
359   seconds __s = duration_cast<seconds>(__ns);
360   timespec __ts;
361   typedef decltype(__ts.tv_sec) ts_sec;
362   _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max();
363
364   if (__s.count() < __ts_sec_max)
365   {
366     __ts.tv_sec = static_cast<ts_sec>(__s.count());
367     __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
368   }
369   else
370   {
371     __ts.tv_sec = __ts_sec_max;
372     __ts.tv_nsec = 999999999; // (10^9 - 1)
373   }
374
375   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
376}
377
378// Thread local storage
379int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
380{
381  return pthread_key_create(__key, __at_exit);
382}
383
384void *__libcpp_tls_get(__libcpp_tls_key __key)
385{
386  return pthread_getspecific(__key);
387}
388
389int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
390{
391    return pthread_setspecific(__key, __p);
392}
393
394#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
395
396_LIBCPP_END_NAMESPACE_STD
397
398_LIBCPP_POP_MACROS
399
400#endif // !_LIBCPP_HAS_NO_THREADS
401
402#endif // _LIBCPP_THREADING_SUPPORT
403