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