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__) 78typedef unsigned long long __libcpp_thread_id; 79# else 80typedef 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 {} 97 98typedef mtx_t __libcpp_recursive_mutex_t; 99 100// Condition Variable 101typedef cnd_t __libcpp_condvar_t; 102// cnd_t is a struct so using {} for initialization is valid. 103# define _LIBCPP_CONDVAR_INITIALIZER \ 104 {} 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 int 163__libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m); 164 165_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool 166__libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m); 167 168_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int 169__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 int __libcpp_mutex_lock(__libcpp_mutex_t* __m); 175 176_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m); 177 178_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __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 int 191__libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 192 193_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int 194__libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, __libcpp_timespec_t* __ts); 195 196_LIBCPP_THREAD_ABI_VISIBILITY 197int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 198 199// Execute once 200_LIBCPP_THREAD_ABI_VISIBILITY 201int __libcpp_execute_once(__libcpp_exec_once_flag* __flag, void (*__init_routine)()); 202 203// Thread id 204_LIBCPP_THREAD_ABI_VISIBILITY 205bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2); 206 207_LIBCPP_THREAD_ABI_VISIBILITY 208bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2); 209 210// Thread 211_LIBCPP_THREAD_ABI_VISIBILITY 212bool __libcpp_thread_isnull(const __libcpp_thread_t* __t); 213 214_LIBCPP_THREAD_ABI_VISIBILITY 215int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg); 216 217_LIBCPP_THREAD_ABI_VISIBILITY 218__libcpp_thread_id __libcpp_thread_get_current_id(); 219 220_LIBCPP_THREAD_ABI_VISIBILITY 221__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t); 222 223_LIBCPP_THREAD_ABI_VISIBILITY 224int __libcpp_thread_join(__libcpp_thread_t* __t); 225 226_LIBCPP_THREAD_ABI_VISIBILITY 227int __libcpp_thread_detach(__libcpp_thread_t* __t); 228 229_LIBCPP_THREAD_ABI_VISIBILITY 230void __libcpp_thread_yield(); 231 232_LIBCPP_THREAD_ABI_VISIBILITY 233void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 234 235// Thread local storage 236_LIBCPP_THREAD_ABI_VISIBILITY 237int __libcpp_tls_create(__libcpp_tls_key* __key, void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 238 239_LIBCPP_THREAD_ABI_VISIBILITY 240void* __libcpp_tls_get(__libcpp_tls_key __key); 241 242_LIBCPP_THREAD_ABI_VISIBILITY 243int __libcpp_tls_set(__libcpp_tls_key __key, void* __p); 244 245# endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 246 247# if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 248 249int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m) { 250 pthread_mutexattr_t __attr; 251 int __ec = pthread_mutexattr_init(&__attr); 252 if (__ec) 253 return __ec; 254 __ec = pthread_mutexattr_settype(&__attr, PTHREAD_MUTEX_RECURSIVE); 255 if (__ec) { 256 pthread_mutexattr_destroy(&__attr); 257 return __ec; 258 } 259 __ec = pthread_mutex_init(__m, &__attr); 260 if (__ec) { 261 pthread_mutexattr_destroy(&__attr); 262 return __ec; 263 } 264 __ec = pthread_mutexattr_destroy(&__attr); 265 if (__ec) { 266 pthread_mutex_destroy(__m); 267 return __ec; 268 } 269 return 0; 270} 271 272int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) { return pthread_mutex_lock(__m); } 273 274bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) { return pthread_mutex_trylock(__m) == 0; } 275 276int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m) { return pthread_mutex_unlock(__m); } 277 278int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m) { return pthread_mutex_destroy(__m); } 279 280int __libcpp_mutex_lock(__libcpp_mutex_t* __m) { return pthread_mutex_lock(__m); } 281 282bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) { return pthread_mutex_trylock(__m) == 0; } 283 284int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) { return pthread_mutex_unlock(__m); } 285 286int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) { return pthread_mutex_destroy(__m); } 287 288// Condition Variable 289int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) { return pthread_cond_signal(__cv); } 290 291int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) { return pthread_cond_broadcast(__cv); } 292 293int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) { return pthread_cond_wait(__cv, __m); } 294 295int __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, __libcpp_timespec_t* __ts) { 296 return pthread_cond_timedwait(__cv, __m, __ts); 297} 298 299int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) { return pthread_cond_destroy(__cv); } 300 301// Execute once 302int __libcpp_execute_once(__libcpp_exec_once_flag* __flag, void (*__init_routine)()) { 303 return pthread_once(__flag, __init_routine); 304} 305 306// Thread id 307// Returns non-zero if the thread ids are equal, otherwise 0 308bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2) { return __t1 == __t2; } 309 310// Returns non-zero if t1 < t2, otherwise 0 311bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2) { return __t1 < __t2; } 312 313// Thread 314bool __libcpp_thread_isnull(const __libcpp_thread_t* __t) { return __libcpp_thread_get_id(__t) == 0; } 315 316int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) { 317 return pthread_create(__t, nullptr, __func, __arg); 318} 319 320__libcpp_thread_id __libcpp_thread_get_current_id() { 321 const __libcpp_thread_t __current_thread = pthread_self(); 322 return __libcpp_thread_get_id(&__current_thread); 323} 324 325__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) { 326# if defined(__MVS__) 327 return __t->__; 328# else 329 return *__t; 330# endif 331} 332 333int __libcpp_thread_join(__libcpp_thread_t* __t) { return pthread_join(*__t, nullptr); } 334 335int __libcpp_thread_detach(__libcpp_thread_t* __t) { return pthread_detach(*__t); } 336 337void __libcpp_thread_yield() { sched_yield(); } 338 339void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) { 340 __libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns); 341 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR) 342 ; 343} 344 345// Thread local storage 346int __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*)) { 347 return pthread_key_create(__key, __at_exit); 348} 349 350void* __libcpp_tls_get(__libcpp_tls_key __key) { return pthread_getspecific(__key); } 351 352int __libcpp_tls_set(__libcpp_tls_key __key, void* __p) { return pthread_setspecific(__key, __p); } 353 354# elif defined(_LIBCPP_HAS_THREAD_API_C11) 355 356int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m) { 357 return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL; 358} 359 360int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) { 361 return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 362} 363 364bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) { return mtx_trylock(__m) == thrd_success; } 365 366int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m) { 367 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 368} 369 370int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m) { 371 mtx_destroy(__m); 372 return 0; 373} 374 375int __libcpp_mutex_lock(__libcpp_mutex_t* __m) { return mtx_lock(__m) == thrd_success ? 0 : EINVAL; } 376 377bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) { return mtx_trylock(__m) == thrd_success; } 378 379int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) { return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; } 380 381int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) { 382 mtx_destroy(__m); 383 return 0; 384} 385 386// Condition Variable 387int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) { return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; } 388 389int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) { return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; } 390 391int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) { 392 return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL; 393} 394 395int __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts) { 396 int __ec = cnd_timedwait(__cv, __m, __ts); 397 return __ec == thrd_timedout ? ETIMEDOUT : __ec; 398} 399 400int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) { 401 cnd_destroy(__cv); 402 return 0; 403} 404 405// Execute once 406int __libcpp_execute_once(__libcpp_exec_once_flag* flag, void (*init_routine)(void)) { 407 ::call_once(flag, init_routine); 408 return 0; 409} 410 411// Thread id 412// Returns non-zero if the thread ids are equal, otherwise 0 413bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) { return thrd_equal(t1, t2) != 0; } 414 415// Returns non-zero if t1 < t2, otherwise 0 416bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) { return t1 < t2; } 417 418// Thread 419bool __libcpp_thread_isnull(const __libcpp_thread_t* __t) { return __libcpp_thread_get_id(__t) == 0; } 420 421int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) { 422 int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg); 423 return __ec == thrd_nomem ? ENOMEM : __ec; 424} 425 426__libcpp_thread_id __libcpp_thread_get_current_id() { return thrd_current(); } 427 428__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) { return *__t; } 429 430int __libcpp_thread_join(__libcpp_thread_t* __t) { return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; } 431 432int __libcpp_thread_detach(__libcpp_thread_t* __t) { return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; } 433 434void __libcpp_thread_yield() { thrd_yield(); } 435 436void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) { 437 __libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns); 438 thrd_sleep(&__ts, nullptr); 439} 440 441// Thread local storage 442int __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*)) { 443 return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL; 444} 445 446void* __libcpp_tls_get(__libcpp_tls_key __key) { return tss_get(__key); } 447 448int __libcpp_tls_set(__libcpp_tls_key __key, void* __p) { return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; } 449 450# endif 451 452#endif // !_LIBCPP_HAS_NO_THREADS 453 454_LIBCPP_END_NAMESPACE_STD 455 456#endif // _LIBCPP___THREADING_SUPPORT 457