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>
142eadbc86SLouis Dionne#include <__availability>
1554a987e1SAsiri Rathnayake#include <chrono>
162b1d4254SMarshall Clow#include <iosfwd>
1754a987e1SAsiri Rathnayake#include <errno.h>
18c7e4239fSAsiri Rathnayake
196a8099e0SZbigniew Sarbinowski#ifdef __MVS__
20b5175681SLouis Dionne# include <__support/ibm/nanosleep.h>
216a8099e0SZbigniew Sarbinowski#endif
226a8099e0SZbigniew Sarbinowski
23c7e4239fSAsiri Rathnayake#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
24c7e4239fSAsiri Rathnayake#pragma GCC system_header
25c7e4239fSAsiri Rathnayake#endif
26c7e4239fSAsiri Rathnayake
2700f6beaeSEric Fiselier#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
283cf2f7bcSAsiri Rathnayake# include <__external_threading>
2900f6beaeSEric Fiselier#elif !defined(_LIBCPP_HAS_NO_THREADS)
30790e10f6SSaleem Abdulrasool
3100f6beaeSEric Fiselier#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
32c7e4239fSAsiri Rathnayake# include <pthread.h>
33c7e4239fSAsiri Rathnayake# include <sched.h>
34e6c89a49SZbigniew Sarbinowski# if defined(__APPLE__) || defined(__MVS__)
3554fa9ecdSOlivier Giroux#  define _LIBCPP_NO_NATIVE_SEMAPHORES
3654fa9ecdSOlivier Giroux# endif
3762138846Sogiroux# ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
3862138846Sogiroux# include <semaphore.h>
3962138846Sogiroux# endif
40ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11)
41ab9aefeeSPetr Hosek# include <threads.h>
42790e10f6SSaleem Abdulrasool#endif
43c7e4239fSAsiri Rathnayake
442a129dc3SPeter Collingbourne#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
452a129dc3SPeter Collingbourne    defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \
462a129dc3SPeter Collingbourne    defined(_LIBCPP_HAS_THREAD_API_WIN32)
472a129dc3SPeter Collingbourne#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
482a129dc3SPeter Collingbourne#else
492a129dc3SPeter Collingbourne#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
502a129dc3SPeter Collingbourne#endif
512a129dc3SPeter Collingbourne
5283dca5c3SDimitry Andric#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
5383dca5c3SDimitry Andric#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
5483dca5c3SDimitry Andric#else
5583dca5c3SDimitry Andric#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
5683dca5c3SDimitry Andric#endif
5783dca5c3SDimitry Andric
58696630eaSMarshall Clowtypedef ::timespec __libcpp_timespec_t;
59696630eaSMarshall Clow#endif // !defined(_LIBCPP_HAS_NO_THREADS)
60696630eaSMarshall Clow
61696630eaSMarshall Clow_LIBCPP_PUSH_MACROS
62696630eaSMarshall Clow#include <__undef_macros>
63696630eaSMarshall Clow
64c7e4239fSAsiri Rathnayake_LIBCPP_BEGIN_NAMESPACE_STD
65c7e4239fSAsiri Rathnayake
66696630eaSMarshall Clow#if !defined(_LIBCPP_HAS_NO_THREADS)
67696630eaSMarshall Clow
682a129dc3SPeter Collingbourne#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
69c7e4239fSAsiri Rathnayake// Mutex
70c7e4239fSAsiri Rathnayaketypedef pthread_mutex_t __libcpp_mutex_t;
718c2bf45dSAsiri Rathnayake#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
72c7e4239fSAsiri Rathnayake
7358a0dceeSSaleem Abdulrasooltypedef pthread_mutex_t __libcpp_recursive_mutex_t;
7458a0dceeSSaleem Abdulrasool
75790e10f6SSaleem Abdulrasool// Condition Variable
76790e10f6SSaleem Abdulrasooltypedef pthread_cond_t __libcpp_condvar_t;
77790e10f6SSaleem Abdulrasool#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
78790e10f6SSaleem Abdulrasool
7962138846Sogiroux#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
8054fa9ecdSOlivier Giroux// Semaphore
8154fa9ecdSOlivier Girouxtypedef sem_t __libcpp_semaphore_t;
8254fa9ecdSOlivier Giroux# define _LIBCPP_SEMAPHORE_MAX SEM_VALUE_MAX
8362138846Sogiroux#endif
8454fa9ecdSOlivier Giroux
85205d7d3fSAsiri Rathnayake// Execute once
86205d7d3fSAsiri Rathnayaketypedef pthread_once_t __libcpp_exec_once_flag;
87205d7d3fSAsiri Rathnayake#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
88205d7d3fSAsiri Rathnayake
89205d7d3fSAsiri Rathnayake// Thread id
90e6c89a49SZbigniew Sarbinowski#if defined(__MVS__)
91e6c89a49SZbigniew Sarbinowski  typedef unsigned long long __libcpp_thread_id;
92e6c89a49SZbigniew Sarbinowski#else
93790e10f6SSaleem Abdulrasool  typedef pthread_t __libcpp_thread_id;
94e6c89a49SZbigniew Sarbinowski#endif
95790e10f6SSaleem Abdulrasool
96790e10f6SSaleem Abdulrasool// Thread
97e6c89a49SZbigniew Sarbinowski#define _LIBCPP_NULL_THREAD ((__libcpp_thread_t()))
98790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_t;
99790e10f6SSaleem Abdulrasool
100cac6d217SFangrui Song// Thread Local Storage
101790e10f6SSaleem Abdulrasooltypedef pthread_key_t __libcpp_tls_key;
1026d7d0becSSaleem Abdulrasool
1036d7d0becSSaleem Abdulrasool#define _LIBCPP_TLS_DESTRUCTOR_CC
104ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11)
105ab9aefeeSPetr Hosek// Mutex
106ab9aefeeSPetr Hosektypedef mtx_t __libcpp_mutex_t;
107ab9aefeeSPetr Hosek// mtx_t is a struct so using {} for initialization is valid.
108ab9aefeeSPetr Hosek#define _LIBCPP_MUTEX_INITIALIZER {}
109ab9aefeeSPetr Hosek
110ab9aefeeSPetr Hosektypedef mtx_t __libcpp_recursive_mutex_t;
111ab9aefeeSPetr Hosek
112ab9aefeeSPetr Hosek// Condition Variable
113ab9aefeeSPetr Hosektypedef cnd_t __libcpp_condvar_t;
114ab9aefeeSPetr Hosek// cnd_t is a struct so using {} for initialization is valid.
115ab9aefeeSPetr Hosek#define _LIBCPP_CONDVAR_INITIALIZER {}
116ab9aefeeSPetr Hosek
117ab9aefeeSPetr Hosek// Execute once
118ab9aefeeSPetr Hosektypedef once_flag __libcpp_exec_once_flag;
119ab9aefeeSPetr Hosek#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT
120ab9aefeeSPetr Hosek
121ab9aefeeSPetr Hosek// Thread id
122ab9aefeeSPetr Hosektypedef thrd_t __libcpp_thread_id;
123ab9aefeeSPetr Hosek
124ab9aefeeSPetr Hosek// Thread
125ab9aefeeSPetr Hosek#define _LIBCPP_NULL_THREAD 0U
126ab9aefeeSPetr Hosek
127ab9aefeeSPetr Hosektypedef thrd_t __libcpp_thread_t;
128ab9aefeeSPetr Hosek
129ab9aefeeSPetr Hosek// Thread Local Storage
130ab9aefeeSPetr Hosektypedef tss_t __libcpp_tls_key;
131ab9aefeeSPetr Hosek
132ab9aefeeSPetr Hosek#define _LIBCPP_TLS_DESTRUCTOR_CC
133e2b200b7SDavid Spickett#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
134ac15ae6dSPeter Collingbourne// Mutex
135ac15ae6dSPeter Collingbournetypedef void* __libcpp_mutex_t;
136ac15ae6dSPeter Collingbourne#define _LIBCPP_MUTEX_INITIALIZER 0
137ac15ae6dSPeter Collingbourne
138ac15ae6dSPeter Collingbourne#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
139ac15ae6dSPeter Collingbournetypedef void* __libcpp_recursive_mutex_t[6];
140ac15ae6dSPeter Collingbourne#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
141ac15ae6dSPeter Collingbournetypedef void* __libcpp_recursive_mutex_t[5];
142ac15ae6dSPeter Collingbourne#else
143ac15ae6dSPeter Collingbourne# error Unsupported architecture
144ac15ae6dSPeter Collingbourne#endif
1456d7d0becSSaleem Abdulrasool
1466d7d0becSSaleem Abdulrasool// Condition Variable
147ac15ae6dSPeter Collingbournetypedef void* __libcpp_condvar_t;
148ac15ae6dSPeter Collingbourne#define _LIBCPP_CONDVAR_INITIALIZER 0
1496d7d0becSSaleem Abdulrasool
15054fa9ecdSOlivier Giroux// Semaphore
15154fa9ecdSOlivier Girouxtypedef void* __libcpp_semaphore_t;
15254fa9ecdSOlivier Giroux
1536d7d0becSSaleem Abdulrasool// Execute Once
154ac15ae6dSPeter Collingbournetypedef void* __libcpp_exec_once_flag;
155ac15ae6dSPeter Collingbourne#define _LIBCPP_EXEC_ONCE_INITIALIZER 0
1566d7d0becSSaleem Abdulrasool
1576d7d0becSSaleem Abdulrasool// Thread ID
158ac15ae6dSPeter Collingbournetypedef long __libcpp_thread_id;
1596d7d0becSSaleem Abdulrasool
1606d7d0becSSaleem Abdulrasool// Thread
161af762e91SAsiri Rathnayake#define _LIBCPP_NULL_THREAD 0U
162af762e91SAsiri Rathnayake
163ac15ae6dSPeter Collingbournetypedef void* __libcpp_thread_t;
1646d7d0becSSaleem Abdulrasool
1656d7d0becSSaleem Abdulrasool// Thread Local Storage
166ac15ae6dSPeter Collingbournetypedef long __libcpp_tls_key;
1676d7d0becSSaleem Abdulrasool
168ac15ae6dSPeter Collingbourne#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
169e2b200b7SDavid Spickett#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
170790e10f6SSaleem Abdulrasool
171e2b200b7SDavid Spickett#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
172790e10f6SSaleem Abdulrasool// Mutex
1738c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
17458a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
17558a0dceeSSaleem Abdulrasool
17683dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
17758a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
17858a0dceeSSaleem Abdulrasool
17983dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
18008e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
18158a0dceeSSaleem Abdulrasool
18283dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
18358a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
18458a0dceeSSaleem Abdulrasool
18558a0dceeSSaleem Abdulrasool_LIBCPP_THREAD_ABI_VISIBILITY
18658a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
187790e10f6SSaleem Abdulrasool
18883dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
1898c2bf45dSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m);
190790e10f6SSaleem Abdulrasool
19183dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
19208e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
193790e10f6SSaleem Abdulrasool
19483dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
1958c2bf45dSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
196790e10f6SSaleem Abdulrasool
1978c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1988c2bf45dSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
1998c2bf45dSAsiri Rathnayake
2008c2bf45dSAsiri Rathnayake// Condition variable
2018c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2028c2bf45dSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
203790e10f6SSaleem Abdulrasool
2048c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2058c2bf45dSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
206790e10f6SSaleem Abdulrasool
20783dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
2088c2bf45dSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
209790e10f6SSaleem Abdulrasool
21083dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
211790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
212cfdc7f0dSMikhail Maltsev                               __libcpp_timespec_t *__ts);
213790e10f6SSaleem Abdulrasool
2148c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2158c2bf45dSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
2168c2bf45dSAsiri Rathnayake
21762138846Sogiroux#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
21862138846Sogiroux
21954fa9ecdSOlivier Giroux// Semaphore
22054fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
22154fa9ecdSOlivier Girouxbool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init);
22254fa9ecdSOlivier Giroux
22354fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
22454fa9ecdSOlivier Girouxbool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem);
22554fa9ecdSOlivier Giroux
22654fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
22754fa9ecdSOlivier Girouxbool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem);
22854fa9ecdSOlivier Giroux
22954fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
23054fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem);
23154fa9ecdSOlivier Giroux
23254fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
23354fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns);
23454fa9ecdSOlivier Giroux
23562138846Sogiroux#endif // _LIBCPP_NO_NATIVE_SEMAPHORES
23662138846Sogiroux
237205d7d3fSAsiri Rathnayake// Execute once
238205d7d3fSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
239205d7d3fSAsiri Rathnayakeint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
2404603460aSBruce Mitchener                          void (*init_routine)());
241205d7d3fSAsiri Rathnayake
242205d7d3fSAsiri Rathnayake// Thread id
2438c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2448c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
245790e10f6SSaleem Abdulrasool
2468c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2478c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
2488c2bf45dSAsiri Rathnayake
2498c2bf45dSAsiri Rathnayake// Thread
2508c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
251af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
252af762e91SAsiri Rathnayake
253af762e91SAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
254790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
255790e10f6SSaleem Abdulrasool                           void *__arg);
256790e10f6SSaleem Abdulrasool
2578c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2588c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id();
259790e10f6SSaleem Abdulrasool
2608c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2618c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
262790e10f6SSaleem Abdulrasool
2638c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2648c2bf45dSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t);
265790e10f6SSaleem Abdulrasool
2668c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2678c2bf45dSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t);
268790e10f6SSaleem Abdulrasool
2698c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2708c2bf45dSAsiri Rathnayakevoid __libcpp_thread_yield();
2718c2bf45dSAsiri Rathnayake
27254a987e1SAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2739e8a082dSJoerg Sonnenbergervoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
27454a987e1SAsiri Rathnayake
2758c2bf45dSAsiri Rathnayake// Thread local storage
2768c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2776d7d0becSSaleem Abdulrasoolint __libcpp_tls_create(__libcpp_tls_key* __key,
2786d7d0becSSaleem Abdulrasool                        void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
279790e10f6SSaleem Abdulrasool
2808c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2818c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key);
282790e10f6SSaleem Abdulrasool
2838c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
284205d7d3fSAsiri Rathnayakeint __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
2858c2bf45dSAsiri Rathnayake
286e2b200b7SDavid Spickett#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
287e2b200b7SDavid Spickett
28814aef536SMikhail Maltsevstruct __libcpp_timed_backoff_policy {
28921a1a263SLouis Dionne  _LIBCPP_INLINE_VISIBILITY
29021a1a263SLouis Dionne  bool operator()(chrono::nanoseconds __elapsed) const
2913411a1a9SDavid Nicuesa  {
2923411a1a9SDavid Nicuesa      if(__elapsed > chrono::milliseconds(128))
2933411a1a9SDavid Nicuesa          __libcpp_thread_sleep_for(chrono::milliseconds(8));
2943411a1a9SDavid Nicuesa      else if(__elapsed > chrono::microseconds(64))
2953411a1a9SDavid Nicuesa          __libcpp_thread_sleep_for(__elapsed / 2);
2963411a1a9SDavid Nicuesa      else if(__elapsed > chrono::microseconds(4))
2973411a1a9SDavid Nicuesa        __libcpp_thread_yield();
2983411a1a9SDavid Nicuesa      else
299d2acf229SMarek Kurdej        {} // poll
3003411a1a9SDavid Nicuesa      return false;
3013411a1a9SDavid Nicuesa  }
30221a1a263SLouis Dionne};
3033411a1a9SDavid Nicuesa
3043411a1a9SDavid Nicuesastatic _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64;
3053411a1a9SDavid Nicuesa
30614aef536SMikhail Maltsevtemplate<class _Fn, class _BFn>
30746c38761SLouis Dionne_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
30814aef536SMikhail Maltsevbool __libcpp_thread_poll_with_backoff(
3093411a1a9SDavid Nicuesa  _Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero())
3103411a1a9SDavid Nicuesa{
3113411a1a9SDavid Nicuesa    auto const __start = chrono::high_resolution_clock::now();
3123411a1a9SDavid Nicuesa    for(int __count = 0;;) {
3133411a1a9SDavid Nicuesa      if(__f())
3143411a1a9SDavid Nicuesa        return true; // _Fn completion means success
3153411a1a9SDavid Nicuesa      if(__count < __libcpp_polling_count) {
3163411a1a9SDavid Nicuesa        __count += 1;
3173411a1a9SDavid Nicuesa        continue;
3183411a1a9SDavid Nicuesa      }
3193411a1a9SDavid Nicuesa      chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start;
3203411a1a9SDavid Nicuesa      if(__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed)
3213411a1a9SDavid Nicuesa          return false; // timeout failure
3223411a1a9SDavid Nicuesa      if(__bf(__elapsed))
3233411a1a9SDavid Nicuesa        return false; // _BFn completion means failure
3243411a1a9SDavid Nicuesa    }
3253411a1a9SDavid Nicuesa}
3263411a1a9SDavid Nicuesa
3273411a1a9SDavid Nicuesa#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
3283411a1a9SDavid Nicuesa     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL))
3293411a1a9SDavid Nicuesa
33014aef536SMikhail Maltsev
331ab9aefeeSPetr Hoseknamespace __thread_detail {
332ab9aefeeSPetr Hosek
333ab9aefeeSPetr Hosekinline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns)
334ab9aefeeSPetr Hosek{
335ab9aefeeSPetr Hosek  using namespace chrono;
336ab9aefeeSPetr Hosek  seconds __s = duration_cast<seconds>(__ns);
337ab9aefeeSPetr Hosek  __libcpp_timespec_t __ts;
338ab9aefeeSPetr Hosek  typedef decltype(__ts.tv_sec) __ts_sec;
339ab9aefeeSPetr Hosek  const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
340ab9aefeeSPetr Hosek
341ab9aefeeSPetr Hosek  if (__s.count() < __ts_sec_max)
342ab9aefeeSPetr Hosek  {
343ab9aefeeSPetr Hosek    __ts.tv_sec = static_cast<__ts_sec>(__s.count());
344ab9aefeeSPetr Hosek    __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
345ab9aefeeSPetr Hosek  }
346ab9aefeeSPetr Hosek  else
347ab9aefeeSPetr Hosek  {
348ab9aefeeSPetr Hosek    __ts.tv_sec = __ts_sec_max;
349ab9aefeeSPetr Hosek    __ts.tv_nsec = 999999999; // (10^9 - 1)
350ab9aefeeSPetr Hosek  }
351ab9aefeeSPetr Hosek
352ab9aefeeSPetr Hosek  return __ts;
353ab9aefeeSPetr Hosek}
354ab9aefeeSPetr Hosek
355ab9aefeeSPetr Hosek}
356ab9aefeeSPetr Hosek
357ab9aefeeSPetr Hosek#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
3588c2bf45dSAsiri Rathnayake
35958a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
360c7e4239fSAsiri Rathnayake{
361c7e4239fSAsiri Rathnayake  pthread_mutexattr_t attr;
362c7e4239fSAsiri Rathnayake  int __ec = pthread_mutexattr_init(&attr);
363c7e4239fSAsiri Rathnayake  if (__ec)
364790e10f6SSaleem Abdulrasool    return __ec;
365790e10f6SSaleem Abdulrasool  __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
366790e10f6SSaleem Abdulrasool  if (__ec) {
367c7e4239fSAsiri Rathnayake    pthread_mutexattr_destroy(&attr);
368c7e4239fSAsiri Rathnayake    return __ec;
369c7e4239fSAsiri Rathnayake  }
370c7e4239fSAsiri Rathnayake  __ec = pthread_mutex_init(__m, &attr);
371790e10f6SSaleem Abdulrasool  if (__ec) {
372c7e4239fSAsiri Rathnayake    pthread_mutexattr_destroy(&attr);
373c7e4239fSAsiri Rathnayake    return __ec;
374c7e4239fSAsiri Rathnayake  }
375c7e4239fSAsiri Rathnayake  __ec = pthread_mutexattr_destroy(&attr);
376790e10f6SSaleem Abdulrasool  if (__ec) {
377c7e4239fSAsiri Rathnayake    pthread_mutex_destroy(__m);
378c7e4239fSAsiri Rathnayake    return __ec;
379c7e4239fSAsiri Rathnayake  }
380c7e4239fSAsiri Rathnayake  return 0;
381c7e4239fSAsiri Rathnayake}
382c7e4239fSAsiri Rathnayake
38358a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
38458a0dceeSSaleem Abdulrasool{
38558a0dceeSSaleem Abdulrasool  return pthread_mutex_lock(__m);
38658a0dceeSSaleem Abdulrasool}
38758a0dceeSSaleem Abdulrasool
38808e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
38958a0dceeSSaleem Abdulrasool{
39008e1477cSEric Fiselier  return pthread_mutex_trylock(__m) == 0;
39158a0dceeSSaleem Abdulrasool}
39258a0dceeSSaleem Abdulrasool
393*ebfadd82SColin Finckint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
39458a0dceeSSaleem Abdulrasool{
39558a0dceeSSaleem Abdulrasool  return pthread_mutex_unlock(__m);
39658a0dceeSSaleem Abdulrasool}
39758a0dceeSSaleem Abdulrasool
39858a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
39958a0dceeSSaleem Abdulrasool{
40058a0dceeSSaleem Abdulrasool  return pthread_mutex_destroy(__m);
40158a0dceeSSaleem Abdulrasool}
40258a0dceeSSaleem Abdulrasool
403c7e4239fSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m)
404c7e4239fSAsiri Rathnayake{
405c7e4239fSAsiri Rathnayake  return pthread_mutex_lock(__m);
406c7e4239fSAsiri Rathnayake}
407c7e4239fSAsiri Rathnayake
40808e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
409c7e4239fSAsiri Rathnayake{
41008e1477cSEric Fiselier  return pthread_mutex_trylock(__m) == 0;
411c7e4239fSAsiri Rathnayake}
412c7e4239fSAsiri Rathnayake
413c7e4239fSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
414c7e4239fSAsiri Rathnayake{
415c7e4239fSAsiri Rathnayake  return pthread_mutex_unlock(__m);
416c7e4239fSAsiri Rathnayake}
417c7e4239fSAsiri Rathnayake
418c7e4239fSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
419c7e4239fSAsiri Rathnayake{
420c7e4239fSAsiri Rathnayake  return pthread_mutex_destroy(__m);
421c7e4239fSAsiri Rathnayake}
422c7e4239fSAsiri Rathnayake
423790e10f6SSaleem Abdulrasool// Condition Variable
424c7e4239fSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
425c7e4239fSAsiri Rathnayake{
426c7e4239fSAsiri Rathnayake  return pthread_cond_signal(__cv);
427c7e4239fSAsiri Rathnayake}
428c7e4239fSAsiri Rathnayake
429c7e4239fSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
430c7e4239fSAsiri Rathnayake{
431c7e4239fSAsiri Rathnayake  return pthread_cond_broadcast(__cv);
432c7e4239fSAsiri Rathnayake}
433c7e4239fSAsiri Rathnayake
434c7e4239fSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
435c7e4239fSAsiri Rathnayake{
436c7e4239fSAsiri Rathnayake  return pthread_cond_wait(__cv, __m);
437c7e4239fSAsiri Rathnayake}
438c7e4239fSAsiri Rathnayake
439790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
440cfdc7f0dSMikhail Maltsev                               __libcpp_timespec_t *__ts)
441c7e4239fSAsiri Rathnayake{
442c7e4239fSAsiri Rathnayake  return pthread_cond_timedwait(__cv, __m, __ts);
443c7e4239fSAsiri Rathnayake}
444c7e4239fSAsiri Rathnayake
445c7e4239fSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
446c7e4239fSAsiri Rathnayake{
447c7e4239fSAsiri Rathnayake  return pthread_cond_destroy(__cv);
448c7e4239fSAsiri Rathnayake}
449c7e4239fSAsiri Rathnayake
45054fa9ecdSOlivier Giroux#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
45154fa9ecdSOlivier Giroux
45254fa9ecdSOlivier Giroux// Semaphore
45354fa9ecdSOlivier Girouxbool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init)
45454fa9ecdSOlivier Giroux{
45554fa9ecdSOlivier Giroux    return sem_init(__sem, 0, __init) == 0;
45654fa9ecdSOlivier Giroux}
45754fa9ecdSOlivier Giroux
45854fa9ecdSOlivier Girouxbool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem)
45954fa9ecdSOlivier Giroux{
46054fa9ecdSOlivier Giroux    return sem_destroy(__sem) == 0;
46154fa9ecdSOlivier Giroux}
46254fa9ecdSOlivier Giroux
46354fa9ecdSOlivier Girouxbool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem)
46454fa9ecdSOlivier Giroux{
46554fa9ecdSOlivier Giroux    return sem_post(__sem) == 0;
46654fa9ecdSOlivier Giroux}
46754fa9ecdSOlivier Giroux
46854fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem)
46954fa9ecdSOlivier Giroux{
47054fa9ecdSOlivier Giroux    return sem_wait(__sem) == 0;
47154fa9ecdSOlivier Giroux}
47254fa9ecdSOlivier Giroux
47354fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns)
47454fa9ecdSOlivier Giroux{
47554fa9ecdSOlivier Giroux    auto const __abs_time = chrono::system_clock::now().time_since_epoch() + __ns;
47654fa9ecdSOlivier Giroux    __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__abs_time);
47754fa9ecdSOlivier Giroux    return sem_timedwait(__sem, &__ts) == 0;
47854fa9ecdSOlivier Giroux}
47954fa9ecdSOlivier Giroux
48054fa9ecdSOlivier Giroux#endif //_LIBCPP_NO_NATIVE_SEMAPHORES
48154fa9ecdSOlivier Giroux
482205d7d3fSAsiri Rathnayake// Execute once
483205d7d3fSAsiri Rathnayakeint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
4844603460aSBruce Mitchener                          void (*init_routine)()) {
485205d7d3fSAsiri Rathnayake  return pthread_once(flag, init_routine);
486205d7d3fSAsiri Rathnayake}
487205d7d3fSAsiri Rathnayake
488205d7d3fSAsiri Rathnayake// Thread id
489c7e4239fSAsiri Rathnayake// Returns non-zero if the thread ids are equal, otherwise 0
490c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
491c7e4239fSAsiri Rathnayake{
492e6c89a49SZbigniew Sarbinowski  return t1 == t2;
493c7e4239fSAsiri Rathnayake}
494c7e4239fSAsiri Rathnayake
495c7e4239fSAsiri Rathnayake// Returns non-zero if t1 < t2, otherwise 0
496c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
497c7e4239fSAsiri Rathnayake{
498c7e4239fSAsiri Rathnayake  return t1 < t2;
499c7e4239fSAsiri Rathnayake}
500c7e4239fSAsiri Rathnayake
501c7e4239fSAsiri Rathnayake// Thread
502af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
503527a7fdfSBruce Mitchener  return *__t == __libcpp_thread_t();
504af762e91SAsiri Rathnayake}
505af762e91SAsiri Rathnayake
506790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
507790e10f6SSaleem Abdulrasool                           void *__arg)
508c7e4239fSAsiri Rathnayake{
509527a7fdfSBruce Mitchener  return pthread_create(__t, nullptr, __func, __arg);
510c7e4239fSAsiri Rathnayake}
511c7e4239fSAsiri Rathnayake
512c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id()
513c7e4239fSAsiri Rathnayake{
514e6c89a49SZbigniew Sarbinowski  const __libcpp_thread_t thread = pthread_self();
515e6c89a49SZbigniew Sarbinowski  return __libcpp_thread_get_id(&thread);
516c7e4239fSAsiri Rathnayake}
517c7e4239fSAsiri Rathnayake
518c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
519c7e4239fSAsiri Rathnayake{
520e6c89a49SZbigniew Sarbinowski#if defined(__MVS__)
521e6c89a49SZbigniew Sarbinowski  return __t->__;
522e6c89a49SZbigniew Sarbinowski#else
523c7e4239fSAsiri Rathnayake  return *__t;
524e6c89a49SZbigniew Sarbinowski#endif
525c7e4239fSAsiri Rathnayake}
526c7e4239fSAsiri Rathnayake
527c7e4239fSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t)
528c7e4239fSAsiri Rathnayake{
529527a7fdfSBruce Mitchener  return pthread_join(*__t, nullptr);
530c7e4239fSAsiri Rathnayake}
531c7e4239fSAsiri Rathnayake
532c7e4239fSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t)
533c7e4239fSAsiri Rathnayake{
534c7e4239fSAsiri Rathnayake  return pthread_detach(*__t);
535c7e4239fSAsiri Rathnayake}
536c7e4239fSAsiri Rathnayake
537c7e4239fSAsiri Rathnayakevoid __libcpp_thread_yield()
538c7e4239fSAsiri Rathnayake{
539c7e4239fSAsiri Rathnayake  sched_yield();
540c7e4239fSAsiri Rathnayake}
541c7e4239fSAsiri Rathnayake
54254a987e1SAsiri Rathnayakevoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
54354a987e1SAsiri Rathnayake{
544ab9aefeeSPetr Hosek   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
54554a987e1SAsiri Rathnayake   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
54654a987e1SAsiri Rathnayake}
54754a987e1SAsiri Rathnayake
548c7e4239fSAsiri Rathnayake// Thread local storage
5498c2bf45dSAsiri Rathnayakeint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
550c7e4239fSAsiri Rathnayake{
551c7e4239fSAsiri Rathnayake  return pthread_key_create(__key, __at_exit);
552c7e4239fSAsiri Rathnayake}
553c7e4239fSAsiri Rathnayake
5548c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key)
555c7e4239fSAsiri Rathnayake{
556c7e4239fSAsiri Rathnayake  return pthread_getspecific(__key);
557c7e4239fSAsiri Rathnayake}
558c7e4239fSAsiri Rathnayake
559205d7d3fSAsiri Rathnayakeint __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
560c7e4239fSAsiri Rathnayake{
561205d7d3fSAsiri Rathnayake    return pthread_setspecific(__key, __p);
562c7e4239fSAsiri Rathnayake}
563c7e4239fSAsiri Rathnayake
564ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11)
565ab9aefeeSPetr Hosek
566ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
567ab9aefeeSPetr Hosek{
5683481e5d7SPetr Hosek  return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
569ab9aefeeSPetr Hosek}
570ab9aefeeSPetr Hosek
571ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
572ab9aefeeSPetr Hosek{
573ab9aefeeSPetr Hosek  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
574ab9aefeeSPetr Hosek}
575ab9aefeeSPetr Hosek
576ab9aefeeSPetr Hosekbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
577ab9aefeeSPetr Hosek{
578ab9aefeeSPetr Hosek  return mtx_trylock(__m) == thrd_success;
579ab9aefeeSPetr Hosek}
580ab9aefeeSPetr Hosek
581*ebfadd82SColin Finckint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
582ab9aefeeSPetr Hosek{
583ab9aefeeSPetr Hosek  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
584ab9aefeeSPetr Hosek}
585ab9aefeeSPetr Hosek
586ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
587ab9aefeeSPetr Hosek{
588ab9aefeeSPetr Hosek  mtx_destroy(__m);
589ab9aefeeSPetr Hosek  return 0;
590ab9aefeeSPetr Hosek}
591ab9aefeeSPetr Hosek
592ab9aefeeSPetr Hosekint __libcpp_mutex_lock(__libcpp_mutex_t *__m)
593ab9aefeeSPetr Hosek{
594ab9aefeeSPetr Hosek  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
595ab9aefeeSPetr Hosek}
596ab9aefeeSPetr Hosek
597ab9aefeeSPetr Hosekbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
598ab9aefeeSPetr Hosek{
599ab9aefeeSPetr Hosek  return mtx_trylock(__m) == thrd_success;
600ab9aefeeSPetr Hosek}
601ab9aefeeSPetr Hosek
602ab9aefeeSPetr Hosekint __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
603ab9aefeeSPetr Hosek{
604ab9aefeeSPetr Hosek  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
605ab9aefeeSPetr Hosek}
606ab9aefeeSPetr Hosek
607ab9aefeeSPetr Hosekint __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
608ab9aefeeSPetr Hosek{
609ab9aefeeSPetr Hosek  mtx_destroy(__m);
610ab9aefeeSPetr Hosek  return 0;
611ab9aefeeSPetr Hosek}
612ab9aefeeSPetr Hosek
613ab9aefeeSPetr Hosek// Condition Variable
614ab9aefeeSPetr Hosekint __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
615ab9aefeeSPetr Hosek{
616ab9aefeeSPetr Hosek  return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
617ab9aefeeSPetr Hosek}
618ab9aefeeSPetr Hosek
619ab9aefeeSPetr Hosekint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
620ab9aefeeSPetr Hosek{
621ab9aefeeSPetr Hosek  return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
622ab9aefeeSPetr Hosek}
623ab9aefeeSPetr Hosek
624ab9aefeeSPetr Hosekint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
625ab9aefeeSPetr Hosek{
626ab9aefeeSPetr Hosek  return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
627ab9aefeeSPetr Hosek}
628ab9aefeeSPetr Hosek
629ab9aefeeSPetr Hosekint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
630ab9aefeeSPetr Hosek                               timespec *__ts)
631ab9aefeeSPetr Hosek{
632ab9aefeeSPetr Hosek  int __ec = cnd_timedwait(__cv, __m, __ts);
633ab9aefeeSPetr Hosek  return __ec == thrd_timedout ? ETIMEDOUT : __ec;
634ab9aefeeSPetr Hosek}
635ab9aefeeSPetr Hosek
636ab9aefeeSPetr Hosekint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
637ab9aefeeSPetr Hosek{
638ab9aefeeSPetr Hosek  cnd_destroy(__cv);
639ab9aefeeSPetr Hosek  return 0;
640ab9aefeeSPetr Hosek}
641ab9aefeeSPetr Hosek
642ab9aefeeSPetr Hosek// Execute once
643ab9aefeeSPetr Hosekint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
644ab9aefeeSPetr Hosek                          void (*init_routine)(void)) {
645ab9aefeeSPetr Hosek  ::call_once(flag, init_routine);
646ab9aefeeSPetr Hosek  return 0;
647ab9aefeeSPetr Hosek}
648ab9aefeeSPetr Hosek
649ab9aefeeSPetr Hosek// Thread id
650ab9aefeeSPetr Hosek// Returns non-zero if the thread ids are equal, otherwise 0
651ab9aefeeSPetr Hosekbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
652ab9aefeeSPetr Hosek{
653ab9aefeeSPetr Hosek  return thrd_equal(t1, t2) != 0;
654ab9aefeeSPetr Hosek}
655ab9aefeeSPetr Hosek
656ab9aefeeSPetr Hosek// Returns non-zero if t1 < t2, otherwise 0
657ab9aefeeSPetr Hosekbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
658ab9aefeeSPetr Hosek{
659ab9aefeeSPetr Hosek  return t1 < t2;
660ab9aefeeSPetr Hosek}
661ab9aefeeSPetr Hosek
662ab9aefeeSPetr Hosek// Thread
663ab9aefeeSPetr Hosekbool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
664e6c89a49SZbigniew Sarbinowski  return __libcpp_thread_get_id(__t) == 0;
665ab9aefeeSPetr Hosek}
666ab9aefeeSPetr Hosek
667ab9aefeeSPetr Hosekint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
668ab9aefeeSPetr Hosek                           void *__arg)
669ab9aefeeSPetr Hosek{
670ab9aefeeSPetr Hosek  int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
671ab9aefeeSPetr Hosek  return __ec == thrd_nomem ? ENOMEM : __ec;
672ab9aefeeSPetr Hosek}
673ab9aefeeSPetr Hosek
674ab9aefeeSPetr Hosek__libcpp_thread_id __libcpp_thread_get_current_id()
675ab9aefeeSPetr Hosek{
676ab9aefeeSPetr Hosek  return thrd_current();
677ab9aefeeSPetr Hosek}
678ab9aefeeSPetr Hosek
679ab9aefeeSPetr Hosek__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
680ab9aefeeSPetr Hosek{
681ab9aefeeSPetr Hosek  return *__t;
682ab9aefeeSPetr Hosek}
683ab9aefeeSPetr Hosek
684ab9aefeeSPetr Hosekint __libcpp_thread_join(__libcpp_thread_t *__t)
685ab9aefeeSPetr Hosek{
686ab9aefeeSPetr Hosek  return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
687ab9aefeeSPetr Hosek}
688ab9aefeeSPetr Hosek
689ab9aefeeSPetr Hosekint __libcpp_thread_detach(__libcpp_thread_t *__t)
690ab9aefeeSPetr Hosek{
691ab9aefeeSPetr Hosek  return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
692ab9aefeeSPetr Hosek}
693ab9aefeeSPetr Hosek
694ab9aefeeSPetr Hosekvoid __libcpp_thread_yield()
695ab9aefeeSPetr Hosek{
696ab9aefeeSPetr Hosek  thrd_yield();
697ab9aefeeSPetr Hosek}
698ab9aefeeSPetr Hosek
699ab9aefeeSPetr Hosekvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
700ab9aefeeSPetr Hosek{
701ab9aefeeSPetr Hosek   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
702ab9aefeeSPetr Hosek  thrd_sleep(&__ts, nullptr);
703ab9aefeeSPetr Hosek}
704ab9aefeeSPetr Hosek
705ab9aefeeSPetr Hosek// Thread local storage
706ab9aefeeSPetr Hosekint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
707ab9aefeeSPetr Hosek{
708ab9aefeeSPetr Hosek  return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
709ab9aefeeSPetr Hosek}
710ab9aefeeSPetr Hosek
711ab9aefeeSPetr Hosekvoid *__libcpp_tls_get(__libcpp_tls_key __key)
712ab9aefeeSPetr Hosek{
713ab9aefeeSPetr Hosek  return tss_get(__key);
714ab9aefeeSPetr Hosek}
715ab9aefeeSPetr Hosek
716ab9aefeeSPetr Hosekint __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
717ab9aefeeSPetr Hosek{
718ab9aefeeSPetr Hosek  return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
719ab9aefeeSPetr Hosek}
720ab9aefeeSPetr Hosek
721ab9aefeeSPetr Hosek#endif
722ab9aefeeSPetr Hosek
723e3add3e5SMartin Storsjö
72400f6beaeSEric Fiselier#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
72500f6beaeSEric Fiselier
7262b1d4254SMarshall Clowclass _LIBCPP_TYPE_VIS thread;
7272b1d4254SMarshall Clowclass _LIBCPP_TYPE_VIS __thread_id;
7282b1d4254SMarshall Clow
7292b1d4254SMarshall Clownamespace this_thread
7302b1d4254SMarshall Clow{
7312b1d4254SMarshall Clow
7322b1d4254SMarshall Clow_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
7332b1d4254SMarshall Clow
7342b1d4254SMarshall Clow}  // this_thread
7352b1d4254SMarshall Clow
7362b1d4254SMarshall Clowtemplate<> struct hash<__thread_id>;
7372b1d4254SMarshall Clow
7382b1d4254SMarshall Clowclass _LIBCPP_TEMPLATE_VIS __thread_id
7392b1d4254SMarshall Clow{
7402b1d4254SMarshall Clow    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
7412b1d4254SMarshall Clow    // NULL is the no-thread value on Darwin.  Someone needs to check
7422b1d4254SMarshall Clow    // on other platforms.  We assume 0 works everywhere for now.
7432b1d4254SMarshall Clow    __libcpp_thread_id __id_;
7442b1d4254SMarshall Clow
7452b1d4254SMarshall Clowpublic:
7462b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
7472b1d4254SMarshall Clow    __thread_id() _NOEXCEPT : __id_(0) {}
7482b1d4254SMarshall Clow
7492b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7502b1d4254SMarshall Clow        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
7512e80d01fSMarshall Clow        { // don't pass id==0 to underlying routines
7522e80d01fSMarshall Clow        if (__x.__id_ == 0) return __y.__id_ == 0;
7532e80d01fSMarshall Clow        if (__y.__id_ == 0) return false;
7542e80d01fSMarshall Clow        return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
7552e80d01fSMarshall Clow        }
7562b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7572b1d4254SMarshall Clow        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
7582b1d4254SMarshall Clow        {return !(__x == __y);}
7592b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7602b1d4254SMarshall Clow        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
7612e80d01fSMarshall Clow        { // id==0 is always less than any other thread_id
7622e80d01fSMarshall Clow        if (__x.__id_ == 0) return __y.__id_ != 0;
7632e80d01fSMarshall Clow        if (__y.__id_ == 0) return false;
7642e80d01fSMarshall Clow        return  __libcpp_thread_id_less(__x.__id_, __y.__id_);
7652e80d01fSMarshall Clow        }
7662b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7672b1d4254SMarshall Clow        bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
7682b1d4254SMarshall Clow        {return !(__y < __x);}
7692b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7702b1d4254SMarshall Clow        bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
7712b1d4254SMarshall Clow        {return   __y < __x ;}
7722b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7732b1d4254SMarshall Clow        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
7742b1d4254SMarshall Clow        {return !(__x < __y);}
7752b1d4254SMarshall Clow
7762b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
7772e80d01fSMarshall Clow    void __reset() { __id_ = 0; }
7782b1d4254SMarshall Clow
7792b1d4254SMarshall Clow    template<class _CharT, class _Traits>
7802b1d4254SMarshall Clow    friend
7812b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
7822b1d4254SMarshall Clow    basic_ostream<_CharT, _Traits>&
7832b1d4254SMarshall Clow    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
7842b1d4254SMarshall Clow
7852b1d4254SMarshall Clowprivate:
7862b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
7872b1d4254SMarshall Clow    __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
7882b1d4254SMarshall Clow
7892b1d4254SMarshall Clow    friend __thread_id this_thread::get_id() _NOEXCEPT;
7902b1d4254SMarshall Clow    friend class _LIBCPP_TYPE_VIS thread;
7912b1d4254SMarshall Clow    friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
7922b1d4254SMarshall Clow};
7932b1d4254SMarshall Clow
7942b1d4254SMarshall Clownamespace this_thread
7952b1d4254SMarshall Clow{
7962b1d4254SMarshall Clow
7972b1d4254SMarshall Clowinline _LIBCPP_INLINE_VISIBILITY
7982b1d4254SMarshall Clow__thread_id
7992b1d4254SMarshall Clowget_id() _NOEXCEPT
8002b1d4254SMarshall Clow{
8012b1d4254SMarshall Clow    return __libcpp_thread_get_current_id();
8022b1d4254SMarshall Clow}
8032b1d4254SMarshall Clow
8042b1d4254SMarshall Clow}  // this_thread
8052b1d4254SMarshall Clow
806696630eaSMarshall Clow#endif // !_LIBCPP_HAS_NO_THREADS
807696630eaSMarshall Clow
808c7e4239fSAsiri Rathnayake_LIBCPP_END_NAMESPACE_STD
809c7e4239fSAsiri Rathnayake
810a016efb1SEric Fiselier_LIBCPP_POP_MACROS
811a016efb1SEric Fiselier
812c7e4239fSAsiri Rathnayake#endif // _LIBCPP_THREADING_SUPPORT
813