1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// The LLVM Compiler Infrastructure 5// 6// This file is dual licensed under the MIT and the University of Illinois Open 7// Source Licenses. See LICENSE.TXT for details. 8// 9//===----------------------------------------------------------------------===// 10 11#ifndef _LIBCPP_THREADING_SUPPORT 12#define _LIBCPP_THREADING_SUPPORT 13 14#include <__config> 15 16#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 17#pragma GCC system_header 18#endif 19 20#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 21# include <__external_threading> 22#elif !defined(_LIBCPP_HAS_NO_THREADS) 23 24#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 25# include <pthread.h> 26# include <sched.h> 27#elif defined(_LIBCPP_HAS_THREAD_API_WIN32) 28#include <assert.h> 29#include <Windows.h> 30#include <process.h> 31#include <fibersapi.h> 32 33#include <chrono> 34#endif 35 36#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 37 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) 38#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 39#else 40#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 41#endif 42 43#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) 44#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) 45#else 46#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 47#endif 48 49_LIBCPP_BEGIN_NAMESPACE_STD 50 51#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 52// Mutex 53typedef pthread_mutex_t __libcpp_mutex_t; 54#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 55 56typedef pthread_mutex_t __libcpp_recursive_mutex_t; 57 58// Condition Variable 59typedef pthread_cond_t __libcpp_condvar_t; 60#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 61 62// Execute once 63typedef pthread_once_t __libcpp_exec_once_flag; 64#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 65 66// Thread id 67typedef pthread_t __libcpp_thread_id; 68 69// Thread 70#define _LIBCPP_NULL_THREAD 0U 71 72typedef pthread_t __libcpp_thread_t; 73 74// Thrad Local Storage 75typedef pthread_key_t __libcpp_tls_key; 76 77#define _LIBCPP_TLS_DESTRUCTOR_CC 78#else 79// Mutex 80typedef SRWLOCK __libcpp_mutex_t; 81#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT 82 83typedef CRITICAL_SECTION __libcpp_recursive_mutex_t; 84 85// Condition Variable 86typedef CONDITION_VARIABLE __libcpp_condvar_t; 87#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT 88 89// Execute Once 90typedef INIT_ONCE __libcpp_exec_once_flag; 91#define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT 92 93// Thread ID 94typedef DWORD __libcpp_thread_id; 95 96// Thread 97#define _LIBCPP_NULL_THREAD 0U 98 99typedef HANDLE __libcpp_thread_t; 100 101// Thread Local Storage 102typedef DWORD __libcpp_tls_key; 103 104#define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI 105#endif 106 107// Mutex 108_LIBCPP_THREAD_ABI_VISIBILITY 109int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 110 111_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 112int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 113 114_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 115bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 116 117_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 118int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 119 120_LIBCPP_THREAD_ABI_VISIBILITY 121int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 122 123_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 124int __libcpp_mutex_lock(__libcpp_mutex_t *__m); 125 126_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 127bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 128 129_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 130int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 131 132_LIBCPP_THREAD_ABI_VISIBILITY 133int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 134 135// Condition variable 136_LIBCPP_THREAD_ABI_VISIBILITY 137int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 138 139_LIBCPP_THREAD_ABI_VISIBILITY 140int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 141 142_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 143int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 144 145_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 146int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 147 timespec *__ts); 148 149_LIBCPP_THREAD_ABI_VISIBILITY 150int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 151 152// Execute once 153_LIBCPP_THREAD_ABI_VISIBILITY 154int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 155 void (*init_routine)(void)); 156 157// Thread id 158_LIBCPP_THREAD_ABI_VISIBILITY 159bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 160 161_LIBCPP_THREAD_ABI_VISIBILITY 162bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 163 164// Thread 165_LIBCPP_THREAD_ABI_VISIBILITY 166bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 167 168_LIBCPP_THREAD_ABI_VISIBILITY 169int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 170 void *__arg); 171 172_LIBCPP_THREAD_ABI_VISIBILITY 173__libcpp_thread_id __libcpp_thread_get_current_id(); 174 175_LIBCPP_THREAD_ABI_VISIBILITY 176__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 177 178_LIBCPP_THREAD_ABI_VISIBILITY 179int __libcpp_thread_join(__libcpp_thread_t *__t); 180 181_LIBCPP_THREAD_ABI_VISIBILITY 182int __libcpp_thread_detach(__libcpp_thread_t *__t); 183 184_LIBCPP_THREAD_ABI_VISIBILITY 185void __libcpp_thread_yield(); 186 187// Thread local storage 188_LIBCPP_THREAD_ABI_VISIBILITY 189int __libcpp_tls_create(__libcpp_tls_key* __key, 190 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 191 192_LIBCPP_THREAD_ABI_VISIBILITY 193void *__libcpp_tls_get(__libcpp_tls_key __key); 194 195_LIBCPP_THREAD_ABI_VISIBILITY 196int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 197 198#if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 199 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) 200 201#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 202 203int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 204{ 205 pthread_mutexattr_t attr; 206 int __ec = pthread_mutexattr_init(&attr); 207 if (__ec) 208 return __ec; 209 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 210 if (__ec) { 211 pthread_mutexattr_destroy(&attr); 212 return __ec; 213 } 214 __ec = pthread_mutex_init(__m, &attr); 215 if (__ec) { 216 pthread_mutexattr_destroy(&attr); 217 return __ec; 218 } 219 __ec = pthread_mutexattr_destroy(&attr); 220 if (__ec) { 221 pthread_mutex_destroy(__m); 222 return __ec; 223 } 224 return 0; 225} 226 227int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 228{ 229 return pthread_mutex_lock(__m); 230} 231 232bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 233{ 234 return pthread_mutex_trylock(__m) == 0; 235} 236 237int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 238{ 239 return pthread_mutex_unlock(__m); 240} 241 242int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 243{ 244 return pthread_mutex_destroy(__m); 245} 246 247int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 248{ 249 return pthread_mutex_lock(__m); 250} 251 252bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 253{ 254 return pthread_mutex_trylock(__m) == 0; 255} 256 257int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 258{ 259 return pthread_mutex_unlock(__m); 260} 261 262int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 263{ 264 return pthread_mutex_destroy(__m); 265} 266 267// Condition Variable 268int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 269{ 270 return pthread_cond_signal(__cv); 271} 272 273int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 274{ 275 return pthread_cond_broadcast(__cv); 276} 277 278int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 279{ 280 return pthread_cond_wait(__cv, __m); 281} 282 283int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 284 timespec *__ts) 285{ 286 return pthread_cond_timedwait(__cv, __m, __ts); 287} 288 289int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 290{ 291 return pthread_cond_destroy(__cv); 292} 293 294// Execute once 295int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 296 void (*init_routine)(void)) { 297 return pthread_once(flag, init_routine); 298} 299 300// Thread id 301// Returns non-zero if the thread ids are equal, otherwise 0 302bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 303{ 304 return pthread_equal(t1, t2) != 0; 305} 306 307// Returns non-zero if t1 < t2, otherwise 0 308bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 309{ 310 return t1 < t2; 311} 312 313// Thread 314bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 315 return *__t == 0; 316} 317 318int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 319 void *__arg) 320{ 321 return pthread_create(__t, 0, __func, __arg); 322} 323 324__libcpp_thread_id __libcpp_thread_get_current_id() 325{ 326 return pthread_self(); 327} 328 329__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 330{ 331 return *__t; 332} 333 334int __libcpp_thread_join(__libcpp_thread_t *__t) 335{ 336 return pthread_join(*__t, 0); 337} 338 339int __libcpp_thread_detach(__libcpp_thread_t *__t) 340{ 341 return pthread_detach(*__t); 342} 343 344void __libcpp_thread_yield() 345{ 346 sched_yield(); 347} 348 349// Thread local storage 350int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 351{ 352 return pthread_key_create(__key, __at_exit); 353} 354 355void *__libcpp_tls_get(__libcpp_tls_key __key) 356{ 357 return pthread_getspecific(__key); 358} 359 360int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 361{ 362 return pthread_setspecific(__key, __p); 363} 364 365#elif defined(_LIBCPP_HAS_THREAD_API_WIN32) 366 367// Mutex 368int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 369{ 370 InitializeCriticalSection(__m); 371 return 0; 372} 373 374int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 375{ 376 EnterCriticalSection(__m); 377 return 0; 378} 379 380bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 381{ 382 return TryEnterCriticalSection(__m) != 0; 383} 384 385int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 386{ 387 LeaveCriticalSection(__m); 388 return 0; 389} 390 391int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 392{ 393 DeleteCriticalSection(__m); 394 return 0; 395} 396 397int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 398{ 399 AcquireSRWLockExclusive(__m); 400 return 0; 401} 402 403bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 404{ 405 return TryAcquireSRWLockExclusive(__m) != 0; 406} 407 408int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 409{ 410 ReleaseSRWLockExclusive(__m); 411 return 0; 412} 413 414int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 415{ 416 static_cast<void>(__m); 417 return 0; 418} 419 420// Condition Variable 421int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 422{ 423 WakeConditionVariable(__cv); 424 return 0; 425} 426 427int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 428{ 429 WakeAllConditionVariable(__cv); 430 return 0; 431} 432 433int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 434{ 435 SleepConditionVariableSRW(__cv, __m, INFINITE, 0); 436 return 0; 437} 438 439int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 440 timespec *__ts) 441{ 442 using namespace _VSTD::chrono; 443 444 auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec); 445 auto abstime = 446 system_clock::time_point(duration_cast<system_clock::duration>(duration)); 447 auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now()); 448 449 if (!SleepConditionVariableSRW(__cv, __m, 450 timeout_ms.count() > 0 ? timeout_ms.count() 451 : 0, 452 0)) 453 return GetLastError(); 454 return 0; 455} 456 457int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 458{ 459 static_cast<void>(__cv); 460 return 0; 461} 462 463// Execute Once 464static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK 465__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter, 466 PVOID *__context) 467{ 468 static_cast<void>(__init_once); 469 static_cast<void>(__context); 470 471 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter); 472 init_routine(); 473 return TRUE; 474} 475 476int __libcpp_execute_once(__libcpp_exec_once_flag *__flag, 477 void (*__init_routine)(void)) 478{ 479 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk, 480 reinterpret_cast<void *>(__init_routine), NULL)) 481 return GetLastError(); 482 return 0; 483} 484 485// Thread ID 486bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs, 487 __libcpp_thread_id __rhs) 488{ 489 return __lhs == __rhs; 490} 491 492bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs) 493{ 494 return __lhs < __rhs; 495} 496 497// Thread 498struct __libcpp_beginthreadex_thunk_data 499{ 500 void *(*__func)(void *); 501 void *__arg; 502}; 503 504static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI 505__libcpp_beginthreadex_thunk(void *__raw_data) 506{ 507 auto *__data = 508 static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data); 509 auto *__func = __data->__func; 510 void *__arg = __data->__arg; 511 delete __data; 512 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg))); 513} 514 515bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 516 return *__t == 0; 517} 518 519int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 520 void *__arg) 521{ 522 auto *__data = new __libcpp_beginthreadex_thunk_data; 523 __data->__func = __func; 524 __data->__arg = __arg; 525 526 *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, 527 __libcpp_beginthreadex_thunk, 528 __data, 0, nullptr)); 529 530 if (*__t) 531 return 0; 532 return GetLastError(); 533} 534 535__libcpp_thread_id __libcpp_thread_get_current_id() 536{ 537 return GetCurrentThreadId(); 538} 539 540__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 541{ 542 return GetThreadId(*__t); 543} 544 545int __libcpp_thread_join(__libcpp_thread_t *__t) 546{ 547 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED) 548 return GetLastError(); 549 if (!CloseHandle(*__t)) 550 return GetLastError(); 551 return 0; 552} 553 554int __libcpp_thread_detach(__libcpp_thread_t *__t) 555{ 556 if (!CloseHandle(*__t)) 557 return GetLastError(); 558 return 0; 559} 560 561void __libcpp_thread_yield() 562{ 563 SwitchToThread(); 564} 565 566// Thread Local Storage 567int __libcpp_tls_create(__libcpp_tls_key* __key, 568 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)) 569{ 570 *__key = FlsAlloc(__at_exit); 571 if (*__key == FLS_OUT_OF_INDEXES) 572 return GetLastError(); 573 return 0; 574} 575 576void *__libcpp_tls_get(__libcpp_tls_key __key) 577{ 578 return FlsGetValue(__key); 579} 580 581int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 582{ 583 if (!FlsSetValue(__key, __p)) 584 return GetLastError(); 585 return 0; 586} 587 588#endif // _LIBCPP_HAS_THREAD_API_PTHREAD 589 590#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 591 592_LIBCPP_END_NAMESPACE_STD 593 594#endif // !_LIBCPP_HAS_NO_THREADS 595 596#endif // _LIBCPP_THREADING_SUPPORT 597