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_LIBCPP_BEGIN_NAMESPACE_STD 44 45#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 46// Mutex 47typedef pthread_mutex_t __libcpp_mutex_t; 48#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 49 50typedef pthread_mutex_t __libcpp_recursive_mutex_t; 51 52// Condition Variable 53typedef pthread_cond_t __libcpp_condvar_t; 54#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 55 56// Execute once 57typedef pthread_once_t __libcpp_exec_once_flag; 58#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 59 60// Thread id 61typedef pthread_t __libcpp_thread_id; 62 63// Thread 64#define _LIBCPP_NULL_THREAD 0U 65 66typedef pthread_t __libcpp_thread_t; 67 68// Thrad Local Storage 69typedef pthread_key_t __libcpp_tls_key; 70 71#define _LIBCPP_TLS_DESTRUCTOR_CC 72#else 73// Mutex 74typedef SRWLOCK __libcpp_mutex_t; 75#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT 76 77typedef CRITICAL_SECTION __libcpp_recursive_mutex_t; 78 79// Condition Variable 80typedef CONDITION_VARIABLE __libcpp_condvar_t; 81#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT 82 83// Execute Once 84typedef INIT_ONCE __libcpp_exec_once_flag; 85#define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT 86 87// Thread ID 88typedef DWORD __libcpp_thread_id; 89 90// Thread 91#define _LIBCPP_NULL_THREAD 0U 92 93typedef HANDLE __libcpp_thread_t; 94 95// Thread Local Storage 96typedef DWORD __libcpp_tls_key; 97 98#define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI 99#endif 100 101// Mutex 102_LIBCPP_THREAD_ABI_VISIBILITY 103int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 104 105_LIBCPP_THREAD_ABI_VISIBILITY 106int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 107 108_LIBCPP_THREAD_ABI_VISIBILITY 109bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 110 111_LIBCPP_THREAD_ABI_VISIBILITY 112int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 113 114_LIBCPP_THREAD_ABI_VISIBILITY 115int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 116 117_LIBCPP_THREAD_ABI_VISIBILITY 118int __libcpp_mutex_lock(__libcpp_mutex_t *__m); 119 120_LIBCPP_THREAD_ABI_VISIBILITY 121bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 122 123_LIBCPP_THREAD_ABI_VISIBILITY 124int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 125 126_LIBCPP_THREAD_ABI_VISIBILITY 127int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 128 129// Condition variable 130_LIBCPP_THREAD_ABI_VISIBILITY 131int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 132 133_LIBCPP_THREAD_ABI_VISIBILITY 134int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 135 136_LIBCPP_THREAD_ABI_VISIBILITY 137int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 138 139_LIBCPP_THREAD_ABI_VISIBILITY 140int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 141 timespec *__ts); 142 143_LIBCPP_THREAD_ABI_VISIBILITY 144int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 145 146// Execute once 147_LIBCPP_THREAD_ABI_VISIBILITY 148int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 149 void (*init_routine)(void)); 150 151// Thread id 152#if defined(__APPLE__) && !defined(__arm__) 153_LIBCPP_THREAD_ABI_VISIBILITY 154mach_port_t __libcpp_thread_get_port(); 155#endif 156 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#if defined(__APPLE__) && !defined(__arm__) 301mach_port_t __libcpp_thread_get_port() { 302 return pthread_mach_thread_np(pthread_self()); 303} 304#endif 305 306// Returns non-zero if the thread ids are equal, otherwise 0 307bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 308{ 309 return pthread_equal(t1, t2) != 0; 310} 311 312// Returns non-zero if t1 < t2, otherwise 0 313bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 314{ 315 return t1 < t2; 316} 317 318// Thread 319bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 320 return *__t == 0; 321} 322 323int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 324 void *__arg) 325{ 326 return pthread_create(__t, 0, __func, __arg); 327} 328 329__libcpp_thread_id __libcpp_thread_get_current_id() 330{ 331 return pthread_self(); 332} 333 334__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 335{ 336 return *__t; 337} 338 339int __libcpp_thread_join(__libcpp_thread_t *__t) 340{ 341 return pthread_join(*__t, 0); 342} 343 344int __libcpp_thread_detach(__libcpp_thread_t *__t) 345{ 346 return pthread_detach(*__t); 347} 348 349void __libcpp_thread_yield() 350{ 351 sched_yield(); 352} 353 354// Thread local storage 355int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 356{ 357 return pthread_key_create(__key, __at_exit); 358} 359 360void *__libcpp_tls_get(__libcpp_tls_key __key) 361{ 362 return pthread_getspecific(__key); 363} 364 365int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 366{ 367 return pthread_setspecific(__key, __p); 368} 369 370#elif defined(_LIBCPP_HAS_THREAD_API_WIN32) 371 372// Mutex 373int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 374{ 375 InitializeCriticalSection(__m); 376 return 0; 377} 378 379int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 380{ 381 EnterCriticalSection(__m); 382 return 0; 383} 384 385bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 386{ 387 return TryEnterCriticalSection(__m) != 0; 388} 389 390int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 391{ 392 LeaveCriticalSection(__m); 393 return 0; 394} 395 396int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 397{ 398 DeleteCriticalSection(__m); 399 return 0; 400} 401 402int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 403{ 404 AcquireSRWLockExclusive(__m); 405 return 0; 406} 407 408bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 409{ 410 return TryAcquireSRWLockExclusive(__m) != 0; 411} 412 413int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 414{ 415 ReleaseSRWLockExclusive(__m); 416 return 0; 417} 418 419int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 420{ 421 static_cast<void>(__m); 422 return 0; 423} 424 425// Condition Variable 426int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 427{ 428 WakeConditionVariable(__cv); 429 return 0; 430} 431 432int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 433{ 434 WakeAllConditionVariable(__cv); 435 return 0; 436} 437 438int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 439{ 440 SleepConditionVariableSRW(__cv, __m, INFINITE, 0); 441 return 0; 442} 443 444int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 445 timespec *__ts) 446{ 447 using namespace _VSTD::chrono; 448 449 auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec); 450 auto abstime = 451 system_clock::time_point(duration_cast<system_clock::duration>(duration)); 452 auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now()); 453 454 if (!SleepConditionVariableSRW(__cv, __m, 455 timeout_ms.count() > 0 ? timeout_ms.count() 456 : 0, 457 0)) 458 return GetLastError(); 459 return 0; 460} 461 462int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 463{ 464 static_cast<void>(__cv); 465 return 0; 466} 467 468// Execute Once 469static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK 470__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter, 471 PVOID *__context) 472{ 473 static_cast<void>(__init_once); 474 static_cast<void>(__context); 475 476 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter); 477 init_routine(); 478 return TRUE; 479} 480 481int __libcpp_execute_once(__libcpp_exec_once_flag *__flag, 482 void (*__init_routine)(void)) 483{ 484 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk, 485 reinterpret_cast<void *>(__init_routine), NULL)) 486 return GetLastError(); 487 return 0; 488} 489 490// Thread ID 491bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs, 492 __libcpp_thread_id __rhs) 493{ 494 return __lhs == __rhs; 495} 496 497bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs) 498{ 499 return __lhs < __rhs; 500} 501 502// Thread 503struct __libcpp_beginthreadex_thunk_data 504{ 505 void *(*__func)(void *); 506 void *__arg; 507}; 508 509static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI 510__libcpp_beginthreadex_thunk(void *__raw_data) 511{ 512 auto *__data = 513 static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data); 514 auto *__func = __data->__func; 515 void *__arg = __data->__arg; 516 delete __data; 517 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg))); 518} 519 520bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 521 return *__t == 0; 522} 523 524int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 525 void *__arg) 526{ 527 auto *__data = new __libcpp_beginthreadex_thunk_data; 528 __data->__func = __func; 529 __data->__arg = __arg; 530 531 *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, 532 __libcpp_beginthreadex_thunk, 533 __data, 0, nullptr)); 534 535 if (*__t) 536 return 0; 537 return GetLastError(); 538} 539 540__libcpp_thread_id __libcpp_thread_get_current_id() 541{ 542 return GetCurrentThreadId(); 543} 544 545__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 546{ 547 return GetThreadId(*__t); 548} 549 550int __libcpp_thread_join(__libcpp_thread_t *__t) 551{ 552 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED) 553 return GetLastError(); 554 if (!CloseHandle(*__t)) 555 return GetLastError(); 556 return 0; 557} 558 559int __libcpp_thread_detach(__libcpp_thread_t *__t) 560{ 561 if (!CloseHandle(*__t)) 562 return GetLastError(); 563 return 0; 564} 565 566void __libcpp_thread_yield() 567{ 568 SwitchToThread(); 569} 570 571// Thread Local Storage 572int __libcpp_tls_create(__libcpp_tls_key* __key, 573 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)) 574{ 575 *__key = FlsAlloc(__at_exit); 576 if (*__key == FLS_OUT_OF_INDEXES) 577 return GetLastError(); 578 return 0; 579} 580 581void *__libcpp_tls_get(__libcpp_tls_key __key) 582{ 583 return FlsGetValue(__key); 584} 585 586int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 587{ 588 if (!FlsSetValue(__key, __p)) 589 return GetLastError(); 590 return 0; 591} 592 593#endif // _LIBCPP_HAS_THREAD_API_PTHREAD 594 595#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 596 597_LIBCPP_END_NAMESPACE_STD 598 599#endif // !_LIBCPP_HAS_NO_THREADS 600 601#endif // _LIBCPP_THREADING_SUPPORT 602