Skip to content

Commit 3085ae0

Browse files
adierkingcompnerd
authored andcommitted
tests: support the timer source tests on Windows
PR #453 provides an initial implementation for timer support on Windows. Support building and running the `DISPATCH_SOURCE_TYPE_TIMER` tests so we can easily verify that timers work correctly. These tests should pass on Windows with this and #453 applied: - dispatch_drift - dispatch_suspend_timer - dispatch_timer - dispatch_timer_bit31 - dispatch_timer_bit63 - dispatch_timer_set_time - dispatch_timer_short - dispatch_timer_timeout
1 parent b6b1975 commit 3085ae0

8 files changed

+78
-16
lines changed

tests/CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,10 @@ add_unit_test(dispatch_c99 NO_BSD_OVERLAY SOURCES dispatch_c99.c)
192192
add_unit_test(dispatch_plusplus SOURCES dispatch_plusplus.cpp)
193193

194194
# test-specific link options
195-
target_link_libraries(dispatch_group PRIVATE m)
196-
target_link_libraries(dispatch_timer_short PRIVATE m)
195+
if(NOT WIN32)
196+
target_link_libraries(dispatch_group PRIVATE m)
197+
target_link_libraries(dispatch_timer_short PRIVATE m)
198+
endif()
197199

198200
# test-specific compile options
199201
set_target_properties(dispatch_c99 PROPERTIES C_STANDARD 99)

tests/dispatch_drift.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
#include <mach/mach_time.h>
2323
#endif
2424
#include <dispatch/dispatch.h>
25-
#include <sys/time.h>
2625
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
26+
#include <sys/time.h>
2727
#include <unistd.h>
2828
#endif
2929
#include <stdio.h>
@@ -46,8 +46,13 @@ main(int argc __attribute__((unused)), char* argv[] __attribute__((unused)))
4646
__block uint32_t count = 0;
4747
__block double last_jitter = 0;
4848
__block double drift_sum = 0;
49+
#if defined(_WIN32)
50+
// 25 times a second (Windows timer resolution is poor)
51+
uint64_t interval = 1000000000 / 25;
52+
#else
4953
// 100 times a second
5054
uint64_t interval = 1000000000 / 100;
55+
#endif
5156
double interval_d = interval / 1000000000.0;
5257
// for 25 seconds
5358
unsigned int target = (unsigned int)(25.0 / interval_d);

tests/dispatch_timer_bit31.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
#include <assert.h>
2222
#include <stdio.h>
2323
#include <string.h>
24+
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
2425
#include <sys/time.h>
26+
#endif
2527

2628
#include <dispatch/dispatch.h>
2729

tests/dispatch_timer_bit63.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
#include <assert.h>
2222
#include <stdio.h>
2323
#include <string.h>
24+
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
2425
#include <sys/time.h>
26+
#endif
2527

2628
#include <dispatch/dispatch.h>
2729

tests/dispatch_timer_set_time.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
* @APPLE_APACHE_LICENSE_HEADER_END@
1919
*/
2020

21-
#include <sys/time.h>
2221
#include <assert.h>
2322
#include <stdio.h>
2423
#include <string.h>
24+
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
2525
#include <sys/time.h>
26+
#endif
2627

2728
#include <dispatch/dispatch.h>
2829

tests/dispatch_timer_timeout.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
#include <assert.h>
2222
#include <stdio.h>
2323
#include <string.h>
24+
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
2425
#include <sys/time.h>
26+
#endif
2527

2628
#include <dispatch/dispatch.h>
2729

tests/generic_win_port.c

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -183,18 +183,50 @@ gettimeofday(struct timeval *tp, void *tzp)
183183
return 0;
184184
}
185185

186+
typedef void (WINAPI *QueryUnbiasedInterruptTimePreciseT)(PULONGLONG);
187+
static QueryUnbiasedInterruptTimePreciseT QueryUnbiasedInterruptTimePrecisePtr;
188+
189+
static BOOL
190+
mach_absolute_time_init(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContext)
191+
{
192+
// QueryUnbiasedInterruptTimePrecise() is declared in the Windows headers
193+
// but it isn't available in any import libraries. We must manually load it
194+
// from KernelBase.dll.
195+
HMODULE kernelbase = LoadLibraryW(L"KernelBase.dll");
196+
if (!kernelbase) {
197+
print_winapi_error("LoadLibraryW", GetLastError());
198+
abort();
199+
}
200+
QueryUnbiasedInterruptTimePrecisePtr =
201+
(QueryUnbiasedInterruptTimePreciseT)GetProcAddress(kernelbase,
202+
"QueryUnbiasedInterruptTimePrecise");
203+
if (!QueryUnbiasedInterruptTimePrecisePtr) {
204+
fprintf(stderr, "QueryUnbiasedInterruptTimePrecise is not available\n");
205+
abort();
206+
}
207+
return TRUE;
208+
}
209+
210+
uint64_t
211+
mach_absolute_time(void)
212+
{
213+
static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
214+
if (!InitOnceExecuteOnce(&init_once, mach_absolute_time_init, NULL, NULL)) {
215+
print_winapi_error("InitOnceExecuteOnce", GetLastError());
216+
abort();
217+
}
218+
ULONGLONG result = 0;
219+
QueryUnbiasedInterruptTimePrecisePtr(&result);
220+
return result * 100; // Convert from 100ns units
221+
}
222+
186223
void
187224
print_winapi_error(const char *function_name, DWORD error)
188225
{
189226
char *message = NULL;
190227
DWORD len = FormatMessageA(
191-
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
192-
NULL,
193-
error,
194-
0,
195-
(LPSTR)&message,
196-
0,
197-
NULL);
228+
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
229+
error, 0, (LPSTR)&message, 0, NULL);
198230
if (len > 0) {
199231
// Note: FormatMessage includes a newline at the end of the message
200232
fprintf(stderr, "%s: %s", function_name, message);
@@ -214,10 +246,6 @@ sleep(unsigned int seconds)
214246
int
215247
usleep(unsigned int usec)
216248
{
217-
DWORD ms = usec / 1000;
218-
if (ms == 0 && usec != 0) {
219-
ms = 1;
220-
}
221-
Sleep(ms);
249+
Sleep((usec + 999) / 1000);
222250
return 0;
223251
}

tests/generic_win_port.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ typedef long long ssize_t;
1212
typedef long ssize_t;
1313
#endif
1414

15+
struct mach_timebase_info {
16+
uint32_t numer;
17+
uint32_t denom;
18+
};
19+
20+
typedef struct mach_timebase_info *mach_timebase_info_t;
21+
typedef struct mach_timebase_info mach_timebase_info_data_t;
22+
1523
static inline int32_t
1624
OSAtomicIncrement32(volatile int32_t *var)
1725
{
@@ -45,6 +53,18 @@ getpid(void);
4553
int
4654
gettimeofday(struct timeval *tp, void *tzp);
4755

56+
uint64_t
57+
mach_absolute_time(void);
58+
59+
static inline
60+
int
61+
mach_timebase_info(mach_timebase_info_t tbi)
62+
{
63+
tbi->numer = 1;
64+
tbi->denom = 1;
65+
return 0;
66+
}
67+
4868
void
4969
print_winapi_error(const char *function_name, DWORD error);
5070

0 commit comments

Comments
 (0)