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