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 <__thread/poll_with_backoff.h> 18#include <errno.h> 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// Some platforms require <bits/atomic_wide_counter.h> in order for 34// PTHREAD_COND_INITIALIZER to be expanded. Normally that would come 35// in via <pthread.h>, but it's a non-modular header on those platforms, 36// so libc++'s <math.h> usually absorbs atomic_wide_counter.h into the 37// module with <math.h> and makes atomic_wide_counter.h invisible. 38// Include <math.h> here to work around that. 39# include <math.h> 40 41# include <pthread.h> 42# include <sched.h> 43#elif defined(_LIBCPP_HAS_THREAD_API_C11) 44# include <threads.h> 45#endif 46 47#if defined(_LIBCPP_HAS_THREAD_API_WIN32) 48#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_EXPORTED_FROM_ABI 49#else 50#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 51#endif 52 53typedef ::timespec __libcpp_timespec_t; 54#endif // !defined(_LIBCPP_HAS_NO_THREADS) 55 56_LIBCPP_BEGIN_NAMESPACE_STD 57 58#if !defined(_LIBCPP_HAS_NO_THREADS) 59 60#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 61// Mutex 62typedef pthread_mutex_t __libcpp_mutex_t; 63#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 64 65typedef pthread_mutex_t __libcpp_recursive_mutex_t; 66 67// Condition Variable 68typedef pthread_cond_t __libcpp_condvar_t; 69#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 70 71// Execute once 72typedef pthread_once_t __libcpp_exec_once_flag; 73#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 74 75// Thread id 76#if defined(__MVS__) 77 typedef unsigned long long __libcpp_thread_id; 78#else 79 typedef pthread_t __libcpp_thread_id; 80#endif 81 82// Thread 83#define _LIBCPP_NULL_THREAD ((__libcpp_thread_t())) 84typedef pthread_t __libcpp_thread_t; 85 86// Thread Local Storage 87typedef pthread_key_t __libcpp_tls_key; 88 89#define _LIBCPP_TLS_DESTRUCTOR_CC 90#elif defined(_LIBCPP_HAS_THREAD_API_C11) 91// Mutex 92typedef mtx_t __libcpp_mutex_t; 93// mtx_t is a struct so using {} for initialization is valid. 94#define _LIBCPP_MUTEX_INITIALIZER {} 95 96typedef mtx_t __libcpp_recursive_mutex_t; 97 98// Condition Variable 99typedef cnd_t __libcpp_condvar_t; 100// cnd_t is a struct so using {} for initialization is valid. 101#define _LIBCPP_CONDVAR_INITIALIZER {} 102 103// Execute once 104typedef once_flag __libcpp_exec_once_flag; 105#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT 106 107// Thread id 108typedef thrd_t __libcpp_thread_id; 109 110// Thread 111#define _LIBCPP_NULL_THREAD 0U 112 113typedef thrd_t __libcpp_thread_t; 114 115// Thread Local Storage 116typedef tss_t __libcpp_tls_key; 117 118#define _LIBCPP_TLS_DESTRUCTOR_CC 119#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 120// Mutex 121typedef void* __libcpp_mutex_t; 122#define _LIBCPP_MUTEX_INITIALIZER 0 123 124#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) 125typedef void* __libcpp_recursive_mutex_t[6]; 126#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) 127typedef void* __libcpp_recursive_mutex_t[5]; 128#else 129# error Unsupported architecture 130#endif 131 132// Condition Variable 133typedef void* __libcpp_condvar_t; 134#define _LIBCPP_CONDVAR_INITIALIZER 0 135 136// Execute Once 137typedef void* __libcpp_exec_once_flag; 138#define _LIBCPP_EXEC_ONCE_INITIALIZER 0 139 140// Thread ID 141typedef long __libcpp_thread_id; 142 143// Thread 144#define _LIBCPP_NULL_THREAD 0U 145 146typedef void* __libcpp_thread_t; 147 148// Thread Local Storage 149typedef long __libcpp_tls_key; 150 151#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall 152#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 153 154#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 155// Mutex 156_LIBCPP_THREAD_ABI_VISIBILITY 157int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 158 159_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 160int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 161 162_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 163bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 164 165_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 166int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 167 168_LIBCPP_THREAD_ABI_VISIBILITY 169int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 170 171_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 172int __libcpp_mutex_lock(__libcpp_mutex_t *__m); 173 174_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 175bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 176 177_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 178int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 179 180_LIBCPP_THREAD_ABI_VISIBILITY 181int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 182 183// Condition variable 184_LIBCPP_THREAD_ABI_VISIBILITY 185int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 186 187_LIBCPP_THREAD_ABI_VISIBILITY 188int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 189 190_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 191int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 192 193_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 194int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 195 __libcpp_timespec_t *__ts); 196 197_LIBCPP_THREAD_ABI_VISIBILITY 198int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 199 200// Execute once 201_LIBCPP_THREAD_ABI_VISIBILITY 202int __libcpp_execute_once(__libcpp_exec_once_flag *__flag, 203 void (*__init_routine)()); 204 205// Thread id 206_LIBCPP_THREAD_ABI_VISIBILITY 207bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2); 208 209_LIBCPP_THREAD_ABI_VISIBILITY 210bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2); 211 212// Thread 213_LIBCPP_THREAD_ABI_VISIBILITY 214bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 215 216_LIBCPP_THREAD_ABI_VISIBILITY 217int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 218 void *__arg); 219 220_LIBCPP_THREAD_ABI_VISIBILITY 221__libcpp_thread_id __libcpp_thread_get_current_id(); 222 223_LIBCPP_THREAD_ABI_VISIBILITY 224__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 225 226_LIBCPP_THREAD_ABI_VISIBILITY 227int __libcpp_thread_join(__libcpp_thread_t *__t); 228 229_LIBCPP_THREAD_ABI_VISIBILITY 230int __libcpp_thread_detach(__libcpp_thread_t *__t); 231 232_LIBCPP_THREAD_ABI_VISIBILITY 233void __libcpp_thread_yield(); 234 235_LIBCPP_THREAD_ABI_VISIBILITY 236void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 237 238// Thread local storage 239_LIBCPP_THREAD_ABI_VISIBILITY 240int __libcpp_tls_create(__libcpp_tls_key* __key, 241 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 242 243_LIBCPP_THREAD_ABI_VISIBILITY 244void *__libcpp_tls_get(__libcpp_tls_key __key); 245 246_LIBCPP_THREAD_ABI_VISIBILITY 247int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 248 249#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 250 251#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 252 253int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 254{ 255 pthread_mutexattr_t __attr; 256 int __ec = pthread_mutexattr_init(&__attr); 257 if (__ec) 258 return __ec; 259 __ec = pthread_mutexattr_settype(&__attr, PTHREAD_MUTEX_RECURSIVE); 260 if (__ec) { 261 pthread_mutexattr_destroy(&__attr); 262 return __ec; 263 } 264 __ec = pthread_mutex_init(__m, &__attr); 265 if (__ec) { 266 pthread_mutexattr_destroy(&__attr); 267 return __ec; 268 } 269 __ec = pthread_mutexattr_destroy(&__attr); 270 if (__ec) { 271 pthread_mutex_destroy(__m); 272 return __ec; 273 } 274 return 0; 275} 276 277int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 278{ 279 return pthread_mutex_lock(__m); 280} 281 282bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 283{ 284 return pthread_mutex_trylock(__m) == 0; 285} 286 287int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 288{ 289 return pthread_mutex_unlock(__m); 290} 291 292int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 293{ 294 return pthread_mutex_destroy(__m); 295} 296 297int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 298{ 299 return pthread_mutex_lock(__m); 300} 301 302bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 303{ 304 return pthread_mutex_trylock(__m) == 0; 305} 306 307int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 308{ 309 return pthread_mutex_unlock(__m); 310} 311 312int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 313{ 314 return pthread_mutex_destroy(__m); 315} 316 317// Condition Variable 318int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 319{ 320 return pthread_cond_signal(__cv); 321} 322 323int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 324{ 325 return pthread_cond_broadcast(__cv); 326} 327 328int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 329{ 330 return pthread_cond_wait(__cv, __m); 331} 332 333int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 334 __libcpp_timespec_t *__ts) 335{ 336 return pthread_cond_timedwait(__cv, __m, __ts); 337} 338 339int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 340{ 341 return pthread_cond_destroy(__cv); 342} 343 344// Execute once 345int __libcpp_execute_once(__libcpp_exec_once_flag *__flag, 346 void (*__init_routine)()) { 347 return pthread_once(__flag, __init_routine); 348} 349 350// Thread id 351// Returns non-zero if the thread ids are equal, otherwise 0 352bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2) 353{ 354 return __t1 == __t2; 355} 356 357// Returns non-zero if t1 < t2, otherwise 0 358bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2) 359{ 360 return __t1 < __t2; 361} 362 363// Thread 364bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 365 return __libcpp_thread_get_id(__t) == 0; 366} 367 368int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 369 void *__arg) 370{ 371 return pthread_create(__t, nullptr, __func, __arg); 372} 373 374__libcpp_thread_id __libcpp_thread_get_current_id() 375{ 376 const __libcpp_thread_t __current_thread = pthread_self(); 377 return __libcpp_thread_get_id(&__current_thread); 378} 379 380__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 381{ 382#if defined(__MVS__) 383 return __t->__; 384#else 385 return *__t; 386#endif 387} 388 389int __libcpp_thread_join(__libcpp_thread_t *__t) 390{ 391 return pthread_join(*__t, nullptr); 392} 393 394int __libcpp_thread_detach(__libcpp_thread_t *__t) 395{ 396 return pthread_detach(*__t); 397} 398 399void __libcpp_thread_yield() 400{ 401 sched_yield(); 402} 403 404void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 405{ 406 __libcpp_timespec_t __ts = _VSTD::__convert_to_timespec<__libcpp_timespec_t>(__ns); 407 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); 408} 409 410// Thread local storage 411int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 412{ 413 return pthread_key_create(__key, __at_exit); 414} 415 416void *__libcpp_tls_get(__libcpp_tls_key __key) 417{ 418 return pthread_getspecific(__key); 419} 420 421int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 422{ 423 return pthread_setspecific(__key, __p); 424} 425 426#elif defined(_LIBCPP_HAS_THREAD_API_C11) 427 428int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 429{ 430 return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL; 431} 432 433int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 434{ 435 return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 436} 437 438bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 439{ 440 return mtx_trylock(__m) == thrd_success; 441} 442 443int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 444{ 445 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 446} 447 448int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 449{ 450 mtx_destroy(__m); 451 return 0; 452} 453 454int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 455{ 456 return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 457} 458 459bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 460{ 461 return mtx_trylock(__m) == thrd_success; 462} 463 464int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 465{ 466 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 467} 468 469int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 470{ 471 mtx_destroy(__m); 472 return 0; 473} 474 475// Condition Variable 476int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 477{ 478 return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; 479} 480 481int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 482{ 483 return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; 484} 485 486int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 487{ 488 return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL; 489} 490 491int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 492 timespec *__ts) 493{ 494 int __ec = cnd_timedwait(__cv, __m, __ts); 495 return __ec == thrd_timedout ? ETIMEDOUT : __ec; 496} 497 498int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 499{ 500 cnd_destroy(__cv); 501 return 0; 502} 503 504// Execute once 505int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 506 void (*init_routine)(void)) { 507 ::call_once(flag, init_routine); 508 return 0; 509} 510 511// Thread id 512// Returns non-zero if the thread ids are equal, otherwise 0 513bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 514{ 515 return thrd_equal(t1, t2) != 0; 516} 517 518// Returns non-zero if t1 < t2, otherwise 0 519bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 520{ 521 return t1 < t2; 522} 523 524// Thread 525bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 526 return __libcpp_thread_get_id(__t) == 0; 527} 528 529int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 530 void *__arg) 531{ 532 int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg); 533 return __ec == thrd_nomem ? ENOMEM : __ec; 534} 535 536__libcpp_thread_id __libcpp_thread_get_current_id() 537{ 538 return thrd_current(); 539} 540 541__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 542{ 543 return *__t; 544} 545 546int __libcpp_thread_join(__libcpp_thread_t *__t) 547{ 548 return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; 549} 550 551int __libcpp_thread_detach(__libcpp_thread_t *__t) 552{ 553 return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; 554} 555 556void __libcpp_thread_yield() 557{ 558 thrd_yield(); 559} 560 561void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 562{ 563 __libcpp_timespec_t __ts = _VSTD::__convert_to_timespec<__libcpp_timespec_t>(__ns); 564 thrd_sleep(&__ts, nullptr); 565} 566 567// Thread local storage 568int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 569{ 570 return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL; 571} 572 573void *__libcpp_tls_get(__libcpp_tls_key __key) 574{ 575 return tss_get(__key); 576} 577 578int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 579{ 580 return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; 581} 582 583#endif 584 585#endif // !_LIBCPP_HAS_NO_THREADS 586 587_LIBCPP_END_NAMESPACE_STD 588 589#endif // _LIBCPP___THREADING_SUPPORT 590