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