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