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