xref: /freebsd-src/contrib/llvm-project/libcxx/include/__thread/support/pthread.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric // -*- C++ -*-
2*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
3*0fca6ea1SDimitry Andric //
4*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*0fca6ea1SDimitry Andric //
8*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
9*0fca6ea1SDimitry Andric 
10*0fca6ea1SDimitry Andric #ifndef _LIBCPP___THREAD_SUPPORT_PTHREAD_H
11*0fca6ea1SDimitry Andric #define _LIBCPP___THREAD_SUPPORT_PTHREAD_H
12*0fca6ea1SDimitry Andric 
13*0fca6ea1SDimitry Andric #include <__chrono/convert_to_timespec.h>
14*0fca6ea1SDimitry Andric #include <__chrono/duration.h>
15*0fca6ea1SDimitry Andric #include <__config>
16*0fca6ea1SDimitry Andric #include <ctime>
17*0fca6ea1SDimitry Andric #include <errno.h>
18*0fca6ea1SDimitry Andric #include <pthread.h>
19*0fca6ea1SDimitry Andric #include <sched.h>
20*0fca6ea1SDimitry Andric 
21*0fca6ea1SDimitry Andric #ifdef __MVS__
22*0fca6ea1SDimitry Andric #  include <__support/ibm/nanosleep.h>
23*0fca6ea1SDimitry Andric #endif
24*0fca6ea1SDimitry Andric 
25*0fca6ea1SDimitry Andric // Some platforms require <bits/atomic_wide_counter.h> in order for
26*0fca6ea1SDimitry Andric // PTHREAD_COND_INITIALIZER to be expanded. Normally that would come
27*0fca6ea1SDimitry Andric // in via <pthread.h>, but it's a non-modular header on those platforms,
28*0fca6ea1SDimitry Andric // so libc++'s <math.h> usually absorbs atomic_wide_counter.h into the
29*0fca6ea1SDimitry Andric // module with <math.h> and makes atomic_wide_counter.h invisible.
30*0fca6ea1SDimitry Andric // Include <math.h> here to work around that.
31*0fca6ea1SDimitry Andric // This checks wheter a Clang module is built
32*0fca6ea1SDimitry Andric #if __building_module(std)
33*0fca6ea1SDimitry Andric #  include <math.h>
34*0fca6ea1SDimitry Andric #endif
35*0fca6ea1SDimitry Andric 
36*0fca6ea1SDimitry Andric #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
37*0fca6ea1SDimitry Andric #  pragma GCC system_header
38*0fca6ea1SDimitry Andric #endif
39*0fca6ea1SDimitry Andric 
40*0fca6ea1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
41*0fca6ea1SDimitry Andric 
42*0fca6ea1SDimitry Andric using __libcpp_timespec_t = ::timespec;
43*0fca6ea1SDimitry Andric 
44*0fca6ea1SDimitry Andric //
45*0fca6ea1SDimitry Andric // Mutex
46*0fca6ea1SDimitry Andric //
47*0fca6ea1SDimitry Andric typedef pthread_mutex_t __libcpp_mutex_t;
48*0fca6ea1SDimitry Andric #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
49*0fca6ea1SDimitry Andric 
50*0fca6ea1SDimitry Andric typedef pthread_mutex_t __libcpp_recursive_mutex_t;
51*0fca6ea1SDimitry Andric 
52*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m) {
53*0fca6ea1SDimitry Andric   pthread_mutexattr_t __attr;
54*0fca6ea1SDimitry Andric   int __ec = pthread_mutexattr_init(&__attr);
55*0fca6ea1SDimitry Andric   if (__ec)
56*0fca6ea1SDimitry Andric     return __ec;
57*0fca6ea1SDimitry Andric   __ec = pthread_mutexattr_settype(&__attr, PTHREAD_MUTEX_RECURSIVE);
58*0fca6ea1SDimitry Andric   if (__ec) {
59*0fca6ea1SDimitry Andric     pthread_mutexattr_destroy(&__attr);
60*0fca6ea1SDimitry Andric     return __ec;
61*0fca6ea1SDimitry Andric   }
62*0fca6ea1SDimitry Andric   __ec = pthread_mutex_init(__m, &__attr);
63*0fca6ea1SDimitry Andric   if (__ec) {
64*0fca6ea1SDimitry Andric     pthread_mutexattr_destroy(&__attr);
65*0fca6ea1SDimitry Andric     return __ec;
66*0fca6ea1SDimitry Andric   }
67*0fca6ea1SDimitry Andric   __ec = pthread_mutexattr_destroy(&__attr);
68*0fca6ea1SDimitry Andric   if (__ec) {
69*0fca6ea1SDimitry Andric     pthread_mutex_destroy(__m);
70*0fca6ea1SDimitry Andric     return __ec;
71*0fca6ea1SDimitry Andric   }
72*0fca6ea1SDimitry Andric   return 0;
73*0fca6ea1SDimitry Andric }
74*0fca6ea1SDimitry Andric 
75*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
76*0fca6ea1SDimitry Andric __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) {
77*0fca6ea1SDimitry Andric   return pthread_mutex_lock(__m);
78*0fca6ea1SDimitry Andric }
79*0fca6ea1SDimitry Andric 
80*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool
81*0fca6ea1SDimitry Andric __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) {
82*0fca6ea1SDimitry Andric   return pthread_mutex_trylock(__m) == 0;
83*0fca6ea1SDimitry Andric }
84*0fca6ea1SDimitry Andric 
85*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
86*0fca6ea1SDimitry Andric __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m) {
87*0fca6ea1SDimitry Andric   return pthread_mutex_unlock(__m);
88*0fca6ea1SDimitry Andric }
89*0fca6ea1SDimitry Andric 
90*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m) {
91*0fca6ea1SDimitry Andric   return pthread_mutex_destroy(__m);
92*0fca6ea1SDimitry Andric }
93*0fca6ea1SDimitry Andric 
94*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t* __m) {
95*0fca6ea1SDimitry Andric   return pthread_mutex_lock(__m);
96*0fca6ea1SDimitry Andric }
97*0fca6ea1SDimitry Andric 
98*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) {
99*0fca6ea1SDimitry Andric   return pthread_mutex_trylock(__m) == 0;
100*0fca6ea1SDimitry Andric }
101*0fca6ea1SDimitry Andric 
102*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) {
103*0fca6ea1SDimitry Andric   return pthread_mutex_unlock(__m);
104*0fca6ea1SDimitry Andric }
105*0fca6ea1SDimitry Andric 
106*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) { return pthread_mutex_destroy(__m); }
107*0fca6ea1SDimitry Andric 
108*0fca6ea1SDimitry Andric //
109*0fca6ea1SDimitry Andric // Condition Variable
110*0fca6ea1SDimitry Andric //
111*0fca6ea1SDimitry Andric typedef pthread_cond_t __libcpp_condvar_t;
112*0fca6ea1SDimitry Andric #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
113*0fca6ea1SDimitry Andric 
114*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) { return pthread_cond_signal(__cv); }
115*0fca6ea1SDimitry Andric 
116*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) {
117*0fca6ea1SDimitry Andric   return pthread_cond_broadcast(__cv);
118*0fca6ea1SDimitry Andric }
119*0fca6ea1SDimitry Andric 
120*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
121*0fca6ea1SDimitry Andric __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) {
122*0fca6ea1SDimitry Andric   return pthread_cond_wait(__cv, __m);
123*0fca6ea1SDimitry Andric }
124*0fca6ea1SDimitry Andric 
125*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
126*0fca6ea1SDimitry Andric __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, __libcpp_timespec_t* __ts) {
127*0fca6ea1SDimitry Andric   return pthread_cond_timedwait(__cv, __m, __ts);
128*0fca6ea1SDimitry Andric }
129*0fca6ea1SDimitry Andric 
130*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) {
131*0fca6ea1SDimitry Andric   return pthread_cond_destroy(__cv);
132*0fca6ea1SDimitry Andric }
133*0fca6ea1SDimitry Andric 
134*0fca6ea1SDimitry Andric //
135*0fca6ea1SDimitry Andric // Execute once
136*0fca6ea1SDimitry Andric //
137*0fca6ea1SDimitry Andric typedef pthread_once_t __libcpp_exec_once_flag;
138*0fca6ea1SDimitry Andric #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
139*0fca6ea1SDimitry Andric 
140*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI int __libcpp_execute_once(__libcpp_exec_once_flag* __flag, void (*__init_routine)()) {
141*0fca6ea1SDimitry Andric   return pthread_once(__flag, __init_routine);
142*0fca6ea1SDimitry Andric }
143*0fca6ea1SDimitry Andric 
144*0fca6ea1SDimitry Andric //
145*0fca6ea1SDimitry Andric // Thread id
146*0fca6ea1SDimitry Andric //
147*0fca6ea1SDimitry Andric #if defined(__MVS__)
148*0fca6ea1SDimitry Andric typedef unsigned long long __libcpp_thread_id;
149*0fca6ea1SDimitry Andric #else
150*0fca6ea1SDimitry Andric typedef pthread_t __libcpp_thread_id;
151*0fca6ea1SDimitry Andric #endif
152*0fca6ea1SDimitry Andric 
153*0fca6ea1SDimitry Andric // Returns non-zero if the thread ids are equal, otherwise 0
154*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2) {
155*0fca6ea1SDimitry Andric   return __t1 == __t2;
156*0fca6ea1SDimitry Andric }
157*0fca6ea1SDimitry Andric 
158*0fca6ea1SDimitry Andric // Returns non-zero if t1 < t2, otherwise 0
159*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2) {
160*0fca6ea1SDimitry Andric   return __t1 < __t2;
161*0fca6ea1SDimitry Andric }
162*0fca6ea1SDimitry Andric 
163*0fca6ea1SDimitry Andric //
164*0fca6ea1SDimitry Andric // Thread
165*0fca6ea1SDimitry Andric //
166*0fca6ea1SDimitry Andric #define _LIBCPP_NULL_THREAD ((__libcpp_thread_t()))
167*0fca6ea1SDimitry Andric typedef pthread_t __libcpp_thread_t;
168*0fca6ea1SDimitry Andric 
169*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) {
170*0fca6ea1SDimitry Andric #if defined(__MVS__)
171*0fca6ea1SDimitry Andric   return __t->__;
172*0fca6ea1SDimitry Andric #else
173*0fca6ea1SDimitry Andric   return *__t;
174*0fca6ea1SDimitry Andric #endif
175*0fca6ea1SDimitry Andric }
176*0fca6ea1SDimitry Andric 
177*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_isnull(const __libcpp_thread_t* __t) {
178*0fca6ea1SDimitry Andric   return __libcpp_thread_get_id(__t) == 0;
179*0fca6ea1SDimitry Andric }
180*0fca6ea1SDimitry Andric 
181*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) {
182*0fca6ea1SDimitry Andric   return pthread_create(__t, nullptr, __func, __arg);
183*0fca6ea1SDimitry Andric }
184*0fca6ea1SDimitry Andric 
185*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_current_id() {
186*0fca6ea1SDimitry Andric   const __libcpp_thread_t __current_thread = pthread_self();
187*0fca6ea1SDimitry Andric   return __libcpp_thread_get_id(&__current_thread);
188*0fca6ea1SDimitry Andric }
189*0fca6ea1SDimitry Andric 
190*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_join(__libcpp_thread_t* __t) { return pthread_join(*__t, nullptr); }
191*0fca6ea1SDimitry Andric 
192*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_detach(__libcpp_thread_t* __t) { return pthread_detach(*__t); }
193*0fca6ea1SDimitry Andric 
194*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_yield() { sched_yield(); }
195*0fca6ea1SDimitry Andric 
196*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) {
197*0fca6ea1SDimitry Andric   __libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns);
198*0fca6ea1SDimitry Andric   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
199*0fca6ea1SDimitry Andric     ;
200*0fca6ea1SDimitry Andric }
201*0fca6ea1SDimitry Andric 
202*0fca6ea1SDimitry Andric //
203*0fca6ea1SDimitry Andric // Thread local storage
204*0fca6ea1SDimitry Andric //
205*0fca6ea1SDimitry Andric #define _LIBCPP_TLS_DESTRUCTOR_CC /* nothing */
206*0fca6ea1SDimitry Andric 
207*0fca6ea1SDimitry Andric typedef pthread_key_t __libcpp_tls_key;
208*0fca6ea1SDimitry Andric 
209*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*)) {
210*0fca6ea1SDimitry Andric   return pthread_key_create(__key, __at_exit);
211*0fca6ea1SDimitry Andric }
212*0fca6ea1SDimitry Andric 
213*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI void* __libcpp_tls_get(__libcpp_tls_key __key) { return pthread_getspecific(__key); }
214*0fca6ea1SDimitry Andric 
215*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_set(__libcpp_tls_key __key, void* __p) {
216*0fca6ea1SDimitry Andric   return pthread_setspecific(__key, __p);
217*0fca6ea1SDimitry Andric }
218*0fca6ea1SDimitry Andric 
219*0fca6ea1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
220*0fca6ea1SDimitry Andric 
221*0fca6ea1SDimitry Andric #endif // _LIBCPP___THREAD_SUPPORT_PTHREAD_H
222