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 <__chrono/convert_to_timespec.h> 15#include <__chrono/duration.h> 16#include <__config> 17#include <__fwd/hash.h> 18#include <ctime> 19#include <errno.h> 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// Some platforms require <bits/atomic_wide_counter.h> in order for 35// PTHREAD_COND_INITIALIZER to be expanded. Normally that would come 36// in via <pthread.h>, but it's a non-modular header on those platforms, 37// so libc++'s <math.h> usually absorbs atomic_wide_counter.h into the 38// module with <math.h> and makes atomic_wide_counter.h invisible. 39// Include <math.h> here to work around that. 40# include <math.h> 41 42# include <pthread.h> 43# include <sched.h> 44#elif defined(_LIBCPP_HAS_THREAD_API_C11) 45# include <threads.h> 46#endif 47 48#if defined(_LIBCPP_HAS_THREAD_API_WIN32) 49#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_EXPORTED_FROM_ABI 50#else 51#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_HIDE_FROM_ABI 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_API_PTHREAD) 253 254int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 255{ 256 pthread_mutexattr_t __attr; 257 int __ec = pthread_mutexattr_init(&__attr); 258 if (__ec) 259 return __ec; 260 __ec = pthread_mutexattr_settype(&__attr, PTHREAD_MUTEX_RECURSIVE); 261 if (__ec) { 262 pthread_mutexattr_destroy(&__attr); 263 return __ec; 264 } 265 __ec = pthread_mutex_init(__m, &__attr); 266 if (__ec) { 267 pthread_mutexattr_destroy(&__attr); 268 return __ec; 269 } 270 __ec = pthread_mutexattr_destroy(&__attr); 271 if (__ec) { 272 pthread_mutex_destroy(__m); 273 return __ec; 274 } 275 return 0; 276} 277 278int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 279{ 280 return pthread_mutex_lock(__m); 281} 282 283bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 284{ 285 return pthread_mutex_trylock(__m) == 0; 286} 287 288int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 289{ 290 return pthread_mutex_unlock(__m); 291} 292 293int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 294{ 295 return pthread_mutex_destroy(__m); 296} 297 298int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 299{ 300 return pthread_mutex_lock(__m); 301} 302 303bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 304{ 305 return pthread_mutex_trylock(__m) == 0; 306} 307 308int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 309{ 310 return pthread_mutex_unlock(__m); 311} 312 313int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 314{ 315 return pthread_mutex_destroy(__m); 316} 317 318// Condition Variable 319int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 320{ 321 return pthread_cond_signal(__cv); 322} 323 324int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 325{ 326 return pthread_cond_broadcast(__cv); 327} 328 329int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 330{ 331 return pthread_cond_wait(__cv, __m); 332} 333 334int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 335 __libcpp_timespec_t *__ts) 336{ 337 return pthread_cond_timedwait(__cv, __m, __ts); 338} 339 340int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 341{ 342 return pthread_cond_destroy(__cv); 343} 344 345// Execute once 346int __libcpp_execute_once(__libcpp_exec_once_flag *__flag, 347 void (*__init_routine)()) { 348 return pthread_once(__flag, __init_routine); 349} 350 351// Thread id 352// Returns non-zero if the thread ids are equal, otherwise 0 353bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2) 354{ 355 return __t1 == __t2; 356} 357 358// Returns non-zero if t1 < t2, otherwise 0 359bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2) 360{ 361 return __t1 < __t2; 362} 363 364// Thread 365bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 366 return __libcpp_thread_get_id(__t) == 0; 367} 368 369int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 370 void *__arg) 371{ 372 return pthread_create(__t, nullptr, __func, __arg); 373} 374 375__libcpp_thread_id __libcpp_thread_get_current_id() 376{ 377 const __libcpp_thread_t __current_thread = pthread_self(); 378 return __libcpp_thread_get_id(&__current_thread); 379} 380 381__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 382{ 383#if defined(__MVS__) 384 return __t->__; 385#else 386 return *__t; 387#endif 388} 389 390int __libcpp_thread_join(__libcpp_thread_t *__t) 391{ 392 return pthread_join(*__t, nullptr); 393} 394 395int __libcpp_thread_detach(__libcpp_thread_t *__t) 396{ 397 return pthread_detach(*__t); 398} 399 400void __libcpp_thread_yield() 401{ 402 sched_yield(); 403} 404 405void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 406{ 407 __libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns); 408 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); 409} 410 411// Thread local storage 412int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 413{ 414 return pthread_key_create(__key, __at_exit); 415} 416 417void *__libcpp_tls_get(__libcpp_tls_key __key) 418{ 419 return pthread_getspecific(__key); 420} 421 422int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 423{ 424 return pthread_setspecific(__key, __p); 425} 426 427#elif defined(_LIBCPP_HAS_THREAD_API_C11) 428 429int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 430{ 431 return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL; 432} 433 434int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 435{ 436 return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 437} 438 439bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 440{ 441 return mtx_trylock(__m) == thrd_success; 442} 443 444int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 445{ 446 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 447} 448 449int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 450{ 451 mtx_destroy(__m); 452 return 0; 453} 454 455int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 456{ 457 return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 458} 459 460bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 461{ 462 return mtx_trylock(__m) == thrd_success; 463} 464 465int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 466{ 467 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 468} 469 470int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 471{ 472 mtx_destroy(__m); 473 return 0; 474} 475 476// Condition Variable 477int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 478{ 479 return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; 480} 481 482int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 483{ 484 return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; 485} 486 487int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 488{ 489 return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL; 490} 491 492int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 493 timespec *__ts) 494{ 495 int __ec = cnd_timedwait(__cv, __m, __ts); 496 return __ec == thrd_timedout ? ETIMEDOUT : __ec; 497} 498 499int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 500{ 501 cnd_destroy(__cv); 502 return 0; 503} 504 505// Execute once 506int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 507 void (*init_routine)(void)) { 508 ::call_once(flag, init_routine); 509 return 0; 510} 511 512// Thread id 513// Returns non-zero if the thread ids are equal, otherwise 0 514bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 515{ 516 return thrd_equal(t1, t2) != 0; 517} 518 519// Returns non-zero if t1 < t2, otherwise 0 520bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 521{ 522 return t1 < t2; 523} 524 525// Thread 526bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 527 return __libcpp_thread_get_id(__t) == 0; 528} 529 530int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 531 void *__arg) 532{ 533 int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg); 534 return __ec == thrd_nomem ? ENOMEM : __ec; 535} 536 537__libcpp_thread_id __libcpp_thread_get_current_id() 538{ 539 return thrd_current(); 540} 541 542__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 543{ 544 return *__t; 545} 546 547int __libcpp_thread_join(__libcpp_thread_t *__t) 548{ 549 return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; 550} 551 552int __libcpp_thread_detach(__libcpp_thread_t *__t) 553{ 554 return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; 555} 556 557void __libcpp_thread_yield() 558{ 559 thrd_yield(); 560} 561 562void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 563{ 564 __libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns); 565 thrd_sleep(&__ts, nullptr); 566} 567 568// Thread local storage 569int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 570{ 571 return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL; 572} 573 574void *__libcpp_tls_get(__libcpp_tls_key __key) 575{ 576 return tss_get(__key); 577} 578 579int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 580{ 581 return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; 582} 583 584#endif 585 586#endif // !_LIBCPP_HAS_NO_THREADS 587 588_LIBCPP_END_NAMESPACE_STD 589 590#endif // _LIBCPP___THREADING_SUPPORT 591