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