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