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 <__config> 14#include <chrono> 15#include <iosfwd> 16#include <errno.h> 17 18#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 19#pragma GCC system_header 20#endif 21 22#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 23# include <__external_threading> 24#elif !defined(_LIBCPP_HAS_NO_THREADS) 25 26#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 27# include <pthread.h> 28# include <sched.h> 29#endif 30 31#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 32 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \ 33 defined(_LIBCPP_HAS_THREAD_API_WIN32) 34#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 35#else 36#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 37#endif 38 39#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) 40#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) 41#else 42#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 43#endif 44 45typedef ::timespec __libcpp_timespec_t; 46#endif // !defined(_LIBCPP_HAS_NO_THREADS) 47 48_LIBCPP_PUSH_MACROS 49#include <__undef_macros> 50 51_LIBCPP_BEGIN_NAMESPACE_STD 52 53#if !defined(_LIBCPP_HAS_NO_THREADS) 54 55#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 56// Mutex 57typedef pthread_mutex_t __libcpp_mutex_t; 58#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 59 60typedef pthread_mutex_t __libcpp_recursive_mutex_t; 61 62// Condition Variable 63typedef pthread_cond_t __libcpp_condvar_t; 64#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 65 66// Execute once 67typedef pthread_once_t __libcpp_exec_once_flag; 68#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 69 70// Thread id 71typedef pthread_t __libcpp_thread_id; 72 73// Thread 74#define _LIBCPP_NULL_THREAD 0U 75 76typedef pthread_t __libcpp_thread_t; 77 78// Thread Local Storage 79typedef pthread_key_t __libcpp_tls_key; 80 81#define _LIBCPP_TLS_DESTRUCTOR_CC 82#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 83// Mutex 84typedef void* __libcpp_mutex_t; 85#define _LIBCPP_MUTEX_INITIALIZER 0 86 87#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) 88typedef void* __libcpp_recursive_mutex_t[6]; 89#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) 90typedef void* __libcpp_recursive_mutex_t[5]; 91#else 92# error Unsupported architecture 93#endif 94 95// Condition Variable 96typedef void* __libcpp_condvar_t; 97#define _LIBCPP_CONDVAR_INITIALIZER 0 98 99// Execute Once 100typedef void* __libcpp_exec_once_flag; 101#define _LIBCPP_EXEC_ONCE_INITIALIZER 0 102 103// Thread ID 104typedef long __libcpp_thread_id; 105 106// Thread 107#define _LIBCPP_NULL_THREAD 0U 108 109typedef void* __libcpp_thread_t; 110 111// Thread Local Storage 112typedef long __libcpp_tls_key; 113 114#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall 115#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 116 117#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 118// Mutex 119_LIBCPP_THREAD_ABI_VISIBILITY 120int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 121 122_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 123int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 124 125_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 126bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 127 128_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 129int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 130 131_LIBCPP_THREAD_ABI_VISIBILITY 132int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 133 134_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 135int __libcpp_mutex_lock(__libcpp_mutex_t *__m); 136 137_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 138bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 139 140_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 141int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 142 143_LIBCPP_THREAD_ABI_VISIBILITY 144int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 145 146// Condition variable 147_LIBCPP_THREAD_ABI_VISIBILITY 148int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 149 150_LIBCPP_THREAD_ABI_VISIBILITY 151int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 152 153_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 154int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 155 156_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 157int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 158 __libcpp_timespec_t *__ts); 159 160_LIBCPP_THREAD_ABI_VISIBILITY 161int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 162 163// Execute once 164_LIBCPP_THREAD_ABI_VISIBILITY 165int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 166 void (*init_routine)()); 167 168// Thread id 169_LIBCPP_THREAD_ABI_VISIBILITY 170bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 171 172_LIBCPP_THREAD_ABI_VISIBILITY 173bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 174 175// Thread 176_LIBCPP_THREAD_ABI_VISIBILITY 177bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 178 179_LIBCPP_THREAD_ABI_VISIBILITY 180int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 181 void *__arg); 182 183_LIBCPP_THREAD_ABI_VISIBILITY 184__libcpp_thread_id __libcpp_thread_get_current_id(); 185 186_LIBCPP_THREAD_ABI_VISIBILITY 187__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 188 189_LIBCPP_THREAD_ABI_VISIBILITY 190int __libcpp_thread_join(__libcpp_thread_t *__t); 191 192_LIBCPP_THREAD_ABI_VISIBILITY 193int __libcpp_thread_detach(__libcpp_thread_t *__t); 194 195_LIBCPP_THREAD_ABI_VISIBILITY 196void __libcpp_thread_yield(); 197 198_LIBCPP_THREAD_ABI_VISIBILITY 199void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 200 201// Thread local storage 202_LIBCPP_THREAD_ABI_VISIBILITY 203int __libcpp_tls_create(__libcpp_tls_key* __key, 204 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 205 206_LIBCPP_THREAD_ABI_VISIBILITY 207void *__libcpp_tls_get(__libcpp_tls_key __key); 208 209_LIBCPP_THREAD_ABI_VISIBILITY 210int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 211 212#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 213 214#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 215 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \ 216 defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 217 218int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 219{ 220 pthread_mutexattr_t attr; 221 int __ec = pthread_mutexattr_init(&attr); 222 if (__ec) 223 return __ec; 224 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 225 if (__ec) { 226 pthread_mutexattr_destroy(&attr); 227 return __ec; 228 } 229 __ec = pthread_mutex_init(__m, &attr); 230 if (__ec) { 231 pthread_mutexattr_destroy(&attr); 232 return __ec; 233 } 234 __ec = pthread_mutexattr_destroy(&attr); 235 if (__ec) { 236 pthread_mutex_destroy(__m); 237 return __ec; 238 } 239 return 0; 240} 241 242int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 243{ 244 return pthread_mutex_lock(__m); 245} 246 247bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 248{ 249 return pthread_mutex_trylock(__m) == 0; 250} 251 252int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 253{ 254 return pthread_mutex_unlock(__m); 255} 256 257int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 258{ 259 return pthread_mutex_destroy(__m); 260} 261 262int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 263{ 264 return pthread_mutex_lock(__m); 265} 266 267bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 268{ 269 return pthread_mutex_trylock(__m) == 0; 270} 271 272int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 273{ 274 return pthread_mutex_unlock(__m); 275} 276 277int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 278{ 279 return pthread_mutex_destroy(__m); 280} 281 282// Condition Variable 283int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 284{ 285 return pthread_cond_signal(__cv); 286} 287 288int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 289{ 290 return pthread_cond_broadcast(__cv); 291} 292 293int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 294{ 295 return pthread_cond_wait(__cv, __m); 296} 297 298int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 299 __libcpp_timespec_t *__ts) 300{ 301 return pthread_cond_timedwait(__cv, __m, __ts); 302} 303 304int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 305{ 306 return pthread_cond_destroy(__cv); 307} 308 309// Execute once 310int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 311 void (*init_routine)()) { 312 return pthread_once(flag, init_routine); 313} 314 315// Thread id 316// Returns non-zero if the thread ids are equal, otherwise 0 317bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 318{ 319 return pthread_equal(t1, t2) != 0; 320} 321 322// Returns non-zero if t1 < t2, otherwise 0 323bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 324{ 325 return t1 < t2; 326} 327 328// Thread 329bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 330 return *__t == 0; 331} 332 333int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 334 void *__arg) 335{ 336 return pthread_create(__t, 0, __func, __arg); 337} 338 339__libcpp_thread_id __libcpp_thread_get_current_id() 340{ 341 return pthread_self(); 342} 343 344__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 345{ 346 return *__t; 347} 348 349int __libcpp_thread_join(__libcpp_thread_t *__t) 350{ 351 return pthread_join(*__t, 0); 352} 353 354int __libcpp_thread_detach(__libcpp_thread_t *__t) 355{ 356 return pthread_detach(*__t); 357} 358 359void __libcpp_thread_yield() 360{ 361 sched_yield(); 362} 363 364void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 365{ 366 using namespace chrono; 367 seconds __s = duration_cast<seconds>(__ns); 368 __libcpp_timespec_t __ts; 369 typedef decltype(__ts.tv_sec) ts_sec; 370 _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max(); 371 372 if (__s.count() < __ts_sec_max) 373 { 374 __ts.tv_sec = static_cast<ts_sec>(__s.count()); 375 __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count()); 376 } 377 else 378 { 379 __ts.tv_sec = __ts_sec_max; 380 __ts.tv_nsec = 999999999; // (10^9 - 1) 381 } 382 383 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); 384} 385 386// Thread local storage 387int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 388{ 389 return pthread_key_create(__key, __at_exit); 390} 391 392void *__libcpp_tls_get(__libcpp_tls_key __key) 393{ 394 return pthread_getspecific(__key); 395} 396 397int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 398{ 399 return pthread_setspecific(__key, __p); 400} 401 402#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 403 404class _LIBCPP_TYPE_VIS thread; 405class _LIBCPP_TYPE_VIS __thread_id; 406 407namespace this_thread 408{ 409 410_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; 411 412} // this_thread 413 414template<> struct hash<__thread_id>; 415 416class _LIBCPP_TEMPLATE_VIS __thread_id 417{ 418 // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 419 // NULL is the no-thread value on Darwin. Someone needs to check 420 // on other platforms. We assume 0 works everywhere for now. 421 __libcpp_thread_id __id_; 422 423public: 424 _LIBCPP_INLINE_VISIBILITY 425 __thread_id() _NOEXCEPT : __id_(0) {} 426 427 friend _LIBCPP_INLINE_VISIBILITY 428 bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT 429 { // don't pass id==0 to underlying routines 430 if (__x.__id_ == 0) return __y.__id_ == 0; 431 if (__y.__id_ == 0) return false; 432 return __libcpp_thread_id_equal(__x.__id_, __y.__id_); 433 } 434 friend _LIBCPP_INLINE_VISIBILITY 435 bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT 436 {return !(__x == __y);} 437 friend _LIBCPP_INLINE_VISIBILITY 438 bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT 439 { // id==0 is always less than any other thread_id 440 if (__x.__id_ == 0) return __y.__id_ != 0; 441 if (__y.__id_ == 0) return false; 442 return __libcpp_thread_id_less(__x.__id_, __y.__id_); 443 } 444 friend _LIBCPP_INLINE_VISIBILITY 445 bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT 446 {return !(__y < __x);} 447 friend _LIBCPP_INLINE_VISIBILITY 448 bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT 449 {return __y < __x ;} 450 friend _LIBCPP_INLINE_VISIBILITY 451 bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT 452 {return !(__x < __y);} 453 454 _LIBCPP_INLINE_VISIBILITY 455 void __reset() { __id_ = 0; } 456 457 template<class _CharT, class _Traits> 458 friend 459 _LIBCPP_INLINE_VISIBILITY 460 basic_ostream<_CharT, _Traits>& 461 operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); 462 463private: 464 _LIBCPP_INLINE_VISIBILITY 465 __thread_id(__libcpp_thread_id __id) : __id_(__id) {} 466 467 friend __thread_id this_thread::get_id() _NOEXCEPT; 468 friend class _LIBCPP_TYPE_VIS thread; 469 friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; 470}; 471 472namespace this_thread 473{ 474 475inline _LIBCPP_INLINE_VISIBILITY 476__thread_id 477get_id() _NOEXCEPT 478{ 479 return __libcpp_thread_get_current_id(); 480} 481 482} // this_thread 483 484#endif // !_LIBCPP_HAS_NO_THREADS 485 486_LIBCPP_END_NAMESPACE_STD 487 488_LIBCPP_POP_MACROS 489 490#endif // _LIBCPP_THREADING_SUPPORT 491