1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// The LLVM Compiler Infrastructure 5// 6// This file is dual licensed under the MIT and the University of Illinois Open 7// Source Licenses. See LICENSE.TXT for details. 8// 9//===----------------------------------------------------------------------===// 10 11#ifndef _LIBCPP_THREADING_SUPPORT 12#define _LIBCPP_THREADING_SUPPORT 13 14#include <__config> 15#include <chrono> 16#include <iosfwd> 17#include <errno.h> 18 19#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 20#pragma GCC system_header 21#endif 22 23#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 24# include <__external_threading> 25#elif !defined(_LIBCPP_HAS_NO_THREADS) 26 27#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 28# include <pthread.h> 29# include <sched.h> 30#endif 31 32_LIBCPP_PUSH_MACROS 33#include <__undef_macros> 34 35#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 36 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \ 37 defined(_LIBCPP_HAS_THREAD_API_WIN32) 38#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 39#else 40#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 41#endif 42 43#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) 44#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) 45#else 46#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 47#endif 48 49_LIBCPP_BEGIN_NAMESPACE_STD 50 51#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 52// Mutex 53typedef pthread_mutex_t __libcpp_mutex_t; 54#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 55 56typedef pthread_mutex_t __libcpp_recursive_mutex_t; 57 58// Condition Variable 59typedef pthread_cond_t __libcpp_condvar_t; 60#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 61 62// Execute once 63typedef pthread_once_t __libcpp_exec_once_flag; 64#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 65 66// Thread id 67typedef pthread_t __libcpp_thread_id; 68 69// Thread 70#define _LIBCPP_NULL_THREAD 0U 71 72typedef pthread_t __libcpp_thread_t; 73 74// Thread Local Storage 75typedef pthread_key_t __libcpp_tls_key; 76 77#define _LIBCPP_TLS_DESTRUCTOR_CC 78#else 79// Mutex 80typedef void* __libcpp_mutex_t; 81#define _LIBCPP_MUTEX_INITIALIZER 0 82 83#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) 84typedef void* __libcpp_recursive_mutex_t[6]; 85#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) 86typedef void* __libcpp_recursive_mutex_t[5]; 87#else 88# error Unsupported architecture 89#endif 90 91// Condition Variable 92typedef void* __libcpp_condvar_t; 93#define _LIBCPP_CONDVAR_INITIALIZER 0 94 95// Execute Once 96typedef void* __libcpp_exec_once_flag; 97#define _LIBCPP_EXEC_ONCE_INITIALIZER 0 98 99// Thread ID 100typedef long __libcpp_thread_id; 101 102// Thread 103#define _LIBCPP_NULL_THREAD 0U 104 105typedef void* __libcpp_thread_t; 106 107// Thread Local Storage 108typedef long __libcpp_tls_key; 109 110#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall 111#endif 112 113// Mutex 114_LIBCPP_THREAD_ABI_VISIBILITY 115int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 116 117_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 118int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 119 120_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 121bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 122 123_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 124int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 125 126_LIBCPP_THREAD_ABI_VISIBILITY 127int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 128 129_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 130int __libcpp_mutex_lock(__libcpp_mutex_t *__m); 131 132_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 133bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 134 135_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 136int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 137 138_LIBCPP_THREAD_ABI_VISIBILITY 139int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 140 141// Condition variable 142_LIBCPP_THREAD_ABI_VISIBILITY 143int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 144 145_LIBCPP_THREAD_ABI_VISIBILITY 146int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 147 148_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 149int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 150 151_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 152int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 153 timespec *__ts); 154 155_LIBCPP_THREAD_ABI_VISIBILITY 156int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 157 158// Execute once 159_LIBCPP_THREAD_ABI_VISIBILITY 160int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 161 void (*init_routine)(void)); 162 163// Thread id 164_LIBCPP_THREAD_ABI_VISIBILITY 165bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 166 167_LIBCPP_THREAD_ABI_VISIBILITY 168bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 169 170// Thread 171_LIBCPP_THREAD_ABI_VISIBILITY 172bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 173 174_LIBCPP_THREAD_ABI_VISIBILITY 175int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 176 void *__arg); 177 178_LIBCPP_THREAD_ABI_VISIBILITY 179__libcpp_thread_id __libcpp_thread_get_current_id(); 180 181_LIBCPP_THREAD_ABI_VISIBILITY 182__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 183 184_LIBCPP_THREAD_ABI_VISIBILITY 185int __libcpp_thread_join(__libcpp_thread_t *__t); 186 187_LIBCPP_THREAD_ABI_VISIBILITY 188int __libcpp_thread_detach(__libcpp_thread_t *__t); 189 190_LIBCPP_THREAD_ABI_VISIBILITY 191void __libcpp_thread_yield(); 192 193_LIBCPP_THREAD_ABI_VISIBILITY 194void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 195 196// Thread local storage 197_LIBCPP_THREAD_ABI_VISIBILITY 198int __libcpp_tls_create(__libcpp_tls_key* __key, 199 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 200 201_LIBCPP_THREAD_ABI_VISIBILITY 202void *__libcpp_tls_get(__libcpp_tls_key __key); 203 204_LIBCPP_THREAD_ABI_VISIBILITY 205int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 206 207#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 208 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \ 209 defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 210 211int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 212{ 213 pthread_mutexattr_t attr; 214 int __ec = pthread_mutexattr_init(&attr); 215 if (__ec) 216 return __ec; 217 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 218 if (__ec) { 219 pthread_mutexattr_destroy(&attr); 220 return __ec; 221 } 222 __ec = pthread_mutex_init(__m, &attr); 223 if (__ec) { 224 pthread_mutexattr_destroy(&attr); 225 return __ec; 226 } 227 __ec = pthread_mutexattr_destroy(&attr); 228 if (__ec) { 229 pthread_mutex_destroy(__m); 230 return __ec; 231 } 232 return 0; 233} 234 235int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 236{ 237 return pthread_mutex_lock(__m); 238} 239 240bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 241{ 242 return pthread_mutex_trylock(__m) == 0; 243} 244 245int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 246{ 247 return pthread_mutex_unlock(__m); 248} 249 250int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 251{ 252 return pthread_mutex_destroy(__m); 253} 254 255int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 256{ 257 return pthread_mutex_lock(__m); 258} 259 260bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 261{ 262 return pthread_mutex_trylock(__m) == 0; 263} 264 265int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 266{ 267 return pthread_mutex_unlock(__m); 268} 269 270int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 271{ 272 return pthread_mutex_destroy(__m); 273} 274 275// Condition Variable 276int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 277{ 278 return pthread_cond_signal(__cv); 279} 280 281int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 282{ 283 return pthread_cond_broadcast(__cv); 284} 285 286int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 287{ 288 return pthread_cond_wait(__cv, __m); 289} 290 291int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 292 timespec *__ts) 293{ 294 return pthread_cond_timedwait(__cv, __m, __ts); 295} 296 297int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 298{ 299 return pthread_cond_destroy(__cv); 300} 301 302// Execute once 303int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 304 void (*init_routine)(void)) { 305 return pthread_once(flag, init_routine); 306} 307 308// Thread id 309// Returns non-zero if the thread ids are equal, otherwise 0 310bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 311{ 312 return pthread_equal(t1, t2) != 0; 313} 314 315// Returns non-zero if t1 < t2, otherwise 0 316bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 317{ 318 return t1 < t2; 319} 320 321// Thread 322bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 323 return *__t == 0; 324} 325 326int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 327 void *__arg) 328{ 329 return pthread_create(__t, 0, __func, __arg); 330} 331 332__libcpp_thread_id __libcpp_thread_get_current_id() 333{ 334 return pthread_self(); 335} 336 337__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 338{ 339 return *__t; 340} 341 342int __libcpp_thread_join(__libcpp_thread_t *__t) 343{ 344 return pthread_join(*__t, 0); 345} 346 347int __libcpp_thread_detach(__libcpp_thread_t *__t) 348{ 349 return pthread_detach(*__t); 350} 351 352void __libcpp_thread_yield() 353{ 354 sched_yield(); 355} 356 357void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 358{ 359 using namespace chrono; 360 seconds __s = duration_cast<seconds>(__ns); 361 timespec __ts; 362 typedef decltype(__ts.tv_sec) ts_sec; 363 _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max(); 364 365 if (__s.count() < __ts_sec_max) 366 { 367 __ts.tv_sec = static_cast<ts_sec>(__s.count()); 368 __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count()); 369 } 370 else 371 { 372 __ts.tv_sec = __ts_sec_max; 373 __ts.tv_nsec = 999999999; // (10^9 - 1) 374 } 375 376 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); 377} 378 379// Thread local storage 380int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 381{ 382 return pthread_key_create(__key, __at_exit); 383} 384 385void *__libcpp_tls_get(__libcpp_tls_key __key) 386{ 387 return pthread_getspecific(__key); 388} 389 390int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 391{ 392 return pthread_setspecific(__key, __p); 393} 394 395#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 396 397class _LIBCPP_TYPE_VIS thread; 398class _LIBCPP_TYPE_VIS __thread_id; 399 400namespace this_thread 401{ 402 403_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; 404 405} // this_thread 406 407template<> struct hash<__thread_id>; 408 409class _LIBCPP_TEMPLATE_VIS __thread_id 410{ 411 // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 412 // NULL is the no-thread value on Darwin. Someone needs to check 413 // on other platforms. We assume 0 works everywhere for now. 414 __libcpp_thread_id __id_; 415 416public: 417 _LIBCPP_INLINE_VISIBILITY 418 __thread_id() _NOEXCEPT : __id_(0) {} 419 420 friend _LIBCPP_INLINE_VISIBILITY 421 bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT 422 { // don't pass id==0 to underlying routines 423 if (__x.__id_ == 0) return __y.__id_ == 0; 424 if (__y.__id_ == 0) return false; 425 return __libcpp_thread_id_equal(__x.__id_, __y.__id_); 426 } 427 friend _LIBCPP_INLINE_VISIBILITY 428 bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT 429 {return !(__x == __y);} 430 friend _LIBCPP_INLINE_VISIBILITY 431 bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT 432 { // id==0 is always less than any other thread_id 433 if (__x.__id_ == 0) return __y.__id_ != 0; 434 if (__y.__id_ == 0) return false; 435 return __libcpp_thread_id_less(__x.__id_, __y.__id_); 436 } 437 friend _LIBCPP_INLINE_VISIBILITY 438 bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT 439 {return !(__y < __x);} 440 friend _LIBCPP_INLINE_VISIBILITY 441 bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT 442 {return __y < __x ;} 443 friend _LIBCPP_INLINE_VISIBILITY 444 bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT 445 {return !(__x < __y);} 446 447 _LIBCPP_INLINE_VISIBILITY 448 void __reset() { __id_ = 0; } 449 450 template<class _CharT, class _Traits> 451 friend 452 _LIBCPP_INLINE_VISIBILITY 453 basic_ostream<_CharT, _Traits>& 454 operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); 455 456private: 457 _LIBCPP_INLINE_VISIBILITY 458 __thread_id(__libcpp_thread_id __id) : __id_(__id) {} 459 460 friend __thread_id this_thread::get_id() _NOEXCEPT; 461 friend class _LIBCPP_TYPE_VIS thread; 462 friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; 463}; 464 465namespace this_thread 466{ 467 468inline _LIBCPP_INLINE_VISIBILITY 469__thread_id 470get_id() _NOEXCEPT 471{ 472 return __libcpp_thread_get_current_id(); 473} 474 475} // this_thread 476 477_LIBCPP_END_NAMESPACE_STD 478 479_LIBCPP_POP_MACROS 480 481#endif // !_LIBCPP_HAS_NO_THREADS 482 483#endif // _LIBCPP_THREADING_SUPPORT 484