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 <__availability> 14#include <__config> 15#include <__thread/poll_with_backoff.h> 16#include <chrono> 17#include <errno.h> 18#include <iosfwd> 19#include <limits> 20 21#ifdef __MVS__ 22# include <__support/ibm/nanosleep.h> 23#endif 24 25#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 26#pragma GCC system_header 27#endif 28 29#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 30# include <__external_threading> 31#elif !defined(_LIBCPP_HAS_NO_THREADS) 32 33#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 34# include <pthread.h> 35# include <sched.h> 36#elif defined(_LIBCPP_HAS_THREAD_API_C11) 37# include <threads.h> 38#endif 39 40#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 41 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \ 42 defined(_LIBCPP_HAS_THREAD_API_WIN32) 43#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 44#else 45#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 46#endif 47 48#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) 49#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) 50#else 51#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 52#endif 53 54typedef ::timespec __libcpp_timespec_t; 55#endif // !defined(_LIBCPP_HAS_NO_THREADS) 56 57_LIBCPP_PUSH_MACROS 58#include <__undef_macros> 59 60_LIBCPP_BEGIN_NAMESPACE_STD 61 62#if !defined(_LIBCPP_HAS_NO_THREADS) 63 64#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 65// Mutex 66typedef pthread_mutex_t __libcpp_mutex_t; 67#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 68 69typedef pthread_mutex_t __libcpp_recursive_mutex_t; 70 71// Condition Variable 72typedef pthread_cond_t __libcpp_condvar_t; 73#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 74 75// Execute once 76typedef pthread_once_t __libcpp_exec_once_flag; 77#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 78 79// Thread id 80#if defined(__MVS__) 81 typedef unsigned long long __libcpp_thread_id; 82#else 83 typedef pthread_t __libcpp_thread_id; 84#endif 85 86// Thread 87#define _LIBCPP_NULL_THREAD ((__libcpp_thread_t())) 88typedef pthread_t __libcpp_thread_t; 89 90// Thread Local Storage 91typedef pthread_key_t __libcpp_tls_key; 92 93#define _LIBCPP_TLS_DESTRUCTOR_CC 94#elif defined(_LIBCPP_HAS_THREAD_API_C11) 95// Mutex 96typedef mtx_t __libcpp_mutex_t; 97// mtx_t is a struct so using {} for initialization is valid. 98#define _LIBCPP_MUTEX_INITIALIZER {} 99 100typedef mtx_t __libcpp_recursive_mutex_t; 101 102// Condition Variable 103typedef cnd_t __libcpp_condvar_t; 104// cnd_t is a struct so using {} for initialization is valid. 105#define _LIBCPP_CONDVAR_INITIALIZER {} 106 107// Execute once 108typedef once_flag __libcpp_exec_once_flag; 109#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT 110 111// Thread id 112typedef thrd_t __libcpp_thread_id; 113 114// Thread 115#define _LIBCPP_NULL_THREAD 0U 116 117typedef thrd_t __libcpp_thread_t; 118 119// Thread Local Storage 120typedef tss_t __libcpp_tls_key; 121 122#define _LIBCPP_TLS_DESTRUCTOR_CC 123#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 124// Mutex 125typedef void* __libcpp_mutex_t; 126#define _LIBCPP_MUTEX_INITIALIZER 0 127 128#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) 129typedef void* __libcpp_recursive_mutex_t[6]; 130#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) 131typedef void* __libcpp_recursive_mutex_t[5]; 132#else 133# error Unsupported architecture 134#endif 135 136// Condition Variable 137typedef void* __libcpp_condvar_t; 138#define _LIBCPP_CONDVAR_INITIALIZER 0 139 140// Execute Once 141typedef void* __libcpp_exec_once_flag; 142#define _LIBCPP_EXEC_ONCE_INITIALIZER 0 143 144// Thread ID 145typedef long __libcpp_thread_id; 146 147// Thread 148#define _LIBCPP_NULL_THREAD 0U 149 150typedef void* __libcpp_thread_t; 151 152// Thread Local Storage 153typedef long __libcpp_tls_key; 154 155#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall 156#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 157 158#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 159// Mutex 160_LIBCPP_THREAD_ABI_VISIBILITY 161int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 162 163_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 164int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 165 166_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 167bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 168 169_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 170int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 171 172_LIBCPP_THREAD_ABI_VISIBILITY 173int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 174 175_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 176int __libcpp_mutex_lock(__libcpp_mutex_t *__m); 177 178_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 179bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 180 181_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 182int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 183 184_LIBCPP_THREAD_ABI_VISIBILITY 185int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 186 187// Condition variable 188_LIBCPP_THREAD_ABI_VISIBILITY 189int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 190 191_LIBCPP_THREAD_ABI_VISIBILITY 192int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 193 194_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 195int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 196 197_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 198int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 199 __libcpp_timespec_t *__ts); 200 201_LIBCPP_THREAD_ABI_VISIBILITY 202int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 203 204// Execute once 205_LIBCPP_THREAD_ABI_VISIBILITY 206int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 207 void (*init_routine)()); 208 209// Thread id 210_LIBCPP_THREAD_ABI_VISIBILITY 211bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 212 213_LIBCPP_THREAD_ABI_VISIBILITY 214bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 215 216// Thread 217_LIBCPP_THREAD_ABI_VISIBILITY 218bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 219 220_LIBCPP_THREAD_ABI_VISIBILITY 221int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 222 void *__arg); 223 224_LIBCPP_THREAD_ABI_VISIBILITY 225__libcpp_thread_id __libcpp_thread_get_current_id(); 226 227_LIBCPP_THREAD_ABI_VISIBILITY 228__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 229 230_LIBCPP_THREAD_ABI_VISIBILITY 231int __libcpp_thread_join(__libcpp_thread_t *__t); 232 233_LIBCPP_THREAD_ABI_VISIBILITY 234int __libcpp_thread_detach(__libcpp_thread_t *__t); 235 236_LIBCPP_THREAD_ABI_VISIBILITY 237void __libcpp_thread_yield(); 238 239_LIBCPP_THREAD_ABI_VISIBILITY 240void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 241 242// Thread local storage 243_LIBCPP_THREAD_ABI_VISIBILITY 244int __libcpp_tls_create(__libcpp_tls_key* __key, 245 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 246 247_LIBCPP_THREAD_ABI_VISIBILITY 248void *__libcpp_tls_get(__libcpp_tls_key __key); 249 250_LIBCPP_THREAD_ABI_VISIBILITY 251int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 252 253#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 254 255struct __libcpp_timed_backoff_policy { 256 _LIBCPP_INLINE_VISIBILITY 257 bool operator()(chrono::nanoseconds __elapsed) const 258 { 259 if(__elapsed > chrono::milliseconds(128)) 260 __libcpp_thread_sleep_for(chrono::milliseconds(8)); 261 else if(__elapsed > chrono::microseconds(64)) 262 __libcpp_thread_sleep_for(__elapsed / 2); 263 else if(__elapsed > chrono::microseconds(4)) 264 __libcpp_thread_yield(); 265 else 266 {} // poll 267 return false; 268 } 269}; 270 271#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 272 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) 273 274 275namespace __thread_detail { 276 277_LIBCPP_HIDE_FROM_ABI inline 278__libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns) 279{ 280 using namespace chrono; 281 seconds __s = duration_cast<seconds>(__ns); 282 __libcpp_timespec_t __ts; 283 typedef decltype(__ts.tv_sec) __ts_sec; 284 const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); 285 286 if (__s.count() < __ts_sec_max) 287 { 288 __ts.tv_sec = static_cast<__ts_sec>(__s.count()); 289 __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count()); 290 } 291 else 292 { 293 __ts.tv_sec = __ts_sec_max; 294 __ts.tv_nsec = 999999999; // (10^9 - 1) 295 } 296 297 return __ts; 298} 299 300} // namespace __thread_detail 301 302#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 303 304_LIBCPP_HIDE_FROM_ABI inline 305int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 306{ 307 pthread_mutexattr_t attr; 308 int __ec = pthread_mutexattr_init(&attr); 309 if (__ec) 310 return __ec; 311 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 312 if (__ec) { 313 pthread_mutexattr_destroy(&attr); 314 return __ec; 315 } 316 __ec = pthread_mutex_init(__m, &attr); 317 if (__ec) { 318 pthread_mutexattr_destroy(&attr); 319 return __ec; 320 } 321 __ec = pthread_mutexattr_destroy(&attr); 322 if (__ec) { 323 pthread_mutex_destroy(__m); 324 return __ec; 325 } 326 return 0; 327} 328 329_LIBCPP_HIDE_FROM_ABI inline 330int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 331{ 332 return pthread_mutex_lock(__m); 333} 334 335_LIBCPP_HIDE_FROM_ABI inline 336bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 337{ 338 return pthread_mutex_trylock(__m) == 0; 339} 340 341_LIBCPP_HIDE_FROM_ABI inline 342int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 343{ 344 return pthread_mutex_unlock(__m); 345} 346 347_LIBCPP_HIDE_FROM_ABI inline 348int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 349{ 350 return pthread_mutex_destroy(__m); 351} 352 353_LIBCPP_HIDE_FROM_ABI inline 354int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 355{ 356 return pthread_mutex_lock(__m); 357} 358 359_LIBCPP_HIDE_FROM_ABI inline 360bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 361{ 362 return pthread_mutex_trylock(__m) == 0; 363} 364 365_LIBCPP_HIDE_FROM_ABI inline 366int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 367{ 368 return pthread_mutex_unlock(__m); 369} 370 371_LIBCPP_HIDE_FROM_ABI inline 372int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 373{ 374 return pthread_mutex_destroy(__m); 375} 376 377// Condition Variable 378_LIBCPP_HIDE_FROM_ABI inline 379int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 380{ 381 return pthread_cond_signal(__cv); 382} 383 384_LIBCPP_HIDE_FROM_ABI inline 385int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 386{ 387 return pthread_cond_broadcast(__cv); 388} 389 390_LIBCPP_HIDE_FROM_ABI inline 391int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 392{ 393 return pthread_cond_wait(__cv, __m); 394} 395 396_LIBCPP_HIDE_FROM_ABI inline 397int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 398 __libcpp_timespec_t *__ts) 399{ 400 return pthread_cond_timedwait(__cv, __m, __ts); 401} 402 403_LIBCPP_HIDE_FROM_ABI inline 404int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 405{ 406 return pthread_cond_destroy(__cv); 407} 408 409// Execute once 410_LIBCPP_HIDE_FROM_ABI inline 411int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 412 void (*init_routine)()) { 413 return pthread_once(flag, init_routine); 414} 415 416// Thread id 417// Returns non-zero if the thread ids are equal, otherwise 0 418_LIBCPP_HIDE_FROM_ABI inline 419bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 420{ 421 return t1 == t2; 422} 423 424// Returns non-zero if t1 < t2, otherwise 0 425_LIBCPP_HIDE_FROM_ABI inline 426bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 427{ 428 return t1 < t2; 429} 430 431// Thread 432_LIBCPP_HIDE_FROM_ABI inline 433bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 434 return __libcpp_thread_get_id(__t) == 0; 435} 436 437_LIBCPP_HIDE_FROM_ABI inline 438int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 439 void *__arg) 440{ 441 return pthread_create(__t, nullptr, __func, __arg); 442} 443 444_LIBCPP_HIDE_FROM_ABI inline 445__libcpp_thread_id __libcpp_thread_get_current_id() 446{ 447 const __libcpp_thread_t thread = pthread_self(); 448 return __libcpp_thread_get_id(&thread); 449} 450 451_LIBCPP_HIDE_FROM_ABI inline 452__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 453{ 454#if defined(__MVS__) 455 return __t->__; 456#else 457 return *__t; 458#endif 459} 460 461_LIBCPP_HIDE_FROM_ABI inline 462int __libcpp_thread_join(__libcpp_thread_t *__t) 463{ 464 return pthread_join(*__t, nullptr); 465} 466 467_LIBCPP_HIDE_FROM_ABI inline 468int __libcpp_thread_detach(__libcpp_thread_t *__t) 469{ 470 return pthread_detach(*__t); 471} 472 473_LIBCPP_HIDE_FROM_ABI inline 474void __libcpp_thread_yield() 475{ 476 sched_yield(); 477} 478 479_LIBCPP_HIDE_FROM_ABI inline 480void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 481{ 482 __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns); 483 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); 484} 485 486// Thread local storage 487_LIBCPP_HIDE_FROM_ABI inline 488int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 489{ 490 return pthread_key_create(__key, __at_exit); 491} 492 493_LIBCPP_HIDE_FROM_ABI inline 494void *__libcpp_tls_get(__libcpp_tls_key __key) 495{ 496 return pthread_getspecific(__key); 497} 498 499_LIBCPP_HIDE_FROM_ABI inline 500int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 501{ 502 return pthread_setspecific(__key, __p); 503} 504 505#elif defined(_LIBCPP_HAS_THREAD_API_C11) 506 507_LIBCPP_HIDE_FROM_ABI inline 508int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 509{ 510 return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL; 511} 512 513_LIBCPP_HIDE_FROM_ABI inline 514int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 515{ 516 return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 517} 518 519_LIBCPP_HIDE_FROM_ABI inline 520bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 521{ 522 return mtx_trylock(__m) == thrd_success; 523} 524 525_LIBCPP_HIDE_FROM_ABI inline 526int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 527{ 528 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 529} 530 531_LIBCPP_HIDE_FROM_ABI inline 532int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 533{ 534 mtx_destroy(__m); 535 return 0; 536} 537 538_LIBCPP_HIDE_FROM_ABI inline 539int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 540{ 541 return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 542} 543 544_LIBCPP_HIDE_FROM_ABI inline 545bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 546{ 547 return mtx_trylock(__m) == thrd_success; 548} 549 550_LIBCPP_HIDE_FROM_ABI inline 551int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 552{ 553 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 554} 555 556_LIBCPP_HIDE_FROM_ABI inline 557int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 558{ 559 mtx_destroy(__m); 560 return 0; 561} 562 563// Condition Variable 564_LIBCPP_HIDE_FROM_ABI inline 565int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 566{ 567 return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; 568} 569 570_LIBCPP_HIDE_FROM_ABI inline 571int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 572{ 573 return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; 574} 575 576_LIBCPP_HIDE_FROM_ABI inline 577int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 578{ 579 return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL; 580} 581 582_LIBCPP_HIDE_FROM_ABI inline 583int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 584 timespec *__ts) 585{ 586 int __ec = cnd_timedwait(__cv, __m, __ts); 587 return __ec == thrd_timedout ? ETIMEDOUT : __ec; 588} 589 590_LIBCPP_HIDE_FROM_ABI inline 591int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 592{ 593 cnd_destroy(__cv); 594 return 0; 595} 596 597// Execute once 598_LIBCPP_HIDE_FROM_ABI inline 599int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 600 void (*init_routine)(void)) { 601 ::call_once(flag, init_routine); 602 return 0; 603} 604 605// Thread id 606// Returns non-zero if the thread ids are equal, otherwise 0 607_LIBCPP_HIDE_FROM_ABI inline 608bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 609{ 610 return thrd_equal(t1, t2) != 0; 611} 612 613// Returns non-zero if t1 < t2, otherwise 0 614_LIBCPP_HIDE_FROM_ABI inline 615bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 616{ 617 return t1 < t2; 618} 619 620// Thread 621_LIBCPP_HIDE_FROM_ABI inline 622bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 623 return __libcpp_thread_get_id(__t) == 0; 624} 625 626_LIBCPP_HIDE_FROM_ABI inline 627int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 628 void *__arg) 629{ 630 int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg); 631 return __ec == thrd_nomem ? ENOMEM : __ec; 632} 633 634_LIBCPP_HIDE_FROM_ABI inline 635__libcpp_thread_id __libcpp_thread_get_current_id() 636{ 637 return thrd_current(); 638} 639 640_LIBCPP_HIDE_FROM_ABI inline 641__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 642{ 643 return *__t; 644} 645 646_LIBCPP_HIDE_FROM_ABI inline 647int __libcpp_thread_join(__libcpp_thread_t *__t) 648{ 649 return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; 650} 651 652_LIBCPP_HIDE_FROM_ABI inline 653int __libcpp_thread_detach(__libcpp_thread_t *__t) 654{ 655 return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; 656} 657 658_LIBCPP_HIDE_FROM_ABI inline 659void __libcpp_thread_yield() 660{ 661 thrd_yield(); 662} 663 664_LIBCPP_HIDE_FROM_ABI inline 665void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 666{ 667 __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns); 668 thrd_sleep(&__ts, nullptr); 669} 670 671// Thread local storage 672_LIBCPP_HIDE_FROM_ABI inline 673int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 674{ 675 return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL; 676} 677 678_LIBCPP_HIDE_FROM_ABI inline 679void *__libcpp_tls_get(__libcpp_tls_key __key) 680{ 681 return tss_get(__key); 682} 683 684_LIBCPP_HIDE_FROM_ABI inline 685int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 686{ 687 return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; 688} 689 690#endif 691 692 693#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 694 695class _LIBCPP_TYPE_VIS thread; 696class _LIBCPP_TYPE_VIS __thread_id; 697 698namespace this_thread 699{ 700 701_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; 702 703} // namespace this_thread 704 705template<> struct hash<__thread_id>; 706 707class _LIBCPP_TEMPLATE_VIS __thread_id 708{ 709 // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 710 // NULL is the no-thread value on Darwin. Someone needs to check 711 // on other platforms. We assume 0 works everywhere for now. 712 __libcpp_thread_id __id_; 713 714public: 715 _LIBCPP_INLINE_VISIBILITY 716 __thread_id() _NOEXCEPT : __id_(0) {} 717 718 friend _LIBCPP_INLINE_VISIBILITY 719 bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT 720 { // don't pass id==0 to underlying routines 721 if (__x.__id_ == 0) return __y.__id_ == 0; 722 if (__y.__id_ == 0) return false; 723 return __libcpp_thread_id_equal(__x.__id_, __y.__id_); 724 } 725 friend _LIBCPP_INLINE_VISIBILITY 726 bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT 727 {return !(__x == __y);} 728 friend _LIBCPP_INLINE_VISIBILITY 729 bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT 730 { // id==0 is always less than any other thread_id 731 if (__x.__id_ == 0) return __y.__id_ != 0; 732 if (__y.__id_ == 0) return false; 733 return __libcpp_thread_id_less(__x.__id_, __y.__id_); 734 } 735 friend _LIBCPP_INLINE_VISIBILITY 736 bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT 737 {return !(__y < __x);} 738 friend _LIBCPP_INLINE_VISIBILITY 739 bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT 740 {return __y < __x ;} 741 friend _LIBCPP_INLINE_VISIBILITY 742 bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT 743 {return !(__x < __y);} 744 745 _LIBCPP_INLINE_VISIBILITY 746 void __reset() { __id_ = 0; } 747 748 template<class _CharT, class _Traits> 749 friend 750 _LIBCPP_INLINE_VISIBILITY 751 basic_ostream<_CharT, _Traits>& 752 operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); 753 754private: 755 _LIBCPP_INLINE_VISIBILITY 756 __thread_id(__libcpp_thread_id __id) : __id_(__id) {} 757 758 friend __thread_id this_thread::get_id() _NOEXCEPT; 759 friend class _LIBCPP_TYPE_VIS thread; 760 friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; 761}; 762 763namespace this_thread 764{ 765 766inline _LIBCPP_INLINE_VISIBILITY 767__thread_id 768get_id() _NOEXCEPT 769{ 770 return __libcpp_thread_get_current_id(); 771} 772 773} // namespace this_thread 774 775#endif // !_LIBCPP_HAS_NO_THREADS 776 777_LIBCPP_END_NAMESPACE_STD 778 779_LIBCPP_POP_MACROS 780 781#endif // _LIBCPP_THREADING_SUPPORT 782