17c82a1ecSDimitry Andric// -*- C++ -*-
27c82a1ecSDimitry Andric//===----------------------------------------------------------------------===//
37c82a1ecSDimitry Andric//
47c82a1ecSDimitry Andric//                     The LLVM Compiler Infrastructure
57c82a1ecSDimitry Andric//
67c82a1ecSDimitry Andric// This file is dual licensed under the MIT and the University of Illinois Open
77c82a1ecSDimitry Andric// Source Licenses. See LICENSE.TXT for details.
87c82a1ecSDimitry Andric//
97c82a1ecSDimitry Andric//===----------------------------------------------------------------------===//
107c82a1ecSDimitry Andric
117c82a1ecSDimitry Andric#ifndef _LIBCPP_THREADING_SUPPORT
127c82a1ecSDimitry Andric#define _LIBCPP_THREADING_SUPPORT
137c82a1ecSDimitry Andric
147c82a1ecSDimitry Andric#include <__config>
15540d2a8bSDimitry Andric#include <chrono>
16*4173b67fSDimitry Andric#include <iosfwd>
17540d2a8bSDimitry Andric#include <errno.h>
187c82a1ecSDimitry Andric
197c82a1ecSDimitry Andric#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
207c82a1ecSDimitry Andric#pragma GCC system_header
217c82a1ecSDimitry Andric#endif
227c82a1ecSDimitry Andric
2380779b37SDimitry Andric#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
24aed8d94eSDimitry Andric# include <__external_threading>
2580779b37SDimitry Andric#elif !defined(_LIBCPP_HAS_NO_THREADS)
26aed8d94eSDimitry Andric
2780779b37SDimitry Andric#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
287c82a1ecSDimitry Andric# include <pthread.h>
297c82a1ecSDimitry Andric# include <sched.h>
307c82a1ecSDimitry Andric#endif
317c82a1ecSDimitry Andric
32f9448bf3SDimitry Andric_LIBCPP_PUSH_MACROS
33f9448bf3SDimitry Andric#include <__undef_macros>
34f9448bf3SDimitry Andric
3580779b37SDimitry Andric#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
364ba319b5SDimitry Andric    defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \
374ba319b5SDimitry Andric    defined(_LIBCPP_HAS_THREAD_API_WIN32)
38aed8d94eSDimitry Andric#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
39aed8d94eSDimitry Andric#else
40aed8d94eSDimitry Andric#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
41aed8d94eSDimitry Andric#endif
42aed8d94eSDimitry Andric
4398221d2eSDimitry Andric#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
4498221d2eSDimitry Andric#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
4598221d2eSDimitry Andric#else
4698221d2eSDimitry Andric#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
4798221d2eSDimitry Andric#endif
4898221d2eSDimitry Andric
497c82a1ecSDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
507c82a1ecSDimitry Andric
5180779b37SDimitry Andric#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
52aed8d94eSDimitry Andric// Mutex
53aed8d94eSDimitry Andrictypedef pthread_mutex_t __libcpp_mutex_t;
54aed8d94eSDimitry Andric#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
55aed8d94eSDimitry Andric
56aed8d94eSDimitry Andrictypedef pthread_mutex_t __libcpp_recursive_mutex_t;
57aed8d94eSDimitry Andric
58aed8d94eSDimitry Andric// Condition Variable
59aed8d94eSDimitry Andrictypedef pthread_cond_t __libcpp_condvar_t;
60aed8d94eSDimitry Andric#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
61aed8d94eSDimitry Andric
62aed8d94eSDimitry Andric// Execute once
63aed8d94eSDimitry Andrictypedef pthread_once_t __libcpp_exec_once_flag;
64aed8d94eSDimitry Andric#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
65aed8d94eSDimitry Andric
66aed8d94eSDimitry Andric// Thread id
67aed8d94eSDimitry Andrictypedef pthread_t __libcpp_thread_id;
68aed8d94eSDimitry Andric
69aed8d94eSDimitry Andric// Thread
70540d2a8bSDimitry Andric#define _LIBCPP_NULL_THREAD 0U
71540d2a8bSDimitry Andric
72aed8d94eSDimitry Andrictypedef pthread_t __libcpp_thread_t;
73aed8d94eSDimitry Andric
74b5893f02SDimitry Andric// Thread Local Storage
75aed8d94eSDimitry Andrictypedef pthread_key_t __libcpp_tls_key;
7680779b37SDimitry Andric
7780779b37SDimitry Andric#define _LIBCPP_TLS_DESTRUCTOR_CC
7880779b37SDimitry Andric#else
7980779b37SDimitry Andric// Mutex
804ba319b5SDimitry Andrictypedef void* __libcpp_mutex_t;
814ba319b5SDimitry Andric#define _LIBCPP_MUTEX_INITIALIZER 0
8280779b37SDimitry Andric
834ba319b5SDimitry Andric#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
844ba319b5SDimitry Andrictypedef void* __libcpp_recursive_mutex_t[6];
854ba319b5SDimitry Andric#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
864ba319b5SDimitry Andrictypedef void* __libcpp_recursive_mutex_t[5];
874ba319b5SDimitry Andric#else
884ba319b5SDimitry Andric# error Unsupported architecture
894ba319b5SDimitry Andric#endif
9080779b37SDimitry Andric
9180779b37SDimitry Andric// Condition Variable
924ba319b5SDimitry Andrictypedef void* __libcpp_condvar_t;
934ba319b5SDimitry Andric#define _LIBCPP_CONDVAR_INITIALIZER 0
9480779b37SDimitry Andric
9580779b37SDimitry Andric// Execute Once
964ba319b5SDimitry Andrictypedef void* __libcpp_exec_once_flag;
974ba319b5SDimitry Andric#define _LIBCPP_EXEC_ONCE_INITIALIZER 0
9880779b37SDimitry Andric
9980779b37SDimitry Andric// Thread ID
1004ba319b5SDimitry Andrictypedef long __libcpp_thread_id;
10180779b37SDimitry Andric
10280779b37SDimitry Andric// Thread
103540d2a8bSDimitry Andric#define _LIBCPP_NULL_THREAD 0U
104540d2a8bSDimitry Andric
1054ba319b5SDimitry Andrictypedef void* __libcpp_thread_t;
10680779b37SDimitry Andric
10780779b37SDimitry Andric// Thread Local Storage
1084ba319b5SDimitry Andrictypedef long __libcpp_tls_key;
10980779b37SDimitry Andric
1104ba319b5SDimitry Andric#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
111aed8d94eSDimitry Andric#endif
1127c82a1ecSDimitry Andric
1137c82a1ecSDimitry Andric// Mutex
114aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
115aed8d94eSDimitry Andricint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
1167c82a1ecSDimitry Andric
11798221d2eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
118aed8d94eSDimitry Andricint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
119aed8d94eSDimitry Andric
12098221d2eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
121540d2a8bSDimitry Andricbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
122aed8d94eSDimitry Andric
12398221d2eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
124aed8d94eSDimitry Andricint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
125aed8d94eSDimitry Andric
126aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
127aed8d94eSDimitry Andricint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
128aed8d94eSDimitry Andric
12998221d2eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
130aed8d94eSDimitry Andricint __libcpp_mutex_lock(__libcpp_mutex_t *__m);
131aed8d94eSDimitry Andric
13298221d2eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
133540d2a8bSDimitry Andricbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
134aed8d94eSDimitry Andric
13598221d2eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
136aed8d94eSDimitry Andricint __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
137aed8d94eSDimitry Andric
138aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
139aed8d94eSDimitry Andricint __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
140aed8d94eSDimitry Andric
141aed8d94eSDimitry Andric// Condition variable
142aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
143aed8d94eSDimitry Andricint __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
144aed8d94eSDimitry Andric
145aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
146aed8d94eSDimitry Andricint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
147aed8d94eSDimitry Andric
14898221d2eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
149aed8d94eSDimitry Andricint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
150aed8d94eSDimitry Andric
15198221d2eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
152aed8d94eSDimitry Andricint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
153aed8d94eSDimitry Andric                               timespec *__ts);
154aed8d94eSDimitry Andric
155aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
156aed8d94eSDimitry Andricint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
157aed8d94eSDimitry Andric
158aed8d94eSDimitry Andric// Execute once
159aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
160aed8d94eSDimitry Andricint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
161aed8d94eSDimitry Andric                          void (*init_routine)(void));
162aed8d94eSDimitry Andric
163aed8d94eSDimitry Andric// Thread id
164aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
165aed8d94eSDimitry Andricbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
166aed8d94eSDimitry Andric
167aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
168aed8d94eSDimitry Andricbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
169aed8d94eSDimitry Andric
170aed8d94eSDimitry Andric// Thread
171aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
172540d2a8bSDimitry Andricbool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
173540d2a8bSDimitry Andric
174540d2a8bSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
175aed8d94eSDimitry Andricint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
176aed8d94eSDimitry Andric                           void *__arg);
177aed8d94eSDimitry Andric
178aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
179aed8d94eSDimitry Andric__libcpp_thread_id __libcpp_thread_get_current_id();
180aed8d94eSDimitry Andric
181aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
182aed8d94eSDimitry Andric__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
183aed8d94eSDimitry Andric
184aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
185aed8d94eSDimitry Andricint __libcpp_thread_join(__libcpp_thread_t *__t);
186aed8d94eSDimitry Andric
187aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
188aed8d94eSDimitry Andricint __libcpp_thread_detach(__libcpp_thread_t *__t);
189aed8d94eSDimitry Andric
190aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
191aed8d94eSDimitry Andricvoid __libcpp_thread_yield();
192aed8d94eSDimitry Andric
193540d2a8bSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
194540d2a8bSDimitry Andricvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
195540d2a8bSDimitry Andric
196aed8d94eSDimitry Andric// Thread local storage
197aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
19880779b37SDimitry Andricint __libcpp_tls_create(__libcpp_tls_key* __key,
19980779b37SDimitry Andric                        void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
200aed8d94eSDimitry Andric
201aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
202aed8d94eSDimitry Andricvoid *__libcpp_tls_get(__libcpp_tls_key __key);
203aed8d94eSDimitry Andric
204aed8d94eSDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY
205aed8d94eSDimitry Andricint __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
206aed8d94eSDimitry Andric
2074ba319b5SDimitry Andric#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
2084ba319b5SDimitry Andric     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \
2094ba319b5SDimitry Andric    defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
210aed8d94eSDimitry Andric
211aed8d94eSDimitry Andricint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
2127c82a1ecSDimitry Andric{
2137c82a1ecSDimitry Andric  pthread_mutexattr_t attr;
2147c82a1ecSDimitry Andric  int __ec = pthread_mutexattr_init(&attr);
2157c82a1ecSDimitry Andric  if (__ec)
216aed8d94eSDimitry Andric    return __ec;
217aed8d94eSDimitry Andric  __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
218aed8d94eSDimitry Andric  if (__ec) {
2197c82a1ecSDimitry Andric    pthread_mutexattr_destroy(&attr);
2207c82a1ecSDimitry Andric    return __ec;
2217c82a1ecSDimitry Andric  }
2227c82a1ecSDimitry Andric  __ec = pthread_mutex_init(__m, &attr);
223aed8d94eSDimitry Andric  if (__ec) {
2247c82a1ecSDimitry Andric    pthread_mutexattr_destroy(&attr);
2257c82a1ecSDimitry Andric    return __ec;
2267c82a1ecSDimitry Andric  }
2277c82a1ecSDimitry Andric  __ec = pthread_mutexattr_destroy(&attr);
228aed8d94eSDimitry Andric  if (__ec) {
2297c82a1ecSDimitry Andric    pthread_mutex_destroy(__m);
2307c82a1ecSDimitry Andric    return __ec;
2317c82a1ecSDimitry Andric  }
2327c82a1ecSDimitry Andric  return 0;
2337c82a1ecSDimitry Andric}
2347c82a1ecSDimitry Andric
235aed8d94eSDimitry Andricint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
236aed8d94eSDimitry Andric{
237aed8d94eSDimitry Andric  return pthread_mutex_lock(__m);
238aed8d94eSDimitry Andric}
239aed8d94eSDimitry Andric
240540d2a8bSDimitry Andricbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
241aed8d94eSDimitry Andric{
242540d2a8bSDimitry Andric  return pthread_mutex_trylock(__m) == 0;
243aed8d94eSDimitry Andric}
244aed8d94eSDimitry Andric
245aed8d94eSDimitry Andricint __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
246aed8d94eSDimitry Andric{
247aed8d94eSDimitry Andric  return pthread_mutex_unlock(__m);
248aed8d94eSDimitry Andric}
249aed8d94eSDimitry Andric
250aed8d94eSDimitry Andricint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
251aed8d94eSDimitry Andric{
252aed8d94eSDimitry Andric  return pthread_mutex_destroy(__m);
253aed8d94eSDimitry Andric}
254aed8d94eSDimitry Andric
2557c82a1ecSDimitry Andricint __libcpp_mutex_lock(__libcpp_mutex_t *__m)
2567c82a1ecSDimitry Andric{
2577c82a1ecSDimitry Andric  return pthread_mutex_lock(__m);
2587c82a1ecSDimitry Andric}
2597c82a1ecSDimitry Andric
260540d2a8bSDimitry Andricbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
2617c82a1ecSDimitry Andric{
262540d2a8bSDimitry Andric  return pthread_mutex_trylock(__m) == 0;
2637c82a1ecSDimitry Andric}
2647c82a1ecSDimitry Andric
2657c82a1ecSDimitry Andricint __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
2667c82a1ecSDimitry Andric{
2677c82a1ecSDimitry Andric  return pthread_mutex_unlock(__m);
2687c82a1ecSDimitry Andric}
2697c82a1ecSDimitry Andric
2707c82a1ecSDimitry Andricint __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
2717c82a1ecSDimitry Andric{
2727c82a1ecSDimitry Andric  return pthread_mutex_destroy(__m);
2737c82a1ecSDimitry Andric}
2747c82a1ecSDimitry Andric
275aed8d94eSDimitry Andric// Condition Variable
2767c82a1ecSDimitry Andricint __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
2777c82a1ecSDimitry Andric{
2787c82a1ecSDimitry Andric  return pthread_cond_signal(__cv);
2797c82a1ecSDimitry Andric}
2807c82a1ecSDimitry Andric
2817c82a1ecSDimitry Andricint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
2827c82a1ecSDimitry Andric{
2837c82a1ecSDimitry Andric  return pthread_cond_broadcast(__cv);
2847c82a1ecSDimitry Andric}
2857c82a1ecSDimitry Andric
2867c82a1ecSDimitry Andricint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
2877c82a1ecSDimitry Andric{
2887c82a1ecSDimitry Andric  return pthread_cond_wait(__cv, __m);
2897c82a1ecSDimitry Andric}
2907c82a1ecSDimitry Andric
291aed8d94eSDimitry Andricint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
292aed8d94eSDimitry Andric                               timespec *__ts)
2937c82a1ecSDimitry Andric{
2947c82a1ecSDimitry Andric  return pthread_cond_timedwait(__cv, __m, __ts);
2957c82a1ecSDimitry Andric}
2967c82a1ecSDimitry Andric
2977c82a1ecSDimitry Andricint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
2987c82a1ecSDimitry Andric{
2997c82a1ecSDimitry Andric  return pthread_cond_destroy(__cv);
3007c82a1ecSDimitry Andric}
3017c82a1ecSDimitry Andric
302aed8d94eSDimitry Andric// Execute once
303aed8d94eSDimitry Andricint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
304aed8d94eSDimitry Andric                          void (*init_routine)(void)) {
305aed8d94eSDimitry Andric  return pthread_once(flag, init_routine);
306aed8d94eSDimitry Andric}
307aed8d94eSDimitry Andric
3087c82a1ecSDimitry Andric// Thread id
3097c82a1ecSDimitry Andric// Returns non-zero if the thread ids are equal, otherwise 0
3107c82a1ecSDimitry Andricbool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
3117c82a1ecSDimitry Andric{
3127c82a1ecSDimitry Andric  return pthread_equal(t1, t2) != 0;
3137c82a1ecSDimitry Andric}
3147c82a1ecSDimitry Andric
3157c82a1ecSDimitry Andric// Returns non-zero if t1 < t2, otherwise 0
3167c82a1ecSDimitry Andricbool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
3177c82a1ecSDimitry Andric{
3187c82a1ecSDimitry Andric  return t1 < t2;
3197c82a1ecSDimitry Andric}
3207c82a1ecSDimitry Andric
3217c82a1ecSDimitry Andric// Thread
322540d2a8bSDimitry Andricbool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
323540d2a8bSDimitry Andric  return *__t == 0;
324540d2a8bSDimitry Andric}
325540d2a8bSDimitry Andric
326aed8d94eSDimitry Andricint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
327aed8d94eSDimitry Andric                           void *__arg)
3287c82a1ecSDimitry Andric{
3297c82a1ecSDimitry Andric  return pthread_create(__t, 0, __func, __arg);
3307c82a1ecSDimitry Andric}
3317c82a1ecSDimitry Andric
3327c82a1ecSDimitry Andric__libcpp_thread_id __libcpp_thread_get_current_id()
3337c82a1ecSDimitry Andric{
3347c82a1ecSDimitry Andric  return pthread_self();
3357c82a1ecSDimitry Andric}
3367c82a1ecSDimitry Andric
3377c82a1ecSDimitry Andric__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
3387c82a1ecSDimitry Andric{
3397c82a1ecSDimitry Andric  return *__t;
3407c82a1ecSDimitry Andric}
3417c82a1ecSDimitry Andric
3427c82a1ecSDimitry Andricint __libcpp_thread_join(__libcpp_thread_t *__t)
3437c82a1ecSDimitry Andric{
3447c82a1ecSDimitry Andric  return pthread_join(*__t, 0);
3457c82a1ecSDimitry Andric}
3467c82a1ecSDimitry Andric
3477c82a1ecSDimitry Andricint __libcpp_thread_detach(__libcpp_thread_t *__t)
3487c82a1ecSDimitry Andric{
3497c82a1ecSDimitry Andric  return pthread_detach(*__t);
3507c82a1ecSDimitry Andric}
3517c82a1ecSDimitry Andric
3527c82a1ecSDimitry Andricvoid __libcpp_thread_yield()
3537c82a1ecSDimitry Andric{
3547c82a1ecSDimitry Andric  sched_yield();
3557c82a1ecSDimitry Andric}
3567c82a1ecSDimitry Andric
357540d2a8bSDimitry Andricvoid __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
358540d2a8bSDimitry Andric{
359540d2a8bSDimitry Andric   using namespace chrono;
360540d2a8bSDimitry Andric   seconds __s = duration_cast<seconds>(__ns);
361540d2a8bSDimitry Andric   timespec __ts;
362540d2a8bSDimitry Andric   typedef decltype(__ts.tv_sec) ts_sec;
363540d2a8bSDimitry Andric   _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max();
364540d2a8bSDimitry Andric
365540d2a8bSDimitry Andric   if (__s.count() < __ts_sec_max)
366540d2a8bSDimitry Andric   {
367540d2a8bSDimitry Andric     __ts.tv_sec = static_cast<ts_sec>(__s.count());
368540d2a8bSDimitry Andric     __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
369540d2a8bSDimitry Andric   }
370540d2a8bSDimitry Andric   else
371540d2a8bSDimitry Andric   {
372540d2a8bSDimitry Andric     __ts.tv_sec = __ts_sec_max;
373540d2a8bSDimitry Andric     __ts.tv_nsec = 999999999; // (10^9 - 1)
374540d2a8bSDimitry Andric   }
375540d2a8bSDimitry Andric
376540d2a8bSDimitry Andric   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
377540d2a8bSDimitry Andric}
378540d2a8bSDimitry Andric
3797c82a1ecSDimitry Andric// Thread local storage
380aed8d94eSDimitry Andricint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
3817c82a1ecSDimitry Andric{
3827c82a1ecSDimitry Andric  return pthread_key_create(__key, __at_exit);
3837c82a1ecSDimitry Andric}
3847c82a1ecSDimitry Andric
385aed8d94eSDimitry Andricvoid *__libcpp_tls_get(__libcpp_tls_key __key)
3867c82a1ecSDimitry Andric{
3877c82a1ecSDimitry Andric  return pthread_getspecific(__key);
3887c82a1ecSDimitry Andric}
3897c82a1ecSDimitry Andric
390aed8d94eSDimitry Andricint __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
3917c82a1ecSDimitry Andric{
392aed8d94eSDimitry Andric    return pthread_setspecific(__key, __p);
3937c82a1ecSDimitry Andric}
3947c82a1ecSDimitry Andric
39580779b37SDimitry Andric#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
39680779b37SDimitry Andric
397*4173b67fSDimitry Andricclass _LIBCPP_TYPE_VIS thread;
398*4173b67fSDimitry Andricclass _LIBCPP_TYPE_VIS __thread_id;
399*4173b67fSDimitry Andric
400*4173b67fSDimitry Andricnamespace this_thread
401*4173b67fSDimitry Andric{
402*4173b67fSDimitry Andric
403*4173b67fSDimitry Andric_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
404*4173b67fSDimitry Andric
405*4173b67fSDimitry Andric}  // this_thread
406*4173b67fSDimitry Andric
407*4173b67fSDimitry Andrictemplate<> struct hash<__thread_id>;
408*4173b67fSDimitry Andric
409*4173b67fSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __thread_id
410*4173b67fSDimitry Andric{
411*4173b67fSDimitry Andric    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
412*4173b67fSDimitry Andric    // NULL is the no-thread value on Darwin.  Someone needs to check
413*4173b67fSDimitry Andric    // on other platforms.  We assume 0 works everywhere for now.
414*4173b67fSDimitry Andric    __libcpp_thread_id __id_;
415*4173b67fSDimitry Andric
416*4173b67fSDimitry Andricpublic:
417*4173b67fSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
418*4173b67fSDimitry Andric    __thread_id() _NOEXCEPT : __id_(0) {}
419*4173b67fSDimitry Andric
420*4173b67fSDimitry Andric    friend _LIBCPP_INLINE_VISIBILITY
421*4173b67fSDimitry Andric        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
422*4173b67fSDimitry Andric        { // don't pass id==0 to underlying routines
423*4173b67fSDimitry Andric        if (__x.__id_ == 0) return __y.__id_ == 0;
424*4173b67fSDimitry Andric        if (__y.__id_ == 0) return false;
425*4173b67fSDimitry Andric        return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
426*4173b67fSDimitry Andric        }
427*4173b67fSDimitry Andric    friend _LIBCPP_INLINE_VISIBILITY
428*4173b67fSDimitry Andric        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
429*4173b67fSDimitry Andric        {return !(__x == __y);}
430*4173b67fSDimitry Andric    friend _LIBCPP_INLINE_VISIBILITY
431*4173b67fSDimitry Andric        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
432*4173b67fSDimitry Andric        { // id==0 is always less than any other thread_id
433*4173b67fSDimitry Andric        if (__x.__id_ == 0) return __y.__id_ != 0;
434*4173b67fSDimitry Andric        if (__y.__id_ == 0) return false;
435*4173b67fSDimitry Andric        return  __libcpp_thread_id_less(__x.__id_, __y.__id_);
436*4173b67fSDimitry Andric        }
437*4173b67fSDimitry Andric    friend _LIBCPP_INLINE_VISIBILITY
438*4173b67fSDimitry Andric        bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
439*4173b67fSDimitry Andric        {return !(__y < __x);}
440*4173b67fSDimitry Andric    friend _LIBCPP_INLINE_VISIBILITY
441*4173b67fSDimitry Andric        bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
442*4173b67fSDimitry Andric        {return   __y < __x ;}
443*4173b67fSDimitry Andric    friend _LIBCPP_INLINE_VISIBILITY
444*4173b67fSDimitry Andric        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
445*4173b67fSDimitry Andric        {return !(__x < __y);}
446*4173b67fSDimitry Andric
447*4173b67fSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
448*4173b67fSDimitry Andric    void __reset() { __id_ = 0; }
449*4173b67fSDimitry Andric
450*4173b67fSDimitry Andric    template<class _CharT, class _Traits>
451*4173b67fSDimitry Andric    friend
452*4173b67fSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
453*4173b67fSDimitry Andric    basic_ostream<_CharT, _Traits>&
454*4173b67fSDimitry Andric    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
455*4173b67fSDimitry Andric
456*4173b67fSDimitry Andricprivate:
457*4173b67fSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
458*4173b67fSDimitry Andric    __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
459*4173b67fSDimitry Andric
460*4173b67fSDimitry Andric    friend __thread_id this_thread::get_id() _NOEXCEPT;
461*4173b67fSDimitry Andric    friend class _LIBCPP_TYPE_VIS thread;
462*4173b67fSDimitry Andric    friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
463*4173b67fSDimitry Andric};
464*4173b67fSDimitry Andric
465*4173b67fSDimitry Andricnamespace this_thread
466*4173b67fSDimitry Andric{
467*4173b67fSDimitry Andric
468*4173b67fSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
469*4173b67fSDimitry Andric__thread_id
470*4173b67fSDimitry Andricget_id() _NOEXCEPT
471*4173b67fSDimitry Andric{
472*4173b67fSDimitry Andric    return __libcpp_thread_get_current_id();
473*4173b67fSDimitry Andric}
474*4173b67fSDimitry Andric
475*4173b67fSDimitry Andric}  // this_thread
476*4173b67fSDimitry Andric
4777c82a1ecSDimitry Andric_LIBCPP_END_NAMESPACE_STD
4787c82a1ecSDimitry Andric
479f9448bf3SDimitry Andric_LIBCPP_POP_MACROS
480f9448bf3SDimitry Andric
48180779b37SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS
4827c82a1ecSDimitry Andric
4837c82a1ecSDimitry Andric#endif // _LIBCPP_THREADING_SUPPORT
484