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_INLINE_VISIBILITY 282 bool operator()(chrono::nanoseconds __elapsed) const 283 { 284 if(__elapsed > chrono::milliseconds(128)) 285 __libcpp_thread_sleep_for(chrono::milliseconds(8)); 286 else if(__elapsed > chrono::microseconds(64)) 287 __libcpp_thread_sleep_for(__elapsed / 2); 288 else if(__elapsed > chrono::microseconds(4)) 289 __libcpp_thread_yield(); 290 else 291 ; // poll 292 return false; 293 } 294}; 295 296static _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64; 297 298template<class _Fn, class _BFn> 299_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 300bool __libcpp_thread_poll_with_backoff( 301 _Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero()) 302{ 303 auto const __start = chrono::high_resolution_clock::now(); 304 for(int __count = 0;;) { 305 if(__f()) 306 return true; // _Fn completion means success 307 if(__count < __libcpp_polling_count) { 308 __count += 1; 309 continue; 310 } 311 chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start; 312 if(__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed) 313 return false; // timeout failure 314 if(__bf(__elapsed)) 315 return false; // _BFn completion means failure 316 } 317} 318 319#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 320 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) 321 322 323namespace __thread_detail { 324 325inline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns) 326{ 327 using namespace chrono; 328 seconds __s = duration_cast<seconds>(__ns); 329 __libcpp_timespec_t __ts; 330 typedef decltype(__ts.tv_sec) __ts_sec; 331 const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); 332 333 if (__s.count() < __ts_sec_max) 334 { 335 __ts.tv_sec = static_cast<__ts_sec>(__s.count()); 336 __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count()); 337 } 338 else 339 { 340 __ts.tv_sec = __ts_sec_max; 341 __ts.tv_nsec = 999999999; // (10^9 - 1) 342 } 343 344 return __ts; 345} 346 347} 348 349#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 350 351int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 352{ 353 pthread_mutexattr_t attr; 354 int __ec = pthread_mutexattr_init(&attr); 355 if (__ec) 356 return __ec; 357 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 358 if (__ec) { 359 pthread_mutexattr_destroy(&attr); 360 return __ec; 361 } 362 __ec = pthread_mutex_init(__m, &attr); 363 if (__ec) { 364 pthread_mutexattr_destroy(&attr); 365 return __ec; 366 } 367 __ec = pthread_mutexattr_destroy(&attr); 368 if (__ec) { 369 pthread_mutex_destroy(__m); 370 return __ec; 371 } 372 return 0; 373} 374 375int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 376{ 377 return pthread_mutex_lock(__m); 378} 379 380bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 381{ 382 return pthread_mutex_trylock(__m) == 0; 383} 384 385int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 386{ 387 return pthread_mutex_unlock(__m); 388} 389 390int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 391{ 392 return pthread_mutex_destroy(__m); 393} 394 395int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 396{ 397 return pthread_mutex_lock(__m); 398} 399 400bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 401{ 402 return pthread_mutex_trylock(__m) == 0; 403} 404 405int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 406{ 407 return pthread_mutex_unlock(__m); 408} 409 410int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 411{ 412 return pthread_mutex_destroy(__m); 413} 414 415// Condition Variable 416int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 417{ 418 return pthread_cond_signal(__cv); 419} 420 421int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 422{ 423 return pthread_cond_broadcast(__cv); 424} 425 426int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 427{ 428 return pthread_cond_wait(__cv, __m); 429} 430 431int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 432 __libcpp_timespec_t *__ts) 433{ 434 return pthread_cond_timedwait(__cv, __m, __ts); 435} 436 437int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 438{ 439 return pthread_cond_destroy(__cv); 440} 441 442#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES 443 444// Semaphore 445bool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init) 446{ 447 return sem_init(__sem, 0, __init) == 0; 448} 449 450bool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem) 451{ 452 return sem_destroy(__sem) == 0; 453} 454 455bool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem) 456{ 457 return sem_post(__sem) == 0; 458} 459 460bool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem) 461{ 462 return sem_wait(__sem) == 0; 463} 464 465bool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns) 466{ 467 auto const __abs_time = chrono::system_clock::now().time_since_epoch() + __ns; 468 __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__abs_time); 469 return sem_timedwait(__sem, &__ts) == 0; 470} 471 472#endif //_LIBCPP_NO_NATIVE_SEMAPHORES 473 474// Execute once 475int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 476 void (*init_routine)()) { 477 return pthread_once(flag, init_routine); 478} 479 480// Thread id 481// Returns non-zero if the thread ids are equal, otherwise 0 482bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 483{ 484 return pthread_equal(t1, t2) != 0; 485} 486 487// Returns non-zero if t1 < t2, otherwise 0 488bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 489{ 490 return t1 < t2; 491} 492 493// Thread 494bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 495 return *__t == 0; 496} 497 498int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 499 void *__arg) 500{ 501 return pthread_create(__t, 0, __func, __arg); 502} 503 504__libcpp_thread_id __libcpp_thread_get_current_id() 505{ 506 return pthread_self(); 507} 508 509__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 510{ 511 return *__t; 512} 513 514int __libcpp_thread_join(__libcpp_thread_t *__t) 515{ 516 return pthread_join(*__t, 0); 517} 518 519int __libcpp_thread_detach(__libcpp_thread_t *__t) 520{ 521 return pthread_detach(*__t); 522} 523 524void __libcpp_thread_yield() 525{ 526 sched_yield(); 527} 528 529void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 530{ 531 __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns); 532 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); 533} 534 535// Thread local storage 536int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 537{ 538 return pthread_key_create(__key, __at_exit); 539} 540 541void *__libcpp_tls_get(__libcpp_tls_key __key) 542{ 543 return pthread_getspecific(__key); 544} 545 546int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 547{ 548 return pthread_setspecific(__key, __p); 549} 550 551#elif defined(_LIBCPP_HAS_THREAD_API_C11) 552 553int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 554{ 555 return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL; 556} 557 558int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 559{ 560 return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 561} 562 563bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 564{ 565 return mtx_trylock(__m) == thrd_success; 566} 567 568int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 569{ 570 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 571} 572 573int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 574{ 575 mtx_destroy(__m); 576 return 0; 577} 578 579int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 580{ 581 return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 582} 583 584bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 585{ 586 return mtx_trylock(__m) == thrd_success; 587} 588 589int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 590{ 591 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 592} 593 594int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 595{ 596 mtx_destroy(__m); 597 return 0; 598} 599 600// Condition Variable 601int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 602{ 603 return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; 604} 605 606int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 607{ 608 return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; 609} 610 611int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 612{ 613 return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL; 614} 615 616int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 617 timespec *__ts) 618{ 619 int __ec = cnd_timedwait(__cv, __m, __ts); 620 return __ec == thrd_timedout ? ETIMEDOUT : __ec; 621} 622 623int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 624{ 625 cnd_destroy(__cv); 626 return 0; 627} 628 629// Execute once 630int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 631 void (*init_routine)(void)) { 632 ::call_once(flag, init_routine); 633 return 0; 634} 635 636// Thread id 637// Returns non-zero if the thread ids are equal, otherwise 0 638bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 639{ 640 return thrd_equal(t1, t2) != 0; 641} 642 643// Returns non-zero if t1 < t2, otherwise 0 644bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 645{ 646 return t1 < t2; 647} 648 649// Thread 650bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 651 return *__t == 0; 652} 653 654int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 655 void *__arg) 656{ 657 int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg); 658 return __ec == thrd_nomem ? ENOMEM : __ec; 659} 660 661__libcpp_thread_id __libcpp_thread_get_current_id() 662{ 663 return thrd_current(); 664} 665 666__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 667{ 668 return *__t; 669} 670 671int __libcpp_thread_join(__libcpp_thread_t *__t) 672{ 673 return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; 674} 675 676int __libcpp_thread_detach(__libcpp_thread_t *__t) 677{ 678 return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; 679} 680 681void __libcpp_thread_yield() 682{ 683 thrd_yield(); 684} 685 686void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 687{ 688 __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns); 689 thrd_sleep(&__ts, nullptr); 690} 691 692// Thread local storage 693int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 694{ 695 return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL; 696} 697 698void *__libcpp_tls_get(__libcpp_tls_key __key) 699{ 700 return tss_get(__key); 701} 702 703int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 704{ 705 return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; 706} 707 708#endif 709 710 711#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 712 713class _LIBCPP_TYPE_VIS thread; 714class _LIBCPP_TYPE_VIS __thread_id; 715 716namespace this_thread 717{ 718 719_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; 720 721} // this_thread 722 723template<> struct hash<__thread_id>; 724 725class _LIBCPP_TEMPLATE_VIS __thread_id 726{ 727 // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 728 // NULL is the no-thread value on Darwin. Someone needs to check 729 // on other platforms. We assume 0 works everywhere for now. 730 __libcpp_thread_id __id_; 731 732public: 733 _LIBCPP_INLINE_VISIBILITY 734 __thread_id() _NOEXCEPT : __id_(0) {} 735 736 friend _LIBCPP_INLINE_VISIBILITY 737 bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT 738 { // don't pass id==0 to underlying routines 739 if (__x.__id_ == 0) return __y.__id_ == 0; 740 if (__y.__id_ == 0) return false; 741 return __libcpp_thread_id_equal(__x.__id_, __y.__id_); 742 } 743 friend _LIBCPP_INLINE_VISIBILITY 744 bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT 745 {return !(__x == __y);} 746 friend _LIBCPP_INLINE_VISIBILITY 747 bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT 748 { // id==0 is always less than any other thread_id 749 if (__x.__id_ == 0) return __y.__id_ != 0; 750 if (__y.__id_ == 0) return false; 751 return __libcpp_thread_id_less(__x.__id_, __y.__id_); 752 } 753 friend _LIBCPP_INLINE_VISIBILITY 754 bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT 755 {return !(__y < __x);} 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 !(__x < __y);} 762 763 _LIBCPP_INLINE_VISIBILITY 764 void __reset() { __id_ = 0; } 765 766 template<class _CharT, class _Traits> 767 friend 768 _LIBCPP_INLINE_VISIBILITY 769 basic_ostream<_CharT, _Traits>& 770 operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); 771 772private: 773 _LIBCPP_INLINE_VISIBILITY 774 __thread_id(__libcpp_thread_id __id) : __id_(__id) {} 775 776 friend __thread_id this_thread::get_id() _NOEXCEPT; 777 friend class _LIBCPP_TYPE_VIS thread; 778 friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; 779}; 780 781namespace this_thread 782{ 783 784inline _LIBCPP_INLINE_VISIBILITY 785__thread_id 786get_id() _NOEXCEPT 787{ 788 return __libcpp_thread_get_current_id(); 789} 790 791} // this_thread 792 793#endif // !_LIBCPP_HAS_NO_THREADS 794 795_LIBCPP_END_NAMESPACE_STD 796 797_LIBCPP_POP_MACROS 798 799#endif // _LIBCPP_THREADING_SUPPORT 800