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