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__
206a8099e0SZbigniew Sarbinowski# 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>
3454fa9ecdSOlivier Giroux# ifdef __APPLE__
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
90790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_id;
91790e10f6SSaleem Abdulrasool
92790e10f6SSaleem Abdulrasool// Thread
93af762e91SAsiri Rathnayake#define _LIBCPP_NULL_THREAD 0U
94af762e91SAsiri Rathnayake
95790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_t;
96790e10f6SSaleem Abdulrasool
97cac6d217SFangrui Song// Thread Local Storage
98790e10f6SSaleem Abdulrasooltypedef pthread_key_t __libcpp_tls_key;
996d7d0becSSaleem Abdulrasool
1006d7d0becSSaleem Abdulrasool#define _LIBCPP_TLS_DESTRUCTOR_CC
101ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11)
102ab9aefeeSPetr Hosek// Mutex
103ab9aefeeSPetr Hosektypedef mtx_t __libcpp_mutex_t;
104ab9aefeeSPetr Hosek// mtx_t is a struct so using {} for initialization is valid.
105ab9aefeeSPetr Hosek#define _LIBCPP_MUTEX_INITIALIZER {}
106ab9aefeeSPetr Hosek
107ab9aefeeSPetr Hosektypedef mtx_t __libcpp_recursive_mutex_t;
108ab9aefeeSPetr Hosek
109ab9aefeeSPetr Hosek// Condition Variable
110ab9aefeeSPetr Hosektypedef cnd_t __libcpp_condvar_t;
111ab9aefeeSPetr Hosek// cnd_t is a struct so using {} for initialization is valid.
112ab9aefeeSPetr Hosek#define _LIBCPP_CONDVAR_INITIALIZER {}
113ab9aefeeSPetr Hosek
114ab9aefeeSPetr Hosek// Execute once
115ab9aefeeSPetr Hosektypedef once_flag __libcpp_exec_once_flag;
116ab9aefeeSPetr Hosek#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT
117ab9aefeeSPetr Hosek
118ab9aefeeSPetr Hosek// Thread id
119ab9aefeeSPetr Hosektypedef thrd_t __libcpp_thread_id;
120ab9aefeeSPetr Hosek
121ab9aefeeSPetr Hosek// Thread
122ab9aefeeSPetr Hosek#define _LIBCPP_NULL_THREAD 0U
123ab9aefeeSPetr Hosek
124ab9aefeeSPetr Hosektypedef thrd_t __libcpp_thread_t;
125ab9aefeeSPetr Hosek
126ab9aefeeSPetr Hosek// Thread Local Storage
127ab9aefeeSPetr Hosektypedef tss_t __libcpp_tls_key;
128ab9aefeeSPetr Hosek
129ab9aefeeSPetr Hosek#define _LIBCPP_TLS_DESTRUCTOR_CC
130e2b200b7SDavid Spickett#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
131ac15ae6dSPeter Collingbourne// Mutex
132ac15ae6dSPeter Collingbournetypedef void* __libcpp_mutex_t;
133ac15ae6dSPeter Collingbourne#define _LIBCPP_MUTEX_INITIALIZER 0
134ac15ae6dSPeter Collingbourne
135ac15ae6dSPeter Collingbourne#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
136ac15ae6dSPeter Collingbournetypedef void* __libcpp_recursive_mutex_t[6];
137ac15ae6dSPeter Collingbourne#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
138ac15ae6dSPeter Collingbournetypedef void* __libcpp_recursive_mutex_t[5];
139ac15ae6dSPeter Collingbourne#else
140ac15ae6dSPeter Collingbourne# error Unsupported architecture
141ac15ae6dSPeter Collingbourne#endif
1426d7d0becSSaleem Abdulrasool
1436d7d0becSSaleem Abdulrasool// Condition Variable
144ac15ae6dSPeter Collingbournetypedef void* __libcpp_condvar_t;
145ac15ae6dSPeter Collingbourne#define _LIBCPP_CONDVAR_INITIALIZER 0
1466d7d0becSSaleem Abdulrasool
14754fa9ecdSOlivier Giroux// Semaphore
14854fa9ecdSOlivier Girouxtypedef void* __libcpp_semaphore_t;
14954fa9ecdSOlivier Giroux
1506d7d0becSSaleem Abdulrasool// Execute Once
151ac15ae6dSPeter Collingbournetypedef void* __libcpp_exec_once_flag;
152ac15ae6dSPeter Collingbourne#define _LIBCPP_EXEC_ONCE_INITIALIZER 0
1536d7d0becSSaleem Abdulrasool
1546d7d0becSSaleem Abdulrasool// Thread ID
155ac15ae6dSPeter Collingbournetypedef long __libcpp_thread_id;
1566d7d0becSSaleem Abdulrasool
1576d7d0becSSaleem Abdulrasool// Thread
158af762e91SAsiri Rathnayake#define _LIBCPP_NULL_THREAD 0U
159af762e91SAsiri Rathnayake
160ac15ae6dSPeter Collingbournetypedef void* __libcpp_thread_t;
1616d7d0becSSaleem Abdulrasool
1626d7d0becSSaleem Abdulrasool// Thread Local Storage
163ac15ae6dSPeter Collingbournetypedef long __libcpp_tls_key;
1646d7d0becSSaleem Abdulrasool
165ac15ae6dSPeter Collingbourne#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
166e2b200b7SDavid Spickett#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
167790e10f6SSaleem Abdulrasool
168e2b200b7SDavid Spickett#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
169790e10f6SSaleem Abdulrasool// Mutex
1708c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
17158a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
17258a0dceeSSaleem Abdulrasool
17383dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
17458a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
17558a0dceeSSaleem Abdulrasool
17683dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
17708e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
17858a0dceeSSaleem Abdulrasool
17983dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
18058a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
18158a0dceeSSaleem Abdulrasool
18258a0dceeSSaleem Abdulrasool_LIBCPP_THREAD_ABI_VISIBILITY
18358a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
184790e10f6SSaleem Abdulrasool
18583dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
1868c2bf45dSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m);
187790e10f6SSaleem Abdulrasool
18883dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
18908e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
190790e10f6SSaleem Abdulrasool
19183dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
1928c2bf45dSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
193790e10f6SSaleem Abdulrasool
1948c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1958c2bf45dSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
1968c2bf45dSAsiri Rathnayake
1978c2bf45dSAsiri Rathnayake// Condition variable
1988c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1998c2bf45dSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
200790e10f6SSaleem Abdulrasool
2018c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2028c2bf45dSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
203790e10f6SSaleem Abdulrasool
20483dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
2058c2bf45dSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
206790e10f6SSaleem Abdulrasool
20783dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
208790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
209cfdc7f0dSMikhail Maltsev                               __libcpp_timespec_t *__ts);
210790e10f6SSaleem Abdulrasool
2118c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2128c2bf45dSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
2138c2bf45dSAsiri Rathnayake
21462138846Sogiroux#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
21562138846Sogiroux
21654fa9ecdSOlivier Giroux// Semaphore
21754fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
21854fa9ecdSOlivier Girouxbool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init);
21954fa9ecdSOlivier Giroux
22054fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
22154fa9ecdSOlivier Girouxbool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem);
22254fa9ecdSOlivier Giroux
22354fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
22454fa9ecdSOlivier Girouxbool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem);
22554fa9ecdSOlivier Giroux
22654fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
22754fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem);
22854fa9ecdSOlivier Giroux
22954fa9ecdSOlivier Giroux_LIBCPP_THREAD_ABI_VISIBILITY
23054fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns);
23154fa9ecdSOlivier Giroux
23262138846Sogiroux#endif // _LIBCPP_NO_NATIVE_SEMAPHORES
23362138846Sogiroux
234205d7d3fSAsiri Rathnayake// Execute once
235205d7d3fSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
236205d7d3fSAsiri Rathnayakeint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
2374603460aSBruce Mitchener                          void (*init_routine)());
238205d7d3fSAsiri Rathnayake
239205d7d3fSAsiri Rathnayake// Thread id
2408c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2418c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
242790e10f6SSaleem Abdulrasool
2438c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2448c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
2458c2bf45dSAsiri Rathnayake
2468c2bf45dSAsiri Rathnayake// Thread
2478c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
248af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
249af762e91SAsiri Rathnayake
250af762e91SAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
251790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
252790e10f6SSaleem Abdulrasool                           void *__arg);
253790e10f6SSaleem Abdulrasool
2548c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2558c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id();
256790e10f6SSaleem Abdulrasool
2578c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2588c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
259790e10f6SSaleem Abdulrasool
2608c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2618c2bf45dSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t);
262790e10f6SSaleem Abdulrasool
2638c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2648c2bf45dSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t);
265790e10f6SSaleem Abdulrasool
2668c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2678c2bf45dSAsiri Rathnayakevoid __libcpp_thread_yield();
2688c2bf45dSAsiri Rathnayake
26954a987e1SAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2709e8a082dSJoerg Sonnenbergervoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
27154a987e1SAsiri Rathnayake
2728c2bf45dSAsiri Rathnayake// Thread local storage
2738c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2746d7d0becSSaleem Abdulrasoolint __libcpp_tls_create(__libcpp_tls_key* __key,
2756d7d0becSSaleem Abdulrasool                        void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
276790e10f6SSaleem Abdulrasool
2778c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
2788c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key);
279790e10f6SSaleem Abdulrasool
2808c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
281205d7d3fSAsiri Rathnayakeint __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
2828c2bf45dSAsiri Rathnayake
283e2b200b7SDavid Spickett#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
284e2b200b7SDavid Spickett
28514aef536SMikhail Maltsevstruct __libcpp_timed_backoff_policy {
28621a1a263SLouis Dionne  _LIBCPP_INLINE_VISIBILITY
28721a1a263SLouis Dionne  bool operator()(chrono::nanoseconds __elapsed) const
2883411a1a9SDavid Nicuesa  {
2893411a1a9SDavid Nicuesa      if(__elapsed > chrono::milliseconds(128))
2903411a1a9SDavid Nicuesa          __libcpp_thread_sleep_for(chrono::milliseconds(8));
2913411a1a9SDavid Nicuesa      else if(__elapsed > chrono::microseconds(64))
2923411a1a9SDavid Nicuesa          __libcpp_thread_sleep_for(__elapsed / 2);
2933411a1a9SDavid Nicuesa      else if(__elapsed > chrono::microseconds(4))
2943411a1a9SDavid Nicuesa        __libcpp_thread_yield();
2953411a1a9SDavid Nicuesa      else
296*d2acf229SMarek Kurdej        {} // poll
2973411a1a9SDavid Nicuesa      return false;
2983411a1a9SDavid Nicuesa  }
29921a1a263SLouis Dionne};
3003411a1a9SDavid Nicuesa
3013411a1a9SDavid Nicuesastatic _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64;
3023411a1a9SDavid Nicuesa
30314aef536SMikhail Maltsevtemplate<class _Fn, class _BFn>
30446c38761SLouis Dionne_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
30514aef536SMikhail Maltsevbool __libcpp_thread_poll_with_backoff(
3063411a1a9SDavid Nicuesa  _Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero())
3073411a1a9SDavid Nicuesa{
3083411a1a9SDavid Nicuesa    auto const __start = chrono::high_resolution_clock::now();
3093411a1a9SDavid Nicuesa    for(int __count = 0;;) {
3103411a1a9SDavid Nicuesa      if(__f())
3113411a1a9SDavid Nicuesa        return true; // _Fn completion means success
3123411a1a9SDavid Nicuesa      if(__count < __libcpp_polling_count) {
3133411a1a9SDavid Nicuesa        __count += 1;
3143411a1a9SDavid Nicuesa        continue;
3153411a1a9SDavid Nicuesa      }
3163411a1a9SDavid Nicuesa      chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start;
3173411a1a9SDavid Nicuesa      if(__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed)
3183411a1a9SDavid Nicuesa          return false; // timeout failure
3193411a1a9SDavid Nicuesa      if(__bf(__elapsed))
3203411a1a9SDavid Nicuesa        return false; // _BFn completion means failure
3213411a1a9SDavid Nicuesa    }
3223411a1a9SDavid Nicuesa}
3233411a1a9SDavid Nicuesa
3243411a1a9SDavid Nicuesa#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
3253411a1a9SDavid Nicuesa     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL))
3263411a1a9SDavid Nicuesa
32714aef536SMikhail Maltsev
328ab9aefeeSPetr Hoseknamespace __thread_detail {
329ab9aefeeSPetr Hosek
330ab9aefeeSPetr Hosekinline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns)
331ab9aefeeSPetr Hosek{
332ab9aefeeSPetr Hosek  using namespace chrono;
333ab9aefeeSPetr Hosek  seconds __s = duration_cast<seconds>(__ns);
334ab9aefeeSPetr Hosek  __libcpp_timespec_t __ts;
335ab9aefeeSPetr Hosek  typedef decltype(__ts.tv_sec) __ts_sec;
336ab9aefeeSPetr Hosek  const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
337ab9aefeeSPetr Hosek
338ab9aefeeSPetr Hosek  if (__s.count() < __ts_sec_max)
339ab9aefeeSPetr Hosek  {
340ab9aefeeSPetr Hosek    __ts.tv_sec = static_cast<__ts_sec>(__s.count());
341ab9aefeeSPetr Hosek    __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
342ab9aefeeSPetr Hosek  }
343ab9aefeeSPetr Hosek  else
344ab9aefeeSPetr Hosek  {
345ab9aefeeSPetr Hosek    __ts.tv_sec = __ts_sec_max;
346ab9aefeeSPetr Hosek    __ts.tv_nsec = 999999999; // (10^9 - 1)
347ab9aefeeSPetr Hosek  }
348ab9aefeeSPetr Hosek
349ab9aefeeSPetr Hosek  return __ts;
350ab9aefeeSPetr Hosek}
351ab9aefeeSPetr Hosek
352ab9aefeeSPetr Hosek}
353ab9aefeeSPetr Hosek
354ab9aefeeSPetr Hosek#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
3558c2bf45dSAsiri Rathnayake
35658a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
357c7e4239fSAsiri Rathnayake{
358c7e4239fSAsiri Rathnayake  pthread_mutexattr_t attr;
359c7e4239fSAsiri Rathnayake  int __ec = pthread_mutexattr_init(&attr);
360c7e4239fSAsiri Rathnayake  if (__ec)
361790e10f6SSaleem Abdulrasool    return __ec;
362790e10f6SSaleem Abdulrasool  __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
363790e10f6SSaleem Abdulrasool  if (__ec) {
364c7e4239fSAsiri Rathnayake    pthread_mutexattr_destroy(&attr);
365c7e4239fSAsiri Rathnayake    return __ec;
366c7e4239fSAsiri Rathnayake  }
367c7e4239fSAsiri Rathnayake  __ec = pthread_mutex_init(__m, &attr);
368790e10f6SSaleem Abdulrasool  if (__ec) {
369c7e4239fSAsiri Rathnayake    pthread_mutexattr_destroy(&attr);
370c7e4239fSAsiri Rathnayake    return __ec;
371c7e4239fSAsiri Rathnayake  }
372c7e4239fSAsiri Rathnayake  __ec = pthread_mutexattr_destroy(&attr);
373790e10f6SSaleem Abdulrasool  if (__ec) {
374c7e4239fSAsiri Rathnayake    pthread_mutex_destroy(__m);
375c7e4239fSAsiri Rathnayake    return __ec;
376c7e4239fSAsiri Rathnayake  }
377c7e4239fSAsiri Rathnayake  return 0;
378c7e4239fSAsiri Rathnayake}
379c7e4239fSAsiri Rathnayake
38058a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
38158a0dceeSSaleem Abdulrasool{
38258a0dceeSSaleem Abdulrasool  return pthread_mutex_lock(__m);
38358a0dceeSSaleem Abdulrasool}
38458a0dceeSSaleem Abdulrasool
38508e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
38658a0dceeSSaleem Abdulrasool{
38708e1477cSEric Fiselier  return pthread_mutex_trylock(__m) == 0;
38858a0dceeSSaleem Abdulrasool}
38958a0dceeSSaleem Abdulrasool
39058a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
39158a0dceeSSaleem Abdulrasool{
39258a0dceeSSaleem Abdulrasool  return pthread_mutex_unlock(__m);
39358a0dceeSSaleem Abdulrasool}
39458a0dceeSSaleem Abdulrasool
39558a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
39658a0dceeSSaleem Abdulrasool{
39758a0dceeSSaleem Abdulrasool  return pthread_mutex_destroy(__m);
39858a0dceeSSaleem Abdulrasool}
39958a0dceeSSaleem Abdulrasool
400c7e4239fSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m)
401c7e4239fSAsiri Rathnayake{
402c7e4239fSAsiri Rathnayake  return pthread_mutex_lock(__m);
403c7e4239fSAsiri Rathnayake}
404c7e4239fSAsiri Rathnayake
40508e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
406c7e4239fSAsiri Rathnayake{
40708e1477cSEric Fiselier  return pthread_mutex_trylock(__m) == 0;
408c7e4239fSAsiri Rathnayake}
409c7e4239fSAsiri Rathnayake
410c7e4239fSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
411c7e4239fSAsiri Rathnayake{
412c7e4239fSAsiri Rathnayake  return pthread_mutex_unlock(__m);
413c7e4239fSAsiri Rathnayake}
414c7e4239fSAsiri Rathnayake
415c7e4239fSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
416c7e4239fSAsiri Rathnayake{
417c7e4239fSAsiri Rathnayake  return pthread_mutex_destroy(__m);
418c7e4239fSAsiri Rathnayake}
419c7e4239fSAsiri Rathnayake
420790e10f6SSaleem Abdulrasool// Condition Variable
421c7e4239fSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
422c7e4239fSAsiri Rathnayake{
423c7e4239fSAsiri Rathnayake  return pthread_cond_signal(__cv);
424c7e4239fSAsiri Rathnayake}
425c7e4239fSAsiri Rathnayake
426c7e4239fSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
427c7e4239fSAsiri Rathnayake{
428c7e4239fSAsiri Rathnayake  return pthread_cond_broadcast(__cv);
429c7e4239fSAsiri Rathnayake}
430c7e4239fSAsiri Rathnayake
431c7e4239fSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
432c7e4239fSAsiri Rathnayake{
433c7e4239fSAsiri Rathnayake  return pthread_cond_wait(__cv, __m);
434c7e4239fSAsiri Rathnayake}
435c7e4239fSAsiri Rathnayake
436790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
437cfdc7f0dSMikhail Maltsev                               __libcpp_timespec_t *__ts)
438c7e4239fSAsiri Rathnayake{
439c7e4239fSAsiri Rathnayake  return pthread_cond_timedwait(__cv, __m, __ts);
440c7e4239fSAsiri Rathnayake}
441c7e4239fSAsiri Rathnayake
442c7e4239fSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
443c7e4239fSAsiri Rathnayake{
444c7e4239fSAsiri Rathnayake  return pthread_cond_destroy(__cv);
445c7e4239fSAsiri Rathnayake}
446c7e4239fSAsiri Rathnayake
44754fa9ecdSOlivier Giroux#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
44854fa9ecdSOlivier Giroux
44954fa9ecdSOlivier Giroux// Semaphore
45054fa9ecdSOlivier Girouxbool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init)
45154fa9ecdSOlivier Giroux{
45254fa9ecdSOlivier Giroux    return sem_init(__sem, 0, __init) == 0;
45354fa9ecdSOlivier Giroux}
45454fa9ecdSOlivier Giroux
45554fa9ecdSOlivier Girouxbool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem)
45654fa9ecdSOlivier Giroux{
45754fa9ecdSOlivier Giroux    return sem_destroy(__sem) == 0;
45854fa9ecdSOlivier Giroux}
45954fa9ecdSOlivier Giroux
46054fa9ecdSOlivier Girouxbool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem)
46154fa9ecdSOlivier Giroux{
46254fa9ecdSOlivier Giroux    return sem_post(__sem) == 0;
46354fa9ecdSOlivier Giroux}
46454fa9ecdSOlivier Giroux
46554fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem)
46654fa9ecdSOlivier Giroux{
46754fa9ecdSOlivier Giroux    return sem_wait(__sem) == 0;
46854fa9ecdSOlivier Giroux}
46954fa9ecdSOlivier Giroux
47054fa9ecdSOlivier Girouxbool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns)
47154fa9ecdSOlivier Giroux{
47254fa9ecdSOlivier Giroux    auto const __abs_time = chrono::system_clock::now().time_since_epoch() + __ns;
47354fa9ecdSOlivier Giroux    __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__abs_time);
47454fa9ecdSOlivier Giroux    return sem_timedwait(__sem, &__ts) == 0;
47554fa9ecdSOlivier Giroux}
47654fa9ecdSOlivier Giroux
47754fa9ecdSOlivier Giroux#endif //_LIBCPP_NO_NATIVE_SEMAPHORES
47854fa9ecdSOlivier Giroux
479205d7d3fSAsiri Rathnayake// Execute once
480205d7d3fSAsiri Rathnayakeint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
4814603460aSBruce Mitchener                          void (*init_routine)()) {
482205d7d3fSAsiri Rathnayake  return pthread_once(flag, init_routine);
483205d7d3fSAsiri Rathnayake}
484205d7d3fSAsiri Rathnayake
485205d7d3fSAsiri Rathnayake// Thread id
486c7e4239fSAsiri Rathnayake// Returns non-zero if the thread ids are equal, otherwise 0
487c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
488c7e4239fSAsiri Rathnayake{
489c7e4239fSAsiri Rathnayake  return pthread_equal(t1, t2) != 0;
490c7e4239fSAsiri Rathnayake}
491c7e4239fSAsiri Rathnayake
492c7e4239fSAsiri Rathnayake// Returns non-zero if t1 < t2, otherwise 0
493c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
494c7e4239fSAsiri Rathnayake{
495c7e4239fSAsiri Rathnayake  return t1 < t2;
496c7e4239fSAsiri Rathnayake}
497c7e4239fSAsiri Rathnayake
498c7e4239fSAsiri Rathnayake// Thread
499af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
500af762e91SAsiri Rathnayake  return *__t == 0;
501af762e91SAsiri Rathnayake}
502af762e91SAsiri Rathnayake
503790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
504790e10f6SSaleem Abdulrasool                           void *__arg)
505c7e4239fSAsiri Rathnayake{
506c7e4239fSAsiri Rathnayake  return pthread_create(__t, 0, __func, __arg);
507c7e4239fSAsiri Rathnayake}
508c7e4239fSAsiri Rathnayake
509c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id()
510c7e4239fSAsiri Rathnayake{
511c7e4239fSAsiri Rathnayake  return pthread_self();
512c7e4239fSAsiri Rathnayake}
513c7e4239fSAsiri Rathnayake
514c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
515c7e4239fSAsiri Rathnayake{
516c7e4239fSAsiri Rathnayake  return *__t;
517c7e4239fSAsiri Rathnayake}
518c7e4239fSAsiri Rathnayake
519c7e4239fSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t)
520c7e4239fSAsiri Rathnayake{
521c7e4239fSAsiri Rathnayake  return pthread_join(*__t, 0);
522c7e4239fSAsiri Rathnayake}
523c7e4239fSAsiri Rathnayake
524c7e4239fSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t)
525c7e4239fSAsiri Rathnayake{
526c7e4239fSAsiri Rathnayake  return pthread_detach(*__t);
527c7e4239fSAsiri Rathnayake}
528c7e4239fSAsiri Rathnayake
529c7e4239fSAsiri Rathnayakevoid __libcpp_thread_yield()
530c7e4239fSAsiri Rathnayake{
531c7e4239fSAsiri Rathnayake  sched_yield();
532c7e4239fSAsiri Rathnayake}
533c7e4239fSAsiri Rathnayake
53454a987e1SAsiri Rathnayakevoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
53554a987e1SAsiri Rathnayake{
536ab9aefeeSPetr Hosek   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
53754a987e1SAsiri Rathnayake   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
53854a987e1SAsiri Rathnayake}
53954a987e1SAsiri Rathnayake
540c7e4239fSAsiri Rathnayake// Thread local storage
5418c2bf45dSAsiri Rathnayakeint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
542c7e4239fSAsiri Rathnayake{
543c7e4239fSAsiri Rathnayake  return pthread_key_create(__key, __at_exit);
544c7e4239fSAsiri Rathnayake}
545c7e4239fSAsiri Rathnayake
5468c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key)
547c7e4239fSAsiri Rathnayake{
548c7e4239fSAsiri Rathnayake  return pthread_getspecific(__key);
549c7e4239fSAsiri Rathnayake}
550c7e4239fSAsiri Rathnayake
551205d7d3fSAsiri Rathnayakeint __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
552c7e4239fSAsiri Rathnayake{
553205d7d3fSAsiri Rathnayake    return pthread_setspecific(__key, __p);
554c7e4239fSAsiri Rathnayake}
555c7e4239fSAsiri Rathnayake
556ab9aefeeSPetr Hosek#elif defined(_LIBCPP_HAS_THREAD_API_C11)
557ab9aefeeSPetr Hosek
558ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
559ab9aefeeSPetr Hosek{
5603481e5d7SPetr Hosek  return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
561ab9aefeeSPetr Hosek}
562ab9aefeeSPetr Hosek
563ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
564ab9aefeeSPetr Hosek{
565ab9aefeeSPetr Hosek  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
566ab9aefeeSPetr Hosek}
567ab9aefeeSPetr Hosek
568ab9aefeeSPetr Hosekbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
569ab9aefeeSPetr Hosek{
570ab9aefeeSPetr Hosek  return mtx_trylock(__m) == thrd_success;
571ab9aefeeSPetr Hosek}
572ab9aefeeSPetr Hosek
573ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
574ab9aefeeSPetr Hosek{
575ab9aefeeSPetr Hosek  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
576ab9aefeeSPetr Hosek}
577ab9aefeeSPetr Hosek
578ab9aefeeSPetr Hosekint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
579ab9aefeeSPetr Hosek{
580ab9aefeeSPetr Hosek  mtx_destroy(__m);
581ab9aefeeSPetr Hosek  return 0;
582ab9aefeeSPetr Hosek}
583ab9aefeeSPetr Hosek
584ab9aefeeSPetr Hosekint __libcpp_mutex_lock(__libcpp_mutex_t *__m)
585ab9aefeeSPetr Hosek{
586ab9aefeeSPetr Hosek  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
587ab9aefeeSPetr Hosek}
588ab9aefeeSPetr Hosek
589ab9aefeeSPetr Hosekbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
590ab9aefeeSPetr Hosek{
591ab9aefeeSPetr Hosek  return mtx_trylock(__m) == thrd_success;
592ab9aefeeSPetr Hosek}
593ab9aefeeSPetr Hosek
594ab9aefeeSPetr Hosekint __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
595ab9aefeeSPetr Hosek{
596ab9aefeeSPetr Hosek  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
597ab9aefeeSPetr Hosek}
598ab9aefeeSPetr Hosek
599ab9aefeeSPetr Hosekint __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
600ab9aefeeSPetr Hosek{
601ab9aefeeSPetr Hosek  mtx_destroy(__m);
602ab9aefeeSPetr Hosek  return 0;
603ab9aefeeSPetr Hosek}
604ab9aefeeSPetr Hosek
605ab9aefeeSPetr Hosek// Condition Variable
606ab9aefeeSPetr Hosekint __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
607ab9aefeeSPetr Hosek{
608ab9aefeeSPetr Hosek  return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
609ab9aefeeSPetr Hosek}
610ab9aefeeSPetr Hosek
611ab9aefeeSPetr Hosekint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
612ab9aefeeSPetr Hosek{
613ab9aefeeSPetr Hosek  return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
614ab9aefeeSPetr Hosek}
615ab9aefeeSPetr Hosek
616ab9aefeeSPetr Hosekint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
617ab9aefeeSPetr Hosek{
618ab9aefeeSPetr Hosek  return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
619ab9aefeeSPetr Hosek}
620ab9aefeeSPetr Hosek
621ab9aefeeSPetr Hosekint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
622ab9aefeeSPetr Hosek                               timespec *__ts)
623ab9aefeeSPetr Hosek{
624ab9aefeeSPetr Hosek  int __ec = cnd_timedwait(__cv, __m, __ts);
625ab9aefeeSPetr Hosek  return __ec == thrd_timedout ? ETIMEDOUT : __ec;
626ab9aefeeSPetr Hosek}
627ab9aefeeSPetr Hosek
628ab9aefeeSPetr Hosekint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
629ab9aefeeSPetr Hosek{
630ab9aefeeSPetr Hosek  cnd_destroy(__cv);
631ab9aefeeSPetr Hosek  return 0;
632ab9aefeeSPetr Hosek}
633ab9aefeeSPetr Hosek
634ab9aefeeSPetr Hosek// Execute once
635ab9aefeeSPetr Hosekint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
636ab9aefeeSPetr Hosek                          void (*init_routine)(void)) {
637ab9aefeeSPetr Hosek  ::call_once(flag, init_routine);
638ab9aefeeSPetr Hosek  return 0;
639ab9aefeeSPetr Hosek}
640ab9aefeeSPetr Hosek
641ab9aefeeSPetr Hosek// Thread id
642ab9aefeeSPetr Hosek// Returns non-zero if the thread ids are equal, otherwise 0
643ab9aefeeSPetr Hosekbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
644ab9aefeeSPetr Hosek{
645ab9aefeeSPetr Hosek  return thrd_equal(t1, t2) != 0;
646ab9aefeeSPetr Hosek}
647ab9aefeeSPetr Hosek
648ab9aefeeSPetr Hosek// Returns non-zero if t1 < t2, otherwise 0
649ab9aefeeSPetr Hosekbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
650ab9aefeeSPetr Hosek{
651ab9aefeeSPetr Hosek  return t1 < t2;
652ab9aefeeSPetr Hosek}
653ab9aefeeSPetr Hosek
654ab9aefeeSPetr Hosek// Thread
655ab9aefeeSPetr Hosekbool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
656ab9aefeeSPetr Hosek  return *__t == 0;
657ab9aefeeSPetr Hosek}
658ab9aefeeSPetr Hosek
659ab9aefeeSPetr Hosekint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
660ab9aefeeSPetr Hosek                           void *__arg)
661ab9aefeeSPetr Hosek{
662ab9aefeeSPetr Hosek  int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
663ab9aefeeSPetr Hosek  return __ec == thrd_nomem ? ENOMEM : __ec;
664ab9aefeeSPetr Hosek}
665ab9aefeeSPetr Hosek
666ab9aefeeSPetr Hosek__libcpp_thread_id __libcpp_thread_get_current_id()
667ab9aefeeSPetr Hosek{
668ab9aefeeSPetr Hosek  return thrd_current();
669ab9aefeeSPetr Hosek}
670ab9aefeeSPetr Hosek
671ab9aefeeSPetr Hosek__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
672ab9aefeeSPetr Hosek{
673ab9aefeeSPetr Hosek  return *__t;
674ab9aefeeSPetr Hosek}
675ab9aefeeSPetr Hosek
676ab9aefeeSPetr Hosekint __libcpp_thread_join(__libcpp_thread_t *__t)
677ab9aefeeSPetr Hosek{
678ab9aefeeSPetr Hosek  return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
679ab9aefeeSPetr Hosek}
680ab9aefeeSPetr Hosek
681ab9aefeeSPetr Hosekint __libcpp_thread_detach(__libcpp_thread_t *__t)
682ab9aefeeSPetr Hosek{
683ab9aefeeSPetr Hosek  return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
684ab9aefeeSPetr Hosek}
685ab9aefeeSPetr Hosek
686ab9aefeeSPetr Hosekvoid __libcpp_thread_yield()
687ab9aefeeSPetr Hosek{
688ab9aefeeSPetr Hosek  thrd_yield();
689ab9aefeeSPetr Hosek}
690ab9aefeeSPetr Hosek
691ab9aefeeSPetr Hosekvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
692ab9aefeeSPetr Hosek{
693ab9aefeeSPetr Hosek   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
694ab9aefeeSPetr Hosek  thrd_sleep(&__ts, nullptr);
695ab9aefeeSPetr Hosek}
696ab9aefeeSPetr Hosek
697ab9aefeeSPetr Hosek// Thread local storage
698ab9aefeeSPetr Hosekint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
699ab9aefeeSPetr Hosek{
700ab9aefeeSPetr Hosek  return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
701ab9aefeeSPetr Hosek}
702ab9aefeeSPetr Hosek
703ab9aefeeSPetr Hosekvoid *__libcpp_tls_get(__libcpp_tls_key __key)
704ab9aefeeSPetr Hosek{
705ab9aefeeSPetr Hosek  return tss_get(__key);
706ab9aefeeSPetr Hosek}
707ab9aefeeSPetr Hosek
708ab9aefeeSPetr Hosekint __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
709ab9aefeeSPetr Hosek{
710ab9aefeeSPetr Hosek  return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
711ab9aefeeSPetr Hosek}
712ab9aefeeSPetr Hosek
713ab9aefeeSPetr Hosek#endif
714ab9aefeeSPetr Hosek
715e3add3e5SMartin Storsjö
71600f6beaeSEric Fiselier#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
71700f6beaeSEric Fiselier
7182b1d4254SMarshall Clowclass _LIBCPP_TYPE_VIS thread;
7192b1d4254SMarshall Clowclass _LIBCPP_TYPE_VIS __thread_id;
7202b1d4254SMarshall Clow
7212b1d4254SMarshall Clownamespace this_thread
7222b1d4254SMarshall Clow{
7232b1d4254SMarshall Clow
7242b1d4254SMarshall Clow_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
7252b1d4254SMarshall Clow
7262b1d4254SMarshall Clow}  // this_thread
7272b1d4254SMarshall Clow
7282b1d4254SMarshall Clowtemplate<> struct hash<__thread_id>;
7292b1d4254SMarshall Clow
7302b1d4254SMarshall Clowclass _LIBCPP_TEMPLATE_VIS __thread_id
7312b1d4254SMarshall Clow{
7322b1d4254SMarshall Clow    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
7332b1d4254SMarshall Clow    // NULL is the no-thread value on Darwin.  Someone needs to check
7342b1d4254SMarshall Clow    // on other platforms.  We assume 0 works everywhere for now.
7352b1d4254SMarshall Clow    __libcpp_thread_id __id_;
7362b1d4254SMarshall Clow
7372b1d4254SMarshall Clowpublic:
7382b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
7392b1d4254SMarshall Clow    __thread_id() _NOEXCEPT : __id_(0) {}
7402b1d4254SMarshall Clow
7412b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7422b1d4254SMarshall Clow        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
7432e80d01fSMarshall Clow        { // don't pass id==0 to underlying routines
7442e80d01fSMarshall Clow        if (__x.__id_ == 0) return __y.__id_ == 0;
7452e80d01fSMarshall Clow        if (__y.__id_ == 0) return false;
7462e80d01fSMarshall Clow        return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
7472e80d01fSMarshall Clow        }
7482b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7492b1d4254SMarshall Clow        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
7502b1d4254SMarshall Clow        {return !(__x == __y);}
7512b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7522b1d4254SMarshall Clow        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
7532e80d01fSMarshall Clow        { // id==0 is always less than any other thread_id
7542e80d01fSMarshall Clow        if (__x.__id_ == 0) return __y.__id_ != 0;
7552e80d01fSMarshall Clow        if (__y.__id_ == 0) return false;
7562e80d01fSMarshall Clow        return  __libcpp_thread_id_less(__x.__id_, __y.__id_);
7572e80d01fSMarshall Clow        }
7582b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7592b1d4254SMarshall Clow        bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
7602b1d4254SMarshall Clow        {return !(__y < __x);}
7612b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7622b1d4254SMarshall Clow        bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
7632b1d4254SMarshall Clow        {return   __y < __x ;}
7642b1d4254SMarshall Clow    friend _LIBCPP_INLINE_VISIBILITY
7652b1d4254SMarshall Clow        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
7662b1d4254SMarshall Clow        {return !(__x < __y);}
7672b1d4254SMarshall Clow
7682b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
7692e80d01fSMarshall Clow    void __reset() { __id_ = 0; }
7702b1d4254SMarshall Clow
7712b1d4254SMarshall Clow    template<class _CharT, class _Traits>
7722b1d4254SMarshall Clow    friend
7732b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
7742b1d4254SMarshall Clow    basic_ostream<_CharT, _Traits>&
7752b1d4254SMarshall Clow    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
7762b1d4254SMarshall Clow
7772b1d4254SMarshall Clowprivate:
7782b1d4254SMarshall Clow    _LIBCPP_INLINE_VISIBILITY
7792b1d4254SMarshall Clow    __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
7802b1d4254SMarshall Clow
7812b1d4254SMarshall Clow    friend __thread_id this_thread::get_id() _NOEXCEPT;
7822b1d4254SMarshall Clow    friend class _LIBCPP_TYPE_VIS thread;
7832b1d4254SMarshall Clow    friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
7842b1d4254SMarshall Clow};
7852b1d4254SMarshall Clow
7862b1d4254SMarshall Clownamespace this_thread
7872b1d4254SMarshall Clow{
7882b1d4254SMarshall Clow
7892b1d4254SMarshall Clowinline _LIBCPP_INLINE_VISIBILITY
7902b1d4254SMarshall Clow__thread_id
7912b1d4254SMarshall Clowget_id() _NOEXCEPT
7922b1d4254SMarshall Clow{
7932b1d4254SMarshall Clow    return __libcpp_thread_get_current_id();
7942b1d4254SMarshall Clow}
7952b1d4254SMarshall Clow
7962b1d4254SMarshall Clow}  // this_thread
7972b1d4254SMarshall Clow
798696630eaSMarshall Clow#endif // !_LIBCPP_HAS_NO_THREADS
799696630eaSMarshall Clow
800c7e4239fSAsiri Rathnayake_LIBCPP_END_NAMESPACE_STD
801c7e4239fSAsiri Rathnayake
802a016efb1SEric Fiselier_LIBCPP_POP_MACROS
803a016efb1SEric Fiselier
804c7e4239fSAsiri Rathnayake#endif // _LIBCPP_THREADING_SUPPORT
805