10b57cec5SDimitry Andric// -*- C++ -*- 20b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 30b57cec5SDimitry Andric// 40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 70b57cec5SDimitry Andric// 80b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 90b57cec5SDimitry Andric 1081ad6265SDimitry Andric#ifndef _LIBCPP___THREADING_SUPPORT 1181ad6265SDimitry Andric#define _LIBCPP___THREADING_SUPPORT 120b57cec5SDimitry Andric 13e8d8bef9SDimitry Andric#include <__availability> 1481ad6265SDimitry Andric#include <__chrono/convert_to_timespec.h> 1581ad6265SDimitry Andric#include <__chrono/duration.h> 16fe6060f1SDimitry Andric#include <__config> 17c9157d92SDimitry Andric#include <__fwd/hash.h> 18c9157d92SDimitry Andric#include <ctime> 190b57cec5SDimitry Andric#include <errno.h> 200b57cec5SDimitry Andric 21e8d8bef9SDimitry Andric#ifdef __MVS__ 22d409305fSDimitry Andric# include <__support/ibm/nanosleep.h> 23e8d8bef9SDimitry Andric#endif 24e8d8bef9SDimitry Andric 250b57cec5SDimitry Andric#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 260b57cec5SDimitry Andric# pragma GCC system_header 270b57cec5SDimitry Andric#endif 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 300b57cec5SDimitry Andric# include <__external_threading> 310b57cec5SDimitry Andric#elif !defined(_LIBCPP_HAS_NO_THREADS) 320b57cec5SDimitry Andric 33fe6060f1SDimitry Andric# if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 34fe013be4SDimitry Andric// Some platforms require <bits/atomic_wide_counter.h> in order for 35fe013be4SDimitry Andric// PTHREAD_COND_INITIALIZER to be expanded. Normally that would come 36fe013be4SDimitry Andric// in via <pthread.h>, but it's a non-modular header on those platforms, 37fe013be4SDimitry Andric// so libc++'s <math.h> usually absorbs atomic_wide_counter.h into the 38fe013be4SDimitry Andric// module with <math.h> and makes atomic_wide_counter.h invisible. 39fe013be4SDimitry Andric// Include <math.h> here to work around that. 40fe013be4SDimitry Andric# include <math.h> 41fe013be4SDimitry Andric 42fe6060f1SDimitry Andric# include <pthread.h> 43fe6060f1SDimitry Andric# include <sched.h> 44480093f4SDimitry Andric# elif defined(_LIBCPP_HAS_THREAD_API_C11) 45480093f4SDimitry Andric# include <threads.h> 460b57cec5SDimitry Andric# endif 470b57cec5SDimitry Andric 48fe013be4SDimitry Andric# if defined(_LIBCPP_HAS_THREAD_API_WIN32) 49fe013be4SDimitry Andric# define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_EXPORTED_FROM_ABI 500b57cec5SDimitry Andric# else 51c9157d92SDimitry Andric# define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_HIDE_FROM_ABI 520b57cec5SDimitry Andric# endif 530b57cec5SDimitry Andric 540b57cec5SDimitry Andrictypedef ::timespec __libcpp_timespec_t; 550b57cec5SDimitry Andric#endif // !defined(_LIBCPP_HAS_NO_THREADS) 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_THREADS) 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric# if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 620b57cec5SDimitry Andric// Mutex 630b57cec5SDimitry Andrictypedef pthread_mutex_t __libcpp_mutex_t; 640b57cec5SDimitry Andric# define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 650b57cec5SDimitry Andric 660b57cec5SDimitry Andrictypedef pthread_mutex_t __libcpp_recursive_mutex_t; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric// Condition Variable 690b57cec5SDimitry Andrictypedef pthread_cond_t __libcpp_condvar_t; 700b57cec5SDimitry Andric# define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric// Execute once 730b57cec5SDimitry Andrictypedef pthread_once_t __libcpp_exec_once_flag; 740b57cec5SDimitry Andric# define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric// Thread id 77e8d8bef9SDimitry Andric# if defined(__MVS__) 78e8d8bef9SDimitry Andrictypedef unsigned long long __libcpp_thread_id; 79e8d8bef9SDimitry Andric# else 800b57cec5SDimitry Andrictypedef pthread_t __libcpp_thread_id; 81e8d8bef9SDimitry Andric# endif 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric// Thread 84e8d8bef9SDimitry Andric# define _LIBCPP_NULL_THREAD ((__libcpp_thread_t())) 850b57cec5SDimitry Andrictypedef pthread_t __libcpp_thread_t; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric// Thread Local Storage 880b57cec5SDimitry Andrictypedef pthread_key_t __libcpp_tls_key; 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric# define _LIBCPP_TLS_DESTRUCTOR_CC 91480093f4SDimitry Andric# elif defined(_LIBCPP_HAS_THREAD_API_C11) 92480093f4SDimitry Andric// Mutex 93480093f4SDimitry Andrictypedef mtx_t __libcpp_mutex_t; 94480093f4SDimitry Andric// mtx_t is a struct so using {} for initialization is valid. 95*e710425bSDimitry Andric# define _LIBCPP_MUTEX_INITIALIZER \ 96*e710425bSDimitry Andric {} 97480093f4SDimitry Andric 98480093f4SDimitry Andrictypedef mtx_t __libcpp_recursive_mutex_t; 99480093f4SDimitry Andric 100480093f4SDimitry Andric// Condition Variable 101480093f4SDimitry Andrictypedef cnd_t __libcpp_condvar_t; 102480093f4SDimitry Andric// cnd_t is a struct so using {} for initialization is valid. 103*e710425bSDimitry Andric# define _LIBCPP_CONDVAR_INITIALIZER \ 104*e710425bSDimitry Andric {} 105480093f4SDimitry Andric 106480093f4SDimitry Andric// Execute once 107c9157d92SDimitry Andrictypedef ::once_flag __libcpp_exec_once_flag; 108480093f4SDimitry Andric# define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT 109480093f4SDimitry Andric 110480093f4SDimitry Andric// Thread id 111480093f4SDimitry Andrictypedef thrd_t __libcpp_thread_id; 112480093f4SDimitry Andric 113480093f4SDimitry Andric// Thread 114480093f4SDimitry Andric# define _LIBCPP_NULL_THREAD 0U 115480093f4SDimitry Andric 116480093f4SDimitry Andrictypedef thrd_t __libcpp_thread_t; 117480093f4SDimitry Andric 118480093f4SDimitry Andric// Thread Local Storage 119480093f4SDimitry Andrictypedef tss_t __libcpp_tls_key; 120480093f4SDimitry Andric 121480093f4SDimitry Andric# define _LIBCPP_TLS_DESTRUCTOR_CC 1220b57cec5SDimitry Andric# elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 1230b57cec5SDimitry Andric// Mutex 1240b57cec5SDimitry Andrictypedef void* __libcpp_mutex_t; 1250b57cec5SDimitry Andric# define _LIBCPP_MUTEX_INITIALIZER 0 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric# if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) 1280b57cec5SDimitry Andrictypedef void* __libcpp_recursive_mutex_t[6]; 1290b57cec5SDimitry Andric# elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) 1300b57cec5SDimitry Andrictypedef void* __libcpp_recursive_mutex_t[5]; 1310b57cec5SDimitry Andric# else 1320b57cec5SDimitry Andric# error Unsupported architecture 1330b57cec5SDimitry Andric# endif 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric// Condition Variable 1360b57cec5SDimitry Andrictypedef void* __libcpp_condvar_t; 1370b57cec5SDimitry Andric# define _LIBCPP_CONDVAR_INITIALIZER 0 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric// Execute Once 1400b57cec5SDimitry Andrictypedef void* __libcpp_exec_once_flag; 1410b57cec5SDimitry Andric# define _LIBCPP_EXEC_ONCE_INITIALIZER 0 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric// Thread ID 1440b57cec5SDimitry Andrictypedef long __libcpp_thread_id; 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric// Thread 1470b57cec5SDimitry Andric# define _LIBCPP_NULL_THREAD 0U 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andrictypedef void* __libcpp_thread_t; 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric// Thread Local Storage 1520b57cec5SDimitry Andrictypedef long __libcpp_tls_key; 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric# define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall 1550b57cec5SDimitry Andric# endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric# if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 1580b57cec5SDimitry Andric// Mutex 1590b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 1600b57cec5SDimitry Andricint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m); 1610b57cec5SDimitry Andric 162*e710425bSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int 163*e710425bSDimitry Andric__libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m); 1640b57cec5SDimitry Andric 165*e710425bSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool 166*e710425bSDimitry Andric__libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m); 1670b57cec5SDimitry Andric 168*e710425bSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int 169*e710425bSDimitry Andric__libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m); 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 1720b57cec5SDimitry Andricint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m); 1730b57cec5SDimitry Andric 174*e710425bSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t* __m); 1750b57cec5SDimitry Andric 176*e710425bSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m); 1770b57cec5SDimitry Andric 178*e710425bSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_unlock(__libcpp_mutex_t* __m); 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 1810b57cec5SDimitry Andricint __libcpp_mutex_destroy(__libcpp_mutex_t* __m); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric// Condition variable 1840b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 1850b57cec5SDimitry Andricint __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 1880b57cec5SDimitry Andricint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 1890b57cec5SDimitry Andric 190*e710425bSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int 191*e710425bSDimitry Andric__libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 1920b57cec5SDimitry Andric 193*e710425bSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int 194*e710425bSDimitry Andric__libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, __libcpp_timespec_t* __ts); 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 1970b57cec5SDimitry Andricint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric// Execute once 2000b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 201*e710425bSDimitry Andricint __libcpp_execute_once(__libcpp_exec_once_flag* __flag, void (*__init_routine)()); 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric// Thread id 2040b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 205753f127fSDimitry Andricbool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2); 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 208753f127fSDimitry Andricbool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2); 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric// Thread 2110b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 2120b57cec5SDimitry Andricbool __libcpp_thread_isnull(const __libcpp_thread_t* __t); 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 215*e710425bSDimitry Andricint __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg); 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 2180b57cec5SDimitry Andric__libcpp_thread_id __libcpp_thread_get_current_id(); 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 2210b57cec5SDimitry Andric__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t); 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 2240b57cec5SDimitry Andricint __libcpp_thread_join(__libcpp_thread_t* __t); 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 2270b57cec5SDimitry Andricint __libcpp_thread_detach(__libcpp_thread_t* __t); 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 2300b57cec5SDimitry Andricvoid __libcpp_thread_yield(); 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 2330b57cec5SDimitry Andricvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric// Thread local storage 2360b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 237*e710425bSDimitry Andricint __libcpp_tls_create(__libcpp_tls_key* __key, void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 2400b57cec5SDimitry Andricvoid* __libcpp_tls_get(__libcpp_tls_key __key); 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY 2430b57cec5SDimitry Andricint __libcpp_tls_set(__libcpp_tls_key __key, void* __p); 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric# endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 2460b57cec5SDimitry Andric 247480093f4SDimitry Andric# if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 2480b57cec5SDimitry Andric 249*e710425bSDimitry Andricint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m) { 250fe013be4SDimitry Andric pthread_mutexattr_t __attr; 251fe013be4SDimitry Andric int __ec = pthread_mutexattr_init(&__attr); 2520b57cec5SDimitry Andric if (__ec) 2530b57cec5SDimitry Andric return __ec; 254fe013be4SDimitry Andric __ec = pthread_mutexattr_settype(&__attr, PTHREAD_MUTEX_RECURSIVE); 2550b57cec5SDimitry Andric if (__ec) { 256fe013be4SDimitry Andric pthread_mutexattr_destroy(&__attr); 2570b57cec5SDimitry Andric return __ec; 2580b57cec5SDimitry Andric } 259fe013be4SDimitry Andric __ec = pthread_mutex_init(__m, &__attr); 2600b57cec5SDimitry Andric if (__ec) { 261fe013be4SDimitry Andric pthread_mutexattr_destroy(&__attr); 2620b57cec5SDimitry Andric return __ec; 2630b57cec5SDimitry Andric } 264fe013be4SDimitry Andric __ec = pthread_mutexattr_destroy(&__attr); 2650b57cec5SDimitry Andric if (__ec) { 2660b57cec5SDimitry Andric pthread_mutex_destroy(__m); 2670b57cec5SDimitry Andric return __ec; 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric return 0; 2700b57cec5SDimitry Andric} 2710b57cec5SDimitry Andric 272*e710425bSDimitry Andricint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) { return pthread_mutex_lock(__m); } 2730b57cec5SDimitry Andric 274*e710425bSDimitry Andricbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) { return pthread_mutex_trylock(__m) == 0; } 2750b57cec5SDimitry Andric 276*e710425bSDimitry Andricint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m) { return pthread_mutex_unlock(__m); } 2770b57cec5SDimitry Andric 278*e710425bSDimitry Andricint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m) { return pthread_mutex_destroy(__m); } 2790b57cec5SDimitry Andric 280*e710425bSDimitry Andricint __libcpp_mutex_lock(__libcpp_mutex_t* __m) { return pthread_mutex_lock(__m); } 2810b57cec5SDimitry Andric 282*e710425bSDimitry Andricbool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) { return pthread_mutex_trylock(__m) == 0; } 2830b57cec5SDimitry Andric 284*e710425bSDimitry Andricint __libcpp_mutex_unlock(__libcpp_mutex_t* __m) { return pthread_mutex_unlock(__m); } 2850b57cec5SDimitry Andric 286*e710425bSDimitry Andricint __libcpp_mutex_destroy(__libcpp_mutex_t* __m) { return pthread_mutex_destroy(__m); } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric// Condition Variable 289*e710425bSDimitry Andricint __libcpp_condvar_signal(__libcpp_condvar_t* __cv) { return pthread_cond_signal(__cv); } 2900b57cec5SDimitry Andric 291*e710425bSDimitry Andricint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) { return pthread_cond_broadcast(__cv); } 2920b57cec5SDimitry Andric 293*e710425bSDimitry Andricint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) { return pthread_cond_wait(__cv, __m); } 2940b57cec5SDimitry Andric 295*e710425bSDimitry Andricint __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, __libcpp_timespec_t* __ts) { 2960b57cec5SDimitry Andric return pthread_cond_timedwait(__cv, __m, __ts); 2970b57cec5SDimitry Andric} 2980b57cec5SDimitry Andric 299*e710425bSDimitry Andricint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) { return pthread_cond_destroy(__cv); } 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric// Execute once 302*e710425bSDimitry Andricint __libcpp_execute_once(__libcpp_exec_once_flag* __flag, void (*__init_routine)()) { 303753f127fSDimitry Andric return pthread_once(__flag, __init_routine); 3040b57cec5SDimitry Andric} 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric// Thread id 3070b57cec5SDimitry Andric// Returns non-zero if the thread ids are equal, otherwise 0 308*e710425bSDimitry Andricbool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2) { return __t1 == __t2; } 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric// Returns non-zero if t1 < t2, otherwise 0 311*e710425bSDimitry Andricbool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2) { return __t1 < __t2; } 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric// Thread 314*e710425bSDimitry Andricbool __libcpp_thread_isnull(const __libcpp_thread_t* __t) { return __libcpp_thread_get_id(__t) == 0; } 3150b57cec5SDimitry Andric 316*e710425bSDimitry Andricint __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) { 317e8d8bef9SDimitry Andric return pthread_create(__t, nullptr, __func, __arg); 3180b57cec5SDimitry Andric} 3190b57cec5SDimitry Andric 320*e710425bSDimitry Andric__libcpp_thread_id __libcpp_thread_get_current_id() { 321fe013be4SDimitry Andric const __libcpp_thread_t __current_thread = pthread_self(); 322fe013be4SDimitry Andric return __libcpp_thread_get_id(&__current_thread); 3230b57cec5SDimitry Andric} 3240b57cec5SDimitry Andric 325*e710425bSDimitry Andric__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) { 326e8d8bef9SDimitry Andric# if defined(__MVS__) 327e8d8bef9SDimitry Andric return __t->__; 328e8d8bef9SDimitry Andric# else 3290b57cec5SDimitry Andric return *__t; 330e8d8bef9SDimitry Andric# endif 3310b57cec5SDimitry Andric} 3320b57cec5SDimitry Andric 333*e710425bSDimitry Andricint __libcpp_thread_join(__libcpp_thread_t* __t) { return pthread_join(*__t, nullptr); } 3340b57cec5SDimitry Andric 335*e710425bSDimitry Andricint __libcpp_thread_detach(__libcpp_thread_t* __t) { return pthread_detach(*__t); } 3360b57cec5SDimitry Andric 337*e710425bSDimitry Andricvoid __libcpp_thread_yield() { sched_yield(); } 3380b57cec5SDimitry Andric 339*e710425bSDimitry Andricvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) { 340c9157d92SDimitry Andric __libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns); 341*e710425bSDimitry Andric while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR) 342*e710425bSDimitry Andric ; 3430b57cec5SDimitry Andric} 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric// Thread local storage 346*e710425bSDimitry Andricint __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*)) { 3470b57cec5SDimitry Andric return pthread_key_create(__key, __at_exit); 3480b57cec5SDimitry Andric} 3490b57cec5SDimitry Andric 350*e710425bSDimitry Andricvoid* __libcpp_tls_get(__libcpp_tls_key __key) { return pthread_getspecific(__key); } 3510b57cec5SDimitry Andric 352*e710425bSDimitry Andricint __libcpp_tls_set(__libcpp_tls_key __key, void* __p) { return pthread_setspecific(__key, __p); } 3530b57cec5SDimitry Andric 354480093f4SDimitry Andric# elif defined(_LIBCPP_HAS_THREAD_API_C11) 355480093f4SDimitry Andric 356*e710425bSDimitry Andricint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m) { 35755e4f9d5SDimitry Andric return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL; 358480093f4SDimitry Andric} 359480093f4SDimitry Andric 360*e710425bSDimitry Andricint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) { 361480093f4SDimitry Andric return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 362480093f4SDimitry Andric} 363480093f4SDimitry Andric 364*e710425bSDimitry Andricbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) { return mtx_trylock(__m) == thrd_success; } 365480093f4SDimitry Andric 366*e710425bSDimitry Andricint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m) { 367480093f4SDimitry Andric return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 368480093f4SDimitry Andric} 369480093f4SDimitry Andric 370*e710425bSDimitry Andricint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m) { 371480093f4SDimitry Andric mtx_destroy(__m); 372480093f4SDimitry Andric return 0; 373480093f4SDimitry Andric} 374480093f4SDimitry Andric 375*e710425bSDimitry Andricint __libcpp_mutex_lock(__libcpp_mutex_t* __m) { return mtx_lock(__m) == thrd_success ? 0 : EINVAL; } 376480093f4SDimitry Andric 377*e710425bSDimitry Andricbool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) { return mtx_trylock(__m) == thrd_success; } 378480093f4SDimitry Andric 379*e710425bSDimitry Andricint __libcpp_mutex_unlock(__libcpp_mutex_t* __m) { return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; } 380480093f4SDimitry Andric 381*e710425bSDimitry Andricint __libcpp_mutex_destroy(__libcpp_mutex_t* __m) { 382480093f4SDimitry Andric mtx_destroy(__m); 383480093f4SDimitry Andric return 0; 384480093f4SDimitry Andric} 385480093f4SDimitry Andric 386480093f4SDimitry Andric// Condition Variable 387*e710425bSDimitry Andricint __libcpp_condvar_signal(__libcpp_condvar_t* __cv) { return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; } 388480093f4SDimitry Andric 389*e710425bSDimitry Andricint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) { return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; } 390480093f4SDimitry Andric 391*e710425bSDimitry Andricint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) { 392480093f4SDimitry Andric return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL; 393480093f4SDimitry Andric} 394480093f4SDimitry Andric 395*e710425bSDimitry Andricint __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts) { 396480093f4SDimitry Andric int __ec = cnd_timedwait(__cv, __m, __ts); 397480093f4SDimitry Andric return __ec == thrd_timedout ? ETIMEDOUT : __ec; 398480093f4SDimitry Andric} 399480093f4SDimitry Andric 400*e710425bSDimitry Andricint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) { 401480093f4SDimitry Andric cnd_destroy(__cv); 402480093f4SDimitry Andric return 0; 403480093f4SDimitry Andric} 404480093f4SDimitry Andric 405480093f4SDimitry Andric// Execute once 406*e710425bSDimitry Andricint __libcpp_execute_once(__libcpp_exec_once_flag* flag, void (*init_routine)(void)) { 407480093f4SDimitry Andric ::call_once(flag, init_routine); 408480093f4SDimitry Andric return 0; 409480093f4SDimitry Andric} 410480093f4SDimitry Andric 411480093f4SDimitry Andric// Thread id 412480093f4SDimitry Andric// Returns non-zero if the thread ids are equal, otherwise 0 413*e710425bSDimitry Andricbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) { return thrd_equal(t1, t2) != 0; } 414480093f4SDimitry Andric 415480093f4SDimitry Andric// Returns non-zero if t1 < t2, otherwise 0 416*e710425bSDimitry Andricbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) { return t1 < t2; } 417480093f4SDimitry Andric 418480093f4SDimitry Andric// Thread 419*e710425bSDimitry Andricbool __libcpp_thread_isnull(const __libcpp_thread_t* __t) { return __libcpp_thread_get_id(__t) == 0; } 420480093f4SDimitry Andric 421*e710425bSDimitry Andricint __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) { 422480093f4SDimitry Andric int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg); 423480093f4SDimitry Andric return __ec == thrd_nomem ? ENOMEM : __ec; 424480093f4SDimitry Andric} 425480093f4SDimitry Andric 426*e710425bSDimitry Andric__libcpp_thread_id __libcpp_thread_get_current_id() { return thrd_current(); } 427480093f4SDimitry Andric 428*e710425bSDimitry Andric__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) { return *__t; } 429480093f4SDimitry Andric 430*e710425bSDimitry Andricint __libcpp_thread_join(__libcpp_thread_t* __t) { return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; } 431480093f4SDimitry Andric 432*e710425bSDimitry Andricint __libcpp_thread_detach(__libcpp_thread_t* __t) { return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; } 433480093f4SDimitry Andric 434*e710425bSDimitry Andricvoid __libcpp_thread_yield() { thrd_yield(); } 435480093f4SDimitry Andric 436*e710425bSDimitry Andricvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) { 437c9157d92SDimitry Andric __libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns); 438480093f4SDimitry Andric thrd_sleep(&__ts, nullptr); 439480093f4SDimitry Andric} 440480093f4SDimitry Andric 441480093f4SDimitry Andric// Thread local storage 442*e710425bSDimitry Andricint __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*)) { 443480093f4SDimitry Andric return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL; 444480093f4SDimitry Andric} 445480093f4SDimitry Andric 446*e710425bSDimitry Andricvoid* __libcpp_tls_get(__libcpp_tls_key __key) { return tss_get(__key); } 447480093f4SDimitry Andric 448*e710425bSDimitry Andricint __libcpp_tls_set(__libcpp_tls_key __key, void* __p) { return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; } 449480093f4SDimitry Andric 450480093f4SDimitry Andric# endif 451480093f4SDimitry Andric 4520b57cec5SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 4550b57cec5SDimitry Andric 45681ad6265SDimitry Andric#endif // _LIBCPP___THREADING_SUPPORT 457