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