Skip to content

Commit d57e86e

Browse files
committed
shims: use the precise Windows time functions
`_dispatch_uptime()` and `_dispatch_monotonic_time()` are currently using interrupt time APIs which return values cached by the scheduler. This is causing the dispatch_after test to fail on Windows. Switch them to the "Precise" APIs which incorporate a hardware time reading into their results. Unfortunately, these functions are not exported by any import libraries and we have to locate them at runtime. Also, `_dispatch_monotonic_time()` should not be using the unbiased version of the API because it is expected to include suspend time.
1 parent d0394bf commit d57e86e

File tree

4 files changed

+39
-18
lines changed

4 files changed

+39
-18
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ if(WIN32)
6464
target_sources(dispatch
6565
PRIVATE
6666
shims/generic_sys_queue.h
67+
shims/generic_win_stubs.c
6768
shims/generic_win_stubs.h
6869
shims/getprogname.c)
6970
endif()

src/shims/generic_win_stubs.c

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,40 @@
11
#include "internal.h"
22

3-
/*
4-
* This file contains stubbed out functions we are using during
5-
* the initial Windows port. When the port is complete, this file
6-
* should be empty (and thus removed).
7-
*/
3+
typedef void (WINAPI *_precise_time_fn_t)(PULONGLONG);
84

9-
void
10-
_dispatch_runloop_queue_dispose(dispatch_queue_t dq DISPATCH_UNUSED,
11-
bool *allow_free DISPATCH_UNUSED)
5+
DISPATCH_STATIC_GLOBAL(dispatch_once_t _dispatch_precise_time_pred);
6+
DISPATCH_STATIC_GLOBAL(_precise_time_fn_t _dispatch_QueryInterruptTimePrecise_ptr);
7+
DISPATCH_STATIC_GLOBAL(_precise_time_fn_t _dispatch_QueryUnbiasedInterruptTimePrecise_ptr);
8+
9+
static void
10+
_dispatch_init_precise_time(void *context DISPATCH_UNUSED)
1211
{
13-
WIN_PORT_ERROR();
12+
HMODULE kernelbase = LoadLibraryW(L"KernelBase.dll");
13+
if (!kernelbase) {
14+
DISPATCH_INTERNAL_CRASH(0, "failed to load KernelBase.dll");
15+
}
16+
_dispatch_QueryInterruptTimePrecise_ptr = (_precise_time_fn_t)
17+
GetProcAddress(kernelbase, "QueryInterruptTimePrecise");
18+
_dispatch_QueryUnbiasedInterruptTimePrecise_ptr = (_precise_time_fn_t)
19+
GetProcAddress(kernelbase, "QueryUnbiasedInterruptTimePrecise");
20+
if (!_dispatch_QueryInterruptTimePrecise_ptr) {
21+
DISPATCH_INTERNAL_CRASH(0, "could not locate QueryInterruptTimePrecise");
22+
}
23+
if (!_dispatch_QueryUnbiasedInterruptTimePrecise_ptr) {
24+
DISPATCH_INTERNAL_CRASH(0, "could not locate QueryUnbiasedInterruptTimePrecise");
25+
}
1426
}
1527

1628
void
17-
_dispatch_runloop_queue_xref_dispose(dispatch_queue_t dq DISPATCH_UNUSED)
29+
_dispatch_QueryInterruptTimePrecise(PULONGLONG lpInterruptTimePrecise)
1830
{
19-
WIN_PORT_ERROR();
31+
dispatch_once_f(&_dispatch_precise_time_pred, NULL, _dispatch_init_precise_time);
32+
return _dispatch_QueryInterruptTimePrecise_ptr(lpInterruptTimePrecise);
2033
}
2134

22-
/*
23-
* Stubbed out static data
24-
*/
35+
void
36+
_dispatch_QueryUnbiasedInterruptTimePrecise(PULONGLONG lpUnbiasedInterruptTimePrecise)
37+
{
38+
dispatch_once_f(&_dispatch_precise_time_pred, NULL, _dispatch_init_precise_time);
39+
return _dispatch_QueryUnbiasedInterruptTimePrecise_ptr(lpUnbiasedInterruptTimePrecise);
40+
}

src/shims/generic_win_stubs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,10 @@ typedef __typeof__(_Generic((__SIZE_TYPE__)0, \
3636

3737
#define strcasecmp _stricmp
3838

39+
/*
40+
* Wrappers for dynamically loaded Windows APIs
41+
*/
42+
void _dispatch_QueryInterruptTimePrecise(PULONGLONG lpInterruptTimePrecise);
43+
void _dispatch_QueryUnbiasedInterruptTimePrecise(PULONGLONG lpUnbiasedInterruptTimePrecise);
44+
3945
#endif

src/shims/time.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ _dispatch_uptime(void)
151151
return _dispatch_timespec_to_nano(ts);
152152
#elif defined(_WIN32)
153153
ULONGLONG ullUnbiasedTime;
154-
QueryUnbiasedInterruptTime(&ullUnbiasedTime);
154+
_dispatch_QueryUnbiasedInterruptTimePrecise(&ullUnbiasedTime);
155155
return ullUnbiasedTime * 100;
156156
#else
157157
#error platform needs to implement _dispatch_uptime()
@@ -173,9 +173,7 @@ _dispatch_monotonic_time(void)
173173
return _dispatch_timespec_to_nano(ts);
174174
#elif defined(_WIN32)
175175
ULONGLONG ullTime;
176-
if (!QueryUnbiasedInterruptTime(&ullTime))
177-
return 0;
178-
176+
_dispatch_QueryInterruptTimePrecise(&ullTime);
179177
return ullTime * 100ull;
180178
#else
181179
#error platform needs to implement _dispatch_monotonic_time()

0 commit comments

Comments
 (0)