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