From ac9236de0bc9ed3000947ef6eeeae1cd874d3071 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Mon, 16 Jan 2017 23:18:46 -0800 Subject: Windows clock fixes. Sleep() on Win32 rounds *down*, leading to truncated timeouts. What we do is change our sleep routing to start incrementally sleeping by 1ms until the tick count is reached. This ensures we don't wake early. This problem affects condition variables too, which means that some timeouts may occur up to one clock tick early (15ish ms). This should not be a problem for most users, who should really only be setting timeouts in quantities of a second or greater. --- src/platform/windows/win_clock.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'src/platform/windows') diff --git a/src/platform/windows/win_clock.c b/src/platform/windows/win_clock.c index 6cf191ee..9064b5e2 100644 --- a/src/platform/windows/win_clock.c +++ b/src/platform/windows/win_clock.c @@ -20,9 +20,27 @@ nni_plat_clock(void) void -nni_plat_usleep(nni_duration usec) +nni_plat_usleep(nni_duration dur) { - Sleep((DWORD) ((usec + 999) / 1000)); + uint64_t exp; + + + // Convert duration to msec, rounding up. + dur += 999; + dur /= 1000; + + exp = (uint64_t) GetTickCount64() + dur; + + // Sleep() would be our preferred API, if it didn't have a nasty + // feature where it rounds *down*. We always want to sleep *at + // least* the requested amount of time, and never ever less. + // If we wind up sleeping less, then we will sleep(1) in the hope + // of waiting until the next clock tick. + + Sleep((DWORD) dur); + while ((uint64_t) GetTickCount64() < exp) { + Sleep(1); + } } -- cgit v1.2.3-70-g09d2