1c7e4239fSAsiri Rathnayake// -*- C++ -*- 2c7e4239fSAsiri Rathnayake//===----------------------------------------------------------------------===// 3c7e4239fSAsiri Rathnayake// 457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information. 657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7c7e4239fSAsiri Rathnayake// 8c7e4239fSAsiri Rathnayake//===----------------------------------------------------------------------===// 9c7e4239fSAsiri Rathnayake 10c7e4239fSAsiri Rathnayake#ifndef _LIBCPP_THREADING_SUPPORT 11c7e4239fSAsiri Rathnayake#define _LIBCPP_THREADING_SUPPORT 12c7e4239fSAsiri Rathnayake 13c7e4239fSAsiri Rathnayake#include <__config> 14*2eadbc86SLouis Dionne#include <__availability> 1554a987e1SAsiri Rathnayake#include <chrono> 162b1d4254SMarshall Clow#include <iosfwd> 1754a987e1SAsiri Rathnayake#include <errno.h> 18c7e4239fSAsiri Rathnayake 19c7e4239fSAsiri Rathnayake#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 20c7e4239fSAsiri Rathnayake#pragma GCC system_header 21c7e4239fSAsiri Rathnayake#endif 22c7e4239fSAsiri Rathnayake 2300f6beaeSEric Fiselier#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 243cf2f7bcSAsiri Rathnayake# include <__external_threading> 2500f6beaeSEric Fiselier#elif !defined(_LIBCPP_HAS_NO_THREADS) 26790e10f6SSaleem Abdulrasool 2700f6beaeSEric Fiselier#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 28c7e4239fSAsiri Rathnayake# include <pthread.h> 29c7e4239fSAsiri Rathnayake# include <sched.h> 3054fa9ecdSOlivier Giroux# ifdef __APPLE__ 3154fa9ecdSOlivier Giroux# define _LIBCPP_NO_NATIVE_SEMAPHORES 3254fa9ecdSOlivier Giroux# endif 3362138846Sogiroux# ifndef _LIBCPP_NO_NATIVE_SEMAPHORES 3462138846Sogiroux# include <semaphore.h> 3562138846Sogiroux# endif 36ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11) 37ab9aefeeSPetr Hosek# include <threads.h> 38790e10f6SSaleem Abdulrasool#endif 39c7e4239fSAsiri Rathnayake 402a129dc3SPeter Collingbourne#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 412a129dc3SPeter Collingbourne defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \ 422a129dc3SPeter Collingbourne defined(_LIBCPP_HAS_THREAD_API_WIN32) 432a129dc3SPeter Collingbourne#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 442a129dc3SPeter Collingbourne#else 452a129dc3SPeter Collingbourne#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 462a129dc3SPeter Collingbourne#endif 472a129dc3SPeter Collingbourne 4883dca5c3SDimitry Andric#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) 4983dca5c3SDimitry Andric#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) 5083dca5c3SDimitry Andric#else 5183dca5c3SDimitry Andric#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 5283dca5c3SDimitry Andric#endif 5383dca5c3SDimitry Andric 54696630eaSMarshall Clowtypedef ::timespec __libcpp_timespec_t; 55696630eaSMarshall Clow#endif // !defined(_LIBCPP_HAS_NO_THREADS) 56696630eaSMarshall Clow 57696630eaSMarshall Clow_LIBCPP_PUSH_MACROS 58696630eaSMarshall Clow#include <__undef_macros> 59696630eaSMarshall Clow 60c7e4239fSAsiri Rathnayake_LIBCPP_BEGIN_NAMESPACE_STD 61c7e4239fSAsiri Rathnayake 62696630eaSMarshall Clow#if !defined(_LIBCPP_HAS_NO_THREADS) 63696630eaSMarshall Clow 642a129dc3SPeter Collingbourne#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 65c7e4239fSAsiri Rathnayake// Mutex 66c7e4239fSAsiri Rathnayaketypedef pthread_mutex_t __libcpp_mutex_t; 678c2bf45dSAsiri Rathnayake#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 68c7e4239fSAsiri Rathnayake 6958a0dceeSSaleem Abdulrasooltypedef pthread_mutex_t __libcpp_recursive_mutex_t; 7058a0dceeSSaleem Abdulrasool 71790e10f6SSaleem Abdulrasool// Condition Variable 72790e10f6SSaleem Abdulrasooltypedef pthread_cond_t __libcpp_condvar_t; 73790e10f6SSaleem Abdulrasool#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 74790e10f6SSaleem Abdulrasool 7562138846Sogiroux#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES 7654fa9ecdSOlivier Giroux// Semaphore 7754fa9ecdSOlivier Girouxtypedef sem_t __libcpp_semaphore_t; 7854fa9ecdSOlivier Giroux# define _LIBCPP_SEMAPHORE_MAX SEM_VALUE_MAX 7962138846Sogiroux#endif 8054fa9ecdSOlivier Giroux 81205d7d3fSAsiri Rathnayake// Execute once 82205d7d3fSAsiri Rathnayaketypedef pthread_once_t __libcpp_exec_once_flag; 83205d7d3fSAsiri Rathnayake#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 84205d7d3fSAsiri Rathnayake 85205d7d3fSAsiri Rathnayake// Thread id 86790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_id; 87790e10f6SSaleem Abdulrasool 88790e10f6SSaleem Abdulrasool// Thread 89af762e91SAsiri Rathnayake#define _LIBCPP_NULL_THREAD 0U 90af762e91SAsiri Rathnayake 91790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_t; 92790e10f6SSaleem Abdulrasool 93cac6d217SFangrui Song// Thread Local Storage 94790e10f6SSaleem Abdulrasooltypedef pthread_key_t __libcpp_tls_key; 956d7d0becSSaleem Abdulrasool 966d7d0becSSaleem Abdulrasool#define _LIBCPP_TLS_DESTRUCTOR_CC 97ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11) 98ab9aefeeSPetr Hosek// Mutex 99ab9aefeeSPetr Hosektypedef mtx_t __libcpp_mutex_t; 100ab9aefeeSPetr Hosek// mtx_t is a struct so using {} for initialization is valid. 101ab9aefeeSPetr Hosek#define _LIBCPP_MUTEX_INITIALIZER {} 102ab9aefeeSPetr Hosek 103ab9aefeeSPetr Hosektypedef mtx_t __libcpp_recursive_mutex_t; 104ab9aefeeSPetr Hosek 105ab9aefeeSPetr Hosek// Condition Variable 106ab9aefeeSPetr Hosektypedef cnd_t __libcpp_condvar_t; 107ab9aefeeSPetr Hosek// cnd_t is a struct so using {} for initialization is valid. 108ab9aefeeSPetr Hosek#define _LIBCPP_CONDVAR_INITIALIZER {} 109ab9aefeeSPetr Hosek 110ab9aefeeSPetr Hosek// Execute once 111ab9aefeeSPetr Hosektypedef once_flag __libcpp_exec_once_flag; 112ab9aefeeSPetr Hosek#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT 113ab9aefeeSPetr Hosek 114ab9aefeeSPetr Hosek// Thread id 115ab9aefeeSPetr Hosektypedef thrd_t __libcpp_thread_id; 116ab9aefeeSPetr Hosek 117ab9aefeeSPetr Hosek// Thread 118ab9aefeeSPetr Hosek#define _LIBCPP_NULL_THREAD 0U 119ab9aefeeSPetr Hosek 120ab9aefeeSPetr Hosektypedef thrd_t __libcpp_thread_t; 121ab9aefeeSPetr Hosek 122ab9aefeeSPetr Hosek// Thread Local Storage 123ab9aefeeSPetr Hosektypedef tss_t __libcpp_tls_key; 124ab9aefeeSPetr Hosek 125ab9aefeeSPetr Hosek#define _LIBCPP_TLS_DESTRUCTOR_CC 126e2b200b7SDavid Spickett#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 127ac15ae6dSPeter Collingbourne// Mutex 128ac15ae6dSPeter Collingbournetypedef void* __libcpp_mutex_t; 129ac15ae6dSPeter Collingbourne#define _LIBCPP_MUTEX_INITIALIZER 0 130ac15ae6dSPeter Collingbourne 131ac15ae6dSPeter Collingbourne#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) 132ac15ae6dSPeter Collingbournetypedef void* __libcpp_recursive_mutex_t[6]; 133ac15ae6dSPeter Collingbourne#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) 134ac15ae6dSPeter Collingbournetypedef void* __libcpp_recursive_mutex_t[5]; 135ac15ae6dSPeter Collingbourne#else 136ac15ae6dSPeter Collingbourne# error Unsupported architecture 137ac15ae6dSPeter Collingbourne#endif 1386d7d0becSSaleem Abdulrasool 1396d7d0becSSaleem Abdulrasool// Condition Variable 140ac15ae6dSPeter Collingbournetypedef void* __libcpp_condvar_t; 141ac15ae6dSPeter Collingbourne#define _LIBCPP_CONDVAR_INITIALIZER 0 1426d7d0becSSaleem Abdulrasool 14354fa9ecdSOlivier Giroux// Semaphore 14454fa9ecdSOlivier Girouxtypedef void* __libcpp_semaphore_t; 14554fa9ecdSOlivier Giroux 1466d7d0becSSaleem Abdulrasool// Execute Once 147ac15ae6dSPeter Collingbournetypedef void* __libcpp_exec_once_flag; 148ac15ae6dSPeter Collingbourne#define _LIBCPP_EXEC_ONCE_INITIALIZER 0 1496d7d0becSSaleem Abdulrasool 1506d7d0becSSaleem Abdulrasool// Thread ID 151ac15ae6dSPeter Collingbournetypedef long __libcpp_thread_id; 1526d7d0becSSaleem Abdulrasool 1536d7d0becSSaleem Abdulrasool// Thread 154af762e91SAsiri Rathnayake#define _LIBCPP_NULL_THREAD 0U 155af762e91SAsiri Rathnayake 156ac15ae6dSPeter Collingbournetypedef void* __libcpp_thread_t; 1576d7d0becSSaleem Abdulrasool 1586d7d0becSSaleem Abdulrasool// Thread Local Storage 159ac15ae6dSPeter Collingbournetypedef long __libcpp_tls_key; 1606d7d0becSSaleem Abdulrasool 161ac15ae6dSPeter Collingbourne#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall 162e2b200b7SDavid Spickett#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 163790e10f6SSaleem Abdulrasool 164e2b200b7SDavid Spickett#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 165790e10f6SSaleem Abdulrasool// Mutex 1668c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 16758a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 16858a0dceeSSaleem Abdulrasool 16983dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 17058a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 17158a0dceeSSaleem Abdulrasool 17283dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 17308e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 17458a0dceeSSaleem Abdulrasool 17583dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 17658a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 17758a0dceeSSaleem Abdulrasool 17858a0dceeSSaleem Abdulrasool_LIBCPP_THREAD_ABI_VISIBILITY 17958a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 180790e10f6SSaleem Abdulrasool 18183dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 1828c2bf45dSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m); 183790e10f6SSaleem Abdulrasool 18483dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 18508e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 186790e10f6SSaleem Abdulrasool 18783dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 1888c2bf45dSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 189790e10f6SSaleem Abdulrasool 1908c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1918c2bf45dSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 1928c2bf45dSAsiri Rathnayake 1938c2bf45dSAsiri Rathnayake// Condition variable 1948c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1958c2bf45dSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 196790e10f6SSaleem Abdulrasool 1978c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1988c2bf45dSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 199790e10f6SSaleem Abdulrasool 20083dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 2018c2bf45dSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 202790e10f6SSaleem Abdulrasool 20383dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 204790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 205cfdc7f0dSMikhail Maltsev __libcpp_timespec_t *__ts); 206790e10f6SSaleem Abdulrasool 2078c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2088c2bf45dSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 2098c2bf45dSAsiri Rathnayake 21062138846Sogiroux#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES 21162138846Sogiroux 21254fa9ecdSOlivier Giroux// Semaphore 21354fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY 21454fa9ecdSOlivier Girouxbool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init); 21554fa9ecdSOlivier Giroux 21654fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY 21754fa9ecdSOlivier Girouxbool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem); 21854fa9ecdSOlivier Giroux 21954fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY 22054fa9ecdSOlivier Girouxbool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem); 22154fa9ecdSOlivier Giroux 22254fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY 22354fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem); 22454fa9ecdSOlivier Giroux 22554fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY 22654fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns); 22754fa9ecdSOlivier Giroux 22862138846Sogiroux#endif // _LIBCPP_NO_NATIVE_SEMAPHORES 22962138846Sogiroux 230205d7d3fSAsiri Rathnayake// Execute once 231205d7d3fSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 232205d7d3fSAsiri Rathnayakeint __libcpp_execute_once(__libcpp_exec_once_flag *flag, 2334603460aSBruce Mitchener void (*init_routine)()); 234205d7d3fSAsiri Rathnayake 235205d7d3fSAsiri Rathnayake// Thread id 2368c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2378c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 238790e10f6SSaleem Abdulrasool 2398c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2408c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 2418c2bf45dSAsiri Rathnayake 2428c2bf45dSAsiri Rathnayake// Thread 2438c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 244af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 245af762e91SAsiri Rathnayake 246af762e91SAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 247790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 248790e10f6SSaleem Abdulrasool void *__arg); 249790e10f6SSaleem Abdulrasool 2508c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2518c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id(); 252790e10f6SSaleem Abdulrasool 2538c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2548c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 255790e10f6SSaleem Abdulrasool 2568c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2578c2bf45dSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t); 258790e10f6SSaleem Abdulrasool 2598c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2608c2bf45dSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t); 261790e10f6SSaleem Abdulrasool 2628c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2638c2bf45dSAsiri Rathnayakevoid __libcpp_thread_yield(); 2648c2bf45dSAsiri Rathnayake 26554a987e1SAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2669e8a082dSJoerg Sonnenbergervoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 26754a987e1SAsiri Rathnayake 2688c2bf45dSAsiri Rathnayake// Thread local storage 2698c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2706d7d0becSSaleem Abdulrasoolint __libcpp_tls_create(__libcpp_tls_key* __key, 2716d7d0becSSaleem Abdulrasool void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 272790e10f6SSaleem Abdulrasool 2738c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2748c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key); 275790e10f6SSaleem Abdulrasool 2768c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 277205d7d3fSAsiri Rathnayakeint __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 2788c2bf45dSAsiri Rathnayake 279e2b200b7SDavid Spickett#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 280e2b200b7SDavid Spickett 28114aef536SMikhail Maltsevstruct __libcpp_timed_backoff_policy { 28221a1a263SLouis Dionne _LIBCPP_INLINE_VISIBILITY 28321a1a263SLouis Dionne bool operator()(chrono::nanoseconds __elapsed) const 2843411a1a9SDavid Nicuesa { 2853411a1a9SDavid Nicuesa if(__elapsed > chrono::milliseconds(128)) 2863411a1a9SDavid Nicuesa __libcpp_thread_sleep_for(chrono::milliseconds(8)); 2873411a1a9SDavid Nicuesa else if(__elapsed > chrono::microseconds(64)) 2883411a1a9SDavid Nicuesa __libcpp_thread_sleep_for(__elapsed / 2); 2893411a1a9SDavid Nicuesa else if(__elapsed > chrono::microseconds(4)) 2903411a1a9SDavid Nicuesa __libcpp_thread_yield(); 2913411a1a9SDavid Nicuesa else 2923411a1a9SDavid Nicuesa ; // poll 2933411a1a9SDavid Nicuesa return false; 2943411a1a9SDavid Nicuesa } 29521a1a263SLouis Dionne}; 2963411a1a9SDavid Nicuesa 2973411a1a9SDavid Nicuesastatic _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64; 2983411a1a9SDavid Nicuesa 29914aef536SMikhail Maltsevtemplate<class _Fn, class _BFn> 30046c38761SLouis Dionne_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 30114aef536SMikhail Maltsevbool __libcpp_thread_poll_with_backoff( 3023411a1a9SDavid Nicuesa _Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero()) 3033411a1a9SDavid Nicuesa{ 3043411a1a9SDavid Nicuesa auto const __start = chrono::high_resolution_clock::now(); 3053411a1a9SDavid Nicuesa for(int __count = 0;;) { 3063411a1a9SDavid Nicuesa if(__f()) 3073411a1a9SDavid Nicuesa return true; // _Fn completion means success 3083411a1a9SDavid Nicuesa if(__count < __libcpp_polling_count) { 3093411a1a9SDavid Nicuesa __count += 1; 3103411a1a9SDavid Nicuesa continue; 3113411a1a9SDavid Nicuesa } 3123411a1a9SDavid Nicuesa chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start; 3133411a1a9SDavid Nicuesa if(__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed) 3143411a1a9SDavid Nicuesa return false; // timeout failure 3153411a1a9SDavid Nicuesa if(__bf(__elapsed)) 3163411a1a9SDavid Nicuesa return false; // _BFn completion means failure 3173411a1a9SDavid Nicuesa } 3183411a1a9SDavid Nicuesa} 3193411a1a9SDavid Nicuesa 3203411a1a9SDavid Nicuesa#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 3213411a1a9SDavid Nicuesa defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) 3223411a1a9SDavid Nicuesa 32314aef536SMikhail Maltsev 324ab9aefeeSPetr Hoseknamespace __thread_detail { 325ab9aefeeSPetr Hosek 326ab9aefeeSPetr Hosekinline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns) 327ab9aefeeSPetr Hosek{ 328ab9aefeeSPetr Hosek using namespace chrono; 329ab9aefeeSPetr Hosek seconds __s = duration_cast<seconds>(__ns); 330ab9aefeeSPetr Hosek __libcpp_timespec_t __ts; 331ab9aefeeSPetr Hosek typedef decltype(__ts.tv_sec) __ts_sec; 332ab9aefeeSPetr Hosek const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); 333ab9aefeeSPetr Hosek 334ab9aefeeSPetr Hosek if (__s.count() < __ts_sec_max) 335ab9aefeeSPetr Hosek { 336ab9aefeeSPetr Hosek __ts.tv_sec = static_cast<__ts_sec>(__s.count()); 337ab9aefeeSPetr Hosek __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count()); 338ab9aefeeSPetr Hosek } 339ab9aefeeSPetr Hosek else 340ab9aefeeSPetr Hosek { 341ab9aefeeSPetr Hosek __ts.tv_sec = __ts_sec_max; 342ab9aefeeSPetr Hosek __ts.tv_nsec = 999999999; // (10^9 - 1) 343ab9aefeeSPetr Hosek } 344ab9aefeeSPetr Hosek 345ab9aefeeSPetr Hosek return __ts; 346ab9aefeeSPetr Hosek} 347ab9aefeeSPetr Hosek 348ab9aefeeSPetr Hosek} 349ab9aefeeSPetr Hosek 350ab9aefeeSPetr Hosek#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 3518c2bf45dSAsiri Rathnayake 35258a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 353c7e4239fSAsiri Rathnayake{ 354c7e4239fSAsiri Rathnayake pthread_mutexattr_t attr; 355c7e4239fSAsiri Rathnayake int __ec = pthread_mutexattr_init(&attr); 356c7e4239fSAsiri Rathnayake if (__ec) 357790e10f6SSaleem Abdulrasool return __ec; 358790e10f6SSaleem Abdulrasool __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 359790e10f6SSaleem Abdulrasool if (__ec) { 360c7e4239fSAsiri Rathnayake pthread_mutexattr_destroy(&attr); 361c7e4239fSAsiri Rathnayake return __ec; 362c7e4239fSAsiri Rathnayake } 363c7e4239fSAsiri Rathnayake __ec = pthread_mutex_init(__m, &attr); 364790e10f6SSaleem Abdulrasool if (__ec) { 365c7e4239fSAsiri Rathnayake pthread_mutexattr_destroy(&attr); 366c7e4239fSAsiri Rathnayake return __ec; 367c7e4239fSAsiri Rathnayake } 368c7e4239fSAsiri Rathnayake __ec = pthread_mutexattr_destroy(&attr); 369790e10f6SSaleem Abdulrasool if (__ec) { 370c7e4239fSAsiri Rathnayake pthread_mutex_destroy(__m); 371c7e4239fSAsiri Rathnayake return __ec; 372c7e4239fSAsiri Rathnayake } 373c7e4239fSAsiri Rathnayake return 0; 374c7e4239fSAsiri Rathnayake} 375c7e4239fSAsiri Rathnayake 37658a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 37758a0dceeSSaleem Abdulrasool{ 37858a0dceeSSaleem Abdulrasool return pthread_mutex_lock(__m); 37958a0dceeSSaleem Abdulrasool} 38058a0dceeSSaleem Abdulrasool 38108e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 38258a0dceeSSaleem Abdulrasool{ 38308e1477cSEric Fiselier return pthread_mutex_trylock(__m) == 0; 38458a0dceeSSaleem Abdulrasool} 38558a0dceeSSaleem Abdulrasool 38658a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 38758a0dceeSSaleem Abdulrasool{ 38858a0dceeSSaleem Abdulrasool return pthread_mutex_unlock(__m); 38958a0dceeSSaleem Abdulrasool} 39058a0dceeSSaleem Abdulrasool 39158a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 39258a0dceeSSaleem Abdulrasool{ 39358a0dceeSSaleem Abdulrasool return pthread_mutex_destroy(__m); 39458a0dceeSSaleem Abdulrasool} 39558a0dceeSSaleem Abdulrasool 396c7e4239fSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m) 397c7e4239fSAsiri Rathnayake{ 398c7e4239fSAsiri Rathnayake return pthread_mutex_lock(__m); 399c7e4239fSAsiri Rathnayake} 400c7e4239fSAsiri Rathnayake 40108e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 402c7e4239fSAsiri Rathnayake{ 40308e1477cSEric Fiselier return pthread_mutex_trylock(__m) == 0; 404c7e4239fSAsiri Rathnayake} 405c7e4239fSAsiri Rathnayake 406c7e4239fSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 407c7e4239fSAsiri Rathnayake{ 408c7e4239fSAsiri Rathnayake return pthread_mutex_unlock(__m); 409c7e4239fSAsiri Rathnayake} 410c7e4239fSAsiri Rathnayake 411c7e4239fSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 412c7e4239fSAsiri Rathnayake{ 413c7e4239fSAsiri Rathnayake return pthread_mutex_destroy(__m); 414c7e4239fSAsiri Rathnayake} 415c7e4239fSAsiri Rathnayake 416790e10f6SSaleem Abdulrasool// Condition Variable 417c7e4239fSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 418c7e4239fSAsiri Rathnayake{ 419c7e4239fSAsiri Rathnayake return pthread_cond_signal(__cv); 420c7e4239fSAsiri Rathnayake} 421c7e4239fSAsiri Rathnayake 422c7e4239fSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 423c7e4239fSAsiri Rathnayake{ 424c7e4239fSAsiri Rathnayake return pthread_cond_broadcast(__cv); 425c7e4239fSAsiri Rathnayake} 426c7e4239fSAsiri Rathnayake 427c7e4239fSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 428c7e4239fSAsiri Rathnayake{ 429c7e4239fSAsiri Rathnayake return pthread_cond_wait(__cv, __m); 430c7e4239fSAsiri Rathnayake} 431c7e4239fSAsiri Rathnayake 432790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 433cfdc7f0dSMikhail Maltsev __libcpp_timespec_t *__ts) 434c7e4239fSAsiri Rathnayake{ 435c7e4239fSAsiri Rathnayake return pthread_cond_timedwait(__cv, __m, __ts); 436c7e4239fSAsiri Rathnayake} 437c7e4239fSAsiri Rathnayake 438c7e4239fSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 439c7e4239fSAsiri Rathnayake{ 440c7e4239fSAsiri Rathnayake return pthread_cond_destroy(__cv); 441c7e4239fSAsiri Rathnayake} 442c7e4239fSAsiri Rathnayake 44354fa9ecdSOlivier Giroux#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES 44454fa9ecdSOlivier Giroux 44554fa9ecdSOlivier Giroux// Semaphore 44654fa9ecdSOlivier Girouxbool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init) 44754fa9ecdSOlivier Giroux{ 44854fa9ecdSOlivier Giroux return sem_init(__sem, 0, __init) == 0; 44954fa9ecdSOlivier Giroux} 45054fa9ecdSOlivier Giroux 45154fa9ecdSOlivier Girouxbool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem) 45254fa9ecdSOlivier Giroux{ 45354fa9ecdSOlivier Giroux return sem_destroy(__sem) == 0; 45454fa9ecdSOlivier Giroux} 45554fa9ecdSOlivier Giroux 45654fa9ecdSOlivier Girouxbool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem) 45754fa9ecdSOlivier Giroux{ 45854fa9ecdSOlivier Giroux return sem_post(__sem) == 0; 45954fa9ecdSOlivier Giroux} 46054fa9ecdSOlivier Giroux 46154fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem) 46254fa9ecdSOlivier Giroux{ 46354fa9ecdSOlivier Giroux return sem_wait(__sem) == 0; 46454fa9ecdSOlivier Giroux} 46554fa9ecdSOlivier Giroux 46654fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns) 46754fa9ecdSOlivier Giroux{ 46854fa9ecdSOlivier Giroux auto const __abs_time = chrono::system_clock::now().time_since_epoch() + __ns; 46954fa9ecdSOlivier Giroux __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__abs_time); 47054fa9ecdSOlivier Giroux return sem_timedwait(__sem, &__ts) == 0; 47154fa9ecdSOlivier Giroux} 47254fa9ecdSOlivier Giroux 47354fa9ecdSOlivier Giroux#endif //_LIBCPP_NO_NATIVE_SEMAPHORES 47454fa9ecdSOlivier Giroux 475205d7d3fSAsiri Rathnayake// Execute once 476205d7d3fSAsiri Rathnayakeint __libcpp_execute_once(__libcpp_exec_once_flag *flag, 4774603460aSBruce Mitchener void (*init_routine)()) { 478205d7d3fSAsiri Rathnayake return pthread_once(flag, init_routine); 479205d7d3fSAsiri Rathnayake} 480205d7d3fSAsiri Rathnayake 481205d7d3fSAsiri Rathnayake// Thread id 482c7e4239fSAsiri Rathnayake// Returns non-zero if the thread ids are equal, otherwise 0 483c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 484c7e4239fSAsiri Rathnayake{ 485c7e4239fSAsiri Rathnayake return pthread_equal(t1, t2) != 0; 486c7e4239fSAsiri Rathnayake} 487c7e4239fSAsiri Rathnayake 488c7e4239fSAsiri Rathnayake// Returns non-zero if t1 < t2, otherwise 0 489c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 490c7e4239fSAsiri Rathnayake{ 491c7e4239fSAsiri Rathnayake return t1 < t2; 492c7e4239fSAsiri Rathnayake} 493c7e4239fSAsiri Rathnayake 494c7e4239fSAsiri Rathnayake// Thread 495af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 496af762e91SAsiri Rathnayake return *__t == 0; 497af762e91SAsiri Rathnayake} 498af762e91SAsiri Rathnayake 499790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 500790e10f6SSaleem Abdulrasool void *__arg) 501c7e4239fSAsiri Rathnayake{ 502c7e4239fSAsiri Rathnayake return pthread_create(__t, 0, __func, __arg); 503c7e4239fSAsiri Rathnayake} 504c7e4239fSAsiri Rathnayake 505c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id() 506c7e4239fSAsiri Rathnayake{ 507c7e4239fSAsiri Rathnayake return pthread_self(); 508c7e4239fSAsiri Rathnayake} 509c7e4239fSAsiri Rathnayake 510c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 511c7e4239fSAsiri Rathnayake{ 512c7e4239fSAsiri Rathnayake return *__t; 513c7e4239fSAsiri Rathnayake} 514c7e4239fSAsiri Rathnayake 515c7e4239fSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t) 516c7e4239fSAsiri Rathnayake{ 517c7e4239fSAsiri Rathnayake return pthread_join(*__t, 0); 518c7e4239fSAsiri Rathnayake} 519c7e4239fSAsiri Rathnayake 520c7e4239fSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t) 521c7e4239fSAsiri Rathnayake{ 522c7e4239fSAsiri Rathnayake return pthread_detach(*__t); 523c7e4239fSAsiri Rathnayake} 524c7e4239fSAsiri Rathnayake 525c7e4239fSAsiri Rathnayakevoid __libcpp_thread_yield() 526c7e4239fSAsiri Rathnayake{ 527c7e4239fSAsiri Rathnayake sched_yield(); 528c7e4239fSAsiri Rathnayake} 529c7e4239fSAsiri Rathnayake 53054a987e1SAsiri Rathnayakevoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 53154a987e1SAsiri Rathnayake{ 532ab9aefeeSPetr Hosek __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns); 53354a987e1SAsiri Rathnayake while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); 53454a987e1SAsiri Rathnayake} 53554a987e1SAsiri Rathnayake 536c7e4239fSAsiri Rathnayake// Thread local storage 5378c2bf45dSAsiri Rathnayakeint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 538c7e4239fSAsiri Rathnayake{ 539c7e4239fSAsiri Rathnayake return pthread_key_create(__key, __at_exit); 540c7e4239fSAsiri Rathnayake} 541c7e4239fSAsiri Rathnayake 5428c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key) 543c7e4239fSAsiri Rathnayake{ 544c7e4239fSAsiri Rathnayake return pthread_getspecific(__key); 545c7e4239fSAsiri Rathnayake} 546c7e4239fSAsiri Rathnayake 547205d7d3fSAsiri Rathnayakeint __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 548c7e4239fSAsiri Rathnayake{ 549205d7d3fSAsiri Rathnayake return pthread_setspecific(__key, __p); 550c7e4239fSAsiri Rathnayake} 551c7e4239fSAsiri Rathnayake 552ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11) 553ab9aefeeSPetr Hosek 554ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 555ab9aefeeSPetr Hosek{ 5563481e5d7SPetr Hosek return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL; 557ab9aefeeSPetr Hosek} 558ab9aefeeSPetr Hosek 559ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 560ab9aefeeSPetr Hosek{ 561ab9aefeeSPetr Hosek return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 562ab9aefeeSPetr Hosek} 563ab9aefeeSPetr Hosek 564ab9aefeeSPetr Hosekbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 565ab9aefeeSPetr Hosek{ 566ab9aefeeSPetr Hosek return mtx_trylock(__m) == thrd_success; 567ab9aefeeSPetr Hosek} 568ab9aefeeSPetr Hosek 569ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 570ab9aefeeSPetr Hosek{ 571ab9aefeeSPetr Hosek return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 572ab9aefeeSPetr Hosek} 573ab9aefeeSPetr Hosek 574ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 575ab9aefeeSPetr Hosek{ 576ab9aefeeSPetr Hosek mtx_destroy(__m); 577ab9aefeeSPetr Hosek return 0; 578ab9aefeeSPetr Hosek} 579ab9aefeeSPetr Hosek 580ab9aefeeSPetr Hosekint __libcpp_mutex_lock(__libcpp_mutex_t *__m) 581ab9aefeeSPetr Hosek{ 582ab9aefeeSPetr Hosek return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 583ab9aefeeSPetr Hosek} 584ab9aefeeSPetr Hosek 585ab9aefeeSPetr Hosekbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 586ab9aefeeSPetr Hosek{ 587ab9aefeeSPetr Hosek return mtx_trylock(__m) == thrd_success; 588ab9aefeeSPetr Hosek} 589ab9aefeeSPetr Hosek 590ab9aefeeSPetr Hosekint __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 591ab9aefeeSPetr Hosek{ 592ab9aefeeSPetr Hosek return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 593ab9aefeeSPetr Hosek} 594ab9aefeeSPetr Hosek 595ab9aefeeSPetr Hosekint __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 596ab9aefeeSPetr Hosek{ 597ab9aefeeSPetr Hosek mtx_destroy(__m); 598ab9aefeeSPetr Hosek return 0; 599ab9aefeeSPetr Hosek} 600ab9aefeeSPetr Hosek 601ab9aefeeSPetr Hosek// Condition Variable 602ab9aefeeSPetr Hosekint __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 603ab9aefeeSPetr Hosek{ 604ab9aefeeSPetr Hosek return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; 605ab9aefeeSPetr Hosek} 606ab9aefeeSPetr Hosek 607ab9aefeeSPetr Hosekint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 608ab9aefeeSPetr Hosek{ 609ab9aefeeSPetr Hosek return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; 610ab9aefeeSPetr Hosek} 611ab9aefeeSPetr Hosek 612ab9aefeeSPetr Hosekint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 613ab9aefeeSPetr Hosek{ 614ab9aefeeSPetr Hosek return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL; 615ab9aefeeSPetr Hosek} 616ab9aefeeSPetr Hosek 617ab9aefeeSPetr Hosekint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 618ab9aefeeSPetr Hosek timespec *__ts) 619ab9aefeeSPetr Hosek{ 620ab9aefeeSPetr Hosek int __ec = cnd_timedwait(__cv, __m, __ts); 621ab9aefeeSPetr Hosek return __ec == thrd_timedout ? ETIMEDOUT : __ec; 622ab9aefeeSPetr Hosek} 623ab9aefeeSPetr Hosek 624ab9aefeeSPetr Hosekint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 625ab9aefeeSPetr Hosek{ 626ab9aefeeSPetr Hosek cnd_destroy(__cv); 627ab9aefeeSPetr Hosek return 0; 628ab9aefeeSPetr Hosek} 629ab9aefeeSPetr Hosek 630ab9aefeeSPetr Hosek// Execute once 631ab9aefeeSPetr Hosekint __libcpp_execute_once(__libcpp_exec_once_flag *flag, 632ab9aefeeSPetr Hosek void (*init_routine)(void)) { 633ab9aefeeSPetr Hosek ::call_once(flag, init_routine); 634ab9aefeeSPetr Hosek return 0; 635ab9aefeeSPetr Hosek} 636ab9aefeeSPetr Hosek 637ab9aefeeSPetr Hosek// Thread id 638ab9aefeeSPetr Hosek// Returns non-zero if the thread ids are equal, otherwise 0 639ab9aefeeSPetr Hosekbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 640ab9aefeeSPetr Hosek{ 641ab9aefeeSPetr Hosek return thrd_equal(t1, t2) != 0; 642ab9aefeeSPetr Hosek} 643ab9aefeeSPetr Hosek 644ab9aefeeSPetr Hosek// Returns non-zero if t1 < t2, otherwise 0 645ab9aefeeSPetr Hosekbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 646ab9aefeeSPetr Hosek{ 647ab9aefeeSPetr Hosek return t1 < t2; 648ab9aefeeSPetr Hosek} 649ab9aefeeSPetr Hosek 650ab9aefeeSPetr Hosek// Thread 651ab9aefeeSPetr Hosekbool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 652ab9aefeeSPetr Hosek return *__t == 0; 653ab9aefeeSPetr Hosek} 654ab9aefeeSPetr Hosek 655ab9aefeeSPetr Hosekint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 656ab9aefeeSPetr Hosek void *__arg) 657ab9aefeeSPetr Hosek{ 658ab9aefeeSPetr Hosek int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg); 659ab9aefeeSPetr Hosek return __ec == thrd_nomem ? ENOMEM : __ec; 660ab9aefeeSPetr Hosek} 661ab9aefeeSPetr Hosek 662ab9aefeeSPetr Hosek__libcpp_thread_id __libcpp_thread_get_current_id() 663ab9aefeeSPetr Hosek{ 664ab9aefeeSPetr Hosek return thrd_current(); 665ab9aefeeSPetr Hosek} 666ab9aefeeSPetr Hosek 667ab9aefeeSPetr Hosek__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 668ab9aefeeSPetr Hosek{ 669ab9aefeeSPetr Hosek return *__t; 670ab9aefeeSPetr Hosek} 671ab9aefeeSPetr Hosek 672ab9aefeeSPetr Hosekint __libcpp_thread_join(__libcpp_thread_t *__t) 673ab9aefeeSPetr Hosek{ 674ab9aefeeSPetr Hosek return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; 675ab9aefeeSPetr Hosek} 676ab9aefeeSPetr Hosek 677ab9aefeeSPetr Hosekint __libcpp_thread_detach(__libcpp_thread_t *__t) 678ab9aefeeSPetr Hosek{ 679ab9aefeeSPetr Hosek return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; 680ab9aefeeSPetr Hosek} 681ab9aefeeSPetr Hosek 682ab9aefeeSPetr Hosekvoid __libcpp_thread_yield() 683ab9aefeeSPetr Hosek{ 684ab9aefeeSPetr Hosek thrd_yield(); 685ab9aefeeSPetr Hosek} 686ab9aefeeSPetr Hosek 687ab9aefeeSPetr Hosekvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 688ab9aefeeSPetr Hosek{ 689ab9aefeeSPetr Hosek __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns); 690ab9aefeeSPetr Hosek thrd_sleep(&__ts, nullptr); 691ab9aefeeSPetr Hosek} 692ab9aefeeSPetr Hosek 693ab9aefeeSPetr Hosek// Thread local storage 694ab9aefeeSPetr Hosekint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 695ab9aefeeSPetr Hosek{ 696ab9aefeeSPetr Hosek return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL; 697ab9aefeeSPetr Hosek} 698ab9aefeeSPetr Hosek 699ab9aefeeSPetr Hosekvoid *__libcpp_tls_get(__libcpp_tls_key __key) 700ab9aefeeSPetr Hosek{ 701ab9aefeeSPetr Hosek return tss_get(__key); 702ab9aefeeSPetr Hosek} 703ab9aefeeSPetr Hosek 704ab9aefeeSPetr Hosekint __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 705ab9aefeeSPetr Hosek{ 706ab9aefeeSPetr Hosek return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; 707ab9aefeeSPetr Hosek} 708ab9aefeeSPetr Hosek 709ab9aefeeSPetr Hosek#endif 710ab9aefeeSPetr Hosek 711e3add3e5SMartin Storsjö 71200f6beaeSEric Fiselier#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 71300f6beaeSEric Fiselier 7142b1d4254SMarshall Clowclass _LIBCPP_TYPE_VIS thread; 7152b1d4254SMarshall Clowclass _LIBCPP_TYPE_VIS __thread_id; 7162b1d4254SMarshall Clow 7172b1d4254SMarshall Clownamespace this_thread 7182b1d4254SMarshall Clow{ 7192b1d4254SMarshall Clow 7202b1d4254SMarshall Clow_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; 7212b1d4254SMarshall Clow 7222b1d4254SMarshall Clow} // this_thread 7232b1d4254SMarshall Clow 7242b1d4254SMarshall Clowtemplate<> struct hash<__thread_id>; 7252b1d4254SMarshall Clow 7262b1d4254SMarshall Clowclass _LIBCPP_TEMPLATE_VIS __thread_id 7272b1d4254SMarshall Clow{ 7282b1d4254SMarshall Clow // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 7292b1d4254SMarshall Clow // NULL is the no-thread value on Darwin. Someone needs to check 7302b1d4254SMarshall Clow // on other platforms. We assume 0 works everywhere for now. 7312b1d4254SMarshall Clow __libcpp_thread_id __id_; 7322b1d4254SMarshall Clow 7332b1d4254SMarshall Clowpublic: 7342b1d4254SMarshall Clow _LIBCPP_INLINE_VISIBILITY 7352b1d4254SMarshall Clow __thread_id() _NOEXCEPT : __id_(0) {} 7362b1d4254SMarshall Clow 7372b1d4254SMarshall Clow friend _LIBCPP_INLINE_VISIBILITY 7382b1d4254SMarshall Clow bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT 7392e80d01fSMarshall Clow { // don't pass id==0 to underlying routines 7402e80d01fSMarshall Clow if (__x.__id_ == 0) return __y.__id_ == 0; 7412e80d01fSMarshall Clow if (__y.__id_ == 0) return false; 7422e80d01fSMarshall Clow return __libcpp_thread_id_equal(__x.__id_, __y.__id_); 7432e80d01fSMarshall Clow } 7442b1d4254SMarshall Clow friend _LIBCPP_INLINE_VISIBILITY 7452b1d4254SMarshall Clow bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT 7462b1d4254SMarshall Clow {return !(__x == __y);} 7472b1d4254SMarshall Clow friend _LIBCPP_INLINE_VISIBILITY 7482b1d4254SMarshall Clow bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT 7492e80d01fSMarshall Clow { // id==0 is always less than any other thread_id 7502e80d01fSMarshall Clow if (__x.__id_ == 0) return __y.__id_ != 0; 7512e80d01fSMarshall Clow if (__y.__id_ == 0) return false; 7522e80d01fSMarshall Clow return __libcpp_thread_id_less(__x.__id_, __y.__id_); 7532e80d01fSMarshall Clow } 7542b1d4254SMarshall Clow friend _LIBCPP_INLINE_VISIBILITY 7552b1d4254SMarshall Clow bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT 7562b1d4254SMarshall Clow {return !(__y < __x);} 7572b1d4254SMarshall Clow friend _LIBCPP_INLINE_VISIBILITY 7582b1d4254SMarshall Clow bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT 7592b1d4254SMarshall Clow {return __y < __x ;} 7602b1d4254SMarshall Clow friend _LIBCPP_INLINE_VISIBILITY 7612b1d4254SMarshall Clow bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT 7622b1d4254SMarshall Clow {return !(__x < __y);} 7632b1d4254SMarshall Clow 7642b1d4254SMarshall Clow _LIBCPP_INLINE_VISIBILITY 7652e80d01fSMarshall Clow void __reset() { __id_ = 0; } 7662b1d4254SMarshall Clow 7672b1d4254SMarshall Clow template<class _CharT, class _Traits> 7682b1d4254SMarshall Clow friend 7692b1d4254SMarshall Clow _LIBCPP_INLINE_VISIBILITY 7702b1d4254SMarshall Clow basic_ostream<_CharT, _Traits>& 7712b1d4254SMarshall Clow operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); 7722b1d4254SMarshall Clow 7732b1d4254SMarshall Clowprivate: 7742b1d4254SMarshall Clow _LIBCPP_INLINE_VISIBILITY 7752b1d4254SMarshall Clow __thread_id(__libcpp_thread_id __id) : __id_(__id) {} 7762b1d4254SMarshall Clow 7772b1d4254SMarshall Clow friend __thread_id this_thread::get_id() _NOEXCEPT; 7782b1d4254SMarshall Clow friend class _LIBCPP_TYPE_VIS thread; 7792b1d4254SMarshall Clow friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; 7802b1d4254SMarshall Clow}; 7812b1d4254SMarshall Clow 7822b1d4254SMarshall Clownamespace this_thread 7832b1d4254SMarshall Clow{ 7842b1d4254SMarshall Clow 7852b1d4254SMarshall Clowinline _LIBCPP_INLINE_VISIBILITY 7862b1d4254SMarshall Clow__thread_id 7872b1d4254SMarshall Clowget_id() _NOEXCEPT 7882b1d4254SMarshall Clow{ 7892b1d4254SMarshall Clow return __libcpp_thread_get_current_id(); 7902b1d4254SMarshall Clow} 7912b1d4254SMarshall Clow 7922b1d4254SMarshall Clow} // this_thread 7932b1d4254SMarshall Clow 794696630eaSMarshall Clow#endif // !_LIBCPP_HAS_NO_THREADS 795696630eaSMarshall Clow 796c7e4239fSAsiri Rathnayake_LIBCPP_END_NAMESPACE_STD 797c7e4239fSAsiri Rathnayake 798a016efb1SEric Fiselier_LIBCPP_POP_MACROS 799a016efb1SEric Fiselier 800c7e4239fSAsiri Rathnayake#endif // _LIBCPP_THREADING_SUPPORT 801