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> 1454a987e1SAsiri Rathnayake#include <chrono> 152b1d4254SMarshall Clow#include <iosfwd> 1654a987e1SAsiri Rathnayake#include <errno.h> 17c7e4239fSAsiri Rathnayake 18c7e4239fSAsiri Rathnayake#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 19c7e4239fSAsiri Rathnayake#pragma GCC system_header 20c7e4239fSAsiri Rathnayake#endif 21c7e4239fSAsiri Rathnayake 2200f6beaeSEric Fiselier#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 233cf2f7bcSAsiri Rathnayake# include <__external_threading> 2400f6beaeSEric Fiselier#elif !defined(_LIBCPP_HAS_NO_THREADS) 25790e10f6SSaleem Abdulrasool 2600f6beaeSEric Fiselier#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 27c7e4239fSAsiri Rathnayake# include <pthread.h> 28c7e4239fSAsiri Rathnayake# include <sched.h> 29*54fa9ecdSOlivier Giroux# include <semaphore.h> 30*54fa9ecdSOlivier Giroux# ifdef __APPLE__ 31*54fa9ecdSOlivier Giroux# define _LIBCPP_NO_NATIVE_SEMAPHORES 32*54fa9ecdSOlivier Giroux# endif 33ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11) 34ab9aefeeSPetr Hosek# include <threads.h> 35790e10f6SSaleem Abdulrasool#endif 36c7e4239fSAsiri Rathnayake 372a129dc3SPeter Collingbourne#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 382a129dc3SPeter Collingbourne defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \ 392a129dc3SPeter Collingbourne defined(_LIBCPP_HAS_THREAD_API_WIN32) 402a129dc3SPeter Collingbourne#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 412a129dc3SPeter Collingbourne#else 422a129dc3SPeter Collingbourne#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 432a129dc3SPeter Collingbourne#endif 442a129dc3SPeter Collingbourne 4583dca5c3SDimitry Andric#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) 4683dca5c3SDimitry Andric#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) 4783dca5c3SDimitry Andric#else 4883dca5c3SDimitry Andric#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 4983dca5c3SDimitry Andric#endif 5083dca5c3SDimitry Andric 51696630eaSMarshall Clowtypedef ::timespec __libcpp_timespec_t; 52696630eaSMarshall Clow#endif // !defined(_LIBCPP_HAS_NO_THREADS) 53696630eaSMarshall Clow 54696630eaSMarshall Clow_LIBCPP_PUSH_MACROS 55696630eaSMarshall Clow#include <__undef_macros> 56696630eaSMarshall Clow 57c7e4239fSAsiri Rathnayake_LIBCPP_BEGIN_NAMESPACE_STD 58c7e4239fSAsiri Rathnayake 59696630eaSMarshall Clow#if !defined(_LIBCPP_HAS_NO_THREADS) 60696630eaSMarshall Clow 612a129dc3SPeter Collingbourne#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 62c7e4239fSAsiri Rathnayake// Mutex 63c7e4239fSAsiri Rathnayaketypedef pthread_mutex_t __libcpp_mutex_t; 648c2bf45dSAsiri Rathnayake#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 65c7e4239fSAsiri Rathnayake 6658a0dceeSSaleem Abdulrasooltypedef pthread_mutex_t __libcpp_recursive_mutex_t; 6758a0dceeSSaleem Abdulrasool 68790e10f6SSaleem Abdulrasool// Condition Variable 69790e10f6SSaleem Abdulrasooltypedef pthread_cond_t __libcpp_condvar_t; 70790e10f6SSaleem Abdulrasool#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 71790e10f6SSaleem Abdulrasool 72*54fa9ecdSOlivier Giroux// Semaphore 73*54fa9ecdSOlivier Girouxtypedef sem_t __libcpp_semaphore_t; 74*54fa9ecdSOlivier Giroux#define _LIBCPP_SEMAPHORE_MAX SEM_VALUE_MAX 75*54fa9ecdSOlivier Giroux 76205d7d3fSAsiri Rathnayake// Execute once 77205d7d3fSAsiri Rathnayaketypedef pthread_once_t __libcpp_exec_once_flag; 78205d7d3fSAsiri Rathnayake#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 79205d7d3fSAsiri Rathnayake 80205d7d3fSAsiri Rathnayake// Thread id 81790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_id; 82790e10f6SSaleem Abdulrasool 83790e10f6SSaleem Abdulrasool// Thread 84af762e91SAsiri Rathnayake#define _LIBCPP_NULL_THREAD 0U 85af762e91SAsiri Rathnayake 86790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_t; 87790e10f6SSaleem Abdulrasool 88cac6d217SFangrui Song// Thread Local Storage 89790e10f6SSaleem Abdulrasooltypedef pthread_key_t __libcpp_tls_key; 906d7d0becSSaleem Abdulrasool 916d7d0becSSaleem Abdulrasool#define _LIBCPP_TLS_DESTRUCTOR_CC 92ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11) 93ab9aefeeSPetr Hosek// Mutex 94ab9aefeeSPetr Hosektypedef mtx_t __libcpp_mutex_t; 95ab9aefeeSPetr Hosek// mtx_t is a struct so using {} for initialization is valid. 96ab9aefeeSPetr Hosek#define _LIBCPP_MUTEX_INITIALIZER {} 97ab9aefeeSPetr Hosek 98ab9aefeeSPetr Hosektypedef mtx_t __libcpp_recursive_mutex_t; 99ab9aefeeSPetr Hosek 100ab9aefeeSPetr Hosek// Condition Variable 101ab9aefeeSPetr Hosektypedef cnd_t __libcpp_condvar_t; 102ab9aefeeSPetr Hosek// cnd_t is a struct so using {} for initialization is valid. 103ab9aefeeSPetr Hosek#define _LIBCPP_CONDVAR_INITIALIZER {} 104ab9aefeeSPetr Hosek 105ab9aefeeSPetr Hosek// Execute once 106ab9aefeeSPetr Hosektypedef once_flag __libcpp_exec_once_flag; 107ab9aefeeSPetr Hosek#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT 108ab9aefeeSPetr Hosek 109ab9aefeeSPetr Hosek// Thread id 110ab9aefeeSPetr Hosektypedef thrd_t __libcpp_thread_id; 111ab9aefeeSPetr Hosek 112ab9aefeeSPetr Hosek// Thread 113ab9aefeeSPetr Hosek#define _LIBCPP_NULL_THREAD 0U 114ab9aefeeSPetr Hosek 115ab9aefeeSPetr Hosektypedef thrd_t __libcpp_thread_t; 116ab9aefeeSPetr Hosek 117ab9aefeeSPetr Hosek// Thread Local Storage 118ab9aefeeSPetr Hosektypedef tss_t __libcpp_tls_key; 119ab9aefeeSPetr Hosek 120ab9aefeeSPetr Hosek#define _LIBCPP_TLS_DESTRUCTOR_CC 121e2b200b7SDavid Spickett#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 122ac15ae6dSPeter Collingbourne// Mutex 123ac15ae6dSPeter Collingbournetypedef void* __libcpp_mutex_t; 124ac15ae6dSPeter Collingbourne#define _LIBCPP_MUTEX_INITIALIZER 0 125ac15ae6dSPeter Collingbourne 126ac15ae6dSPeter Collingbourne#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) 127ac15ae6dSPeter Collingbournetypedef void* __libcpp_recursive_mutex_t[6]; 128ac15ae6dSPeter Collingbourne#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) 129ac15ae6dSPeter Collingbournetypedef void* __libcpp_recursive_mutex_t[5]; 130ac15ae6dSPeter Collingbourne#else 131ac15ae6dSPeter Collingbourne# error Unsupported architecture 132ac15ae6dSPeter Collingbourne#endif 1336d7d0becSSaleem Abdulrasool 1346d7d0becSSaleem Abdulrasool// Condition Variable 135ac15ae6dSPeter Collingbournetypedef void* __libcpp_condvar_t; 136ac15ae6dSPeter Collingbourne#define _LIBCPP_CONDVAR_INITIALIZER 0 1376d7d0becSSaleem Abdulrasool 138*54fa9ecdSOlivier Giroux// Semaphore 139*54fa9ecdSOlivier Girouxtypedef void* __libcpp_semaphore_t; 140*54fa9ecdSOlivier Giroux 1416d7d0becSSaleem Abdulrasool// Execute Once 142ac15ae6dSPeter Collingbournetypedef void* __libcpp_exec_once_flag; 143ac15ae6dSPeter Collingbourne#define _LIBCPP_EXEC_ONCE_INITIALIZER 0 1446d7d0becSSaleem Abdulrasool 1456d7d0becSSaleem Abdulrasool// Thread ID 146ac15ae6dSPeter Collingbournetypedef long __libcpp_thread_id; 1476d7d0becSSaleem Abdulrasool 1486d7d0becSSaleem Abdulrasool// Thread 149af762e91SAsiri Rathnayake#define _LIBCPP_NULL_THREAD 0U 150af762e91SAsiri Rathnayake 151ac15ae6dSPeter Collingbournetypedef void* __libcpp_thread_t; 1526d7d0becSSaleem Abdulrasool 1536d7d0becSSaleem Abdulrasool// Thread Local Storage 154ac15ae6dSPeter Collingbournetypedef long __libcpp_tls_key; 1556d7d0becSSaleem Abdulrasool 156ac15ae6dSPeter Collingbourne#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall 157e2b200b7SDavid Spickett#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 158790e10f6SSaleem Abdulrasool 159e2b200b7SDavid Spickett#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 160790e10f6SSaleem Abdulrasool// Mutex 1618c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 16258a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 16358a0dceeSSaleem Abdulrasool 16483dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 16558a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 16658a0dceeSSaleem Abdulrasool 16783dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 16808e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 16958a0dceeSSaleem Abdulrasool 17083dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 17158a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 17258a0dceeSSaleem Abdulrasool 17358a0dceeSSaleem Abdulrasool_LIBCPP_THREAD_ABI_VISIBILITY 17458a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 175790e10f6SSaleem Abdulrasool 17683dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 1778c2bf45dSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m); 178790e10f6SSaleem Abdulrasool 17983dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 18008e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 181790e10f6SSaleem Abdulrasool 18283dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 1838c2bf45dSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 184790e10f6SSaleem Abdulrasool 1858c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1868c2bf45dSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 1878c2bf45dSAsiri Rathnayake 1888c2bf45dSAsiri Rathnayake// Condition variable 1898c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1908c2bf45dSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 191790e10f6SSaleem Abdulrasool 1928c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1938c2bf45dSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 194790e10f6SSaleem Abdulrasool 19583dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 1968c2bf45dSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 197790e10f6SSaleem Abdulrasool 19883dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 199790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 200cfdc7f0dSMikhail Maltsev __libcpp_timespec_t *__ts); 201790e10f6SSaleem Abdulrasool 2028c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2038c2bf45dSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 2048c2bf45dSAsiri Rathnayake 205*54fa9ecdSOlivier Giroux// Semaphore 206*54fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY 207*54fa9ecdSOlivier Girouxbool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init); 208*54fa9ecdSOlivier Giroux 209*54fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY 210*54fa9ecdSOlivier Girouxbool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem); 211*54fa9ecdSOlivier Giroux 212*54fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY 213*54fa9ecdSOlivier Girouxbool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem); 214*54fa9ecdSOlivier Giroux 215*54fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY 216*54fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem); 217*54fa9ecdSOlivier Giroux 218*54fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY 219*54fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns); 220*54fa9ecdSOlivier Giroux 221205d7d3fSAsiri Rathnayake// Execute once 222205d7d3fSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 223205d7d3fSAsiri Rathnayakeint __libcpp_execute_once(__libcpp_exec_once_flag *flag, 2244603460aSBruce Mitchener void (*init_routine)()); 225205d7d3fSAsiri Rathnayake 226205d7d3fSAsiri Rathnayake// Thread id 2278c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2288c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 229790e10f6SSaleem Abdulrasool 2308c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2318c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 2328c2bf45dSAsiri Rathnayake 2338c2bf45dSAsiri Rathnayake// Thread 2348c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 235af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 236af762e91SAsiri Rathnayake 237af762e91SAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 238790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 239790e10f6SSaleem Abdulrasool void *__arg); 240790e10f6SSaleem Abdulrasool 2418c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2428c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id(); 243790e10f6SSaleem Abdulrasool 2448c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2458c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 246790e10f6SSaleem Abdulrasool 2478c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2488c2bf45dSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t); 249790e10f6SSaleem Abdulrasool 2508c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2518c2bf45dSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t); 252790e10f6SSaleem Abdulrasool 2538c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2548c2bf45dSAsiri Rathnayakevoid __libcpp_thread_yield(); 2558c2bf45dSAsiri Rathnayake 25654a987e1SAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2579e8a082dSJoerg Sonnenbergervoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 25854a987e1SAsiri Rathnayake 259*54fa9ecdSOlivier Girouxstruct __libcpp_timed_backoff_policy { 260*54fa9ecdSOlivier Giroux _LIBCPP_THREAD_ABI_VISIBILITY 261*54fa9ecdSOlivier Giroux bool operator()(chrono::nanoseconds __elapsed) const; 262*54fa9ecdSOlivier Giroux}; 263*54fa9ecdSOlivier Giroux 264*54fa9ecdSOlivier Girouxtemplate<class _Fn, class _BFn> 265*54fa9ecdSOlivier Giroux_LIBCPP_INLINE_VISIBILITY 266*54fa9ecdSOlivier Girouxbool __libcpp_thread_poll_with_backoff( 267*54fa9ecdSOlivier Giroux _Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero()); 268*54fa9ecdSOlivier Giroux 2698c2bf45dSAsiri Rathnayake// Thread local storage 2708c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2716d7d0becSSaleem Abdulrasoolint __libcpp_tls_create(__libcpp_tls_key* __key, 2726d7d0becSSaleem Abdulrasool void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 273790e10f6SSaleem Abdulrasool 2748c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 2758c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key); 276790e10f6SSaleem Abdulrasool 2778c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 278205d7d3fSAsiri Rathnayakeint __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 2798c2bf45dSAsiri Rathnayake 280e2b200b7SDavid Spickett#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 281e2b200b7SDavid Spickett 282ac15ae6dSPeter Collingbourne#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 283ab9aefeeSPetr Hosek defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) 284ab9aefeeSPetr Hosek 285ab9aefeeSPetr Hoseknamespace __thread_detail { 286ab9aefeeSPetr Hosek 287ab9aefeeSPetr Hosekinline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns) 288ab9aefeeSPetr Hosek{ 289ab9aefeeSPetr Hosek using namespace chrono; 290ab9aefeeSPetr Hosek seconds __s = duration_cast<seconds>(__ns); 291ab9aefeeSPetr Hosek __libcpp_timespec_t __ts; 292ab9aefeeSPetr Hosek typedef decltype(__ts.tv_sec) __ts_sec; 293ab9aefeeSPetr Hosek const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); 294ab9aefeeSPetr Hosek 295ab9aefeeSPetr Hosek if (__s.count() < __ts_sec_max) 296ab9aefeeSPetr Hosek { 297ab9aefeeSPetr Hosek __ts.tv_sec = static_cast<__ts_sec>(__s.count()); 298ab9aefeeSPetr Hosek __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count()); 299ab9aefeeSPetr Hosek } 300ab9aefeeSPetr Hosek else 301ab9aefeeSPetr Hosek { 302ab9aefeeSPetr Hosek __ts.tv_sec = __ts_sec_max; 303ab9aefeeSPetr Hosek __ts.tv_nsec = 999999999; // (10^9 - 1) 304ab9aefeeSPetr Hosek } 305ab9aefeeSPetr Hosek 306ab9aefeeSPetr Hosek return __ts; 307ab9aefeeSPetr Hosek} 308ab9aefeeSPetr Hosek 309ab9aefeeSPetr Hosek} 310ab9aefeeSPetr Hosek 311ab9aefeeSPetr Hosek#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 3128c2bf45dSAsiri Rathnayake 31358a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 314c7e4239fSAsiri Rathnayake{ 315c7e4239fSAsiri Rathnayake pthread_mutexattr_t attr; 316c7e4239fSAsiri Rathnayake int __ec = pthread_mutexattr_init(&attr); 317c7e4239fSAsiri Rathnayake if (__ec) 318790e10f6SSaleem Abdulrasool return __ec; 319790e10f6SSaleem Abdulrasool __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 320790e10f6SSaleem Abdulrasool if (__ec) { 321c7e4239fSAsiri Rathnayake pthread_mutexattr_destroy(&attr); 322c7e4239fSAsiri Rathnayake return __ec; 323c7e4239fSAsiri Rathnayake } 324c7e4239fSAsiri Rathnayake __ec = pthread_mutex_init(__m, &attr); 325790e10f6SSaleem Abdulrasool if (__ec) { 326c7e4239fSAsiri Rathnayake pthread_mutexattr_destroy(&attr); 327c7e4239fSAsiri Rathnayake return __ec; 328c7e4239fSAsiri Rathnayake } 329c7e4239fSAsiri Rathnayake __ec = pthread_mutexattr_destroy(&attr); 330790e10f6SSaleem Abdulrasool if (__ec) { 331c7e4239fSAsiri Rathnayake pthread_mutex_destroy(__m); 332c7e4239fSAsiri Rathnayake return __ec; 333c7e4239fSAsiri Rathnayake } 334c7e4239fSAsiri Rathnayake return 0; 335c7e4239fSAsiri Rathnayake} 336c7e4239fSAsiri Rathnayake 33758a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 33858a0dceeSSaleem Abdulrasool{ 33958a0dceeSSaleem Abdulrasool return pthread_mutex_lock(__m); 34058a0dceeSSaleem Abdulrasool} 34158a0dceeSSaleem Abdulrasool 34208e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 34358a0dceeSSaleem Abdulrasool{ 34408e1477cSEric Fiselier return pthread_mutex_trylock(__m) == 0; 34558a0dceeSSaleem Abdulrasool} 34658a0dceeSSaleem Abdulrasool 34758a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 34858a0dceeSSaleem Abdulrasool{ 34958a0dceeSSaleem Abdulrasool return pthread_mutex_unlock(__m); 35058a0dceeSSaleem Abdulrasool} 35158a0dceeSSaleem Abdulrasool 35258a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 35358a0dceeSSaleem Abdulrasool{ 35458a0dceeSSaleem Abdulrasool return pthread_mutex_destroy(__m); 35558a0dceeSSaleem Abdulrasool} 35658a0dceeSSaleem Abdulrasool 357c7e4239fSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m) 358c7e4239fSAsiri Rathnayake{ 359c7e4239fSAsiri Rathnayake return pthread_mutex_lock(__m); 360c7e4239fSAsiri Rathnayake} 361c7e4239fSAsiri Rathnayake 36208e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 363c7e4239fSAsiri Rathnayake{ 36408e1477cSEric Fiselier return pthread_mutex_trylock(__m) == 0; 365c7e4239fSAsiri Rathnayake} 366c7e4239fSAsiri Rathnayake 367c7e4239fSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 368c7e4239fSAsiri Rathnayake{ 369c7e4239fSAsiri Rathnayake return pthread_mutex_unlock(__m); 370c7e4239fSAsiri Rathnayake} 371c7e4239fSAsiri Rathnayake 372c7e4239fSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 373c7e4239fSAsiri Rathnayake{ 374c7e4239fSAsiri Rathnayake return pthread_mutex_destroy(__m); 375c7e4239fSAsiri Rathnayake} 376c7e4239fSAsiri Rathnayake 377790e10f6SSaleem Abdulrasool// Condition Variable 378c7e4239fSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 379c7e4239fSAsiri Rathnayake{ 380c7e4239fSAsiri Rathnayake return pthread_cond_signal(__cv); 381c7e4239fSAsiri Rathnayake} 382c7e4239fSAsiri Rathnayake 383c7e4239fSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 384c7e4239fSAsiri Rathnayake{ 385c7e4239fSAsiri Rathnayake return pthread_cond_broadcast(__cv); 386c7e4239fSAsiri Rathnayake} 387c7e4239fSAsiri Rathnayake 388c7e4239fSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 389c7e4239fSAsiri Rathnayake{ 390c7e4239fSAsiri Rathnayake return pthread_cond_wait(__cv, __m); 391c7e4239fSAsiri Rathnayake} 392c7e4239fSAsiri Rathnayake 393790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 394cfdc7f0dSMikhail Maltsev __libcpp_timespec_t *__ts) 395c7e4239fSAsiri Rathnayake{ 396c7e4239fSAsiri Rathnayake return pthread_cond_timedwait(__cv, __m, __ts); 397c7e4239fSAsiri Rathnayake} 398c7e4239fSAsiri Rathnayake 399c7e4239fSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 400c7e4239fSAsiri Rathnayake{ 401c7e4239fSAsiri Rathnayake return pthread_cond_destroy(__cv); 402c7e4239fSAsiri Rathnayake} 403c7e4239fSAsiri Rathnayake 404*54fa9ecdSOlivier Giroux#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES 405*54fa9ecdSOlivier Giroux 406*54fa9ecdSOlivier Giroux// Semaphore 407*54fa9ecdSOlivier Girouxbool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init) 408*54fa9ecdSOlivier Giroux{ 409*54fa9ecdSOlivier Giroux return sem_init(__sem, 0, __init) == 0; 410*54fa9ecdSOlivier Giroux} 411*54fa9ecdSOlivier Giroux 412*54fa9ecdSOlivier Girouxbool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem) 413*54fa9ecdSOlivier Giroux{ 414*54fa9ecdSOlivier Giroux return sem_destroy(__sem) == 0; 415*54fa9ecdSOlivier Giroux} 416*54fa9ecdSOlivier Giroux 417*54fa9ecdSOlivier Girouxbool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem) 418*54fa9ecdSOlivier Giroux{ 419*54fa9ecdSOlivier Giroux return sem_post(__sem) == 0; 420*54fa9ecdSOlivier Giroux} 421*54fa9ecdSOlivier Giroux 422*54fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem) 423*54fa9ecdSOlivier Giroux{ 424*54fa9ecdSOlivier Giroux return sem_wait(__sem) == 0; 425*54fa9ecdSOlivier Giroux} 426*54fa9ecdSOlivier Giroux 427*54fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns) 428*54fa9ecdSOlivier Giroux{ 429*54fa9ecdSOlivier Giroux auto const __abs_time = chrono::system_clock::now().time_since_epoch() + __ns; 430*54fa9ecdSOlivier Giroux __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__abs_time); 431*54fa9ecdSOlivier Giroux return sem_timedwait(__sem, &__ts) == 0; 432*54fa9ecdSOlivier Giroux} 433*54fa9ecdSOlivier Giroux 434*54fa9ecdSOlivier Giroux#endif //_LIBCPP_NO_NATIVE_SEMAPHORES 435*54fa9ecdSOlivier Giroux 436205d7d3fSAsiri Rathnayake// Execute once 437205d7d3fSAsiri Rathnayakeint __libcpp_execute_once(__libcpp_exec_once_flag *flag, 4384603460aSBruce Mitchener void (*init_routine)()) { 439205d7d3fSAsiri Rathnayake return pthread_once(flag, init_routine); 440205d7d3fSAsiri Rathnayake} 441205d7d3fSAsiri Rathnayake 442205d7d3fSAsiri Rathnayake// Thread id 443c7e4239fSAsiri Rathnayake// Returns non-zero if the thread ids are equal, otherwise 0 444c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 445c7e4239fSAsiri Rathnayake{ 446c7e4239fSAsiri Rathnayake return pthread_equal(t1, t2) != 0; 447c7e4239fSAsiri Rathnayake} 448c7e4239fSAsiri Rathnayake 449c7e4239fSAsiri Rathnayake// Returns non-zero if t1 < t2, otherwise 0 450c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 451c7e4239fSAsiri Rathnayake{ 452c7e4239fSAsiri Rathnayake return t1 < t2; 453c7e4239fSAsiri Rathnayake} 454c7e4239fSAsiri Rathnayake 455c7e4239fSAsiri Rathnayake// Thread 456af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 457af762e91SAsiri Rathnayake return *__t == 0; 458af762e91SAsiri Rathnayake} 459af762e91SAsiri Rathnayake 460790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 461790e10f6SSaleem Abdulrasool void *__arg) 462c7e4239fSAsiri Rathnayake{ 463c7e4239fSAsiri Rathnayake return pthread_create(__t, 0, __func, __arg); 464c7e4239fSAsiri Rathnayake} 465c7e4239fSAsiri Rathnayake 466c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id() 467c7e4239fSAsiri Rathnayake{ 468c7e4239fSAsiri Rathnayake return pthread_self(); 469c7e4239fSAsiri Rathnayake} 470c7e4239fSAsiri Rathnayake 471c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 472c7e4239fSAsiri Rathnayake{ 473c7e4239fSAsiri Rathnayake return *__t; 474c7e4239fSAsiri Rathnayake} 475c7e4239fSAsiri Rathnayake 476c7e4239fSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t) 477c7e4239fSAsiri Rathnayake{ 478c7e4239fSAsiri Rathnayake return pthread_join(*__t, 0); 479c7e4239fSAsiri Rathnayake} 480c7e4239fSAsiri Rathnayake 481c7e4239fSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t) 482c7e4239fSAsiri Rathnayake{ 483c7e4239fSAsiri Rathnayake return pthread_detach(*__t); 484c7e4239fSAsiri Rathnayake} 485c7e4239fSAsiri Rathnayake 486c7e4239fSAsiri Rathnayakevoid __libcpp_thread_yield() 487c7e4239fSAsiri Rathnayake{ 488c7e4239fSAsiri Rathnayake sched_yield(); 489c7e4239fSAsiri Rathnayake} 490c7e4239fSAsiri Rathnayake 49154a987e1SAsiri Rathnayakevoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 49254a987e1SAsiri Rathnayake{ 493ab9aefeeSPetr Hosek __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns); 49454a987e1SAsiri Rathnayake while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); 49554a987e1SAsiri Rathnayake} 49654a987e1SAsiri Rathnayake 497*54fa9ecdSOlivier Girouxbool __libcpp_timed_backoff_policy::operator()(chrono::nanoseconds __elapsed) const 498*54fa9ecdSOlivier Giroux{ 499*54fa9ecdSOlivier Giroux if(__elapsed > chrono::milliseconds(128)) 500*54fa9ecdSOlivier Giroux __libcpp_thread_sleep_for(chrono::milliseconds(8)); 501*54fa9ecdSOlivier Giroux else if(__elapsed > chrono::microseconds(64)) 502*54fa9ecdSOlivier Giroux __libcpp_thread_sleep_for(__elapsed / 2); 503*54fa9ecdSOlivier Giroux else if(__elapsed > chrono::microseconds(4)) 504*54fa9ecdSOlivier Giroux __libcpp_thread_yield(); 505*54fa9ecdSOlivier Giroux else 506*54fa9ecdSOlivier Giroux ; // poll 507*54fa9ecdSOlivier Giroux return false; 508*54fa9ecdSOlivier Giroux} 509*54fa9ecdSOlivier Giroux 510*54fa9ecdSOlivier Girouxstatic constexpr int __libcpp_polling_count = 64; 511*54fa9ecdSOlivier Giroux 512*54fa9ecdSOlivier Girouxtemplate<class _Fn, class _BFn> 513*54fa9ecdSOlivier Girouxbool __libcpp_thread_poll_with_backoff(_Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed) 514*54fa9ecdSOlivier Giroux{ 515*54fa9ecdSOlivier Giroux auto const __start = chrono::high_resolution_clock::now(); 516*54fa9ecdSOlivier Giroux for(int __count = 0;;) { 517*54fa9ecdSOlivier Giroux if(__f()) 518*54fa9ecdSOlivier Giroux return true; // _Fn completion means success 519*54fa9ecdSOlivier Giroux if(__count < __libcpp_polling_count) { 520*54fa9ecdSOlivier Giroux __count += 1; 521*54fa9ecdSOlivier Giroux continue; 522*54fa9ecdSOlivier Giroux } 523*54fa9ecdSOlivier Giroux chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start; 524*54fa9ecdSOlivier Giroux if(__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed) 525*54fa9ecdSOlivier Giroux return false; // timeout failure 526*54fa9ecdSOlivier Giroux if(__bf(__elapsed)) 527*54fa9ecdSOlivier Giroux return false; // _BFn completion means failure 528*54fa9ecdSOlivier Giroux } 529*54fa9ecdSOlivier Giroux} 530*54fa9ecdSOlivier Giroux 531c7e4239fSAsiri Rathnayake// Thread local storage 5328c2bf45dSAsiri Rathnayakeint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 533c7e4239fSAsiri Rathnayake{ 534c7e4239fSAsiri Rathnayake return pthread_key_create(__key, __at_exit); 535c7e4239fSAsiri Rathnayake} 536c7e4239fSAsiri Rathnayake 5378c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key) 538c7e4239fSAsiri Rathnayake{ 539c7e4239fSAsiri Rathnayake return pthread_getspecific(__key); 540c7e4239fSAsiri Rathnayake} 541c7e4239fSAsiri Rathnayake 542205d7d3fSAsiri Rathnayakeint __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 543c7e4239fSAsiri Rathnayake{ 544205d7d3fSAsiri Rathnayake return pthread_setspecific(__key, __p); 545c7e4239fSAsiri Rathnayake} 546c7e4239fSAsiri Rathnayake 547ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11) 548ab9aefeeSPetr Hosek 549ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 550ab9aefeeSPetr Hosek{ 5513481e5d7SPetr Hosek return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL; 552ab9aefeeSPetr Hosek} 553ab9aefeeSPetr Hosek 554ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 555ab9aefeeSPetr Hosek{ 556ab9aefeeSPetr Hosek return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 557ab9aefeeSPetr Hosek} 558ab9aefeeSPetr Hosek 559ab9aefeeSPetr Hosekbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 560ab9aefeeSPetr Hosek{ 561ab9aefeeSPetr Hosek return mtx_trylock(__m) == thrd_success; 562ab9aefeeSPetr Hosek} 563ab9aefeeSPetr Hosek 564ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 565ab9aefeeSPetr Hosek{ 566ab9aefeeSPetr Hosek return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 567ab9aefeeSPetr Hosek} 568ab9aefeeSPetr Hosek 569ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 570ab9aefeeSPetr Hosek{ 571ab9aefeeSPetr Hosek mtx_destroy(__m); 572ab9aefeeSPetr Hosek return 0; 573ab9aefeeSPetr Hosek} 574ab9aefeeSPetr Hosek 575ab9aefeeSPetr Hosekint __libcpp_mutex_lock(__libcpp_mutex_t *__m) 576ab9aefeeSPetr Hosek{ 577ab9aefeeSPetr Hosek return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 578ab9aefeeSPetr Hosek} 579ab9aefeeSPetr Hosek 580ab9aefeeSPetr Hosekbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 581ab9aefeeSPetr Hosek{ 582ab9aefeeSPetr Hosek return mtx_trylock(__m) == thrd_success; 583ab9aefeeSPetr Hosek} 584ab9aefeeSPetr Hosek 585ab9aefeeSPetr Hosekint __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 586ab9aefeeSPetr Hosek{ 587ab9aefeeSPetr Hosek return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 588ab9aefeeSPetr Hosek} 589ab9aefeeSPetr Hosek 590ab9aefeeSPetr Hosekint __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 591ab9aefeeSPetr Hosek{ 592ab9aefeeSPetr Hosek mtx_destroy(__m); 593ab9aefeeSPetr Hosek return 0; 594ab9aefeeSPetr Hosek} 595ab9aefeeSPetr Hosek 596ab9aefeeSPetr Hosek// Condition Variable 597ab9aefeeSPetr Hosekint __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 598ab9aefeeSPetr Hosek{ 599ab9aefeeSPetr Hosek return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; 600ab9aefeeSPetr Hosek} 601ab9aefeeSPetr Hosek 602ab9aefeeSPetr Hosekint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 603ab9aefeeSPetr Hosek{ 604ab9aefeeSPetr Hosek return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; 605ab9aefeeSPetr Hosek} 606ab9aefeeSPetr Hosek 607ab9aefeeSPetr Hosekint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 608ab9aefeeSPetr Hosek{ 609ab9aefeeSPetr Hosek return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL; 610ab9aefeeSPetr Hosek} 611ab9aefeeSPetr Hosek 612ab9aefeeSPetr Hosekint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 613ab9aefeeSPetr Hosek timespec *__ts) 614ab9aefeeSPetr Hosek{ 615ab9aefeeSPetr Hosek int __ec = cnd_timedwait(__cv, __m, __ts); 616ab9aefeeSPetr Hosek return __ec == thrd_timedout ? ETIMEDOUT : __ec; 617ab9aefeeSPetr Hosek} 618ab9aefeeSPetr Hosek 619ab9aefeeSPetr Hosekint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 620ab9aefeeSPetr Hosek{ 621ab9aefeeSPetr Hosek cnd_destroy(__cv); 622ab9aefeeSPetr Hosek return 0; 623ab9aefeeSPetr Hosek} 624ab9aefeeSPetr Hosek 625ab9aefeeSPetr Hosek// Execute once 626ab9aefeeSPetr Hosekint __libcpp_execute_once(__libcpp_exec_once_flag *flag, 627ab9aefeeSPetr Hosek void (*init_routine)(void)) { 628ab9aefeeSPetr Hosek ::call_once(flag, init_routine); 629ab9aefeeSPetr Hosek return 0; 630ab9aefeeSPetr Hosek} 631ab9aefeeSPetr Hosek 632ab9aefeeSPetr Hosek// Thread id 633ab9aefeeSPetr Hosek// Returns non-zero if the thread ids are equal, otherwise 0 634ab9aefeeSPetr Hosekbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 635ab9aefeeSPetr Hosek{ 636ab9aefeeSPetr Hosek return thrd_equal(t1, t2) != 0; 637ab9aefeeSPetr Hosek} 638ab9aefeeSPetr Hosek 639ab9aefeeSPetr Hosek// Returns non-zero if t1 < t2, otherwise 0 640ab9aefeeSPetr Hosekbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 641ab9aefeeSPetr Hosek{ 642ab9aefeeSPetr Hosek return t1 < t2; 643ab9aefeeSPetr Hosek} 644ab9aefeeSPetr Hosek 645ab9aefeeSPetr Hosek// Thread 646ab9aefeeSPetr Hosekbool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 647ab9aefeeSPetr Hosek return *__t == 0; 648ab9aefeeSPetr Hosek} 649ab9aefeeSPetr Hosek 650ab9aefeeSPetr Hosekint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 651ab9aefeeSPetr Hosek void *__arg) 652ab9aefeeSPetr Hosek{ 653ab9aefeeSPetr Hosek int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg); 654ab9aefeeSPetr Hosek return __ec == thrd_nomem ? ENOMEM : __ec; 655ab9aefeeSPetr Hosek} 656ab9aefeeSPetr Hosek 657ab9aefeeSPetr Hosek__libcpp_thread_id __libcpp_thread_get_current_id() 658ab9aefeeSPetr Hosek{ 659ab9aefeeSPetr Hosek return thrd_current(); 660ab9aefeeSPetr Hosek} 661ab9aefeeSPetr Hosek 662ab9aefeeSPetr Hosek__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 663ab9aefeeSPetr Hosek{ 664ab9aefeeSPetr Hosek return *__t; 665ab9aefeeSPetr Hosek} 666ab9aefeeSPetr Hosek 667ab9aefeeSPetr Hosekint __libcpp_thread_join(__libcpp_thread_t *__t) 668ab9aefeeSPetr Hosek{ 669ab9aefeeSPetr Hosek return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; 670ab9aefeeSPetr Hosek} 671ab9aefeeSPetr Hosek 672ab9aefeeSPetr Hosekint __libcpp_thread_detach(__libcpp_thread_t *__t) 673ab9aefeeSPetr Hosek{ 674ab9aefeeSPetr Hosek return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; 675ab9aefeeSPetr Hosek} 676ab9aefeeSPetr Hosek 677ab9aefeeSPetr Hosekvoid __libcpp_thread_yield() 678ab9aefeeSPetr Hosek{ 679ab9aefeeSPetr Hosek thrd_yield(); 680ab9aefeeSPetr Hosek} 681ab9aefeeSPetr Hosek 682ab9aefeeSPetr Hosekvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 683ab9aefeeSPetr Hosek{ 684ab9aefeeSPetr Hosek __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns); 685ab9aefeeSPetr Hosek thrd_sleep(&__ts, nullptr); 686ab9aefeeSPetr Hosek} 687ab9aefeeSPetr Hosek 688ab9aefeeSPetr Hosek// Thread local storage 689ab9aefeeSPetr Hosekint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 690ab9aefeeSPetr Hosek{ 691ab9aefeeSPetr Hosek return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL; 692ab9aefeeSPetr Hosek} 693ab9aefeeSPetr Hosek 694ab9aefeeSPetr Hosekvoid *__libcpp_tls_get(__libcpp_tls_key __key) 695ab9aefeeSPetr Hosek{ 696ab9aefeeSPetr Hosek return tss_get(__key); 697ab9aefeeSPetr Hosek} 698ab9aefeeSPetr Hosek 699ab9aefeeSPetr Hosekint __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 700ab9aefeeSPetr Hosek{ 701ab9aefeeSPetr Hosek return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; 702ab9aefeeSPetr Hosek} 703ab9aefeeSPetr Hosek 704ab9aefeeSPetr Hosek#endif 705ab9aefeeSPetr Hosek 70600f6beaeSEric Fiselier#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 70700f6beaeSEric Fiselier 7082b1d4254SMarshall Clowclass _LIBCPP_TYPE_VIS thread; 7092b1d4254SMarshall Clowclass _LIBCPP_TYPE_VIS __thread_id; 7102b1d4254SMarshall Clow 7112b1d4254SMarshall Clownamespace this_thread 7122b1d4254SMarshall Clow{ 7132b1d4254SMarshall Clow 7142b1d4254SMarshall Clow_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; 7152b1d4254SMarshall Clow 7162b1d4254SMarshall Clow} // this_thread 7172b1d4254SMarshall Clow 7182b1d4254SMarshall Clowtemplate<> struct hash<__thread_id>; 7192b1d4254SMarshall Clow 7202b1d4254SMarshall Clowclass _LIBCPP_TEMPLATE_VIS __thread_id 7212b1d4254SMarshall Clow{ 7222b1d4254SMarshall Clow // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 7232b1d4254SMarshall Clow // NULL is the no-thread value on Darwin. Someone needs to check 7242b1d4254SMarshall Clow // on other platforms. We assume 0 works everywhere for now. 7252b1d4254SMarshall Clow __libcpp_thread_id __id_; 7262b1d4254SMarshall Clow 7272b1d4254SMarshall Clowpublic: 7282b1d4254SMarshall Clow _LIBCPP_INLINE_VISIBILITY 7292b1d4254SMarshall Clow __thread_id() _NOEXCEPT : __id_(0) {} 7302b1d4254SMarshall Clow 7312b1d4254SMarshall Clow friend _LIBCPP_INLINE_VISIBILITY 7322b1d4254SMarshall Clow bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT 7332e80d01fSMarshall Clow { // don't pass id==0 to underlying routines 7342e80d01fSMarshall Clow if (__x.__id_ == 0) return __y.__id_ == 0; 7352e80d01fSMarshall Clow if (__y.__id_ == 0) return false; 7362e80d01fSMarshall Clow return __libcpp_thread_id_equal(__x.__id_, __y.__id_); 7372e80d01fSMarshall Clow } 7382b1d4254SMarshall Clow friend _LIBCPP_INLINE_VISIBILITY 7392b1d4254SMarshall Clow bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT 7402b1d4254SMarshall Clow {return !(__x == __y);} 7412b1d4254SMarshall Clow friend _LIBCPP_INLINE_VISIBILITY 7422b1d4254SMarshall Clow bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT 7432e80d01fSMarshall Clow { // id==0 is always less than any other thread_id 7442e80d01fSMarshall Clow if (__x.__id_ == 0) return __y.__id_ != 0; 7452e80d01fSMarshall Clow if (__y.__id_ == 0) return false; 7462e80d01fSMarshall Clow return __libcpp_thread_id_less(__x.__id_, __y.__id_); 7472e80d01fSMarshall Clow } 7482b1d4254SMarshall Clow friend _LIBCPP_INLINE_VISIBILITY 7492b1d4254SMarshall Clow bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT 7502b1d4254SMarshall Clow {return !(__y < __x);} 7512b1d4254SMarshall Clow friend _LIBCPP_INLINE_VISIBILITY 7522b1d4254SMarshall Clow bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT 7532b1d4254SMarshall Clow {return __y < __x ;} 7542b1d4254SMarshall Clow friend _LIBCPP_INLINE_VISIBILITY 7552b1d4254SMarshall Clow bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT 7562b1d4254SMarshall Clow {return !(__x < __y);} 7572b1d4254SMarshall Clow 7582b1d4254SMarshall Clow _LIBCPP_INLINE_VISIBILITY 7592e80d01fSMarshall Clow void __reset() { __id_ = 0; } 7602b1d4254SMarshall Clow 7612b1d4254SMarshall Clow template<class _CharT, class _Traits> 7622b1d4254SMarshall Clow friend 7632b1d4254SMarshall Clow _LIBCPP_INLINE_VISIBILITY 7642b1d4254SMarshall Clow basic_ostream<_CharT, _Traits>& 7652b1d4254SMarshall Clow operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); 7662b1d4254SMarshall Clow 7672b1d4254SMarshall Clowprivate: 7682b1d4254SMarshall Clow _LIBCPP_INLINE_VISIBILITY 7692b1d4254SMarshall Clow __thread_id(__libcpp_thread_id __id) : __id_(__id) {} 7702b1d4254SMarshall Clow 7712b1d4254SMarshall Clow friend __thread_id this_thread::get_id() _NOEXCEPT; 7722b1d4254SMarshall Clow friend class _LIBCPP_TYPE_VIS thread; 7732b1d4254SMarshall Clow friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; 7742b1d4254SMarshall Clow}; 7752b1d4254SMarshall Clow 7762b1d4254SMarshall Clownamespace this_thread 7772b1d4254SMarshall Clow{ 7782b1d4254SMarshall Clow 7792b1d4254SMarshall Clowinline _LIBCPP_INLINE_VISIBILITY 7802b1d4254SMarshall Clow__thread_id 7812b1d4254SMarshall Clowget_id() _NOEXCEPT 7822b1d4254SMarshall Clow{ 7832b1d4254SMarshall Clow return __libcpp_thread_get_current_id(); 7842b1d4254SMarshall Clow} 7852b1d4254SMarshall Clow 7862b1d4254SMarshall Clow} // this_thread 7872b1d4254SMarshall Clow 788696630eaSMarshall Clow#endif // !_LIBCPP_HAS_NO_THREADS 789696630eaSMarshall Clow 790c7e4239fSAsiri Rathnayake_LIBCPP_END_NAMESPACE_STD 791c7e4239fSAsiri Rathnayake 792a016efb1SEric Fiselier_LIBCPP_POP_MACROS 793a016efb1SEric Fiselier 794c7e4239fSAsiri Rathnayake#endif // _LIBCPP_THREADING_SUPPORT 795