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