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