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