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