xref: /llvm-project/libcxx/include/__thread/support/c11.h (revision 30f776f8149dcbda0b6467176488e6551d068e40)
17162fd75SLouis Dionne // -*- C++ -*-
27162fd75SLouis Dionne //===----------------------------------------------------------------------===//
37162fd75SLouis Dionne //
47162fd75SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
57162fd75SLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
67162fd75SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
77162fd75SLouis Dionne //
87162fd75SLouis Dionne //===----------------------------------------------------------------------===//
97162fd75SLouis Dionne 
107162fd75SLouis Dionne #ifndef _LIBCPP___THREAD_SUPPORT_C11_H
117162fd75SLouis Dionne #define _LIBCPP___THREAD_SUPPORT_C11_H
127162fd75SLouis Dionne 
137162fd75SLouis Dionne #include <__chrono/convert_to_timespec.h>
147162fd75SLouis Dionne #include <__chrono/duration.h>
157162fd75SLouis Dionne #include <__config>
167162fd75SLouis Dionne #include <ctime>
17*30f776f8SLouis Dionne #include <errno.h>
187162fd75SLouis Dionne #include <threads.h>
197162fd75SLouis Dionne 
207162fd75SLouis Dionne #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
217162fd75SLouis Dionne #  pragma GCC system_header
227162fd75SLouis Dionne #endif
237162fd75SLouis Dionne 
247162fd75SLouis Dionne _LIBCPP_BEGIN_NAMESPACE_STD
257162fd75SLouis Dionne 
26e1ddc333SLouis Dionne using __libcpp_timespec_t = ::timespec;
27e1ddc333SLouis Dionne 
287162fd75SLouis Dionne //
297162fd75SLouis Dionne // Mutex
307162fd75SLouis Dionne //
317162fd75SLouis Dionne typedef mtx_t __libcpp_mutex_t;
327162fd75SLouis Dionne // mtx_t is a struct so using {} for initialization is valid.
337162fd75SLouis Dionne #define _LIBCPP_MUTEX_INITIALIZER                                                                                      \
347162fd75SLouis Dionne   {}
357162fd75SLouis Dionne 
367162fd75SLouis Dionne typedef mtx_t __libcpp_recursive_mutex_t;
377162fd75SLouis Dionne 
__libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t * __m)387162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m) {
397162fd75SLouis Dionne   return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
407162fd75SLouis Dionne }
417162fd75SLouis Dionne 
427162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
__libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t * __m)437162fd75SLouis Dionne __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) {
447162fd75SLouis Dionne   return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
457162fd75SLouis Dionne }
467162fd75SLouis Dionne 
477162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool
__libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t * __m)487162fd75SLouis Dionne __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) {
497162fd75SLouis Dionne   return mtx_trylock(__m) == thrd_success;
507162fd75SLouis Dionne }
517162fd75SLouis Dionne 
527162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
__libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t * __m)537162fd75SLouis Dionne __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m) {
547162fd75SLouis Dionne   return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
557162fd75SLouis Dionne }
567162fd75SLouis Dionne 
__libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t * __m)577162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m) {
587162fd75SLouis Dionne   mtx_destroy(__m);
597162fd75SLouis Dionne   return 0;
607162fd75SLouis Dionne }
617162fd75SLouis Dionne 
__libcpp_mutex_lock(__libcpp_mutex_t * __m)627162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t* __m) {
637162fd75SLouis Dionne   return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
647162fd75SLouis Dionne }
657162fd75SLouis Dionne 
__libcpp_mutex_trylock(__libcpp_mutex_t * __m)667162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) {
677162fd75SLouis Dionne   return mtx_trylock(__m) == thrd_success;
687162fd75SLouis Dionne }
697162fd75SLouis Dionne 
__libcpp_mutex_unlock(__libcpp_mutex_t * __m)707162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) {
717162fd75SLouis Dionne   return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
727162fd75SLouis Dionne }
737162fd75SLouis Dionne 
__libcpp_mutex_destroy(__libcpp_mutex_t * __m)747162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) {
757162fd75SLouis Dionne   mtx_destroy(__m);
767162fd75SLouis Dionne   return 0;
777162fd75SLouis Dionne }
787162fd75SLouis Dionne 
797162fd75SLouis Dionne //
807162fd75SLouis Dionne // Condition Variable
817162fd75SLouis Dionne //
827162fd75SLouis Dionne typedef cnd_t __libcpp_condvar_t;
837162fd75SLouis Dionne // cnd_t is a struct so using {} for initialization is valid.
847162fd75SLouis Dionne #define _LIBCPP_CONDVAR_INITIALIZER                                                                                    \
857162fd75SLouis Dionne   {}
867162fd75SLouis Dionne 
__libcpp_condvar_signal(__libcpp_condvar_t * __cv)877162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) {
887162fd75SLouis Dionne   return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
897162fd75SLouis Dionne }
907162fd75SLouis Dionne 
__libcpp_condvar_broadcast(__libcpp_condvar_t * __cv)917162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) {
927162fd75SLouis Dionne   return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
937162fd75SLouis Dionne }
947162fd75SLouis Dionne 
957162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
__libcpp_condvar_wait(__libcpp_condvar_t * __cv,__libcpp_mutex_t * __m)967162fd75SLouis Dionne __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) {
977162fd75SLouis Dionne   return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
987162fd75SLouis Dionne }
997162fd75SLouis Dionne 
1007162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
__libcpp_condvar_timedwait(__libcpp_condvar_t * __cv,__libcpp_mutex_t * __m,timespec * __ts)1017162fd75SLouis Dionne __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts) {
1027162fd75SLouis Dionne   int __ec = cnd_timedwait(__cv, __m, __ts);
1037162fd75SLouis Dionne   return __ec == thrd_timedout ? ETIMEDOUT : __ec;
1047162fd75SLouis Dionne }
1057162fd75SLouis Dionne 
__libcpp_condvar_destroy(__libcpp_condvar_t * __cv)1067162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) {
1077162fd75SLouis Dionne   cnd_destroy(__cv);
1087162fd75SLouis Dionne   return 0;
1097162fd75SLouis Dionne }
1107162fd75SLouis Dionne 
1117162fd75SLouis Dionne //
1127162fd75SLouis Dionne // Execute once
1137162fd75SLouis Dionne //
1147162fd75SLouis Dionne typedef ::once_flag __libcpp_exec_once_flag;
1157162fd75SLouis Dionne #define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT
1167162fd75SLouis Dionne 
__libcpp_execute_once(__libcpp_exec_once_flag * flag,void (* init_routine)(void))1177162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI int __libcpp_execute_once(__libcpp_exec_once_flag* flag, void (*init_routine)(void)) {
1187162fd75SLouis Dionne   ::call_once(flag, init_routine);
1197162fd75SLouis Dionne   return 0;
1207162fd75SLouis Dionne }
1217162fd75SLouis Dionne 
1227162fd75SLouis Dionne //
1237162fd75SLouis Dionne // Thread id
1247162fd75SLouis Dionne //
1257162fd75SLouis Dionne typedef thrd_t __libcpp_thread_id;
1267162fd75SLouis Dionne 
1277162fd75SLouis Dionne // Returns non-zero if the thread ids are equal, otherwise 0
__libcpp_thread_id_equal(__libcpp_thread_id t1,__libcpp_thread_id t2)1287162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) {
1297162fd75SLouis Dionne   return thrd_equal(t1, t2) != 0;
1307162fd75SLouis Dionne }
1317162fd75SLouis Dionne 
1327162fd75SLouis Dionne // Returns non-zero if t1 < t2, otherwise 0
__libcpp_thread_id_less(__libcpp_thread_id t1,__libcpp_thread_id t2)1337162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) {
1347162fd75SLouis Dionne   return t1 < t2;
1357162fd75SLouis Dionne }
1367162fd75SLouis Dionne 
1377162fd75SLouis Dionne //
1387162fd75SLouis Dionne // Thread
1397162fd75SLouis Dionne //
1407162fd75SLouis Dionne #define _LIBCPP_NULL_THREAD 0U
1417162fd75SLouis Dionne 
1427162fd75SLouis Dionne typedef thrd_t __libcpp_thread_t;
1437162fd75SLouis Dionne 
__libcpp_thread_get_id(const __libcpp_thread_t * __t)1447162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) { return *__t; }
1457162fd75SLouis Dionne 
__libcpp_thread_isnull(const __libcpp_thread_t * __t)1467162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_isnull(const __libcpp_thread_t* __t) {
1477162fd75SLouis Dionne   return __libcpp_thread_get_id(__t) == 0;
1487162fd75SLouis Dionne }
1497162fd75SLouis Dionne 
__libcpp_thread_create(__libcpp_thread_t * __t,void * (* __func)(void *),void * __arg)1507162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) {
1517162fd75SLouis Dionne   int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
1527162fd75SLouis Dionne   return __ec == thrd_nomem ? ENOMEM : __ec;
1537162fd75SLouis Dionne }
1547162fd75SLouis Dionne 
__libcpp_thread_get_current_id()1557162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_current_id() { return thrd_current(); }
1567162fd75SLouis Dionne 
__libcpp_thread_join(__libcpp_thread_t * __t)1577162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_join(__libcpp_thread_t* __t) {
1587162fd75SLouis Dionne   return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
1597162fd75SLouis Dionne }
1607162fd75SLouis Dionne 
__libcpp_thread_detach(__libcpp_thread_t * __t)1617162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_detach(__libcpp_thread_t* __t) {
1627162fd75SLouis Dionne   return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
1637162fd75SLouis Dionne }
1647162fd75SLouis Dionne 
__libcpp_thread_yield()1657162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_yield() { thrd_yield(); }
1667162fd75SLouis Dionne 
__libcpp_thread_sleep_for(const chrono::nanoseconds & __ns)1677162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) {
1687162fd75SLouis Dionne   __libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns);
1697162fd75SLouis Dionne   thrd_sleep(&__ts, nullptr);
1707162fd75SLouis Dionne }
1717162fd75SLouis Dionne 
1727162fd75SLouis Dionne //
1737162fd75SLouis Dionne // Thread local storage
1747162fd75SLouis Dionne //
1757162fd75SLouis Dionne #define _LIBCPP_TLS_DESTRUCTOR_CC /* nothing */
1767162fd75SLouis Dionne 
1777162fd75SLouis Dionne typedef tss_t __libcpp_tls_key;
1787162fd75SLouis Dionne 
__libcpp_tls_create(__libcpp_tls_key * __key,void (* __at_exit)(void *))1797162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*)) {
1807162fd75SLouis Dionne   return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
1817162fd75SLouis Dionne }
1827162fd75SLouis Dionne 
__libcpp_tls_get(__libcpp_tls_key __key)1837162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI void* __libcpp_tls_get(__libcpp_tls_key __key) { return tss_get(__key); }
1847162fd75SLouis Dionne 
__libcpp_tls_set(__libcpp_tls_key __key,void * __p)1857162fd75SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_set(__libcpp_tls_key __key, void* __p) {
1867162fd75SLouis Dionne   return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
1877162fd75SLouis Dionne }
1887162fd75SLouis Dionne 
1897162fd75SLouis Dionne _LIBCPP_END_NAMESPACE_STD
1907162fd75SLouis Dionne 
1917162fd75SLouis Dionne #endif // _LIBCPP___THREAD_SUPPORT_C11_H
192