diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1bd58676a..c2fa8fa64 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,7 @@ if(WIN32) target_sources(dispatch PRIVATE shims/generic_sys_queue.h + shims/generic_win_stubs.c shims/generic_win_stubs.h shims/getprogname.c) endif() diff --git a/src/shims/generic_win_stubs.c b/src/shims/generic_win_stubs.c index 67b6f5134..c48eef66a 100644 --- a/src/shims/generic_win_stubs.c +++ b/src/shims/generic_win_stubs.c @@ -1,24 +1,40 @@ #include "internal.h" -/* - * This file contains stubbed out functions we are using during - * the initial Windows port. When the port is complete, this file - * should be empty (and thus removed). - */ +typedef void (WINAPI *_precise_time_fn_t)(PULONGLONG); -void -_dispatch_runloop_queue_dispose(dispatch_queue_t dq DISPATCH_UNUSED, - bool *allow_free DISPATCH_UNUSED) +DISPATCH_STATIC_GLOBAL(dispatch_once_t _dispatch_precise_time_pred); +DISPATCH_STATIC_GLOBAL(_precise_time_fn_t _dispatch_QueryInterruptTimePrecise_ptr); +DISPATCH_STATIC_GLOBAL(_precise_time_fn_t _dispatch_QueryUnbiasedInterruptTimePrecise_ptr); + +static void +_dispatch_init_precise_time(void *context DISPATCH_UNUSED) { - WIN_PORT_ERROR(); + HMODULE kernelbase = LoadLibraryW(L"KernelBase.dll"); + if (!kernelbase) { + DISPATCH_INTERNAL_CRASH(0, "failed to load KernelBase.dll"); + } + _dispatch_QueryInterruptTimePrecise_ptr = (_precise_time_fn_t) + GetProcAddress(kernelbase, "QueryInterruptTimePrecise"); + _dispatch_QueryUnbiasedInterruptTimePrecise_ptr = (_precise_time_fn_t) + GetProcAddress(kernelbase, "QueryUnbiasedInterruptTimePrecise"); + if (!_dispatch_QueryInterruptTimePrecise_ptr) { + DISPATCH_INTERNAL_CRASH(0, "could not locate QueryInterruptTimePrecise"); + } + if (!_dispatch_QueryUnbiasedInterruptTimePrecise_ptr) { + DISPATCH_INTERNAL_CRASH(0, "could not locate QueryUnbiasedInterruptTimePrecise"); + } } void -_dispatch_runloop_queue_xref_dispose(dispatch_queue_t dq DISPATCH_UNUSED) +_dispatch_QueryInterruptTimePrecise(PULONGLONG lpInterruptTimePrecise) { - WIN_PORT_ERROR(); + dispatch_once_f(&_dispatch_precise_time_pred, NULL, _dispatch_init_precise_time); + return _dispatch_QueryInterruptTimePrecise_ptr(lpInterruptTimePrecise); } -/* - * Stubbed out static data - */ +void +_dispatch_QueryUnbiasedInterruptTimePrecise(PULONGLONG lpUnbiasedInterruptTimePrecise) +{ + dispatch_once_f(&_dispatch_precise_time_pred, NULL, _dispatch_init_precise_time); + return _dispatch_QueryUnbiasedInterruptTimePrecise_ptr(lpUnbiasedInterruptTimePrecise); +} diff --git a/src/shims/generic_win_stubs.h b/src/shims/generic_win_stubs.h index 1ce41f7ec..10b14beeb 100644 --- a/src/shims/generic_win_stubs.h +++ b/src/shims/generic_win_stubs.h @@ -36,4 +36,10 @@ typedef __typeof__(_Generic((__SIZE_TYPE__)0, \ #define strcasecmp _stricmp +/* + * Wrappers for dynamically loaded Windows APIs + */ +void _dispatch_QueryInterruptTimePrecise(PULONGLONG lpInterruptTimePrecise); +void _dispatch_QueryUnbiasedInterruptTimePrecise(PULONGLONG lpUnbiasedInterruptTimePrecise); + #endif diff --git a/src/shims/time.h b/src/shims/time.h index 8fae5a2f2..b57731c9a 100644 --- a/src/shims/time.h +++ b/src/shims/time.h @@ -151,7 +151,7 @@ _dispatch_uptime(void) return _dispatch_timespec_to_nano(ts); #elif defined(_WIN32) ULONGLONG ullUnbiasedTime; - QueryUnbiasedInterruptTime(&ullUnbiasedTime); + _dispatch_QueryUnbiasedInterruptTimePrecise(&ullUnbiasedTime); return ullUnbiasedTime * 100; #else #error platform needs to implement _dispatch_uptime() @@ -173,9 +173,7 @@ _dispatch_monotonic_time(void) return _dispatch_timespec_to_nano(ts); #elif defined(_WIN32) ULONGLONG ullTime; - if (!QueryUnbiasedInterruptTime(&ullTime)) - return 0; - + _dispatch_QueryInterruptTimePrecise(&ullTime); return ullTime * 100ull; #else #error platform needs to implement _dispatch_monotonic_time()