146035553Spatrick// -*- C++ -*- 246035553Spatrick//===----------------------------------------------------------------------===// 346035553Spatrick// 446035553Spatrick// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 546035553Spatrick// See https://llvm.org/LICENSE.txt for license information. 646035553Spatrick// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 746035553Spatrick// 846035553Spatrick//===----------------------------------------------------------------------===// 946035553Spatrick 10*4bdff4beSrobert#ifndef _LIBCPP___THREADING_SUPPORT 11*4bdff4beSrobert#define _LIBCPP___THREADING_SUPPORT 1246035553Spatrick 1376d0caaeSpatrick#include <__availability> 14*4bdff4beSrobert#include <__chrono/convert_to_timespec.h> 15*4bdff4beSrobert#include <__chrono/duration.h> 16*4bdff4beSrobert#include <__compare/ordering.h> 1746035553Spatrick#include <__config> 18*4bdff4beSrobert#include <__fwd/hash.h> 19*4bdff4beSrobert#include <__thread/poll_with_backoff.h> 2046035553Spatrick#include <errno.h> 2176d0caaeSpatrick#include <iosfwd> 2276d0caaeSpatrick#include <limits> 2376d0caaeSpatrick 2476d0caaeSpatrick#ifdef __MVS__ 2576d0caaeSpatrick# include <__support/ibm/nanosleep.h> 2676d0caaeSpatrick#endif 2746035553Spatrick 2846035553Spatrick#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 2946035553Spatrick# pragma GCC system_header 3046035553Spatrick#endif 3146035553Spatrick 3246035553Spatrick#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 3346035553Spatrick# include <__external_threading> 3446035553Spatrick#elif !defined(_LIBCPP_HAS_NO_THREADS) 3546035553Spatrick 3646035553Spatrick#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 3746035553Spatrick# include <pthread.h> 3846035553Spatrick# include <sched.h> 3946035553Spatrick#elif defined(_LIBCPP_HAS_THREAD_API_C11) 4046035553Spatrick# include <threads.h> 4146035553Spatrick#endif 4246035553Spatrick 4346035553Spatrick#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 4446035553Spatrick defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \ 4546035553Spatrick defined(_LIBCPP_HAS_THREAD_API_WIN32) 4646035553Spatrick#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 4746035553Spatrick#else 4846035553Spatrick#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 4946035553Spatrick#endif 5046035553Spatrick 5146035553Spatrick#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) 5246035553Spatrick#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) 5346035553Spatrick#else 5446035553Spatrick#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 5546035553Spatrick#endif 5646035553Spatrick 5746035553Spatricktypedef ::timespec __libcpp_timespec_t; 5846035553Spatrick#endif // !defined(_LIBCPP_HAS_NO_THREADS) 5946035553Spatrick 6046035553Spatrick_LIBCPP_BEGIN_NAMESPACE_STD 6146035553Spatrick 6246035553Spatrick#if !defined(_LIBCPP_HAS_NO_THREADS) 6346035553Spatrick 6446035553Spatrick#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 6546035553Spatrick// Mutex 6646035553Spatricktypedef pthread_mutex_t __libcpp_mutex_t; 6746035553Spatrick#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 6846035553Spatrick 6946035553Spatricktypedef pthread_mutex_t __libcpp_recursive_mutex_t; 7046035553Spatrick 7146035553Spatrick// Condition Variable 7246035553Spatricktypedef pthread_cond_t __libcpp_condvar_t; 7346035553Spatrick#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 7446035553Spatrick 7546035553Spatrick// Execute once 7646035553Spatricktypedef pthread_once_t __libcpp_exec_once_flag; 7746035553Spatrick#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 7846035553Spatrick 7946035553Spatrick// Thread id 8076d0caaeSpatrick#if defined(__MVS__) 8176d0caaeSpatrick typedef unsigned long long __libcpp_thread_id; 8276d0caaeSpatrick#else 8346035553Spatrick typedef pthread_t __libcpp_thread_id; 8476d0caaeSpatrick#endif 8546035553Spatrick 8646035553Spatrick// Thread 8776d0caaeSpatrick#define _LIBCPP_NULL_THREAD ((__libcpp_thread_t())) 8846035553Spatricktypedef pthread_t __libcpp_thread_t; 8946035553Spatrick 9046035553Spatrick// Thread Local Storage 9146035553Spatricktypedef pthread_key_t __libcpp_tls_key; 9246035553Spatrick 9346035553Spatrick#define _LIBCPP_TLS_DESTRUCTOR_CC 9446035553Spatrick#elif defined(_LIBCPP_HAS_THREAD_API_C11) 9546035553Spatrick// Mutex 9646035553Spatricktypedef mtx_t __libcpp_mutex_t; 9746035553Spatrick// mtx_t is a struct so using {} for initialization is valid. 9846035553Spatrick#define _LIBCPP_MUTEX_INITIALIZER {} 9946035553Spatrick 10046035553Spatricktypedef mtx_t __libcpp_recursive_mutex_t; 10146035553Spatrick 10246035553Spatrick// Condition Variable 10346035553Spatricktypedef cnd_t __libcpp_condvar_t; 10446035553Spatrick// cnd_t is a struct so using {} for initialization is valid. 10546035553Spatrick#define _LIBCPP_CONDVAR_INITIALIZER {} 10646035553Spatrick 10746035553Spatrick// Execute once 10846035553Spatricktypedef once_flag __libcpp_exec_once_flag; 10946035553Spatrick#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT 11046035553Spatrick 11146035553Spatrick// Thread id 11246035553Spatricktypedef thrd_t __libcpp_thread_id; 11346035553Spatrick 11446035553Spatrick// Thread 11546035553Spatrick#define _LIBCPP_NULL_THREAD 0U 11646035553Spatrick 11746035553Spatricktypedef thrd_t __libcpp_thread_t; 11846035553Spatrick 11946035553Spatrick// Thread Local Storage 12046035553Spatricktypedef tss_t __libcpp_tls_key; 12146035553Spatrick 12246035553Spatrick#define _LIBCPP_TLS_DESTRUCTOR_CC 12346035553Spatrick#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 12446035553Spatrick// Mutex 12546035553Spatricktypedef void* __libcpp_mutex_t; 12646035553Spatrick#define _LIBCPP_MUTEX_INITIALIZER 0 12746035553Spatrick 12846035553Spatrick#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) 12946035553Spatricktypedef void* __libcpp_recursive_mutex_t[6]; 13046035553Spatrick#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) 13146035553Spatricktypedef void* __libcpp_recursive_mutex_t[5]; 13246035553Spatrick#else 13346035553Spatrick# error Unsupported architecture 13446035553Spatrick#endif 13546035553Spatrick 13646035553Spatrick// Condition Variable 13746035553Spatricktypedef void* __libcpp_condvar_t; 13846035553Spatrick#define _LIBCPP_CONDVAR_INITIALIZER 0 13946035553Spatrick 14046035553Spatrick// Execute Once 14146035553Spatricktypedef void* __libcpp_exec_once_flag; 14246035553Spatrick#define _LIBCPP_EXEC_ONCE_INITIALIZER 0 14346035553Spatrick 14446035553Spatrick// Thread ID 14546035553Spatricktypedef long __libcpp_thread_id; 14646035553Spatrick 14746035553Spatrick// Thread 14846035553Spatrick#define _LIBCPP_NULL_THREAD 0U 14946035553Spatrick 15046035553Spatricktypedef void* __libcpp_thread_t; 15146035553Spatrick 15246035553Spatrick// Thread Local Storage 15346035553Spatricktypedef long __libcpp_tls_key; 15446035553Spatrick 15546035553Spatrick#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall 15646035553Spatrick#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 15746035553Spatrick 15846035553Spatrick#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 15946035553Spatrick// Mutex 16046035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 16146035553Spatrickint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 16246035553Spatrick 16346035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 16446035553Spatrickint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 16546035553Spatrick 16646035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 16746035553Spatrickbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 16846035553Spatrick 16946035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 17046035553Spatrickint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 17146035553Spatrick 17246035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 17346035553Spatrickint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 17446035553Spatrick 17546035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 17646035553Spatrickint __libcpp_mutex_lock(__libcpp_mutex_t *__m); 17746035553Spatrick 17846035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 17946035553Spatrickbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 18046035553Spatrick 18146035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 18246035553Spatrickint __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 18346035553Spatrick 18446035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 18546035553Spatrickint __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 18646035553Spatrick 18746035553Spatrick// Condition variable 18846035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 18946035553Spatrickint __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 19046035553Spatrick 19146035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 19246035553Spatrickint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 19346035553Spatrick 19446035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 19546035553Spatrickint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 19646035553Spatrick 19746035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 19846035553Spatrickint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 19946035553Spatrick __libcpp_timespec_t *__ts); 20046035553Spatrick 20146035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 20246035553Spatrickint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 20346035553Spatrick 20446035553Spatrick// Execute once 20546035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 206*4bdff4beSrobertint __libcpp_execute_once(__libcpp_exec_once_flag *__flag, 207*4bdff4beSrobert void (*__init_routine)()); 20846035553Spatrick 20946035553Spatrick// Thread id 21046035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 211*4bdff4beSrobertbool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2); 21246035553Spatrick 21346035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 214*4bdff4beSrobertbool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2); 21546035553Spatrick 21646035553Spatrick// Thread 21746035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 21846035553Spatrickbool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 21946035553Spatrick 22046035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 22146035553Spatrickint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 22246035553Spatrick void *__arg); 22346035553Spatrick 22446035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 22546035553Spatrick__libcpp_thread_id __libcpp_thread_get_current_id(); 22646035553Spatrick 22746035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 22846035553Spatrick__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 22946035553Spatrick 23046035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 23146035553Spatrickint __libcpp_thread_join(__libcpp_thread_t *__t); 23246035553Spatrick 23346035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 23446035553Spatrickint __libcpp_thread_detach(__libcpp_thread_t *__t); 23546035553Spatrick 23646035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 23746035553Spatrickvoid __libcpp_thread_yield(); 23846035553Spatrick 23946035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 24046035553Spatrickvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 24146035553Spatrick 24246035553Spatrick// Thread local storage 24346035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 24446035553Spatrickint __libcpp_tls_create(__libcpp_tls_key* __key, 24546035553Spatrick void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 24646035553Spatrick 24746035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 24846035553Spatrickvoid *__libcpp_tls_get(__libcpp_tls_key __key); 24946035553Spatrick 25046035553Spatrick_LIBCPP_THREAD_ABI_VISIBILITY 25146035553Spatrickint __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 25246035553Spatrick 25346035553Spatrick#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 25446035553Spatrick 25546035553Spatrick#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 25646035553Spatrick defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) 25746035553Spatrick 25846035553Spatrick#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 25946035553Spatrick 26046035553Spatrickint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 26146035553Spatrick{ 26246035553Spatrick pthread_mutexattr_t attr; 26346035553Spatrick int __ec = pthread_mutexattr_init(&attr); 26446035553Spatrick if (__ec) 26546035553Spatrick return __ec; 26646035553Spatrick __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 26746035553Spatrick if (__ec) { 26846035553Spatrick pthread_mutexattr_destroy(&attr); 26946035553Spatrick return __ec; 27046035553Spatrick } 27146035553Spatrick __ec = pthread_mutex_init(__m, &attr); 27246035553Spatrick if (__ec) { 27346035553Spatrick pthread_mutexattr_destroy(&attr); 27446035553Spatrick return __ec; 27546035553Spatrick } 27646035553Spatrick __ec = pthread_mutexattr_destroy(&attr); 27746035553Spatrick if (__ec) { 27846035553Spatrick pthread_mutex_destroy(__m); 27946035553Spatrick return __ec; 28046035553Spatrick } 28146035553Spatrick return 0; 28246035553Spatrick} 28346035553Spatrick 28446035553Spatrickint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 28546035553Spatrick{ 28646035553Spatrick return pthread_mutex_lock(__m); 28746035553Spatrick} 28846035553Spatrick 28946035553Spatrickbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 29046035553Spatrick{ 29146035553Spatrick return pthread_mutex_trylock(__m) == 0; 29246035553Spatrick} 29346035553Spatrick 29476d0caaeSpatrickint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 29546035553Spatrick{ 29646035553Spatrick return pthread_mutex_unlock(__m); 29746035553Spatrick} 29846035553Spatrick 29946035553Spatrickint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 30046035553Spatrick{ 30146035553Spatrick return pthread_mutex_destroy(__m); 30246035553Spatrick} 30346035553Spatrick 30446035553Spatrickint __libcpp_mutex_lock(__libcpp_mutex_t *__m) 30546035553Spatrick{ 30646035553Spatrick return pthread_mutex_lock(__m); 30746035553Spatrick} 30846035553Spatrick 30946035553Spatrickbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 31046035553Spatrick{ 31146035553Spatrick return pthread_mutex_trylock(__m) == 0; 31246035553Spatrick} 31346035553Spatrick 31446035553Spatrickint __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 31546035553Spatrick{ 31646035553Spatrick return pthread_mutex_unlock(__m); 31746035553Spatrick} 31846035553Spatrick 31946035553Spatrickint __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 32046035553Spatrick{ 32146035553Spatrick return pthread_mutex_destroy(__m); 32246035553Spatrick} 32346035553Spatrick 32446035553Spatrick// Condition Variable 32546035553Spatrickint __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 32646035553Spatrick{ 32746035553Spatrick return pthread_cond_signal(__cv); 32846035553Spatrick} 32946035553Spatrick 33046035553Spatrickint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 33146035553Spatrick{ 33246035553Spatrick return pthread_cond_broadcast(__cv); 33346035553Spatrick} 33446035553Spatrick 33546035553Spatrickint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 33646035553Spatrick{ 33746035553Spatrick return pthread_cond_wait(__cv, __m); 33846035553Spatrick} 33946035553Spatrick 34046035553Spatrickint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 34146035553Spatrick __libcpp_timespec_t *__ts) 34246035553Spatrick{ 34346035553Spatrick return pthread_cond_timedwait(__cv, __m, __ts); 34446035553Spatrick} 34546035553Spatrick 34646035553Spatrickint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 34746035553Spatrick{ 34846035553Spatrick return pthread_cond_destroy(__cv); 34946035553Spatrick} 35046035553Spatrick 35146035553Spatrick// Execute once 352*4bdff4beSrobertint __libcpp_execute_once(__libcpp_exec_once_flag *__flag, 353*4bdff4beSrobert void (*__init_routine)()) { 354*4bdff4beSrobert return pthread_once(__flag, __init_routine); 35546035553Spatrick} 35646035553Spatrick 35746035553Spatrick// Thread id 35846035553Spatrick// Returns non-zero if the thread ids are equal, otherwise 0 359*4bdff4beSrobertbool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2) 36046035553Spatrick{ 361*4bdff4beSrobert return __t1 == __t2; 36246035553Spatrick} 36346035553Spatrick 36446035553Spatrick// Returns non-zero if t1 < t2, otherwise 0 365*4bdff4beSrobertbool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2) 36646035553Spatrick{ 367*4bdff4beSrobert return __t1 < __t2; 36846035553Spatrick} 36946035553Spatrick 37046035553Spatrick// Thread 37146035553Spatrickbool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 37276d0caaeSpatrick return __libcpp_thread_get_id(__t) == 0; 37346035553Spatrick} 37446035553Spatrick 37546035553Spatrickint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 37646035553Spatrick void *__arg) 37746035553Spatrick{ 37876d0caaeSpatrick return pthread_create(__t, nullptr, __func, __arg); 37946035553Spatrick} 38046035553Spatrick 38146035553Spatrick__libcpp_thread_id __libcpp_thread_get_current_id() 38246035553Spatrick{ 38376d0caaeSpatrick const __libcpp_thread_t thread = pthread_self(); 38476d0caaeSpatrick return __libcpp_thread_get_id(&thread); 38546035553Spatrick} 38646035553Spatrick 38746035553Spatrick__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 38846035553Spatrick{ 38976d0caaeSpatrick#if defined(__MVS__) 39076d0caaeSpatrick return __t->__; 39176d0caaeSpatrick#else 39246035553Spatrick return *__t; 39376d0caaeSpatrick#endif 39446035553Spatrick} 39546035553Spatrick 39646035553Spatrickint __libcpp_thread_join(__libcpp_thread_t *__t) 39746035553Spatrick{ 39876d0caaeSpatrick return pthread_join(*__t, nullptr); 39946035553Spatrick} 40046035553Spatrick 40146035553Spatrickint __libcpp_thread_detach(__libcpp_thread_t *__t) 40246035553Spatrick{ 40346035553Spatrick return pthread_detach(*__t); 40446035553Spatrick} 40546035553Spatrick 40646035553Spatrickvoid __libcpp_thread_yield() 40746035553Spatrick{ 40846035553Spatrick sched_yield(); 40946035553Spatrick} 41046035553Spatrick 41146035553Spatrickvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 41246035553Spatrick{ 413*4bdff4beSrobert __libcpp_timespec_t __ts = _VSTD::__convert_to_timespec<__libcpp_timespec_t>(__ns); 41446035553Spatrick while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); 41546035553Spatrick} 41646035553Spatrick 41746035553Spatrick// Thread local storage 41846035553Spatrickint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 41946035553Spatrick{ 42046035553Spatrick return pthread_key_create(__key, __at_exit); 42146035553Spatrick} 42246035553Spatrick 42346035553Spatrickvoid *__libcpp_tls_get(__libcpp_tls_key __key) 42446035553Spatrick{ 42546035553Spatrick return pthread_getspecific(__key); 42646035553Spatrick} 42746035553Spatrick 42846035553Spatrickint __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 42946035553Spatrick{ 43046035553Spatrick return pthread_setspecific(__key, __p); 43146035553Spatrick} 43246035553Spatrick 43346035553Spatrick#elif defined(_LIBCPP_HAS_THREAD_API_C11) 43446035553Spatrick 43546035553Spatrickint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 43646035553Spatrick{ 43746035553Spatrick return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL; 43846035553Spatrick} 43946035553Spatrick 44046035553Spatrickint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 44146035553Spatrick{ 44246035553Spatrick return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 44346035553Spatrick} 44446035553Spatrick 44546035553Spatrickbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 44646035553Spatrick{ 44746035553Spatrick return mtx_trylock(__m) == thrd_success; 44846035553Spatrick} 44946035553Spatrick 45076d0caaeSpatrickint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 45146035553Spatrick{ 45246035553Spatrick return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 45346035553Spatrick} 45446035553Spatrick 45546035553Spatrickint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 45646035553Spatrick{ 45746035553Spatrick mtx_destroy(__m); 45846035553Spatrick return 0; 45946035553Spatrick} 46046035553Spatrick 46146035553Spatrickint __libcpp_mutex_lock(__libcpp_mutex_t *__m) 46246035553Spatrick{ 46346035553Spatrick return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 46446035553Spatrick} 46546035553Spatrick 46646035553Spatrickbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 46746035553Spatrick{ 46846035553Spatrick return mtx_trylock(__m) == thrd_success; 46946035553Spatrick} 47046035553Spatrick 47146035553Spatrickint __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 47246035553Spatrick{ 47346035553Spatrick return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 47446035553Spatrick} 47546035553Spatrick 47646035553Spatrickint __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 47746035553Spatrick{ 47846035553Spatrick mtx_destroy(__m); 47946035553Spatrick return 0; 48046035553Spatrick} 48146035553Spatrick 48246035553Spatrick// Condition Variable 48346035553Spatrickint __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 48446035553Spatrick{ 48546035553Spatrick return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; 48646035553Spatrick} 48746035553Spatrick 48846035553Spatrickint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 48946035553Spatrick{ 49046035553Spatrick return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; 49146035553Spatrick} 49246035553Spatrick 49346035553Spatrickint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 49446035553Spatrick{ 49546035553Spatrick return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL; 49646035553Spatrick} 49746035553Spatrick 49846035553Spatrickint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 49946035553Spatrick timespec *__ts) 50046035553Spatrick{ 50146035553Spatrick int __ec = cnd_timedwait(__cv, __m, __ts); 50246035553Spatrick return __ec == thrd_timedout ? ETIMEDOUT : __ec; 50346035553Spatrick} 50446035553Spatrick 50546035553Spatrickint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 50646035553Spatrick{ 50746035553Spatrick cnd_destroy(__cv); 50846035553Spatrick return 0; 50946035553Spatrick} 51046035553Spatrick 51146035553Spatrick// Execute once 51246035553Spatrickint __libcpp_execute_once(__libcpp_exec_once_flag *flag, 51346035553Spatrick void (*init_routine)(void)) { 51446035553Spatrick ::call_once(flag, init_routine); 51546035553Spatrick return 0; 51646035553Spatrick} 51746035553Spatrick 51846035553Spatrick// Thread id 51946035553Spatrick// Returns non-zero if the thread ids are equal, otherwise 0 52046035553Spatrickbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 52146035553Spatrick{ 52246035553Spatrick return thrd_equal(t1, t2) != 0; 52346035553Spatrick} 52446035553Spatrick 52546035553Spatrick// Returns non-zero if t1 < t2, otherwise 0 52646035553Spatrickbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 52746035553Spatrick{ 52846035553Spatrick return t1 < t2; 52946035553Spatrick} 53046035553Spatrick 53146035553Spatrick// Thread 53246035553Spatrickbool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 53376d0caaeSpatrick return __libcpp_thread_get_id(__t) == 0; 53446035553Spatrick} 53546035553Spatrick 53646035553Spatrickint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 53746035553Spatrick void *__arg) 53846035553Spatrick{ 53946035553Spatrick int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg); 54046035553Spatrick return __ec == thrd_nomem ? ENOMEM : __ec; 54146035553Spatrick} 54246035553Spatrick 54346035553Spatrick__libcpp_thread_id __libcpp_thread_get_current_id() 54446035553Spatrick{ 54546035553Spatrick return thrd_current(); 54646035553Spatrick} 54746035553Spatrick 54846035553Spatrick__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 54946035553Spatrick{ 55046035553Spatrick return *__t; 55146035553Spatrick} 55246035553Spatrick 55346035553Spatrickint __libcpp_thread_join(__libcpp_thread_t *__t) 55446035553Spatrick{ 55546035553Spatrick return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; 55646035553Spatrick} 55746035553Spatrick 55846035553Spatrickint __libcpp_thread_detach(__libcpp_thread_t *__t) 55946035553Spatrick{ 56046035553Spatrick return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; 56146035553Spatrick} 56246035553Spatrick 56346035553Spatrickvoid __libcpp_thread_yield() 56446035553Spatrick{ 56546035553Spatrick thrd_yield(); 56646035553Spatrick} 56746035553Spatrick 56846035553Spatrickvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 56946035553Spatrick{ 570*4bdff4beSrobert __libcpp_timespec_t __ts = _VSTD::__convert_to_timespec<__libcpp_timespec_t>(__ns); 57146035553Spatrick thrd_sleep(&__ts, nullptr); 57246035553Spatrick} 57346035553Spatrick 57446035553Spatrick// Thread local storage 57546035553Spatrickint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 57646035553Spatrick{ 57746035553Spatrick return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL; 57846035553Spatrick} 57946035553Spatrick 58046035553Spatrickvoid *__libcpp_tls_get(__libcpp_tls_key __key) 58146035553Spatrick{ 58246035553Spatrick return tss_get(__key); 58346035553Spatrick} 58446035553Spatrick 58546035553Spatrickint __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 58646035553Spatrick{ 58746035553Spatrick return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; 58846035553Spatrick} 58946035553Spatrick 59046035553Spatrick#endif 59146035553Spatrick 592037e7968Spatrick 59346035553Spatrick#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 59446035553Spatrick 59546035553Spatrickclass _LIBCPP_TYPE_VIS thread; 59646035553Spatrickclass _LIBCPP_TYPE_VIS __thread_id; 59746035553Spatrick 59846035553Spatricknamespace this_thread 59946035553Spatrick{ 60046035553Spatrick 60146035553Spatrick_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; 60246035553Spatrick 603*4bdff4beSrobert} // namespace this_thread 60446035553Spatrick 60546035553Spatricktemplate<> struct hash<__thread_id>; 60646035553Spatrick 60746035553Spatrickclass _LIBCPP_TEMPLATE_VIS __thread_id 60846035553Spatrick{ 60946035553Spatrick // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 61046035553Spatrick // NULL is the no-thread value on Darwin. Someone needs to check 61146035553Spatrick // on other platforms. We assume 0 works everywhere for now. 61246035553Spatrick __libcpp_thread_id __id_; 61346035553Spatrick 614*4bdff4beSrobert static _LIBCPP_HIDE_FROM_ABI 615*4bdff4beSrobert bool __lt_impl(__thread_id __x, __thread_id __y) _NOEXCEPT 61646035553Spatrick { // id==0 is always less than any other thread_id 61746035553Spatrick if (__x.__id_ == 0) return __y.__id_ != 0; 61846035553Spatrick if (__y.__id_ == 0) return false; 61946035553Spatrick return __libcpp_thread_id_less(__x.__id_, __y.__id_); 62046035553Spatrick } 621*4bdff4beSrobert 622*4bdff4beSrobertpublic: 623*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 624*4bdff4beSrobert __thread_id() _NOEXCEPT : __id_(0) {} 62546035553Spatrick 62646035553Spatrick _LIBCPP_INLINE_VISIBILITY 62746035553Spatrick void __reset() { __id_ = 0; } 62846035553Spatrick 629*4bdff4beSrobert friend _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT; 630*4bdff4beSrobert#if _LIBCPP_STD_VER <= 17 631*4bdff4beSrobert friend _LIBCPP_HIDE_FROM_ABI bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT; 632*4bdff4beSrobert#else // _LIBCPP_STD_VER <= 17 633*4bdff4beSrobert friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept; 634*4bdff4beSrobert#endif // _LIBCPP_STD_VER <= 17 635*4bdff4beSrobert 63646035553Spatrick template<class _CharT, class _Traits> 63746035553Spatrick friend 63846035553Spatrick _LIBCPP_INLINE_VISIBILITY 63946035553Spatrick basic_ostream<_CharT, _Traits>& 64046035553Spatrick operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); 64146035553Spatrick 64246035553Spatrickprivate: 64346035553Spatrick _LIBCPP_INLINE_VISIBILITY 64446035553Spatrick __thread_id(__libcpp_thread_id __id) : __id_(__id) {} 64546035553Spatrick 64646035553Spatrick friend __thread_id this_thread::get_id() _NOEXCEPT; 64746035553Spatrick friend class _LIBCPP_TYPE_VIS thread; 64846035553Spatrick friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; 64946035553Spatrick}; 65046035553Spatrick 651*4bdff4beSrobertinline _LIBCPP_HIDE_FROM_ABI 652*4bdff4beSrobertbool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT { 653*4bdff4beSrobert // Don't pass id==0 to underlying routines 654*4bdff4beSrobert if (__x.__id_ == 0) 655*4bdff4beSrobert return __y.__id_ == 0; 656*4bdff4beSrobert if (__y.__id_ == 0) 657*4bdff4beSrobert return false; 658*4bdff4beSrobert return __libcpp_thread_id_equal(__x.__id_, __y.__id_); 659*4bdff4beSrobert} 660*4bdff4beSrobert 661*4bdff4beSrobert#if _LIBCPP_STD_VER <= 17 662*4bdff4beSrobert 663*4bdff4beSrobertinline _LIBCPP_HIDE_FROM_ABI 664*4bdff4beSrobertbool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT { 665*4bdff4beSrobert return !(__x == __y); 666*4bdff4beSrobert} 667*4bdff4beSrobert 668*4bdff4beSrobertinline _LIBCPP_HIDE_FROM_ABI 669*4bdff4beSrobertbool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT { 670*4bdff4beSrobert return __thread_id::__lt_impl(__x.__id_, __y.__id_); 671*4bdff4beSrobert} 672*4bdff4beSrobert 673*4bdff4beSrobertinline _LIBCPP_HIDE_FROM_ABI bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__y < __x); } 674*4bdff4beSrobertinline _LIBCPP_HIDE_FROM_ABI bool operator>(__thread_id __x, __thread_id __y) _NOEXCEPT { return __y < __x; } 675*4bdff4beSrobertinline _LIBCPP_HIDE_FROM_ABI bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__x < __y); } 676*4bdff4beSrobert 677*4bdff4beSrobert#else // _LIBCPP_STD_VER <= 17 678*4bdff4beSrobert 679*4bdff4beSrobertinline _LIBCPP_HIDE_FROM_ABI 680*4bdff4beSrobertstrong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept { 681*4bdff4beSrobert if (__x == __y) 682*4bdff4beSrobert return strong_ordering::equal; 683*4bdff4beSrobert if (__thread_id::__lt_impl(__x, __y)) 684*4bdff4beSrobert return strong_ordering::less; 685*4bdff4beSrobert return strong_ordering::greater; 686*4bdff4beSrobert} 687*4bdff4beSrobert 688*4bdff4beSrobert#endif // _LIBCPP_STD_VER <= 17 689*4bdff4beSrobert 69046035553Spatricknamespace this_thread 69146035553Spatrick{ 69246035553Spatrick 69346035553Spatrickinline _LIBCPP_INLINE_VISIBILITY 69446035553Spatrick__thread_id 69546035553Spatrickget_id() _NOEXCEPT 69646035553Spatrick{ 69746035553Spatrick return __libcpp_thread_get_current_id(); 69846035553Spatrick} 69946035553Spatrick 700*4bdff4beSrobert} // namespace this_thread 70146035553Spatrick 70246035553Spatrick#endif // !_LIBCPP_HAS_NO_THREADS 70346035553Spatrick 70446035553Spatrick_LIBCPP_END_NAMESPACE_STD 70546035553Spatrick 706*4bdff4beSrobert#endif // _LIBCPP___THREADING_SUPPORT 707