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