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