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