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