From ca3cfbae742bc0c87632374bd8542cb467512692 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Tue, 19 Jul 2011 17:32:43 +0200 Subject: [PATCH] Windows: use low-res event loop clock. For much better performance. Closes #88. --- src/win/core.c | 3 --- src/win/internal.h | 3 --- src/win/timer.c | 38 ++++++++++++++++++++------------------ 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/win/core.c b/src/win/core.c index 32009478..e2d5a32c 100644 --- a/src/win/core.c +++ b/src/win/core.c @@ -70,9 +70,6 @@ void uv_init() { /* Initialize winsock */ uv_winsock_startup(); - /* Initialize timers */ - uv_timer_startup(); - /* Intialize event loop */ uv_loop_init(); } diff --git a/src/win/internal.h b/src/win/internal.h index 7c42a774..33783f6e 100644 --- a/src/win/internal.h +++ b/src/win/internal.h @@ -30,11 +30,8 @@ /* * Timers */ - RB_HEAD(uv_timer_tree_s, uv_timer_s); -void uv_timer_startup(); - void uv_timer_endgame(uv_timer_t* handle); DWORD uv_get_poll_timeout(); diff --git a/src/win/timer.c b/src/win/timer.c index d2ab89e9..ea5e7195 100644 --- a/src/win/timer.c +++ b/src/win/timer.c @@ -37,12 +37,19 @@ static char uv_hrtime_initialized_ = 0; void uv_update_time() { - LARGE_INTEGER counter; + DWORD ticks = GetTickCount(); - if (!QueryPerformanceCounter(&counter)) - uv_fatal_error(GetLastError(), "QueryPerformanceCounter"); + /* The assumption is made that LARGE_INTEGER.QuadPart has the same type */ + /* LOOP->time, which happens to be. Is there any way to assert this? */ + LARGE_INTEGER* time = (LARGE_INTEGER*) &LOOP->time; - LOOP->time = counter.QuadPart / uv_ticks_per_msec_; + /* If the timer has wrapped, add 1 to it's high-order dword. */ + /* uv_poll must make sure that the timer can never overflow more than */ + /* once between two subsequent uv_update_time calls. */ + if (ticks < time->LowPart) { + time->HighPart += 1; + } + time->LowPart = ticks; } @@ -88,16 +95,6 @@ uint64_t uv_hrtime(void) { } -void uv_timer_startup() { - LARGE_INTEGER timer_frequency; - - /* Initialize the event loop time */ - if (!QueryPerformanceFrequency(&timer_frequency)) - uv_fatal_error(GetLastError(), "QueryPerformanceFrequency"); - uv_ticks_per_msec_ = timer_frequency.QuadPart / 1000; -} - - static int uv_timer_compare(uv_timer_t* a, uv_timer_t* b) { if (a->due < b->due) return -1; @@ -222,10 +219,15 @@ DWORD uv_get_poll_timeout() { uv_update_time(); delta = timer->due - LOOP->time; - if (delta >= UINT_MAX) { - /* Can't have a timeout greater than UINT_MAX, and a timeout value of */ - /* UINT_MAX means infinite, so that's no good either. */ - return UINT_MAX - 1; + if (delta >= UINT_MAX >> 1) { + /* A timeout value of UINT_MAX means infinite, so that's no good. But */ + /* more importantly, there's always the risk that GetTickCount wraps. */ + /* uv_update_time can detect this, but we must make sure that the */ + /* tick counter never overflows twice between two subsequent */ + /* uv_update_time calls. We do this by never sleeping more than half */ + /* the time it takes to wrap the counter - which is huge overkill, */ + /* but hey, it's not so bad to wake up every 25 days. */ + return UINT_MAX >> 1; } else if (delta < 0) { /* Negative timeout values are not allowed */ return 0;