1*4d6fc14bSjoerg// -*- C++ -*- 2*4d6fc14bSjoerg//===----------------------------------------------------------------------===// 3*4d6fc14bSjoerg// 4*4d6fc14bSjoerg// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*4d6fc14bSjoerg// See https://llvm.org/LICENSE.txt for license information. 6*4d6fc14bSjoerg// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*4d6fc14bSjoerg// 8*4d6fc14bSjoerg//===----------------------------------------------------------------------===// 9*4d6fc14bSjoerg 10*4d6fc14bSjoerg#ifndef _LIBCPP_THREADING_SUPPORT 11*4d6fc14bSjoerg#define _LIBCPP_THREADING_SUPPORT 12*4d6fc14bSjoerg 13*4d6fc14bSjoerg#include <__config> 14*4d6fc14bSjoerg#include <__availability> 15*4d6fc14bSjoerg#include <chrono> 16*4d6fc14bSjoerg#include <iosfwd> 17*4d6fc14bSjoerg#include <errno.h> 18*4d6fc14bSjoerg#include <limits> 19*4d6fc14bSjoerg 20*4d6fc14bSjoerg#ifdef __MVS__ 21*4d6fc14bSjoerg# include <__support/ibm/nanosleep.h> 22*4d6fc14bSjoerg#endif 23*4d6fc14bSjoerg 24*4d6fc14bSjoerg#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 25*4d6fc14bSjoerg#pragma GCC system_header 26*4d6fc14bSjoerg#endif 27*4d6fc14bSjoerg 28*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 29*4d6fc14bSjoerg# include <__external_threading> 30*4d6fc14bSjoerg#elif !defined(_LIBCPP_HAS_NO_THREADS) 31*4d6fc14bSjoerg 32*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 33*4d6fc14bSjoerg# include <pthread.h> 34*4d6fc14bSjoerg# include <sched.h> 35*4d6fc14bSjoerg# if defined(__APPLE__) || defined(__MVS__) 36*4d6fc14bSjoerg# define _LIBCPP_NO_NATIVE_SEMAPHORES 37*4d6fc14bSjoerg# endif 38*4d6fc14bSjoerg# ifndef _LIBCPP_NO_NATIVE_SEMAPHORES 39*4d6fc14bSjoerg# include <semaphore.h> 40*4d6fc14bSjoerg# endif 41*4d6fc14bSjoerg#elif defined(_LIBCPP_HAS_THREAD_API_C11) 42*4d6fc14bSjoerg# include <threads.h> 43*4d6fc14bSjoerg#endif 44*4d6fc14bSjoerg 45*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 46*4d6fc14bSjoerg defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \ 47*4d6fc14bSjoerg defined(_LIBCPP_HAS_THREAD_API_WIN32) 48*4d6fc14bSjoerg#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 49*4d6fc14bSjoerg#else 50*4d6fc14bSjoerg#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 51*4d6fc14bSjoerg#endif 52*4d6fc14bSjoerg 53*4d6fc14bSjoerg#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) 54*4d6fc14bSjoerg#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) 55*4d6fc14bSjoerg#else 56*4d6fc14bSjoerg#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 57*4d6fc14bSjoerg#endif 58*4d6fc14bSjoerg 59*4d6fc14bSjoergtypedef ::timespec __libcpp_timespec_t; 60*4d6fc14bSjoerg#endif // !defined(_LIBCPP_HAS_NO_THREADS) 61*4d6fc14bSjoerg 62*4d6fc14bSjoerg_LIBCPP_PUSH_MACROS 63*4d6fc14bSjoerg#include <__undef_macros> 64*4d6fc14bSjoerg 65*4d6fc14bSjoerg_LIBCPP_BEGIN_NAMESPACE_STD 66*4d6fc14bSjoerg 67*4d6fc14bSjoerg#if !defined(_LIBCPP_HAS_NO_THREADS) 68*4d6fc14bSjoerg 69*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 70*4d6fc14bSjoerg// Mutex 71*4d6fc14bSjoergtypedef pthread_mutex_t __libcpp_mutex_t; 72*4d6fc14bSjoerg#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 73*4d6fc14bSjoerg 74*4d6fc14bSjoergtypedef pthread_mutex_t __libcpp_recursive_mutex_t; 75*4d6fc14bSjoerg 76*4d6fc14bSjoerg// Condition Variable 77*4d6fc14bSjoergtypedef pthread_cond_t __libcpp_condvar_t; 78*4d6fc14bSjoerg#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 79*4d6fc14bSjoerg 80*4d6fc14bSjoerg#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES 81*4d6fc14bSjoerg// Semaphore 82*4d6fc14bSjoergtypedef sem_t __libcpp_semaphore_t; 83*4d6fc14bSjoerg# define _LIBCPP_SEMAPHORE_MAX SEM_VALUE_MAX 84*4d6fc14bSjoerg#endif 85*4d6fc14bSjoerg 86*4d6fc14bSjoerg// Execute once 87*4d6fc14bSjoergtypedef pthread_once_t __libcpp_exec_once_flag; 88*4d6fc14bSjoerg#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 89*4d6fc14bSjoerg 90*4d6fc14bSjoerg// Thread id 91*4d6fc14bSjoerg#if defined(__MVS__) 92*4d6fc14bSjoerg typedef unsigned long long __libcpp_thread_id; 93*4d6fc14bSjoerg#else 94*4d6fc14bSjoerg typedef pthread_t __libcpp_thread_id; 95*4d6fc14bSjoerg#endif 96*4d6fc14bSjoerg 97*4d6fc14bSjoerg// Thread 98*4d6fc14bSjoerg#define _LIBCPP_NULL_THREAD ((__libcpp_thread_t())) 99*4d6fc14bSjoergtypedef pthread_t __libcpp_thread_t; 100*4d6fc14bSjoerg 101*4d6fc14bSjoerg// Thread Local Storage 102*4d6fc14bSjoergtypedef pthread_key_t __libcpp_tls_key; 103*4d6fc14bSjoerg 104*4d6fc14bSjoerg#define _LIBCPP_TLS_DESTRUCTOR_CC 105*4d6fc14bSjoerg#elif defined(_LIBCPP_HAS_THREAD_API_C11) 106*4d6fc14bSjoerg// Mutex 107*4d6fc14bSjoergtypedef mtx_t __libcpp_mutex_t; 108*4d6fc14bSjoerg// mtx_t is a struct so using {} for initialization is valid. 109*4d6fc14bSjoerg#define _LIBCPP_MUTEX_INITIALIZER {} 110*4d6fc14bSjoerg 111*4d6fc14bSjoergtypedef mtx_t __libcpp_recursive_mutex_t; 112*4d6fc14bSjoerg 113*4d6fc14bSjoerg// Condition Variable 114*4d6fc14bSjoergtypedef cnd_t __libcpp_condvar_t; 115*4d6fc14bSjoerg// cnd_t is a struct so using {} for initialization is valid. 116*4d6fc14bSjoerg#define _LIBCPP_CONDVAR_INITIALIZER {} 117*4d6fc14bSjoerg 118*4d6fc14bSjoerg// Execute once 119*4d6fc14bSjoergtypedef once_flag __libcpp_exec_once_flag; 120*4d6fc14bSjoerg#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT 121*4d6fc14bSjoerg 122*4d6fc14bSjoerg// Thread id 123*4d6fc14bSjoergtypedef thrd_t __libcpp_thread_id; 124*4d6fc14bSjoerg 125*4d6fc14bSjoerg// Thread 126*4d6fc14bSjoerg#define _LIBCPP_NULL_THREAD 0U 127*4d6fc14bSjoerg 128*4d6fc14bSjoergtypedef thrd_t __libcpp_thread_t; 129*4d6fc14bSjoerg 130*4d6fc14bSjoerg// Thread Local Storage 131*4d6fc14bSjoergtypedef tss_t __libcpp_tls_key; 132*4d6fc14bSjoerg 133*4d6fc14bSjoerg#define _LIBCPP_TLS_DESTRUCTOR_CC 134*4d6fc14bSjoerg#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 135*4d6fc14bSjoerg// Mutex 136*4d6fc14bSjoergtypedef void* __libcpp_mutex_t; 137*4d6fc14bSjoerg#define _LIBCPP_MUTEX_INITIALIZER 0 138*4d6fc14bSjoerg 139*4d6fc14bSjoerg#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) 140*4d6fc14bSjoergtypedef void* __libcpp_recursive_mutex_t[6]; 141*4d6fc14bSjoerg#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) 142*4d6fc14bSjoergtypedef void* __libcpp_recursive_mutex_t[5]; 143*4d6fc14bSjoerg#else 144*4d6fc14bSjoerg# error Unsupported architecture 145*4d6fc14bSjoerg#endif 146*4d6fc14bSjoerg 147*4d6fc14bSjoerg// Condition Variable 148*4d6fc14bSjoergtypedef void* __libcpp_condvar_t; 149*4d6fc14bSjoerg#define _LIBCPP_CONDVAR_INITIALIZER 0 150*4d6fc14bSjoerg 151*4d6fc14bSjoerg// Semaphore 152*4d6fc14bSjoergtypedef void* __libcpp_semaphore_t; 153*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_THREAD_API_WIN32) 154*4d6fc14bSjoerg# define _LIBCPP_SEMAPHORE_MAX (::std::numeric_limits<long>::max()) 155*4d6fc14bSjoerg#endif 156*4d6fc14bSjoerg 157*4d6fc14bSjoerg// Execute Once 158*4d6fc14bSjoergtypedef void* __libcpp_exec_once_flag; 159*4d6fc14bSjoerg#define _LIBCPP_EXEC_ONCE_INITIALIZER 0 160*4d6fc14bSjoerg 161*4d6fc14bSjoerg// Thread ID 162*4d6fc14bSjoergtypedef long __libcpp_thread_id; 163*4d6fc14bSjoerg 164*4d6fc14bSjoerg// Thread 165*4d6fc14bSjoerg#define _LIBCPP_NULL_THREAD 0U 166*4d6fc14bSjoerg 167*4d6fc14bSjoergtypedef void* __libcpp_thread_t; 168*4d6fc14bSjoerg 169*4d6fc14bSjoerg// Thread Local Storage 170*4d6fc14bSjoergtypedef long __libcpp_tls_key; 171*4d6fc14bSjoerg 172*4d6fc14bSjoerg#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall 173*4d6fc14bSjoerg#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 174*4d6fc14bSjoerg 175*4d6fc14bSjoerg#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 176*4d6fc14bSjoerg// Mutex 177*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 178*4d6fc14bSjoergint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 179*4d6fc14bSjoerg 180*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 181*4d6fc14bSjoergint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 182*4d6fc14bSjoerg 183*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 184*4d6fc14bSjoergbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 185*4d6fc14bSjoerg 186*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 187*4d6fc14bSjoergint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 188*4d6fc14bSjoerg 189*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 190*4d6fc14bSjoergint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 191*4d6fc14bSjoerg 192*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 193*4d6fc14bSjoergint __libcpp_mutex_lock(__libcpp_mutex_t *__m); 194*4d6fc14bSjoerg 195*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 196*4d6fc14bSjoergbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 197*4d6fc14bSjoerg 198*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 199*4d6fc14bSjoergint __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 200*4d6fc14bSjoerg 201*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 202*4d6fc14bSjoergint __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 203*4d6fc14bSjoerg 204*4d6fc14bSjoerg// Condition variable 205*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 206*4d6fc14bSjoergint __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 207*4d6fc14bSjoerg 208*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 209*4d6fc14bSjoergint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 210*4d6fc14bSjoerg 211*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 212*4d6fc14bSjoergint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 213*4d6fc14bSjoerg 214*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 215*4d6fc14bSjoergint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 216*4d6fc14bSjoerg __libcpp_timespec_t *__ts); 217*4d6fc14bSjoerg 218*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 219*4d6fc14bSjoergint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 220*4d6fc14bSjoerg 221*4d6fc14bSjoerg#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES 222*4d6fc14bSjoerg 223*4d6fc14bSjoerg// Semaphore 224*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 225*4d6fc14bSjoergbool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init); 226*4d6fc14bSjoerg 227*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 228*4d6fc14bSjoergbool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem); 229*4d6fc14bSjoerg 230*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 231*4d6fc14bSjoergbool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem); 232*4d6fc14bSjoerg 233*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 234*4d6fc14bSjoergbool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem); 235*4d6fc14bSjoerg 236*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 237*4d6fc14bSjoergbool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns); 238*4d6fc14bSjoerg 239*4d6fc14bSjoerg#endif // _LIBCPP_NO_NATIVE_SEMAPHORES 240*4d6fc14bSjoerg 241*4d6fc14bSjoerg// Execute once 242*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 243*4d6fc14bSjoergint __libcpp_execute_once(__libcpp_exec_once_flag *flag, 244*4d6fc14bSjoerg void (*init_routine)()); 245*4d6fc14bSjoerg 246*4d6fc14bSjoerg// Thread id 247*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 248*4d6fc14bSjoergbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 249*4d6fc14bSjoerg 250*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 251*4d6fc14bSjoergbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 252*4d6fc14bSjoerg 253*4d6fc14bSjoerg// Thread 254*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 255*4d6fc14bSjoergbool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 256*4d6fc14bSjoerg 257*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 258*4d6fc14bSjoergint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 259*4d6fc14bSjoerg void *__arg); 260*4d6fc14bSjoerg 261*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 262*4d6fc14bSjoerg__libcpp_thread_id __libcpp_thread_get_current_id(); 263*4d6fc14bSjoerg 264*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 265*4d6fc14bSjoerg__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 266*4d6fc14bSjoerg 267*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 268*4d6fc14bSjoergint __libcpp_thread_join(__libcpp_thread_t *__t); 269*4d6fc14bSjoerg 270*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 271*4d6fc14bSjoergint __libcpp_thread_detach(__libcpp_thread_t *__t); 272*4d6fc14bSjoerg 273*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 274*4d6fc14bSjoergvoid __libcpp_thread_yield(); 275*4d6fc14bSjoerg 276*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 277*4d6fc14bSjoergvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 278*4d6fc14bSjoerg 279*4d6fc14bSjoerg// Thread local storage 280*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 281*4d6fc14bSjoergint __libcpp_tls_create(__libcpp_tls_key* __key, 282*4d6fc14bSjoerg void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 283*4d6fc14bSjoerg 284*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 285*4d6fc14bSjoergvoid *__libcpp_tls_get(__libcpp_tls_key __key); 286*4d6fc14bSjoerg 287*4d6fc14bSjoerg_LIBCPP_THREAD_ABI_VISIBILITY 288*4d6fc14bSjoergint __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 289*4d6fc14bSjoerg 290*4d6fc14bSjoerg#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 291*4d6fc14bSjoerg 292*4d6fc14bSjoergstruct __libcpp_timed_backoff_policy { 293*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 294*4d6fc14bSjoerg bool operator()(chrono::nanoseconds __elapsed) const 295*4d6fc14bSjoerg { 296*4d6fc14bSjoerg if(__elapsed > chrono::milliseconds(128)) 297*4d6fc14bSjoerg __libcpp_thread_sleep_for(chrono::milliseconds(8)); 298*4d6fc14bSjoerg else if(__elapsed > chrono::microseconds(64)) 299*4d6fc14bSjoerg __libcpp_thread_sleep_for(__elapsed / 2); 300*4d6fc14bSjoerg else if(__elapsed > chrono::microseconds(4)) 301*4d6fc14bSjoerg __libcpp_thread_yield(); 302*4d6fc14bSjoerg else 303*4d6fc14bSjoerg {} // poll 304*4d6fc14bSjoerg return false; 305*4d6fc14bSjoerg } 306*4d6fc14bSjoerg}; 307*4d6fc14bSjoerg 308*4d6fc14bSjoergstatic _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64; 309*4d6fc14bSjoerg 310*4d6fc14bSjoergtemplate<class _Fn, class _BFn> 311*4d6fc14bSjoerg_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 312*4d6fc14bSjoergbool __libcpp_thread_poll_with_backoff( 313*4d6fc14bSjoerg _Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero()) 314*4d6fc14bSjoerg{ 315*4d6fc14bSjoerg auto const __start = chrono::high_resolution_clock::now(); 316*4d6fc14bSjoerg for(int __count = 0;;) { 317*4d6fc14bSjoerg if(__f()) 318*4d6fc14bSjoerg return true; // _Fn completion means success 319*4d6fc14bSjoerg if(__count < __libcpp_polling_count) { 320*4d6fc14bSjoerg __count += 1; 321*4d6fc14bSjoerg continue; 322*4d6fc14bSjoerg } 323*4d6fc14bSjoerg chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start; 324*4d6fc14bSjoerg if(__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed) 325*4d6fc14bSjoerg return false; // timeout failure 326*4d6fc14bSjoerg if(__bf(__elapsed)) 327*4d6fc14bSjoerg return false; // _BFn completion means failure 328*4d6fc14bSjoerg } 329*4d6fc14bSjoerg} 330*4d6fc14bSjoerg 331*4d6fc14bSjoerg#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 332*4d6fc14bSjoerg defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) 333*4d6fc14bSjoerg 334*4d6fc14bSjoerg 335*4d6fc14bSjoergnamespace __thread_detail { 336*4d6fc14bSjoerg 337*4d6fc14bSjoerginline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns) 338*4d6fc14bSjoerg{ 339*4d6fc14bSjoerg using namespace chrono; 340*4d6fc14bSjoerg seconds __s = duration_cast<seconds>(__ns); 341*4d6fc14bSjoerg __libcpp_timespec_t __ts; 342*4d6fc14bSjoerg typedef decltype(__ts.tv_sec) __ts_sec; 343*4d6fc14bSjoerg const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); 344*4d6fc14bSjoerg 345*4d6fc14bSjoerg if (__s.count() < __ts_sec_max) 346*4d6fc14bSjoerg { 347*4d6fc14bSjoerg __ts.tv_sec = static_cast<__ts_sec>(__s.count()); 348*4d6fc14bSjoerg __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count()); 349*4d6fc14bSjoerg } 350*4d6fc14bSjoerg else 351*4d6fc14bSjoerg { 352*4d6fc14bSjoerg __ts.tv_sec = __ts_sec_max; 353*4d6fc14bSjoerg __ts.tv_nsec = 999999999; // (10^9 - 1) 354*4d6fc14bSjoerg } 355*4d6fc14bSjoerg 356*4d6fc14bSjoerg return __ts; 357*4d6fc14bSjoerg} 358*4d6fc14bSjoerg 359*4d6fc14bSjoerg} 360*4d6fc14bSjoerg 361*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 362*4d6fc14bSjoerg 363*4d6fc14bSjoergint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 364*4d6fc14bSjoerg{ 365*4d6fc14bSjoerg pthread_mutexattr_t attr; 366*4d6fc14bSjoerg int __ec = pthread_mutexattr_init(&attr); 367*4d6fc14bSjoerg if (__ec) 368*4d6fc14bSjoerg return __ec; 369*4d6fc14bSjoerg __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 370*4d6fc14bSjoerg if (__ec) { 371*4d6fc14bSjoerg pthread_mutexattr_destroy(&attr); 372*4d6fc14bSjoerg return __ec; 373*4d6fc14bSjoerg } 374*4d6fc14bSjoerg __ec = pthread_mutex_init(__m, &attr); 375*4d6fc14bSjoerg if (__ec) { 376*4d6fc14bSjoerg pthread_mutexattr_destroy(&attr); 377*4d6fc14bSjoerg return __ec; 378*4d6fc14bSjoerg } 379*4d6fc14bSjoerg __ec = pthread_mutexattr_destroy(&attr); 380*4d6fc14bSjoerg if (__ec) { 381*4d6fc14bSjoerg pthread_mutex_destroy(__m); 382*4d6fc14bSjoerg return __ec; 383*4d6fc14bSjoerg } 384*4d6fc14bSjoerg return 0; 385*4d6fc14bSjoerg} 386*4d6fc14bSjoerg 387*4d6fc14bSjoergint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 388*4d6fc14bSjoerg{ 389*4d6fc14bSjoerg return pthread_mutex_lock(__m); 390*4d6fc14bSjoerg} 391*4d6fc14bSjoerg 392*4d6fc14bSjoergbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 393*4d6fc14bSjoerg{ 394*4d6fc14bSjoerg return pthread_mutex_trylock(__m) == 0; 395*4d6fc14bSjoerg} 396*4d6fc14bSjoerg 397*4d6fc14bSjoergint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 398*4d6fc14bSjoerg{ 399*4d6fc14bSjoerg return pthread_mutex_unlock(__m); 400*4d6fc14bSjoerg} 401*4d6fc14bSjoerg 402*4d6fc14bSjoergint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 403*4d6fc14bSjoerg{ 404*4d6fc14bSjoerg return pthread_mutex_destroy(__m); 405*4d6fc14bSjoerg} 406*4d6fc14bSjoerg 407*4d6fc14bSjoergint __libcpp_mutex_lock(__libcpp_mutex_t *__m) 408*4d6fc14bSjoerg{ 409*4d6fc14bSjoerg return pthread_mutex_lock(__m); 410*4d6fc14bSjoerg} 411*4d6fc14bSjoerg 412*4d6fc14bSjoergbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 413*4d6fc14bSjoerg{ 414*4d6fc14bSjoerg return pthread_mutex_trylock(__m) == 0; 415*4d6fc14bSjoerg} 416*4d6fc14bSjoerg 417*4d6fc14bSjoergint __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 418*4d6fc14bSjoerg{ 419*4d6fc14bSjoerg return pthread_mutex_unlock(__m); 420*4d6fc14bSjoerg} 421*4d6fc14bSjoerg 422*4d6fc14bSjoergint __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 423*4d6fc14bSjoerg{ 424*4d6fc14bSjoerg return pthread_mutex_destroy(__m); 425*4d6fc14bSjoerg} 426*4d6fc14bSjoerg 427*4d6fc14bSjoerg// Condition Variable 428*4d6fc14bSjoergint __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 429*4d6fc14bSjoerg{ 430*4d6fc14bSjoerg return pthread_cond_signal(__cv); 431*4d6fc14bSjoerg} 432*4d6fc14bSjoerg 433*4d6fc14bSjoergint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 434*4d6fc14bSjoerg{ 435*4d6fc14bSjoerg return pthread_cond_broadcast(__cv); 436*4d6fc14bSjoerg} 437*4d6fc14bSjoerg 438*4d6fc14bSjoergint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 439*4d6fc14bSjoerg{ 440*4d6fc14bSjoerg return pthread_cond_wait(__cv, __m); 441*4d6fc14bSjoerg} 442*4d6fc14bSjoerg 443*4d6fc14bSjoergint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 444*4d6fc14bSjoerg __libcpp_timespec_t *__ts) 445*4d6fc14bSjoerg{ 446*4d6fc14bSjoerg return pthread_cond_timedwait(__cv, __m, __ts); 447*4d6fc14bSjoerg} 448*4d6fc14bSjoerg 449*4d6fc14bSjoergint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 450*4d6fc14bSjoerg{ 451*4d6fc14bSjoerg return pthread_cond_destroy(__cv); 452*4d6fc14bSjoerg} 453*4d6fc14bSjoerg 454*4d6fc14bSjoerg#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES 455*4d6fc14bSjoerg 456*4d6fc14bSjoerg// Semaphore 457*4d6fc14bSjoergbool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init) 458*4d6fc14bSjoerg{ 459*4d6fc14bSjoerg return sem_init(__sem, 0, __init) == 0; 460*4d6fc14bSjoerg} 461*4d6fc14bSjoerg 462*4d6fc14bSjoergbool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem) 463*4d6fc14bSjoerg{ 464*4d6fc14bSjoerg return sem_destroy(__sem) == 0; 465*4d6fc14bSjoerg} 466*4d6fc14bSjoerg 467*4d6fc14bSjoergbool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem) 468*4d6fc14bSjoerg{ 469*4d6fc14bSjoerg return sem_post(__sem) == 0; 470*4d6fc14bSjoerg} 471*4d6fc14bSjoerg 472*4d6fc14bSjoergbool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem) 473*4d6fc14bSjoerg{ 474*4d6fc14bSjoerg return sem_wait(__sem) == 0; 475*4d6fc14bSjoerg} 476*4d6fc14bSjoerg 477*4d6fc14bSjoergbool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns) 478*4d6fc14bSjoerg{ 479*4d6fc14bSjoerg auto const __abs_time = chrono::system_clock::now().time_since_epoch() + __ns; 480*4d6fc14bSjoerg __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__abs_time); 481*4d6fc14bSjoerg return sem_timedwait(__sem, &__ts) == 0; 482*4d6fc14bSjoerg} 483*4d6fc14bSjoerg 484*4d6fc14bSjoerg#endif //_LIBCPP_NO_NATIVE_SEMAPHORES 485*4d6fc14bSjoerg 486*4d6fc14bSjoerg// Execute once 487*4d6fc14bSjoergint __libcpp_execute_once(__libcpp_exec_once_flag *flag, 488*4d6fc14bSjoerg void (*init_routine)()) { 489*4d6fc14bSjoerg return pthread_once(flag, init_routine); 490*4d6fc14bSjoerg} 491*4d6fc14bSjoerg 492*4d6fc14bSjoerg// Thread id 493*4d6fc14bSjoerg// Returns non-zero if the thread ids are equal, otherwise 0 494*4d6fc14bSjoergbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 495*4d6fc14bSjoerg{ 496*4d6fc14bSjoerg return t1 == t2; 497*4d6fc14bSjoerg} 498*4d6fc14bSjoerg 499*4d6fc14bSjoerg// Returns non-zero if t1 < t2, otherwise 0 500*4d6fc14bSjoergbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 501*4d6fc14bSjoerg{ 502*4d6fc14bSjoerg return t1 < t2; 503*4d6fc14bSjoerg} 504*4d6fc14bSjoerg 505*4d6fc14bSjoerg// Thread 506*4d6fc14bSjoergbool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 507*4d6fc14bSjoerg return __libcpp_thread_get_id(__t) == 0; 508*4d6fc14bSjoerg} 509*4d6fc14bSjoerg 510*4d6fc14bSjoergint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 511*4d6fc14bSjoerg void *__arg) 512*4d6fc14bSjoerg{ 513*4d6fc14bSjoerg return pthread_create(__t, nullptr, __func, __arg); 514*4d6fc14bSjoerg} 515*4d6fc14bSjoerg 516*4d6fc14bSjoerg__libcpp_thread_id __libcpp_thread_get_current_id() 517*4d6fc14bSjoerg{ 518*4d6fc14bSjoerg const __libcpp_thread_t thread = pthread_self(); 519*4d6fc14bSjoerg return __libcpp_thread_get_id(&thread); 520*4d6fc14bSjoerg} 521*4d6fc14bSjoerg 522*4d6fc14bSjoerg__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 523*4d6fc14bSjoerg{ 524*4d6fc14bSjoerg#if defined(__MVS__) 525*4d6fc14bSjoerg return __t->__; 526*4d6fc14bSjoerg#else 527*4d6fc14bSjoerg return *__t; 528*4d6fc14bSjoerg#endif 529*4d6fc14bSjoerg} 530*4d6fc14bSjoerg 531*4d6fc14bSjoergint __libcpp_thread_join(__libcpp_thread_t *__t) 532*4d6fc14bSjoerg{ 533*4d6fc14bSjoerg return pthread_join(*__t, nullptr); 534*4d6fc14bSjoerg} 535*4d6fc14bSjoerg 536*4d6fc14bSjoergint __libcpp_thread_detach(__libcpp_thread_t *__t) 537*4d6fc14bSjoerg{ 538*4d6fc14bSjoerg return pthread_detach(*__t); 539*4d6fc14bSjoerg} 540*4d6fc14bSjoerg 541*4d6fc14bSjoergvoid __libcpp_thread_yield() 542*4d6fc14bSjoerg{ 543*4d6fc14bSjoerg sched_yield(); 544*4d6fc14bSjoerg} 545*4d6fc14bSjoerg 546*4d6fc14bSjoergvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 547*4d6fc14bSjoerg{ 548*4d6fc14bSjoerg __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns); 549*4d6fc14bSjoerg while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); 550*4d6fc14bSjoerg} 551*4d6fc14bSjoerg 552*4d6fc14bSjoerg// Thread local storage 553*4d6fc14bSjoergint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 554*4d6fc14bSjoerg{ 555*4d6fc14bSjoerg return pthread_key_create(__key, __at_exit); 556*4d6fc14bSjoerg} 557*4d6fc14bSjoerg 558*4d6fc14bSjoergvoid *__libcpp_tls_get(__libcpp_tls_key __key) 559*4d6fc14bSjoerg{ 560*4d6fc14bSjoerg return pthread_getspecific(__key); 561*4d6fc14bSjoerg} 562*4d6fc14bSjoerg 563*4d6fc14bSjoergint __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 564*4d6fc14bSjoerg{ 565*4d6fc14bSjoerg return pthread_setspecific(__key, __p); 566*4d6fc14bSjoerg} 567*4d6fc14bSjoerg 568*4d6fc14bSjoerg#elif defined(_LIBCPP_HAS_THREAD_API_C11) 569*4d6fc14bSjoerg 570*4d6fc14bSjoergint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 571*4d6fc14bSjoerg{ 572*4d6fc14bSjoerg return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL; 573*4d6fc14bSjoerg} 574*4d6fc14bSjoerg 575*4d6fc14bSjoergint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 576*4d6fc14bSjoerg{ 577*4d6fc14bSjoerg return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 578*4d6fc14bSjoerg} 579*4d6fc14bSjoerg 580*4d6fc14bSjoergbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 581*4d6fc14bSjoerg{ 582*4d6fc14bSjoerg return mtx_trylock(__m) == thrd_success; 583*4d6fc14bSjoerg} 584*4d6fc14bSjoerg 585*4d6fc14bSjoergint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 586*4d6fc14bSjoerg{ 587*4d6fc14bSjoerg return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 588*4d6fc14bSjoerg} 589*4d6fc14bSjoerg 590*4d6fc14bSjoergint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 591*4d6fc14bSjoerg{ 592*4d6fc14bSjoerg mtx_destroy(__m); 593*4d6fc14bSjoerg return 0; 594*4d6fc14bSjoerg} 595*4d6fc14bSjoerg 596*4d6fc14bSjoergint __libcpp_mutex_lock(__libcpp_mutex_t *__m) 597*4d6fc14bSjoerg{ 598*4d6fc14bSjoerg return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 599*4d6fc14bSjoerg} 600*4d6fc14bSjoerg 601*4d6fc14bSjoergbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 602*4d6fc14bSjoerg{ 603*4d6fc14bSjoerg return mtx_trylock(__m) == thrd_success; 604*4d6fc14bSjoerg} 605*4d6fc14bSjoerg 606*4d6fc14bSjoergint __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 607*4d6fc14bSjoerg{ 608*4d6fc14bSjoerg return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 609*4d6fc14bSjoerg} 610*4d6fc14bSjoerg 611*4d6fc14bSjoergint __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 612*4d6fc14bSjoerg{ 613*4d6fc14bSjoerg mtx_destroy(__m); 614*4d6fc14bSjoerg return 0; 615*4d6fc14bSjoerg} 616*4d6fc14bSjoerg 617*4d6fc14bSjoerg// Condition Variable 618*4d6fc14bSjoergint __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 619*4d6fc14bSjoerg{ 620*4d6fc14bSjoerg return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; 621*4d6fc14bSjoerg} 622*4d6fc14bSjoerg 623*4d6fc14bSjoergint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 624*4d6fc14bSjoerg{ 625*4d6fc14bSjoerg return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; 626*4d6fc14bSjoerg} 627*4d6fc14bSjoerg 628*4d6fc14bSjoergint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 629*4d6fc14bSjoerg{ 630*4d6fc14bSjoerg return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL; 631*4d6fc14bSjoerg} 632*4d6fc14bSjoerg 633*4d6fc14bSjoergint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 634*4d6fc14bSjoerg timespec *__ts) 635*4d6fc14bSjoerg{ 636*4d6fc14bSjoerg int __ec = cnd_timedwait(__cv, __m, __ts); 637*4d6fc14bSjoerg return __ec == thrd_timedout ? ETIMEDOUT : __ec; 638*4d6fc14bSjoerg} 639*4d6fc14bSjoerg 640*4d6fc14bSjoergint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 641*4d6fc14bSjoerg{ 642*4d6fc14bSjoerg cnd_destroy(__cv); 643*4d6fc14bSjoerg return 0; 644*4d6fc14bSjoerg} 645*4d6fc14bSjoerg 646*4d6fc14bSjoerg// Execute once 647*4d6fc14bSjoergint __libcpp_execute_once(__libcpp_exec_once_flag *flag, 648*4d6fc14bSjoerg void (*init_routine)(void)) { 649*4d6fc14bSjoerg ::call_once(flag, init_routine); 650*4d6fc14bSjoerg return 0; 651*4d6fc14bSjoerg} 652*4d6fc14bSjoerg 653*4d6fc14bSjoerg// Thread id 654*4d6fc14bSjoerg// Returns non-zero if the thread ids are equal, otherwise 0 655*4d6fc14bSjoergbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 656*4d6fc14bSjoerg{ 657*4d6fc14bSjoerg return thrd_equal(t1, t2) != 0; 658*4d6fc14bSjoerg} 659*4d6fc14bSjoerg 660*4d6fc14bSjoerg// Returns non-zero if t1 < t2, otherwise 0 661*4d6fc14bSjoergbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 662*4d6fc14bSjoerg{ 663*4d6fc14bSjoerg return t1 < t2; 664*4d6fc14bSjoerg} 665*4d6fc14bSjoerg 666*4d6fc14bSjoerg// Thread 667*4d6fc14bSjoergbool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 668*4d6fc14bSjoerg return __libcpp_thread_get_id(__t) == 0; 669*4d6fc14bSjoerg} 670*4d6fc14bSjoerg 671*4d6fc14bSjoergint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 672*4d6fc14bSjoerg void *__arg) 673*4d6fc14bSjoerg{ 674*4d6fc14bSjoerg int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg); 675*4d6fc14bSjoerg return __ec == thrd_nomem ? ENOMEM : __ec; 676*4d6fc14bSjoerg} 677*4d6fc14bSjoerg 678*4d6fc14bSjoerg__libcpp_thread_id __libcpp_thread_get_current_id() 679*4d6fc14bSjoerg{ 680*4d6fc14bSjoerg return thrd_current(); 681*4d6fc14bSjoerg} 682*4d6fc14bSjoerg 683*4d6fc14bSjoerg__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 684*4d6fc14bSjoerg{ 685*4d6fc14bSjoerg return *__t; 686*4d6fc14bSjoerg} 687*4d6fc14bSjoerg 688*4d6fc14bSjoergint __libcpp_thread_join(__libcpp_thread_t *__t) 689*4d6fc14bSjoerg{ 690*4d6fc14bSjoerg return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; 691*4d6fc14bSjoerg} 692*4d6fc14bSjoerg 693*4d6fc14bSjoergint __libcpp_thread_detach(__libcpp_thread_t *__t) 694*4d6fc14bSjoerg{ 695*4d6fc14bSjoerg return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; 696*4d6fc14bSjoerg} 697*4d6fc14bSjoerg 698*4d6fc14bSjoergvoid __libcpp_thread_yield() 699*4d6fc14bSjoerg{ 700*4d6fc14bSjoerg thrd_yield(); 701*4d6fc14bSjoerg} 702*4d6fc14bSjoerg 703*4d6fc14bSjoergvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 704*4d6fc14bSjoerg{ 705*4d6fc14bSjoerg __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns); 706*4d6fc14bSjoerg thrd_sleep(&__ts, nullptr); 707*4d6fc14bSjoerg} 708*4d6fc14bSjoerg 709*4d6fc14bSjoerg// Thread local storage 710*4d6fc14bSjoergint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 711*4d6fc14bSjoerg{ 712*4d6fc14bSjoerg return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL; 713*4d6fc14bSjoerg} 714*4d6fc14bSjoerg 715*4d6fc14bSjoergvoid *__libcpp_tls_get(__libcpp_tls_key __key) 716*4d6fc14bSjoerg{ 717*4d6fc14bSjoerg return tss_get(__key); 718*4d6fc14bSjoerg} 719*4d6fc14bSjoerg 720*4d6fc14bSjoergint __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 721*4d6fc14bSjoerg{ 722*4d6fc14bSjoerg return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; 723*4d6fc14bSjoerg} 724*4d6fc14bSjoerg 725*4d6fc14bSjoerg#endif 726*4d6fc14bSjoerg 727*4d6fc14bSjoerg 728*4d6fc14bSjoerg#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 729*4d6fc14bSjoerg 730*4d6fc14bSjoergclass _LIBCPP_TYPE_VIS thread; 731*4d6fc14bSjoergclass _LIBCPP_TYPE_VIS __thread_id; 732*4d6fc14bSjoerg 733*4d6fc14bSjoergnamespace this_thread 734*4d6fc14bSjoerg{ 735*4d6fc14bSjoerg 736*4d6fc14bSjoerg_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; 737*4d6fc14bSjoerg 738*4d6fc14bSjoerg} // this_thread 739*4d6fc14bSjoerg 740*4d6fc14bSjoergtemplate<> struct hash<__thread_id>; 741*4d6fc14bSjoerg 742*4d6fc14bSjoergclass _LIBCPP_TEMPLATE_VIS __thread_id 743*4d6fc14bSjoerg{ 744*4d6fc14bSjoerg // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 745*4d6fc14bSjoerg // NULL is the no-thread value on Darwin. Someone needs to check 746*4d6fc14bSjoerg // on other platforms. We assume 0 works everywhere for now. 747*4d6fc14bSjoerg __libcpp_thread_id __id_; 748*4d6fc14bSjoerg 749*4d6fc14bSjoergpublic: 750*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 751*4d6fc14bSjoerg __thread_id() _NOEXCEPT : __id_(0) {} 752*4d6fc14bSjoerg 753*4d6fc14bSjoerg friend _LIBCPP_INLINE_VISIBILITY 754*4d6fc14bSjoerg bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT 755*4d6fc14bSjoerg { // don't pass id==0 to underlying routines 756*4d6fc14bSjoerg if (__x.__id_ == 0) return __y.__id_ == 0; 757*4d6fc14bSjoerg if (__y.__id_ == 0) return false; 758*4d6fc14bSjoerg return __libcpp_thread_id_equal(__x.__id_, __y.__id_); 759*4d6fc14bSjoerg } 760*4d6fc14bSjoerg friend _LIBCPP_INLINE_VISIBILITY 761*4d6fc14bSjoerg bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT 762*4d6fc14bSjoerg {return !(__x == __y);} 763*4d6fc14bSjoerg friend _LIBCPP_INLINE_VISIBILITY 764*4d6fc14bSjoerg bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT 765*4d6fc14bSjoerg { // id==0 is always less than any other thread_id 766*4d6fc14bSjoerg if (__x.__id_ == 0) return __y.__id_ != 0; 767*4d6fc14bSjoerg if (__y.__id_ == 0) return false; 768*4d6fc14bSjoerg return __libcpp_thread_id_less(__x.__id_, __y.__id_); 769*4d6fc14bSjoerg } 770*4d6fc14bSjoerg friend _LIBCPP_INLINE_VISIBILITY 771*4d6fc14bSjoerg bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT 772*4d6fc14bSjoerg {return !(__y < __x);} 773*4d6fc14bSjoerg friend _LIBCPP_INLINE_VISIBILITY 774*4d6fc14bSjoerg bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT 775*4d6fc14bSjoerg {return __y < __x ;} 776*4d6fc14bSjoerg friend _LIBCPP_INLINE_VISIBILITY 777*4d6fc14bSjoerg bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT 778*4d6fc14bSjoerg {return !(__x < __y);} 779*4d6fc14bSjoerg 780*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 781*4d6fc14bSjoerg void __reset() { __id_ = 0; } 782*4d6fc14bSjoerg 783*4d6fc14bSjoerg template<class _CharT, class _Traits> 784*4d6fc14bSjoerg friend 785*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 786*4d6fc14bSjoerg basic_ostream<_CharT, _Traits>& 787*4d6fc14bSjoerg operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); 788*4d6fc14bSjoerg 789*4d6fc14bSjoergprivate: 790*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 791*4d6fc14bSjoerg __thread_id(__libcpp_thread_id __id) : __id_(__id) {} 792*4d6fc14bSjoerg 793*4d6fc14bSjoerg friend __thread_id this_thread::get_id() _NOEXCEPT; 794*4d6fc14bSjoerg friend class _LIBCPP_TYPE_VIS thread; 795*4d6fc14bSjoerg friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; 796*4d6fc14bSjoerg}; 797*4d6fc14bSjoerg 798*4d6fc14bSjoergnamespace this_thread 799*4d6fc14bSjoerg{ 800*4d6fc14bSjoerg 801*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY 802*4d6fc14bSjoerg__thread_id 803*4d6fc14bSjoergget_id() _NOEXCEPT 804*4d6fc14bSjoerg{ 805*4d6fc14bSjoerg return __libcpp_thread_get_current_id(); 806*4d6fc14bSjoerg} 807*4d6fc14bSjoerg 808*4d6fc14bSjoerg} // this_thread 809*4d6fc14bSjoerg 810*4d6fc14bSjoerg#endif // !_LIBCPP_HAS_NO_THREADS 811*4d6fc14bSjoerg 812*4d6fc14bSjoerg_LIBCPP_END_NAMESPACE_STD 813*4d6fc14bSjoerg 814*4d6fc14bSjoerg_LIBCPP_POP_MACROS 815*4d6fc14bSjoerg 816*4d6fc14bSjoerg#endif // _LIBCPP_THREADING_SUPPORT 817