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
132eadbc86SLouis Dionne#include <__availability>
14*bfbd73f8SArthur O'Dwyer#include <__config>
1554a987e1SAsiri Rathnayake#include <chrono>
1654a987e1SAsiri Rathnayake#include <errno.h>
17*bfbd73f8SArthur O'Dwyer#include <iosfwd>
181773eec6SMartin Storsjö#include <limits>
19c7e4239fSAsiri Rathnayake
206a8099e0SZbigniew Sarbinowski#ifdef __MVS__
21b5175681SLouis Dionne# include <__support/ibm/nanosleep.h>
226a8099e0SZbigniew Sarbinowski#endif
236a8099e0SZbigniew Sarbinowski
24c7e4239fSAsiri Rathnayake#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
25c7e4239fSAsiri Rathnayake#pragma GCC system_header
26c7e4239fSAsiri Rathnayake#endif
27c7e4239fSAsiri Rathnayake
2800f6beaeSEric Fiselier#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
293cf2f7bcSAsiri Rathnayake# include <__external_threading>
3000f6beaeSEric Fiselier#elif !defined(_LIBCPP_HAS_NO_THREADS)
31790e10f6SSaleem Abdulrasool
3200f6beaeSEric Fiselier#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
33c7e4239fSAsiri Rathnayake# include <pthread.h>
34c7e4239fSAsiri Rathnayake# include <sched.h>
35e6c89a49SZbigniew Sarbinowski# if defined(__APPLE__) || defined(__MVS__)
3654fa9ecdSOlivier Giroux#  define _LIBCPP_NO_NATIVE_SEMAPHORES
3754fa9ecdSOlivier Giroux# endif
3862138846Sogiroux# ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
3962138846Sogiroux# include <semaphore.h>
4062138846Sogiroux# endif
41ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11)
42ab9aefeeSPetr Hosek# include <threads.h>
43790e10f6SSaleem Abdulrasool#endif
44c7e4239fSAsiri Rathnayake
452a129dc3SPeter Collingbourne#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
462a129dc3SPeter Collingbourne    defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \
472a129dc3SPeter Collingbourne    defined(_LIBCPP_HAS_THREAD_API_WIN32)
482a129dc3SPeter Collingbourne#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
492a129dc3SPeter Collingbourne#else
502a129dc3SPeter Collingbourne#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
512a129dc3SPeter Collingbourne#endif
522a129dc3SPeter Collingbourne
5383dca5c3SDimitry Andric#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
5483dca5c3SDimitry Andric#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
5583dca5c3SDimitry Andric#else
5683dca5c3SDimitry Andric#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
5783dca5c3SDimitry Andric#endif
5883dca5c3SDimitry Andric
59696630eaSMarshall Clowtypedef ::timespec __libcpp_timespec_t;
60696630eaSMarshall Clow#endif // !defined(_LIBCPP_HAS_NO_THREADS)
61696630eaSMarshall Clow
62696630eaSMarshall Clow_LIBCPP_PUSH_MACROS
63696630eaSMarshall Clow#include <__undef_macros>
64696630eaSMarshall Clow
65c7e4239fSAsiri Rathnayake_LIBCPP_BEGIN_NAMESPACE_STD
66c7e4239fSAsiri Rathnayake
67696630eaSMarshall Clow#if !defined(_LIBCPP_HAS_NO_THREADS)
68696630eaSMarshall Clow
692a129dc3SPeter Collingbourne#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
70c7e4239fSAsiri Rathnayake// Mutex
71c7e4239fSAsiri Rathnayaketypedef pthread_mutex_t __libcpp_mutex_t;
728c2bf45dSAsiri Rathnayake#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
73c7e4239fSAsiri Rathnayake
7458a0dceeSSaleem Abdulrasooltypedef pthread_mutex_t __libcpp_recursive_mutex_t;
7558a0dceeSSaleem Abdulrasool
76790e10f6SSaleem Abdulrasool// Condition Variable
77790e10f6SSaleem Abdulrasooltypedef pthread_cond_t __libcpp_condvar_t;
78790e10f6SSaleem Abdulrasool#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
79790e10f6SSaleem Abdulrasool
8062138846Sogiroux#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
8154fa9ecdSOlivier Giroux// Semaphore
8254fa9ecdSOlivier Girouxtypedef sem_t __libcpp_semaphore_t;
8354fa9ecdSOlivier Giroux# define _LIBCPP_SEMAPHORE_MAX SEM_VALUE_MAX
8462138846Sogiroux#endif
8554fa9ecdSOlivier Giroux
86205d7d3fSAsiri Rathnayake// Execute once
87205d7d3fSAsiri Rathnayaketypedef pthread_once_t __libcpp_exec_once_flag;
88205d7d3fSAsiri Rathnayake#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
89205d7d3fSAsiri Rathnayake
90205d7d3fSAsiri Rathnayake// Thread id
91e6c89a49SZbigniew Sarbinowski#if defined(__MVS__)
92e6c89a49SZbigniew Sarbinowski  typedef unsigned long long __libcpp_thread_id;
93e6c89a49SZbigniew Sarbinowski#else
94790e10f6SSaleem Abdulrasool  typedef pthread_t __libcpp_thread_id;
95e6c89a49SZbigniew Sarbinowski#endif
96790e10f6SSaleem Abdulrasool
97790e10f6SSaleem Abdulrasool// Thread
98e6c89a49SZbigniew Sarbinowski#define _LIBCPP_NULL_THREAD ((__libcpp_thread_t()))
99790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_t;
100790e10f6SSaleem Abdulrasool
101cac6d217SFangrui Song// Thread Local Storage
102790e10f6SSaleem Abdulrasooltypedef pthread_key_t __libcpp_tls_key;
1036d7d0becSSaleem Abdulrasool
1046d7d0becSSaleem Abdulrasool#define _LIBCPP_TLS_DESTRUCTOR_CC
105ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11)
106ab9aefeeSPetr Hosek// Mutex
107ab9aefeeSPetr Hosektypedef mtx_t __libcpp_mutex_t;
108ab9aefeeSPetr Hosek// mtx_t is a struct so using {} for initialization is valid.
109ab9aefeeSPetr Hosek#define _LIBCPP_MUTEX_INITIALIZER {}
110ab9aefeeSPetr Hosek
111ab9aefeeSPetr Hosektypedef mtx_t __libcpp_recursive_mutex_t;
112ab9aefeeSPetr Hosek
113ab9aefeeSPetr Hosek// Condition Variable
114ab9aefeeSPetr Hosektypedef cnd_t __libcpp_condvar_t;
115ab9aefeeSPetr Hosek// cnd_t is a struct so using {} for initialization is valid.
116ab9aefeeSPetr Hosek#define _LIBCPP_CONDVAR_INITIALIZER {}
117ab9aefeeSPetr Hosek
118ab9aefeeSPetr Hosek// Execute once
119ab9aefeeSPetr Hosektypedef once_flag __libcpp_exec_once_flag;
120ab9aefeeSPetr Hosek#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT
121ab9aefeeSPetr Hosek
122ab9aefeeSPetr Hosek// Thread id
123ab9aefeeSPetr Hosektypedef thrd_t __libcpp_thread_id;
124ab9aefeeSPetr Hosek
125ab9aefeeSPetr Hosek// Thread
126ab9aefeeSPetr Hosek#define _LIBCPP_NULL_THREAD 0U
127ab9aefeeSPetr Hosek
128ab9aefeeSPetr Hosektypedef thrd_t __libcpp_thread_t;
129ab9aefeeSPetr Hosek
130ab9aefeeSPetr Hosek// Thread Local Storage
131ab9aefeeSPetr Hosektypedef tss_t __libcpp_tls_key;
132ab9aefeeSPetr Hosek
133ab9aefeeSPetr Hosek#define _LIBCPP_TLS_DESTRUCTOR_CC
134e2b200b7SDavid Spickett#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
135ac15ae6dSPeter Collingbourne// Mutex
136ac15ae6dSPeter Collingbournetypedef void* __libcpp_mutex_t;
137ac15ae6dSPeter Collingbourne#define _LIBCPP_MUTEX_INITIALIZER 0
138ac15ae6dSPeter Collingbourne
139ac15ae6dSPeter Collingbourne#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
140ac15ae6dSPeter Collingbournetypedef void* __libcpp_recursive_mutex_t[6];
141ac15ae6dSPeter Collingbourne#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
142ac15ae6dSPeter Collingbournetypedef void* __libcpp_recursive_mutex_t[5];
143ac15ae6dSPeter Collingbourne#else
144ac15ae6dSPeter Collingbourne# error Unsupported architecture
145ac15ae6dSPeter Collingbourne#endif
1466d7d0becSSaleem Abdulrasool
1476d7d0becSSaleem Abdulrasool// Condition Variable
148ac15ae6dSPeter Collingbournetypedef void* __libcpp_condvar_t;
149ac15ae6dSPeter Collingbourne#define _LIBCPP_CONDVAR_INITIALIZER 0
1506d7d0becSSaleem Abdulrasool
15154fa9ecdSOlivier Giroux// Semaphore
15254fa9ecdSOlivier Girouxtypedef void* __libcpp_semaphore_t;
1531773eec6SMartin Storsjö#if defined(_LIBCPP_HAS_THREAD_API_WIN32)
1541773eec6SMartin Storsjö# define _LIBCPP_SEMAPHORE_MAX (::std::numeric_limits<long>::max())
1551773eec6SMartin Storsjö#endif
15654fa9ecdSOlivier Giroux
1576d7d0becSSaleem Abdulrasool// Execute Once
158ac15ae6dSPeter Collingbournetypedef void* __libcpp_exec_once_flag;
159ac15ae6dSPeter Collingbourne#define _LIBCPP_EXEC_ONCE_INITIALIZER 0
1606d7d0becSSaleem Abdulrasool
1616d7d0becSSaleem Abdulrasool// Thread ID
162ac15ae6dSPeter Collingbournetypedef long __libcpp_thread_id;
1636d7d0becSSaleem Abdulrasool
1646d7d0becSSaleem Abdulrasool// Thread
165af762e91SAsiri Rathnayake#define _LIBCPP_NULL_THREAD 0U
166af762e91SAsiri Rathnayake
167ac15ae6dSPeter Collingbournetypedef void* __libcpp_thread_t;
1686d7d0becSSaleem Abdulrasool
1696d7d0becSSaleem Abdulrasool// Thread Local Storage
170ac15ae6dSPeter Collingbournetypedef long __libcpp_tls_key;
1716d7d0becSSaleem Abdulrasool
172ac15ae6dSPeter Collingbourne#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
173e2b200b7SDavid Spickett#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
174790e10f6SSaleem Abdulrasool
175e2b200b7SDavid Spickett#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
176790e10f6SSaleem Abdulrasool// Mutex
1778c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
17858a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
17958a0dceeSSaleem Abdulrasool
18083dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
18158a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
18258a0dceeSSaleem Abdulrasool
18383dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
18408e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
18558a0dceeSSaleem Abdulrasool
18683dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
18758a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
18858a0dceeSSaleem Abdulrasool
18958a0dceeSSaleem Abdulrasool_LIBCPP_THREAD_ABI_VISIBILITY
19058a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
191790e10f6SSaleem Abdulrasool
19283dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
1938c2bf45dSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m);
194790e10f6SSaleem Abdulrasool
19583dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
19608e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
197790e10f6SSaleem Abdulrasool
19883dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
1998c2bf45dSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
200790e10f6SSaleem Abdulrasool
2018c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2028c2bf45dSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
2038c2bf45dSAsiri Rathnayake
2048c2bf45dSAsiri Rathnayake// Condition variable
2058c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2068c2bf45dSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
207790e10f6SSaleem Abdulrasool
2088c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2098c2bf45dSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
210790e10f6SSaleem Abdulrasool
21183dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
2128c2bf45dSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
213790e10f6SSaleem Abdulrasool
21483dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
215790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
216cfdc7f0dSMikhail Maltsev                               __libcpp_timespec_t *__ts);
217790e10f6SSaleem Abdulrasool
2188c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2198c2bf45dSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
2208c2bf45dSAsiri Rathnayake
22162138846Sogiroux#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
22262138846Sogiroux
22354fa9ecdSOlivier Giroux// Semaphore
22454fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
22554fa9ecdSOlivier Girouxbool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init);
22654fa9ecdSOlivier Giroux
22754fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
22854fa9ecdSOlivier Girouxbool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem);
22954fa9ecdSOlivier Giroux
23054fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
23154fa9ecdSOlivier Girouxbool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem);
23254fa9ecdSOlivier Giroux
23354fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
23454fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem);
23554fa9ecdSOlivier Giroux
23654fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
23754fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns);
23854fa9ecdSOlivier Giroux
23962138846Sogiroux#endif // _LIBCPP_NO_NATIVE_SEMAPHORES
24062138846Sogiroux
241205d7d3fSAsiri Rathnayake// Execute once
242205d7d3fSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
243205d7d3fSAsiri Rathnayakeint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
2444603460aSBruce Mitchener                          void (*init_routine)());
245205d7d3fSAsiri Rathnayake
246205d7d3fSAsiri Rathnayake// Thread id
2478c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2488c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
249790e10f6SSaleem Abdulrasool
2508c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2518c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
2528c2bf45dSAsiri Rathnayake
2538c2bf45dSAsiri Rathnayake// Thread
2548c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
255af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
256af762e91SAsiri Rathnayake
257af762e91SAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
258790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
259790e10f6SSaleem Abdulrasool                           void *__arg);
260790e10f6SSaleem Abdulrasool
2618c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2628c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id();
263790e10f6SSaleem Abdulrasool
2648c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2658c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
266790e10f6SSaleem Abdulrasool
2678c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2688c2bf45dSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t);
269790e10f6SSaleem Abdulrasool
2708c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2718c2bf45dSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t);
272790e10f6SSaleem Abdulrasool
2738c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2748c2bf45dSAsiri Rathnayakevoid __libcpp_thread_yield();
2758c2bf45dSAsiri Rathnayake
27654a987e1SAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2779e8a082dSJoerg Sonnenbergervoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
27854a987e1SAsiri Rathnayake
2798c2bf45dSAsiri Rathnayake// Thread local storage
2808c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2816d7d0becSSaleem Abdulrasoolint __libcpp_tls_create(__libcpp_tls_key* __key,
2826d7d0becSSaleem Abdulrasool                        void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
283790e10f6SSaleem Abdulrasool
2848c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2858c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key);
286790e10f6SSaleem Abdulrasool
2878c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
288205d7d3fSAsiri Rathnayakeint __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
2898c2bf45dSAsiri Rathnayake
290e2b200b7SDavid Spickett#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
291e2b200b7SDavid Spickett
29214aef536SMikhail Maltsevstruct __libcpp_timed_backoff_policy {
29321a1a263SLouis Dionne  _LIBCPP_INLINE_VISIBILITY
29421a1a263SLouis Dionne  bool operator()(chrono::nanoseconds __elapsed) const
2953411a1a9SDavid Nicuesa  {
2963411a1a9SDavid Nicuesa      if(__elapsed > chrono::milliseconds(128))
2973411a1a9SDavid Nicuesa          __libcpp_thread_sleep_for(chrono::milliseconds(8));
2983411a1a9SDavid Nicuesa      else if(__elapsed > chrono::microseconds(64))
2993411a1a9SDavid Nicuesa          __libcpp_thread_sleep_for(__elapsed / 2);
3003411a1a9SDavid Nicuesa      else if(__elapsed > chrono::microseconds(4))
3013411a1a9SDavid Nicuesa        __libcpp_thread_yield();
3023411a1a9SDavid Nicuesa      else
303d2acf229SMarek Kurdej        {} // poll
3043411a1a9SDavid Nicuesa      return false;
3053411a1a9SDavid Nicuesa  }
30621a1a263SLouis Dionne};
3073411a1a9SDavid Nicuesa
3083411a1a9SDavid Nicuesastatic _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64;
3093411a1a9SDavid Nicuesa
31014aef536SMikhail Maltsevtemplate<class _Fn, class _BFn>
31146c38761SLouis Dionne_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
31214aef536SMikhail Maltsevbool __libcpp_thread_poll_with_backoff(
3133411a1a9SDavid Nicuesa  _Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero())
3143411a1a9SDavid Nicuesa{
3153411a1a9SDavid Nicuesa    auto const __start = chrono::high_resolution_clock::now();
3163411a1a9SDavid Nicuesa    for(int __count = 0;;) {
3173411a1a9SDavid Nicuesa      if(__f())
3183411a1a9SDavid Nicuesa        return true; // _Fn completion means success
3193411a1a9SDavid Nicuesa      if(__count < __libcpp_polling_count) {
3203411a1a9SDavid Nicuesa        __count += 1;
3213411a1a9SDavid Nicuesa        continue;
3223411a1a9SDavid Nicuesa      }
3233411a1a9SDavid Nicuesa      chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start;
3243411a1a9SDavid Nicuesa      if(__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed)
3253411a1a9SDavid Nicuesa          return false; // timeout failure
3263411a1a9SDavid Nicuesa      if(__bf(__elapsed))
3273411a1a9SDavid Nicuesa        return false; // _BFn completion means failure
3283411a1a9SDavid Nicuesa    }
3293411a1a9SDavid Nicuesa}
3303411a1a9SDavid Nicuesa
3313411a1a9SDavid Nicuesa#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
3323411a1a9SDavid Nicuesa     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL))
3333411a1a9SDavid Nicuesa
33414aef536SMikhail Maltsev
335ab9aefeeSPetr Hoseknamespace __thread_detail {
336ab9aefeeSPetr Hosek
337ab9aefeeSPetr Hosekinline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns)
338ab9aefeeSPetr Hosek{
339ab9aefeeSPetr Hosek  using namespace chrono;
340ab9aefeeSPetr Hosek  seconds __s = duration_cast<seconds>(__ns);
341ab9aefeeSPetr Hosek  __libcpp_timespec_t __ts;
342ab9aefeeSPetr Hosek  typedef decltype(__ts.tv_sec) __ts_sec;
343ab9aefeeSPetr Hosek  const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
344ab9aefeeSPetr Hosek
345ab9aefeeSPetr Hosek  if (__s.count() < __ts_sec_max)
346ab9aefeeSPetr Hosek  {
347ab9aefeeSPetr Hosek    __ts.tv_sec = static_cast<__ts_sec>(__s.count());
348ab9aefeeSPetr Hosek    __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
349ab9aefeeSPetr Hosek  }
350ab9aefeeSPetr Hosek  else
351ab9aefeeSPetr Hosek  {
352ab9aefeeSPetr Hosek    __ts.tv_sec = __ts_sec_max;
353ab9aefeeSPetr Hosek    __ts.tv_nsec = 999999999; // (10^9 - 1)
354ab9aefeeSPetr Hosek  }
355ab9aefeeSPetr Hosek
356ab9aefeeSPetr Hosek  return __ts;
357ab9aefeeSPetr Hosek}
358ab9aefeeSPetr Hosek
359ab9aefeeSPetr Hosek}
360ab9aefeeSPetr Hosek
361ab9aefeeSPetr Hosek#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
3628c2bf45dSAsiri Rathnayake
36358a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
364c7e4239fSAsiri Rathnayake{
365c7e4239fSAsiri Rathnayake  pthread_mutexattr_t attr;
366c7e4239fSAsiri Rathnayake  int __ec = pthread_mutexattr_init(&attr);
367c7e4239fSAsiri Rathnayake  if (__ec)
368790e10f6SSaleem Abdulrasool    return __ec;
369790e10f6SSaleem Abdulrasool  __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
370790e10f6SSaleem Abdulrasool  if (__ec) {
371c7e4239fSAsiri Rathnayake    pthread_mutexattr_destroy(&attr);
372c7e4239fSAsiri Rathnayake    return __ec;
373c7e4239fSAsiri Rathnayake  }
374c7e4239fSAsiri Rathnayake  __ec = pthread_mutex_init(__m, &attr);
375790e10f6SSaleem Abdulrasool  if (__ec) {
376c7e4239fSAsiri Rathnayake    pthread_mutexattr_destroy(&attr);
377c7e4239fSAsiri Rathnayake    return __ec;
378c7e4239fSAsiri Rathnayake  }
379c7e4239fSAsiri Rathnayake  __ec = pthread_mutexattr_destroy(&attr);
380790e10f6SSaleem Abdulrasool  if (__ec) {
381c7e4239fSAsiri Rathnayake    pthread_mutex_destroy(__m);
382c7e4239fSAsiri Rathnayake    return __ec;
383c7e4239fSAsiri Rathnayake  }
384c7e4239fSAsiri Rathnayake  return 0;
385c7e4239fSAsiri Rathnayake}
386c7e4239fSAsiri Rathnayake
38758a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
38858a0dceeSSaleem Abdulrasool{
38958a0dceeSSaleem Abdulrasool  return pthread_mutex_lock(__m);
39058a0dceeSSaleem Abdulrasool}
39158a0dceeSSaleem Abdulrasool
39208e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
39358a0dceeSSaleem Abdulrasool{
39408e1477cSEric Fiselier  return pthread_mutex_trylock(__m) == 0;
39558a0dceeSSaleem Abdulrasool}
39658a0dceeSSaleem Abdulrasool
397ebfadd82SColin Finckint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
39858a0dceeSSaleem Abdulrasool{
39958a0dceeSSaleem Abdulrasool  return pthread_mutex_unlock(__m);
40058a0dceeSSaleem Abdulrasool}
40158a0dceeSSaleem Abdulrasool
40258a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
40358a0dceeSSaleem Abdulrasool{
40458a0dceeSSaleem Abdulrasool  return pthread_mutex_destroy(__m);
40558a0dceeSSaleem Abdulrasool}
40658a0dceeSSaleem Abdulrasool
407c7e4239fSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m)
408c7e4239fSAsiri Rathnayake{
409c7e4239fSAsiri Rathnayake  return pthread_mutex_lock(__m);
410c7e4239fSAsiri Rathnayake}
411c7e4239fSAsiri Rathnayake
41208e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
413c7e4239fSAsiri Rathnayake{
41408e1477cSEric Fiselier  return pthread_mutex_trylock(__m) == 0;
415c7e4239fSAsiri Rathnayake}
416c7e4239fSAsiri Rathnayake
417c7e4239fSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
418c7e4239fSAsiri Rathnayake{
419c7e4239fSAsiri Rathnayake  return pthread_mutex_unlock(__m);
420c7e4239fSAsiri Rathnayake}
421c7e4239fSAsiri Rathnayake
422c7e4239fSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
423c7e4239fSAsiri Rathnayake{
424c7e4239fSAsiri Rathnayake  return pthread_mutex_destroy(__m);
425c7e4239fSAsiri Rathnayake}
426c7e4239fSAsiri Rathnayake
427790e10f6SSaleem Abdulrasool// Condition Variable
428c7e4239fSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
429c7e4239fSAsiri Rathnayake{
430c7e4239fSAsiri Rathnayake  return pthread_cond_signal(__cv);
431c7e4239fSAsiri Rathnayake}
432c7e4239fSAsiri Rathnayake
433c7e4239fSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
434c7e4239fSAsiri Rathnayake{
435c7e4239fSAsiri Rathnayake  return pthread_cond_broadcast(__cv);
436c7e4239fSAsiri Rathnayake}
437c7e4239fSAsiri Rathnayake
438c7e4239fSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
439c7e4239fSAsiri Rathnayake{
440c7e4239fSAsiri Rathnayake  return pthread_cond_wait(__cv, __m);
441c7e4239fSAsiri Rathnayake}
442c7e4239fSAsiri Rathnayake
443790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
444cfdc7f0dSMikhail Maltsev                               __libcpp_timespec_t *__ts)
445c7e4239fSAsiri Rathnayake{
446c7e4239fSAsiri Rathnayake  return pthread_cond_timedwait(__cv, __m, __ts);
447c7e4239fSAsiri Rathnayake}
448c7e4239fSAsiri Rathnayake
449c7e4239fSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
450c7e4239fSAsiri Rathnayake{
451c7e4239fSAsiri Rathnayake  return pthread_cond_destroy(__cv);
452c7e4239fSAsiri Rathnayake}
453c7e4239fSAsiri Rathnayake
45454fa9ecdSOlivier Giroux#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
45554fa9ecdSOlivier Giroux
45654fa9ecdSOlivier Giroux// Semaphore
45754fa9ecdSOlivier Girouxbool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init)
45854fa9ecdSOlivier Giroux{
45954fa9ecdSOlivier Giroux    return sem_init(__sem, 0, __init) == 0;
46054fa9ecdSOlivier Giroux}
46154fa9ecdSOlivier Giroux
46254fa9ecdSOlivier Girouxbool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem)
46354fa9ecdSOlivier Giroux{
46454fa9ecdSOlivier Giroux    return sem_destroy(__sem) == 0;
46554fa9ecdSOlivier Giroux}
46654fa9ecdSOlivier Giroux
46754fa9ecdSOlivier Girouxbool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem)
46854fa9ecdSOlivier Giroux{
46954fa9ecdSOlivier Giroux    return sem_post(__sem) == 0;
47054fa9ecdSOlivier Giroux}
47154fa9ecdSOlivier Giroux
47254fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem)
47354fa9ecdSOlivier Giroux{
47454fa9ecdSOlivier Giroux    return sem_wait(__sem) == 0;
47554fa9ecdSOlivier Giroux}
47654fa9ecdSOlivier Giroux
47754fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns)
47854fa9ecdSOlivier Giroux{
47954fa9ecdSOlivier Giroux    auto const __abs_time = chrono::system_clock::now().time_since_epoch() + __ns;
48054fa9ecdSOlivier Giroux    __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__abs_time);
48154fa9ecdSOlivier Giroux    return sem_timedwait(__sem, &__ts) == 0;
48254fa9ecdSOlivier Giroux}
48354fa9ecdSOlivier Giroux
48454fa9ecdSOlivier Giroux#endif //_LIBCPP_NO_NATIVE_SEMAPHORES
48554fa9ecdSOlivier Giroux
486205d7d3fSAsiri Rathnayake// Execute once
487205d7d3fSAsiri Rathnayakeint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
4884603460aSBruce Mitchener                          void (*init_routine)()) {
489205d7d3fSAsiri Rathnayake  return pthread_once(flag, init_routine);
490205d7d3fSAsiri Rathnayake}
491205d7d3fSAsiri Rathnayake
492205d7d3fSAsiri Rathnayake// Thread id
493c7e4239fSAsiri Rathnayake// Returns non-zero if the thread ids are equal, otherwise 0
494c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
495c7e4239fSAsiri Rathnayake{
496e6c89a49SZbigniew Sarbinowski  return t1 == t2;
497c7e4239fSAsiri Rathnayake}
498c7e4239fSAsiri Rathnayake
499c7e4239fSAsiri Rathnayake// Returns non-zero if t1 < t2, otherwise 0
500c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
501c7e4239fSAsiri Rathnayake{
502c7e4239fSAsiri Rathnayake  return t1 < t2;
503c7e4239fSAsiri Rathnayake}
504c7e4239fSAsiri Rathnayake
505c7e4239fSAsiri Rathnayake// Thread
506af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
50748fcce1aSZbigniew Sarbinowski  return __libcpp_thread_get_id(__t) == 0;
508af762e91SAsiri Rathnayake}
509af762e91SAsiri Rathnayake
510790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
511790e10f6SSaleem Abdulrasool                           void *__arg)
512c7e4239fSAsiri Rathnayake{
513527a7fdfSBruce Mitchener  return pthread_create(__t, nullptr, __func, __arg);
514c7e4239fSAsiri Rathnayake}
515c7e4239fSAsiri Rathnayake
516c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id()
517c7e4239fSAsiri Rathnayake{
518e6c89a49SZbigniew Sarbinowski  const __libcpp_thread_t thread = pthread_self();
519e6c89a49SZbigniew Sarbinowski  return __libcpp_thread_get_id(&thread);
520c7e4239fSAsiri Rathnayake}
521c7e4239fSAsiri Rathnayake
522c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
523c7e4239fSAsiri Rathnayake{
524e6c89a49SZbigniew Sarbinowski#if defined(__MVS__)
525e6c89a49SZbigniew Sarbinowski  return __t->__;
526e6c89a49SZbigniew Sarbinowski#else
527c7e4239fSAsiri Rathnayake  return *__t;
528e6c89a49SZbigniew Sarbinowski#endif
529c7e4239fSAsiri Rathnayake}
530c7e4239fSAsiri Rathnayake
531c7e4239fSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t)
532c7e4239fSAsiri Rathnayake{
533527a7fdfSBruce Mitchener  return pthread_join(*__t, nullptr);
534c7e4239fSAsiri Rathnayake}
535c7e4239fSAsiri Rathnayake
536c7e4239fSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t)
537c7e4239fSAsiri Rathnayake{
538c7e4239fSAsiri Rathnayake  return pthread_detach(*__t);
539c7e4239fSAsiri Rathnayake}
540c7e4239fSAsiri Rathnayake
541c7e4239fSAsiri Rathnayakevoid __libcpp_thread_yield()
542c7e4239fSAsiri Rathnayake{
543c7e4239fSAsiri Rathnayake  sched_yield();
544c7e4239fSAsiri Rathnayake}
545c7e4239fSAsiri Rathnayake
54654a987e1SAsiri Rathnayakevoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
54754a987e1SAsiri Rathnayake{
548ab9aefeeSPetr Hosek   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
54954a987e1SAsiri Rathnayake   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
55054a987e1SAsiri Rathnayake}
55154a987e1SAsiri Rathnayake
552c7e4239fSAsiri Rathnayake// Thread local storage
5538c2bf45dSAsiri Rathnayakeint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
554c7e4239fSAsiri Rathnayake{
555c7e4239fSAsiri Rathnayake  return pthread_key_create(__key, __at_exit);
556c7e4239fSAsiri Rathnayake}
557c7e4239fSAsiri Rathnayake
5588c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key)
559c7e4239fSAsiri Rathnayake{
560c7e4239fSAsiri Rathnayake  return pthread_getspecific(__key);
561c7e4239fSAsiri Rathnayake}
562c7e4239fSAsiri Rathnayake
563205d7d3fSAsiri Rathnayakeint __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
564c7e4239fSAsiri Rathnayake{
565205d7d3fSAsiri Rathnayake    return pthread_setspecific(__key, __p);
566c7e4239fSAsiri Rathnayake}
567c7e4239fSAsiri Rathnayake
568ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11)
569ab9aefeeSPetr Hosek
570ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
571ab9aefeeSPetr Hosek{
5723481e5d7SPetr Hosek  return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
573ab9aefeeSPetr Hosek}
574ab9aefeeSPetr Hosek
575ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
576ab9aefeeSPetr Hosek{
577ab9aefeeSPetr Hosek  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
578ab9aefeeSPetr Hosek}
579ab9aefeeSPetr Hosek
580ab9aefeeSPetr Hosekbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
581ab9aefeeSPetr Hosek{
582ab9aefeeSPetr Hosek  return mtx_trylock(__m) == thrd_success;
583ab9aefeeSPetr Hosek}
584ab9aefeeSPetr Hosek
585ebfadd82SColin Finckint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
586ab9aefeeSPetr Hosek{
587ab9aefeeSPetr Hosek  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
588ab9aefeeSPetr Hosek}
589ab9aefeeSPetr Hosek
590ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
591ab9aefeeSPetr Hosek{
592ab9aefeeSPetr Hosek  mtx_destroy(__m);
593ab9aefeeSPetr Hosek  return 0;
594ab9aefeeSPetr Hosek}
595ab9aefeeSPetr Hosek
596ab9aefeeSPetr Hosekint __libcpp_mutex_lock(__libcpp_mutex_t *__m)
597ab9aefeeSPetr Hosek{
598ab9aefeeSPetr Hosek  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
599ab9aefeeSPetr Hosek}
600ab9aefeeSPetr Hosek
601ab9aefeeSPetr Hosekbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
602ab9aefeeSPetr Hosek{
603ab9aefeeSPetr Hosek  return mtx_trylock(__m) == thrd_success;
604ab9aefeeSPetr Hosek}
605ab9aefeeSPetr Hosek
606ab9aefeeSPetr Hosekint __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
607ab9aefeeSPetr Hosek{
608ab9aefeeSPetr Hosek  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
609ab9aefeeSPetr Hosek}
610ab9aefeeSPetr Hosek
611ab9aefeeSPetr Hosekint __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
612ab9aefeeSPetr Hosek{
613ab9aefeeSPetr Hosek  mtx_destroy(__m);
614ab9aefeeSPetr Hosek  return 0;
615ab9aefeeSPetr Hosek}
616ab9aefeeSPetr Hosek
617ab9aefeeSPetr Hosek// Condition Variable
618ab9aefeeSPetr Hosekint __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
619ab9aefeeSPetr Hosek{
620ab9aefeeSPetr Hosek  return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
621ab9aefeeSPetr Hosek}
622ab9aefeeSPetr Hosek
623ab9aefeeSPetr Hosekint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
624ab9aefeeSPetr Hosek{
625ab9aefeeSPetr Hosek  return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
626ab9aefeeSPetr Hosek}
627ab9aefeeSPetr Hosek
628ab9aefeeSPetr Hosekint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
629ab9aefeeSPetr Hosek{
630ab9aefeeSPetr Hosek  return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
631ab9aefeeSPetr Hosek}
632ab9aefeeSPetr Hosek
633ab9aefeeSPetr Hosekint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
634ab9aefeeSPetr Hosek                               timespec *__ts)
635ab9aefeeSPetr Hosek{
636ab9aefeeSPetr Hosek  int __ec = cnd_timedwait(__cv, __m, __ts);
637ab9aefeeSPetr Hosek  return __ec == thrd_timedout ? ETIMEDOUT : __ec;
638ab9aefeeSPetr Hosek}
639ab9aefeeSPetr Hosek
640ab9aefeeSPetr Hosekint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
641ab9aefeeSPetr Hosek{
642ab9aefeeSPetr Hosek  cnd_destroy(__cv);
643ab9aefeeSPetr Hosek  return 0;
644ab9aefeeSPetr Hosek}
645ab9aefeeSPetr Hosek
646ab9aefeeSPetr Hosek// Execute once
647ab9aefeeSPetr Hosekint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
648ab9aefeeSPetr Hosek                          void (*init_routine)(void)) {
649ab9aefeeSPetr Hosek  ::call_once(flag, init_routine);
650ab9aefeeSPetr Hosek  return 0;
651ab9aefeeSPetr Hosek}
652ab9aefeeSPetr Hosek
653ab9aefeeSPetr Hosek// Thread id
654ab9aefeeSPetr Hosek// Returns non-zero if the thread ids are equal, otherwise 0
655ab9aefeeSPetr Hosekbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
656ab9aefeeSPetr Hosek{
657ab9aefeeSPetr Hosek  return thrd_equal(t1, t2) != 0;
658ab9aefeeSPetr Hosek}
659ab9aefeeSPetr Hosek
660ab9aefeeSPetr Hosek// Returns non-zero if t1 < t2, otherwise 0
661ab9aefeeSPetr Hosekbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
662ab9aefeeSPetr Hosek{
663ab9aefeeSPetr Hosek  return t1 < t2;
664ab9aefeeSPetr Hosek}
665ab9aefeeSPetr Hosek
666ab9aefeeSPetr Hosek// Thread
667ab9aefeeSPetr Hosekbool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
668e6c89a49SZbigniew Sarbinowski  return __libcpp_thread_get_id(__t) == 0;
669ab9aefeeSPetr Hosek}
670ab9aefeeSPetr Hosek
671ab9aefeeSPetr Hosekint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
672ab9aefeeSPetr Hosek                           void *__arg)
673ab9aefeeSPetr Hosek{
674ab9aefeeSPetr Hosek  int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
675ab9aefeeSPetr Hosek  return __ec == thrd_nomem ? ENOMEM : __ec;
676ab9aefeeSPetr Hosek}
677ab9aefeeSPetr Hosek
678ab9aefeeSPetr Hosek__libcpp_thread_id __libcpp_thread_get_current_id()
679ab9aefeeSPetr Hosek{
680ab9aefeeSPetr Hosek  return thrd_current();
681ab9aefeeSPetr Hosek}
682ab9aefeeSPetr Hosek
683ab9aefeeSPetr Hosek__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
684ab9aefeeSPetr Hosek{
685ab9aefeeSPetr Hosek  return *__t;
686ab9aefeeSPetr Hosek}
687ab9aefeeSPetr Hosek
688ab9aefeeSPetr Hosekint __libcpp_thread_join(__libcpp_thread_t *__t)
689ab9aefeeSPetr Hosek{
690ab9aefeeSPetr Hosek  return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
691ab9aefeeSPetr Hosek}
692ab9aefeeSPetr Hosek
693ab9aefeeSPetr Hosekint __libcpp_thread_detach(__libcpp_thread_t *__t)
694ab9aefeeSPetr Hosek{
695ab9aefeeSPetr Hosek  return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
696ab9aefeeSPetr Hosek}
697ab9aefeeSPetr Hosek
698ab9aefeeSPetr Hosekvoid __libcpp_thread_yield()
699ab9aefeeSPetr Hosek{
700ab9aefeeSPetr Hosek  thrd_yield();
701ab9aefeeSPetr Hosek}
702ab9aefeeSPetr Hosek
703ab9aefeeSPetr Hosekvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
704ab9aefeeSPetr Hosek{
705ab9aefeeSPetr Hosek   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
706ab9aefeeSPetr Hosek  thrd_sleep(&__ts, nullptr);
707ab9aefeeSPetr Hosek}
708ab9aefeeSPetr Hosek
709ab9aefeeSPetr Hosek// Thread local storage
710ab9aefeeSPetr Hosekint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
711ab9aefeeSPetr Hosek{
712ab9aefeeSPetr Hosek  return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
713ab9aefeeSPetr Hosek}
714ab9aefeeSPetr Hosek
715ab9aefeeSPetr Hosekvoid *__libcpp_tls_get(__libcpp_tls_key __key)
716ab9aefeeSPetr Hosek{
717ab9aefeeSPetr Hosek  return tss_get(__key);
718ab9aefeeSPetr Hosek}
719ab9aefeeSPetr Hosek
720ab9aefeeSPetr Hosekint __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
721ab9aefeeSPetr Hosek{
722ab9aefeeSPetr Hosek  return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
723ab9aefeeSPetr Hosek}
724ab9aefeeSPetr Hosek
725ab9aefeeSPetr Hosek#endif
726ab9aefeeSPetr Hosek
727e3add3e5SMartin Storsjö
72800f6beaeSEric Fiselier#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
72900f6beaeSEric Fiselier
7302b1d4254SMarshall Clowclass _LIBCPP_TYPE_VIS thread;
7312b1d4254SMarshall Clowclass _LIBCPP_TYPE_VIS __thread_id;
7322b1d4254SMarshall Clow
7332b1d4254SMarshall Clownamespace this_thread
7342b1d4254SMarshall Clow{
7352b1d4254SMarshall Clow
7362b1d4254SMarshall Clow_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
7372b1d4254SMarshall Clow
7382b1d4254SMarshall Clow}  // this_thread
7392b1d4254SMarshall Clow
7402b1d4254SMarshall Clowtemplate<> struct hash<__thread_id>;
7412b1d4254SMarshall Clow
7422b1d4254SMarshall Clowclass _LIBCPP_TEMPLATE_VIS __thread_id
7432b1d4254SMarshall Clow{
7442b1d4254SMarshall Clow    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
7452b1d4254SMarshall Clow    // NULL is the no-thread value on Darwin.  Someone needs to check
7462b1d4254SMarshall Clow    // on other platforms.  We assume 0 works everywhere for now.
7472b1d4254SMarshall Clow    __libcpp_thread_id __id_;
7482b1d4254SMarshall Clow
7492b1d4254SMarshall Clowpublic:
7502b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
7512b1d4254SMarshall Clow    __thread_id() _NOEXCEPT : __id_(0) {}
7522b1d4254SMarshall Clow
7532b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7542b1d4254SMarshall Clow        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
7552e80d01fSMarshall Clow        { // don't pass id==0 to underlying routines
7562e80d01fSMarshall Clow        if (__x.__id_ == 0) return __y.__id_ == 0;
7572e80d01fSMarshall Clow        if (__y.__id_ == 0) return false;
7582e80d01fSMarshall Clow        return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
7592e80d01fSMarshall Clow        }
7602b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7612b1d4254SMarshall Clow        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
7622b1d4254SMarshall Clow        {return !(__x == __y);}
7632b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7642b1d4254SMarshall Clow        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
7652e80d01fSMarshall Clow        { // id==0 is always less than any other thread_id
7662e80d01fSMarshall Clow        if (__x.__id_ == 0) return __y.__id_ != 0;
7672e80d01fSMarshall Clow        if (__y.__id_ == 0) return false;
7682e80d01fSMarshall Clow        return  __libcpp_thread_id_less(__x.__id_, __y.__id_);
7692e80d01fSMarshall Clow        }
7702b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7712b1d4254SMarshall Clow        bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
7722b1d4254SMarshall Clow        {return !(__y < __x);}
7732b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7742b1d4254SMarshall Clow        bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
7752b1d4254SMarshall Clow        {return   __y < __x ;}
7762b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7772b1d4254SMarshall Clow        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
7782b1d4254SMarshall Clow        {return !(__x < __y);}
7792b1d4254SMarshall Clow
7802b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
7812e80d01fSMarshall Clow    void __reset() { __id_ = 0; }
7822b1d4254SMarshall Clow
7832b1d4254SMarshall Clow    template<class _CharT, class _Traits>
7842b1d4254SMarshall Clow    friend
7852b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
7862b1d4254SMarshall Clow    basic_ostream<_CharT, _Traits>&
7872b1d4254SMarshall Clow    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
7882b1d4254SMarshall Clow
7892b1d4254SMarshall Clowprivate:
7902b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
7912b1d4254SMarshall Clow    __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
7922b1d4254SMarshall Clow
7932b1d4254SMarshall Clow    friend __thread_id this_thread::get_id() _NOEXCEPT;
7942b1d4254SMarshall Clow    friend class _LIBCPP_TYPE_VIS thread;
7952b1d4254SMarshall Clow    friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
7962b1d4254SMarshall Clow};
7972b1d4254SMarshall Clow
7982b1d4254SMarshall Clownamespace this_thread
7992b1d4254SMarshall Clow{
8002b1d4254SMarshall Clow
8012b1d4254SMarshall Clowinline _LIBCPP_INLINE_VISIBILITY
8022b1d4254SMarshall Clow__thread_id
8032b1d4254SMarshall Clowget_id() _NOEXCEPT
8042b1d4254SMarshall Clow{
8052b1d4254SMarshall Clow    return __libcpp_thread_get_current_id();
8062b1d4254SMarshall Clow}
8072b1d4254SMarshall Clow
8082b1d4254SMarshall Clow}  // this_thread
8092b1d4254SMarshall Clow
810696630eaSMarshall Clow#endif // !_LIBCPP_HAS_NO_THREADS
811696630eaSMarshall Clow
812c7e4239fSAsiri Rathnayake_LIBCPP_END_NAMESPACE_STD
813c7e4239fSAsiri Rathnayake
814a016efb1SEric Fiselier_LIBCPP_POP_MACROS
815a016efb1SEric Fiselier
816c7e4239fSAsiri Rathnayake#endif // _LIBCPP_THREADING_SUPPORT
817