|
24 | 24 | #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) |
25 | 25 | # include <pthread.h> |
26 | 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> |
27 | 34 | #endif |
28 | 35 |
|
29 | 36 | #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ |
@@ -58,6 +65,33 @@ typedef pthread_t __libcpp_thread_t; |
58 | 65 |
|
59 | 66 | // Thrad Local Storage |
60 | 67 | typedef pthread_key_t __libcpp_tls_key; |
| 68 | + |
| 69 | +#define _LIBCPP_TLS_DESTRUCTOR_CC |
| 70 | +#else |
| 71 | +// Mutex |
| 72 | +typedef SRWLOCK __libcpp_mutex_t; |
| 73 | +#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT |
| 74 | + |
| 75 | +typedef CRITICAL_SECTION __libcpp_recursive_mutex_t; |
| 76 | + |
| 77 | +// Condition Variable |
| 78 | +typedef CONDITION_VARIABLE __libcpp_condvar_t; |
| 79 | +#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT |
| 80 | + |
| 81 | +// Execute Once |
| 82 | +typedef INIT_ONCE __libcpp_exec_once_flag; |
| 83 | +#define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT |
| 84 | + |
| 85 | +// Thread ID |
| 86 | +typedef DWORD __libcpp_thread_id; |
| 87 | + |
| 88 | +// Thread |
| 89 | +typedef HANDLE __libcpp_thread_t; |
| 90 | + |
| 91 | +// Thread Local Storage |
| 92 | +typedef DWORD __libcpp_tls_key; |
| 93 | + |
| 94 | +#define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI |
61 | 95 | #endif |
62 | 96 |
|
63 | 97 | // Mutex |
@@ -144,7 +178,8 @@ void __libcpp_thread_yield(); |
144 | 178 |
|
145 | 179 | // Thread local storage |
146 | 180 | _LIBCPP_THREAD_ABI_VISIBILITY |
147 | | -int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)); |
| 181 | +int __libcpp_tls_create(__libcpp_tls_key* __key, |
| 182 | + void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); |
148 | 183 |
|
149 | 184 | _LIBCPP_THREAD_ABI_VISIBILITY |
150 | 185 | void *__libcpp_tls_get(__libcpp_tls_key __key); |
@@ -321,6 +356,224 @@ int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) |
321 | 356 | return pthread_setspecific(__key, __p); |
322 | 357 | } |
323 | 358 |
|
| 359 | +#elif defined(_LIBCPP_HAS_THREAD_API_WIN32) |
| 360 | + |
| 361 | +// Mutex |
| 362 | +int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) |
| 363 | +{ |
| 364 | + InitializeCriticalSection(__m); |
| 365 | + return 0; |
| 366 | +} |
| 367 | + |
| 368 | +int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) |
| 369 | +{ |
| 370 | + EnterCriticalSection(__m); |
| 371 | + return 0; |
| 372 | +} |
| 373 | + |
| 374 | +int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) |
| 375 | +{ |
| 376 | + TryEnterCriticalSection(__m); |
| 377 | + return 0; |
| 378 | +} |
| 379 | + |
| 380 | +int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) |
| 381 | +{ |
| 382 | + LeaveCriticalSection(__m); |
| 383 | + return 0; |
| 384 | +} |
| 385 | + |
| 386 | +int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) |
| 387 | +{ |
| 388 | + static_cast<void>(__m); |
| 389 | + return 0; |
| 390 | +} |
| 391 | + |
| 392 | +int __libcpp_mutex_lock(__libcpp_mutex_t *__m) |
| 393 | +{ |
| 394 | + AcquireSRWLockExclusive(__m); |
| 395 | + return 0; |
| 396 | +} |
| 397 | + |
| 398 | +int __libcpp_mutex_trylock(__libcpp_mutex_t *__m) |
| 399 | +{ |
| 400 | + TryAcquireSRWLockExclusive(__m); |
| 401 | + return 0; |
| 402 | +} |
| 403 | + |
| 404 | +int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) |
| 405 | +{ |
| 406 | + ReleaseSRWLockExclusive(__m); |
| 407 | + return 0; |
| 408 | +} |
| 409 | + |
| 410 | +int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) |
| 411 | +{ |
| 412 | + static_cast<void>(__m); |
| 413 | + return 0; |
| 414 | +} |
| 415 | + |
| 416 | +// Condition Variable |
| 417 | +int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) |
| 418 | +{ |
| 419 | + WakeConditionVariable(__cv); |
| 420 | + return 0; |
| 421 | +} |
| 422 | + |
| 423 | +int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) |
| 424 | +{ |
| 425 | + WakeAllConditionVariable(__cv); |
| 426 | + return 0; |
| 427 | +} |
| 428 | + |
| 429 | +int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) |
| 430 | +{ |
| 431 | + SleepConditionVariableSRW(__cv, __m, INFINITE, 0); |
| 432 | + return 0; |
| 433 | +} |
| 434 | + |
| 435 | +int __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 | + |
| 453 | +int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) |
| 454 | +{ |
| 455 | + static_cast<void>(__cv); |
| 456 | + return 0; |
| 457 | +} |
| 458 | + |
| 459 | +// Execute Once |
| 460 | +static 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 | + |
| 472 | +int __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 |
| 482 | +bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs, |
| 483 | + __libcpp_thread_id __rhs) |
| 484 | +{ |
| 485 | + return __lhs == __rhs; |
| 486 | +} |
| 487 | + |
| 488 | +bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs) |
| 489 | +{ |
| 490 | + return __lhs < __rhs; |
| 491 | +} |
| 492 | + |
| 493 | +// Thread |
| 494 | +struct __libcpp_beginthreadex_thunk_data |
| 495 | +{ |
| 496 | + void *(*__func)(void *); |
| 497 | + void *__arg; |
| 498 | +}; |
| 499 | + |
| 500 | +static 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 | + |
| 509 | +int __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 | + |
| 534 | +int __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 | + |
| 543 | +int __libcpp_thread_detach(__libcpp_thread_t *__t) |
| 544 | +{ |
| 545 | + if (!CloseHandle(*__t)) |
| 546 | + return GetLastError(); |
| 547 | + return 0; |
| 548 | +} |
| 549 | + |
| 550 | +void __libcpp_thread_yield() |
| 551 | +{ |
| 552 | + SwitchToThread(); |
| 553 | +} |
| 554 | + |
| 555 | +// Thread Local Storage |
| 556 | +int __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 | + |
| 565 | +void *__libcpp_tls_get(__libcpp_tls_key __key) |
| 566 | +{ |
| 567 | + return FlsGetValue(__key); |
| 568 | +} |
| 569 | + |
| 570 | +int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) |
| 571 | +{ |
| 572 | + if (!FlsSetValue(__key, __p)) |
| 573 | + return GetLastError(); |
| 574 | + return 0; |
| 575 | +} |
| 576 | + |
324 | 577 | #endif // _LIBCPP_HAS_THREAD_API_PTHREAD |
325 | 578 |
|
326 | 579 | #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL |
|
0 commit comments