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 <__availability>
14#include <__chrono/convert_to_timespec.h>
15#include <__chrono/duration.h>
16#include <__config>
17#include <__thread/poll_with_backoff.h>
18#include <errno.h>
19
20#ifdef __MVS__
21# include <__support/ibm/nanosleep.h>
22#endif
23
24#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
25#  pragma GCC system_header
26#endif
27
28#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
29# include <__external_threading>
30#elif !defined(_LIBCPP_HAS_NO_THREADS)
31
32#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
33// Some platforms require <bits/atomic_wide_counter.h> in order for
34// PTHREAD_COND_INITIALIZER to be expanded. Normally that would come
35// in via <pthread.h>, but it's a non-modular header on those platforms,
36// so libc++'s <math.h> usually absorbs atomic_wide_counter.h into the
37// module with <math.h> and makes atomic_wide_counter.h invisible.
38// Include <math.h> here to work around that.
39# include <math.h>
40
41# include <pthread.h>
42# include <sched.h>
43#elif defined(_LIBCPP_HAS_THREAD_API_C11)
44# include <threads.h>
45#endif
46
47#if defined(_LIBCPP_HAS_THREAD_API_WIN32)
48#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_EXPORTED_FROM_ABI
49#else
50#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
51#endif
52
53typedef ::timespec __libcpp_timespec_t;
54#endif // !defined(_LIBCPP_HAS_NO_THREADS)
55
56_LIBCPP_BEGIN_NAMESPACE_STD
57
58#if !defined(_LIBCPP_HAS_NO_THREADS)
59
60#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
61// Mutex
62typedef pthread_mutex_t __libcpp_mutex_t;
63#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
64
65typedef pthread_mutex_t __libcpp_recursive_mutex_t;
66
67// Condition Variable
68typedef pthread_cond_t __libcpp_condvar_t;
69#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
70
71// Execute once
72typedef pthread_once_t __libcpp_exec_once_flag;
73#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
74
75// Thread id
76#if defined(__MVS__)
77  typedef unsigned long long __libcpp_thread_id;
78#else
79  typedef pthread_t __libcpp_thread_id;
80#endif
81
82// Thread
83#define _LIBCPP_NULL_THREAD ((__libcpp_thread_t()))
84typedef pthread_t __libcpp_thread_t;
85
86// Thread Local Storage
87typedef pthread_key_t __libcpp_tls_key;
88
89#define _LIBCPP_TLS_DESTRUCTOR_CC
90#elif defined(_LIBCPP_HAS_THREAD_API_C11)
91// Mutex
92typedef mtx_t __libcpp_mutex_t;
93// mtx_t is a struct so using {} for initialization is valid.
94#define _LIBCPP_MUTEX_INITIALIZER {}
95
96typedef mtx_t __libcpp_recursive_mutex_t;
97
98// Condition Variable
99typedef cnd_t __libcpp_condvar_t;
100// cnd_t is a struct so using {} for initialization is valid.
101#define _LIBCPP_CONDVAR_INITIALIZER {}
102
103// Execute once
104typedef once_flag __libcpp_exec_once_flag;
105#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT
106
107// Thread id
108typedef thrd_t __libcpp_thread_id;
109
110// Thread
111#define _LIBCPP_NULL_THREAD 0U
112
113typedef thrd_t __libcpp_thread_t;
114
115// Thread Local Storage
116typedef tss_t __libcpp_tls_key;
117
118#define _LIBCPP_TLS_DESTRUCTOR_CC
119#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
120// Mutex
121typedef void* __libcpp_mutex_t;
122#define _LIBCPP_MUTEX_INITIALIZER 0
123
124#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
125typedef void* __libcpp_recursive_mutex_t[6];
126#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
127typedef void* __libcpp_recursive_mutex_t[5];
128#else
129# error Unsupported architecture
130#endif
131
132// Condition Variable
133typedef void* __libcpp_condvar_t;
134#define _LIBCPP_CONDVAR_INITIALIZER 0
135
136// Execute Once
137typedef void* __libcpp_exec_once_flag;
138#define _LIBCPP_EXEC_ONCE_INITIALIZER 0
139
140// Thread ID
141typedef long __libcpp_thread_id;
142
143// Thread
144#define _LIBCPP_NULL_THREAD 0U
145
146typedef void* __libcpp_thread_t;
147
148// Thread Local Storage
149typedef long __libcpp_tls_key;
150
151#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
152#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
153
154#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
155// Mutex
156_LIBCPP_THREAD_ABI_VISIBILITY
157int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
158
159_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
160int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
161
162_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
163bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
164
165_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
166int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
167
168_LIBCPP_THREAD_ABI_VISIBILITY
169int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
170
171_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
172int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
173
174_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
175bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
176
177_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
178int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
179
180_LIBCPP_THREAD_ABI_VISIBILITY
181int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
182
183// Condition variable
184_LIBCPP_THREAD_ABI_VISIBILITY
185int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
186
187_LIBCPP_THREAD_ABI_VISIBILITY
188int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
189
190_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
191int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
192
193_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
194int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
195                               __libcpp_timespec_t *__ts);
196
197_LIBCPP_THREAD_ABI_VISIBILITY
198int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
199
200// Execute once
201_LIBCPP_THREAD_ABI_VISIBILITY
202int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
203                          void (*__init_routine)());
204
205// Thread id
206_LIBCPP_THREAD_ABI_VISIBILITY
207bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2);
208
209_LIBCPP_THREAD_ABI_VISIBILITY
210bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2);
211
212// Thread
213_LIBCPP_THREAD_ABI_VISIBILITY
214bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
215
216_LIBCPP_THREAD_ABI_VISIBILITY
217int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
218                           void *__arg);
219
220_LIBCPP_THREAD_ABI_VISIBILITY
221__libcpp_thread_id __libcpp_thread_get_current_id();
222
223_LIBCPP_THREAD_ABI_VISIBILITY
224__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
225
226_LIBCPP_THREAD_ABI_VISIBILITY
227int __libcpp_thread_join(__libcpp_thread_t *__t);
228
229_LIBCPP_THREAD_ABI_VISIBILITY
230int __libcpp_thread_detach(__libcpp_thread_t *__t);
231
232_LIBCPP_THREAD_ABI_VISIBILITY
233void __libcpp_thread_yield();
234
235_LIBCPP_THREAD_ABI_VISIBILITY
236void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
237
238// Thread local storage
239_LIBCPP_THREAD_ABI_VISIBILITY
240int __libcpp_tls_create(__libcpp_tls_key* __key,
241                        void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
242
243_LIBCPP_THREAD_ABI_VISIBILITY
244void *__libcpp_tls_get(__libcpp_tls_key __key);
245
246_LIBCPP_THREAD_ABI_VISIBILITY
247int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
248
249#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
250
251#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
252
253int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
254{
255  pthread_mutexattr_t __attr;
256  int __ec = pthread_mutexattr_init(&__attr);
257  if (__ec)
258    return __ec;
259  __ec = pthread_mutexattr_settype(&__attr, PTHREAD_MUTEX_RECURSIVE);
260  if (__ec) {
261    pthread_mutexattr_destroy(&__attr);
262    return __ec;
263  }
264  __ec = pthread_mutex_init(__m, &__attr);
265  if (__ec) {
266    pthread_mutexattr_destroy(&__attr);
267    return __ec;
268  }
269  __ec = pthread_mutexattr_destroy(&__attr);
270  if (__ec) {
271    pthread_mutex_destroy(__m);
272    return __ec;
273  }
274  return 0;
275}
276
277int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
278{
279  return pthread_mutex_lock(__m);
280}
281
282bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
283{
284  return pthread_mutex_trylock(__m) == 0;
285}
286
287int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
288{
289  return pthread_mutex_unlock(__m);
290}
291
292int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
293{
294  return pthread_mutex_destroy(__m);
295}
296
297int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
298{
299  return pthread_mutex_lock(__m);
300}
301
302bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
303{
304  return pthread_mutex_trylock(__m) == 0;
305}
306
307int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
308{
309  return pthread_mutex_unlock(__m);
310}
311
312int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
313{
314  return pthread_mutex_destroy(__m);
315}
316
317// Condition Variable
318int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
319{
320  return pthread_cond_signal(__cv);
321}
322
323int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
324{
325  return pthread_cond_broadcast(__cv);
326}
327
328int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
329{
330  return pthread_cond_wait(__cv, __m);
331}
332
333int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
334                               __libcpp_timespec_t *__ts)
335{
336  return pthread_cond_timedwait(__cv, __m, __ts);
337}
338
339int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
340{
341  return pthread_cond_destroy(__cv);
342}
343
344// Execute once
345int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
346                          void (*__init_routine)()) {
347  return pthread_once(__flag, __init_routine);
348}
349
350// Thread id
351// Returns non-zero if the thread ids are equal, otherwise 0
352bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2)
353{
354  return __t1 == __t2;
355}
356
357// Returns non-zero if t1 < t2, otherwise 0
358bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2)
359{
360  return __t1 < __t2;
361}
362
363// Thread
364bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
365  return __libcpp_thread_get_id(__t) == 0;
366}
367
368int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
369                           void *__arg)
370{
371  return pthread_create(__t, nullptr, __func, __arg);
372}
373
374__libcpp_thread_id __libcpp_thread_get_current_id()
375{
376  const __libcpp_thread_t __current_thread = pthread_self();
377  return __libcpp_thread_get_id(&__current_thread);
378}
379
380__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
381{
382#if defined(__MVS__)
383  return __t->__;
384#else
385  return *__t;
386#endif
387}
388
389int __libcpp_thread_join(__libcpp_thread_t *__t)
390{
391  return pthread_join(*__t, nullptr);
392}
393
394int __libcpp_thread_detach(__libcpp_thread_t *__t)
395{
396  return pthread_detach(*__t);
397}
398
399void __libcpp_thread_yield()
400{
401  sched_yield();
402}
403
404void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
405{
406   __libcpp_timespec_t __ts = _VSTD::__convert_to_timespec<__libcpp_timespec_t>(__ns);
407   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
408}
409
410// Thread local storage
411int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
412{
413  return pthread_key_create(__key, __at_exit);
414}
415
416void *__libcpp_tls_get(__libcpp_tls_key __key)
417{
418  return pthread_getspecific(__key);
419}
420
421int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
422{
423    return pthread_setspecific(__key, __p);
424}
425
426#elif defined(_LIBCPP_HAS_THREAD_API_C11)
427
428int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
429{
430  return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
431}
432
433int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
434{
435  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
436}
437
438bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
439{
440  return mtx_trylock(__m) == thrd_success;
441}
442
443int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
444{
445  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
446}
447
448int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
449{
450  mtx_destroy(__m);
451  return 0;
452}
453
454int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
455{
456  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
457}
458
459bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
460{
461  return mtx_trylock(__m) == thrd_success;
462}
463
464int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
465{
466  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
467}
468
469int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
470{
471  mtx_destroy(__m);
472  return 0;
473}
474
475// Condition Variable
476int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
477{
478  return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
479}
480
481int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
482{
483  return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
484}
485
486int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
487{
488  return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
489}
490
491int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
492                               timespec *__ts)
493{
494  int __ec = cnd_timedwait(__cv, __m, __ts);
495  return __ec == thrd_timedout ? ETIMEDOUT : __ec;
496}
497
498int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
499{
500  cnd_destroy(__cv);
501  return 0;
502}
503
504// Execute once
505int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
506                          void (*init_routine)(void)) {
507  ::call_once(flag, init_routine);
508  return 0;
509}
510
511// Thread id
512// Returns non-zero if the thread ids are equal, otherwise 0
513bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
514{
515  return thrd_equal(t1, t2) != 0;
516}
517
518// Returns non-zero if t1 < t2, otherwise 0
519bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
520{
521  return t1 < t2;
522}
523
524// Thread
525bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
526  return __libcpp_thread_get_id(__t) == 0;
527}
528
529int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
530                           void *__arg)
531{
532  int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
533  return __ec == thrd_nomem ? ENOMEM : __ec;
534}
535
536__libcpp_thread_id __libcpp_thread_get_current_id()
537{
538  return thrd_current();
539}
540
541__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
542{
543  return *__t;
544}
545
546int __libcpp_thread_join(__libcpp_thread_t *__t)
547{
548  return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
549}
550
551int __libcpp_thread_detach(__libcpp_thread_t *__t)
552{
553  return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
554}
555
556void __libcpp_thread_yield()
557{
558  thrd_yield();
559}
560
561void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
562{
563   __libcpp_timespec_t __ts = _VSTD::__convert_to_timespec<__libcpp_timespec_t>(__ns);
564  thrd_sleep(&__ts, nullptr);
565}
566
567// Thread local storage
568int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
569{
570  return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
571}
572
573void *__libcpp_tls_get(__libcpp_tls_key __key)
574{
575  return tss_get(__key);
576}
577
578int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
579{
580  return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
581}
582
583#endif
584
585#endif // !_LIBCPP_HAS_NO_THREADS
586
587_LIBCPP_END_NAMESPACE_STD
588
589#endif // _LIBCPP___THREADING_SUPPORT
590