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 <iosfwd>
17#include <errno.h>
18
19#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
20#pragma GCC system_header
21#endif
22
23#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
24# include <__external_threading>
25#elif !defined(_LIBCPP_HAS_NO_THREADS)
26
27#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
28# include <pthread.h>
29# include <sched.h>
30#endif
31
32_LIBCPP_PUSH_MACROS
33#include <__undef_macros>
34
35#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
36    defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \
37    defined(_LIBCPP_HAS_THREAD_API_WIN32)
38#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
39#else
40#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
41#endif
42
43#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
44#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
45#else
46#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
47#endif
48
49_LIBCPP_BEGIN_NAMESPACE_STD
50
51#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
52// Mutex
53typedef pthread_mutex_t __libcpp_mutex_t;
54#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
55
56typedef pthread_mutex_t __libcpp_recursive_mutex_t;
57
58// Condition Variable
59typedef pthread_cond_t __libcpp_condvar_t;
60#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
61
62// Execute once
63typedef pthread_once_t __libcpp_exec_once_flag;
64#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
65
66// Thread id
67typedef pthread_t __libcpp_thread_id;
68
69// Thread
70#define _LIBCPP_NULL_THREAD 0U
71
72typedef pthread_t __libcpp_thread_t;
73
74// Thread Local Storage
75typedef pthread_key_t __libcpp_tls_key;
76
77#define _LIBCPP_TLS_DESTRUCTOR_CC
78#else
79// Mutex
80typedef void* __libcpp_mutex_t;
81#define _LIBCPP_MUTEX_INITIALIZER 0
82
83#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
84typedef void* __libcpp_recursive_mutex_t[6];
85#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
86typedef void* __libcpp_recursive_mutex_t[5];
87#else
88# error Unsupported architecture
89#endif
90
91// Condition Variable
92typedef void* __libcpp_condvar_t;
93#define _LIBCPP_CONDVAR_INITIALIZER 0
94
95// Execute Once
96typedef void* __libcpp_exec_once_flag;
97#define _LIBCPP_EXEC_ONCE_INITIALIZER 0
98
99// Thread ID
100typedef long __libcpp_thread_id;
101
102// Thread
103#define _LIBCPP_NULL_THREAD 0U
104
105typedef void* __libcpp_thread_t;
106
107// Thread Local Storage
108typedef long __libcpp_tls_key;
109
110#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
111#endif
112
113// Mutex
114_LIBCPP_THREAD_ABI_VISIBILITY
115int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
116
117_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
118int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
119
120_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
121bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
122
123_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
124int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
125
126_LIBCPP_THREAD_ABI_VISIBILITY
127int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
128
129_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
130int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
131
132_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
133bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
134
135_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
136int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
137
138_LIBCPP_THREAD_ABI_VISIBILITY
139int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
140
141// Condition variable
142_LIBCPP_THREAD_ABI_VISIBILITY
143int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
144
145_LIBCPP_THREAD_ABI_VISIBILITY
146int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
147
148_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
149int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
150
151_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
152int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
153                               timespec *__ts);
154
155_LIBCPP_THREAD_ABI_VISIBILITY
156int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
157
158// Execute once
159_LIBCPP_THREAD_ABI_VISIBILITY
160int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
161                          void (*init_routine)(void));
162
163// Thread id
164_LIBCPP_THREAD_ABI_VISIBILITY
165bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
166
167_LIBCPP_THREAD_ABI_VISIBILITY
168bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
169
170// Thread
171_LIBCPP_THREAD_ABI_VISIBILITY
172bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
173
174_LIBCPP_THREAD_ABI_VISIBILITY
175int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
176                           void *__arg);
177
178_LIBCPP_THREAD_ABI_VISIBILITY
179__libcpp_thread_id __libcpp_thread_get_current_id();
180
181_LIBCPP_THREAD_ABI_VISIBILITY
182__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
183
184_LIBCPP_THREAD_ABI_VISIBILITY
185int __libcpp_thread_join(__libcpp_thread_t *__t);
186
187_LIBCPP_THREAD_ABI_VISIBILITY
188int __libcpp_thread_detach(__libcpp_thread_t *__t);
189
190_LIBCPP_THREAD_ABI_VISIBILITY
191void __libcpp_thread_yield();
192
193_LIBCPP_THREAD_ABI_VISIBILITY
194void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
195
196// Thread local storage
197_LIBCPP_THREAD_ABI_VISIBILITY
198int __libcpp_tls_create(__libcpp_tls_key* __key,
199                        void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
200
201_LIBCPP_THREAD_ABI_VISIBILITY
202void *__libcpp_tls_get(__libcpp_tls_key __key);
203
204_LIBCPP_THREAD_ABI_VISIBILITY
205int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
206
207#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
208     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \
209    defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
210
211int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
212{
213  pthread_mutexattr_t attr;
214  int __ec = pthread_mutexattr_init(&attr);
215  if (__ec)
216    return __ec;
217  __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
218  if (__ec) {
219    pthread_mutexattr_destroy(&attr);
220    return __ec;
221  }
222  __ec = pthread_mutex_init(__m, &attr);
223  if (__ec) {
224    pthread_mutexattr_destroy(&attr);
225    return __ec;
226  }
227  __ec = pthread_mutexattr_destroy(&attr);
228  if (__ec) {
229    pthread_mutex_destroy(__m);
230    return __ec;
231  }
232  return 0;
233}
234
235int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
236{
237  return pthread_mutex_lock(__m);
238}
239
240bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
241{
242  return pthread_mutex_trylock(__m) == 0;
243}
244
245int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
246{
247  return pthread_mutex_unlock(__m);
248}
249
250int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
251{
252  return pthread_mutex_destroy(__m);
253}
254
255int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
256{
257  return pthread_mutex_lock(__m);
258}
259
260bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
261{
262  return pthread_mutex_trylock(__m) == 0;
263}
264
265int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
266{
267  return pthread_mutex_unlock(__m);
268}
269
270int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
271{
272  return pthread_mutex_destroy(__m);
273}
274
275// Condition Variable
276int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
277{
278  return pthread_cond_signal(__cv);
279}
280
281int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
282{
283  return pthread_cond_broadcast(__cv);
284}
285
286int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
287{
288  return pthread_cond_wait(__cv, __m);
289}
290
291int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
292                               timespec *__ts)
293{
294  return pthread_cond_timedwait(__cv, __m, __ts);
295}
296
297int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
298{
299  return pthread_cond_destroy(__cv);
300}
301
302// Execute once
303int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
304                          void (*init_routine)(void)) {
305  return pthread_once(flag, init_routine);
306}
307
308// Thread id
309// Returns non-zero if the thread ids are equal, otherwise 0
310bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
311{
312  return pthread_equal(t1, t2) != 0;
313}
314
315// Returns non-zero if t1 < t2, otherwise 0
316bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
317{
318  return t1 < t2;
319}
320
321// Thread
322bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
323  return *__t == 0;
324}
325
326int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
327                           void *__arg)
328{
329  return pthread_create(__t, 0, __func, __arg);
330}
331
332__libcpp_thread_id __libcpp_thread_get_current_id()
333{
334  return pthread_self();
335}
336
337__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
338{
339  return *__t;
340}
341
342int __libcpp_thread_join(__libcpp_thread_t *__t)
343{
344  return pthread_join(*__t, 0);
345}
346
347int __libcpp_thread_detach(__libcpp_thread_t *__t)
348{
349  return pthread_detach(*__t);
350}
351
352void __libcpp_thread_yield()
353{
354  sched_yield();
355}
356
357void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
358{
359   using namespace chrono;
360   seconds __s = duration_cast<seconds>(__ns);
361   timespec __ts;
362   typedef decltype(__ts.tv_sec) ts_sec;
363   _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max();
364
365   if (__s.count() < __ts_sec_max)
366   {
367     __ts.tv_sec = static_cast<ts_sec>(__s.count());
368     __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
369   }
370   else
371   {
372     __ts.tv_sec = __ts_sec_max;
373     __ts.tv_nsec = 999999999; // (10^9 - 1)
374   }
375
376   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
377}
378
379// Thread local storage
380int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
381{
382  return pthread_key_create(__key, __at_exit);
383}
384
385void *__libcpp_tls_get(__libcpp_tls_key __key)
386{
387  return pthread_getspecific(__key);
388}
389
390int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
391{
392    return pthread_setspecific(__key, __p);
393}
394
395#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
396
397class _LIBCPP_TYPE_VIS thread;
398class _LIBCPP_TYPE_VIS __thread_id;
399
400namespace this_thread
401{
402
403_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
404
405}  // this_thread
406
407template<> struct hash<__thread_id>;
408
409class _LIBCPP_TEMPLATE_VIS __thread_id
410{
411    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
412    // NULL is the no-thread value on Darwin.  Someone needs to check
413    // on other platforms.  We assume 0 works everywhere for now.
414    __libcpp_thread_id __id_;
415
416public:
417    _LIBCPP_INLINE_VISIBILITY
418    __thread_id() _NOEXCEPT : __id_(0) {}
419
420    friend _LIBCPP_INLINE_VISIBILITY
421        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
422        { // don't pass id==0 to underlying routines
423        if (__x.__id_ == 0) return __y.__id_ == 0;
424        if (__y.__id_ == 0) return false;
425        return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
426        }
427    friend _LIBCPP_INLINE_VISIBILITY
428        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
429        {return !(__x == __y);}
430    friend _LIBCPP_INLINE_VISIBILITY
431        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
432        { // id==0 is always less than any other thread_id
433        if (__x.__id_ == 0) return __y.__id_ != 0;
434        if (__y.__id_ == 0) return false;
435        return  __libcpp_thread_id_less(__x.__id_, __y.__id_);
436        }
437    friend _LIBCPP_INLINE_VISIBILITY
438        bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
439        {return !(__y < __x);}
440    friend _LIBCPP_INLINE_VISIBILITY
441        bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
442        {return   __y < __x ;}
443    friend _LIBCPP_INLINE_VISIBILITY
444        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
445        {return !(__x < __y);}
446
447    _LIBCPP_INLINE_VISIBILITY
448    void __reset() { __id_ = 0; }
449
450    template<class _CharT, class _Traits>
451    friend
452    _LIBCPP_INLINE_VISIBILITY
453    basic_ostream<_CharT, _Traits>&
454    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
455
456private:
457    _LIBCPP_INLINE_VISIBILITY
458    __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
459
460    friend __thread_id this_thread::get_id() _NOEXCEPT;
461    friend class _LIBCPP_TYPE_VIS thread;
462    friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
463};
464
465namespace this_thread
466{
467
468inline _LIBCPP_INLINE_VISIBILITY
469__thread_id
470get_id() _NOEXCEPT
471{
472    return __libcpp_thread_get_current_id();
473}
474
475}  // this_thread
476
477_LIBCPP_END_NAMESPACE_STD
478
479_LIBCPP_POP_MACROS
480
481#endif // !_LIBCPP_HAS_NO_THREADS
482
483#endif // _LIBCPP_THREADING_SUPPORT
484