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 10*ce777190SNikolas Klauser #ifndef _LIBCPP___CXX03___THREAD_SUPPORT_C11_H 11*ce777190SNikolas Klauser #define _LIBCPP___CXX03___THREAD_SUPPORT_C11_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> 1873fbae83SNikolas Klauser #include <__cxx03/threads.h> 19e78f53d1SNikolas Klauser 20e78f53d1SNikolas Klauser #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 21e78f53d1SNikolas Klauser # pragma GCC system_header 22e78f53d1SNikolas Klauser #endif 23e78f53d1SNikolas Klauser 24e78f53d1SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD 25e78f53d1SNikolas Klauser 26e78f53d1SNikolas Klauser using __libcpp_timespec_t = ::timespec; 27e78f53d1SNikolas Klauser 28e78f53d1SNikolas Klauser // 29e78f53d1SNikolas Klauser // Mutex 30e78f53d1SNikolas Klauser // 31e78f53d1SNikolas Klauser typedef mtx_t __libcpp_mutex_t; 32e78f53d1SNikolas Klauser // mtx_t is a struct so using {} for initialization is valid. 33e78f53d1SNikolas Klauser #define _LIBCPP_MUTEX_INITIALIZER \ 34e78f53d1SNikolas Klauser {} 35e78f53d1SNikolas Klauser 36e78f53d1SNikolas Klauser typedef mtx_t __libcpp_recursive_mutex_t; 37e78f53d1SNikolas Klauser 38e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m) { 39e78f53d1SNikolas Klauser return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL; 40e78f53d1SNikolas Klauser } 41e78f53d1SNikolas Klauser 42e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int 43e78f53d1SNikolas Klauser __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) { 44e78f53d1SNikolas Klauser return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 45e78f53d1SNikolas Klauser } 46e78f53d1SNikolas Klauser 47e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool 48e78f53d1SNikolas Klauser __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) { 49e78f53d1SNikolas Klauser return mtx_trylock(__m) == thrd_success; 50e78f53d1SNikolas Klauser } 51e78f53d1SNikolas Klauser 52e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int 53e78f53d1SNikolas Klauser __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m) { 54e78f53d1SNikolas Klauser return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 55e78f53d1SNikolas Klauser } 56e78f53d1SNikolas Klauser 57e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m) { 58e78f53d1SNikolas Klauser mtx_destroy(__m); 59e78f53d1SNikolas Klauser return 0; 60e78f53d1SNikolas Klauser } 61e78f53d1SNikolas Klauser 62e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t* __m) { 63e78f53d1SNikolas Klauser return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 64e78f53d1SNikolas Klauser } 65e78f53d1SNikolas Klauser 66e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) { 67e78f53d1SNikolas Klauser return mtx_trylock(__m) == thrd_success; 68e78f53d1SNikolas Klauser } 69e78f53d1SNikolas Klauser 70e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) { 71e78f53d1SNikolas Klauser return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 72e78f53d1SNikolas Klauser } 73e78f53d1SNikolas Klauser 74e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) { 75e78f53d1SNikolas Klauser mtx_destroy(__m); 76e78f53d1SNikolas Klauser return 0; 77e78f53d1SNikolas Klauser } 78e78f53d1SNikolas Klauser 79e78f53d1SNikolas Klauser // 80e78f53d1SNikolas Klauser // Condition Variable 81e78f53d1SNikolas Klauser // 82e78f53d1SNikolas Klauser typedef cnd_t __libcpp_condvar_t; 83e78f53d1SNikolas Klauser // cnd_t is a struct so using {} for initialization is valid. 84e78f53d1SNikolas Klauser #define _LIBCPP_CONDVAR_INITIALIZER \ 85e78f53d1SNikolas Klauser {} 86e78f53d1SNikolas Klauser 87e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) { 88e78f53d1SNikolas Klauser return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; 89e78f53d1SNikolas Klauser } 90e78f53d1SNikolas Klauser 91e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) { 92e78f53d1SNikolas Klauser return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; 93e78f53d1SNikolas Klauser } 94e78f53d1SNikolas Klauser 95e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int 96e78f53d1SNikolas Klauser __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) { 97e78f53d1SNikolas Klauser return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL; 98e78f53d1SNikolas Klauser } 99e78f53d1SNikolas Klauser 100e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int 101e78f53d1SNikolas Klauser __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts) { 102e78f53d1SNikolas Klauser int __ec = cnd_timedwait(__cv, __m, __ts); 103e78f53d1SNikolas Klauser return __ec == thrd_timedout ? ETIMEDOUT : __ec; 104e78f53d1SNikolas Klauser } 105e78f53d1SNikolas Klauser 106e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) { 107e78f53d1SNikolas Klauser cnd_destroy(__cv); 108e78f53d1SNikolas Klauser return 0; 109e78f53d1SNikolas Klauser } 110e78f53d1SNikolas Klauser 111e78f53d1SNikolas Klauser // 112e78f53d1SNikolas Klauser // Execute once 113e78f53d1SNikolas Klauser // 114e78f53d1SNikolas Klauser typedef ::once_flag __libcpp_exec_once_flag; 115e78f53d1SNikolas Klauser #define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT 116e78f53d1SNikolas Klauser 117e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI int __libcpp_execute_once(__libcpp_exec_once_flag* flag, void (*init_routine)(void)) { 118e78f53d1SNikolas Klauser ::call_once(flag, init_routine); 119e78f53d1SNikolas Klauser return 0; 120e78f53d1SNikolas Klauser } 121e78f53d1SNikolas Klauser 122e78f53d1SNikolas Klauser // 123e78f53d1SNikolas Klauser // Thread id 124e78f53d1SNikolas Klauser // 125e78f53d1SNikolas Klauser typedef thrd_t __libcpp_thread_id; 126e78f53d1SNikolas Klauser 127e78f53d1SNikolas Klauser // Returns non-zero if the thread ids are equal, otherwise 0 128e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) { 129e78f53d1SNikolas Klauser return thrd_equal(t1, t2) != 0; 130e78f53d1SNikolas Klauser } 131e78f53d1SNikolas Klauser 132e78f53d1SNikolas Klauser // Returns non-zero if t1 < t2, otherwise 0 133e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) { 134e78f53d1SNikolas Klauser return t1 < t2; 135e78f53d1SNikolas Klauser } 136e78f53d1SNikolas Klauser 137e78f53d1SNikolas Klauser // 138e78f53d1SNikolas Klauser // Thread 139e78f53d1SNikolas Klauser // 140e78f53d1SNikolas Klauser #define _LIBCPP_NULL_THREAD 0U 141e78f53d1SNikolas Klauser 142e78f53d1SNikolas Klauser typedef thrd_t __libcpp_thread_t; 143e78f53d1SNikolas Klauser 144e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) { return *__t; } 145e78f53d1SNikolas Klauser 146e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_isnull(const __libcpp_thread_t* __t) { 147e78f53d1SNikolas Klauser return __libcpp_thread_get_id(__t) == 0; 148e78f53d1SNikolas Klauser } 149e78f53d1SNikolas Klauser 150e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) { 151e78f53d1SNikolas Klauser int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg); 152e78f53d1SNikolas Klauser return __ec == thrd_nomem ? ENOMEM : __ec; 153e78f53d1SNikolas Klauser } 154e78f53d1SNikolas Klauser 155e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_current_id() { return thrd_current(); } 156e78f53d1SNikolas Klauser 157e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_join(__libcpp_thread_t* __t) { 158e78f53d1SNikolas Klauser return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; 159e78f53d1SNikolas Klauser } 160e78f53d1SNikolas Klauser 161e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_detach(__libcpp_thread_t* __t) { 162e78f53d1SNikolas Klauser return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; 163e78f53d1SNikolas Klauser } 164e78f53d1SNikolas Klauser 165e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_yield() { thrd_yield(); } 166e78f53d1SNikolas Klauser 167e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) { 168e78f53d1SNikolas Klauser __libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns); 169e78f53d1SNikolas Klauser thrd_sleep(&__ts, nullptr); 170e78f53d1SNikolas Klauser } 171e78f53d1SNikolas Klauser 172e78f53d1SNikolas Klauser // 173e78f53d1SNikolas Klauser // Thread local storage 174e78f53d1SNikolas Klauser // 175e78f53d1SNikolas Klauser #define _LIBCPP_TLS_DESTRUCTOR_CC /* nothing */ 176e78f53d1SNikolas Klauser 177e78f53d1SNikolas Klauser typedef tss_t __libcpp_tls_key; 178e78f53d1SNikolas Klauser 179e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*)) { 180e78f53d1SNikolas Klauser return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL; 181e78f53d1SNikolas Klauser } 182e78f53d1SNikolas Klauser 183e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI void* __libcpp_tls_get(__libcpp_tls_key __key) { return tss_get(__key); } 184e78f53d1SNikolas Klauser 185e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_set(__libcpp_tls_key __key, void* __p) { 186e78f53d1SNikolas Klauser return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; 187e78f53d1SNikolas Klauser } 188e78f53d1SNikolas Klauser 189e78f53d1SNikolas Klauser _LIBCPP_END_NAMESPACE_STD 190e78f53d1SNikolas Klauser 191*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03___THREAD_SUPPORT_C11_H 192