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