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