Index: lib/rtl/timerqueue.c =================================================================== --- lib/rtl/timerqueue.c (revision 70072) +++ lib/rtl/timerqueue.c (working copy) @@ -77,7 +77,7 @@ NtSetEvent(t->event, NULL); RtlFreeHeap(RtlGetProcessHeap(), 0, t); - if (q->quit && list_count(&q->timers) == 0) + if (q->quit && list_empty(&q->timers)) NtSetEvent(q->event, NULL); } @@ -105,9 +105,9 @@ static inline ULONGLONG queue_current_time(void) { - LARGE_INTEGER now; - NtQuerySystemTime(&now); - return now.QuadPart / 10000; + LARGE_INTEGER now, freq; + NtQueryPerformanceCounter(&now, &freq); + return now.QuadPart * 1000 / freq.QuadPart; } static void queue_add_timer(struct queue_timer *t, ULONGLONG time, @@ -151,15 +151,23 @@ RtlEnterCriticalSection(&q->cs); if (list_head(&q->timers)) { + ULONGLONG now, next; t = LIST_ENTRY(list_head(&q->timers), struct queue_timer, entry); - if (!t->destroy && t->expire <= queue_current_time()) + if (!t->destroy && t->expire <= ((now = queue_current_time()))) { ++t->runcount; - queue_move_timer( - t, t->period ? queue_current_time() + t->period : EXPIRE_NEVER, - FALSE); + if (t->period) + { + next = t->expire + t->period; + /* avoid trigger cascade if overloaded / hibernated */ + if (next < now) + next = now + t->period; } else + next = EXPIRE_NEVER; + queue_move_timer(t, next, FALSE); + } + else t = NULL; } RtlLeaveCriticalSection(&q->cs); @@ -225,7 +233,7 @@ timer got put at the head of the list so we need to adjust our timeout. */ RtlEnterCriticalSection(&q->cs); - if (q->quit && list_count(&q->timers) == 0) + if (q->quit && list_empty(&q->timers)) done = TRUE; RtlLeaveCriticalSection(&q->cs); } @@ -281,7 +289,7 @@ RtlInitializeCriticalSection(&q->cs); list_init(&q->timers); q->quit = FALSE; - status = NtCreateEvent(&q->event, EVENT_ALL_ACCESS, NULL, FALSE, FALSE); + status = NtCreateEvent(&q->event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); if (status != STATUS_SUCCESS) { RtlFreeHeap(RtlGetProcessHeap(), 0, q); @@ -378,7 +386,7 @@ (void **) &default_timer_queue, q, NULL); if (p) /* Got beat to the punch. */ - RtlDeleteTimerQueueEx(p, NULL); + RtlDeleteTimerQueueEx(q, NULL); } } return default_timer_queue; @@ -401,7 +409,7 @@ * after the first callback. If zero, the timer will only * fire once. It still needs to be deleted with * RtlDeleteTimer. - * Flags [I] Flags controling the execution of the callback. In + * Flags [I] Flags controlling the execution of the callback. In * addition to the WT_* thread pool flags (see * RtlQueueWorkItem), WT_EXECUTEINTIMERTHREAD and * WT_EXECUTEONLYONCE are supported. @@ -516,7 +524,11 @@ return STATUS_INVALID_PARAMETER_1; q = t->q; if (CompletionEvent == INVALID_HANDLE_VALUE) - status = NtCreateEvent(&event, EVENT_ALL_ACCESS, NULL, FALSE, FALSE); + { + status = NtCreateEvent(&event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); + if (status == STATUS_SUCCESS) + status = STATUS_PENDING; + } else if (CompletionEvent) event = CompletionEvent; @@ -530,7 +542,10 @@ if (CompletionEvent == INVALID_HANDLE_VALUE && event) { if (status == STATUS_PENDING) + { NtWaitForSingleObject(event, FALSE, NULL); + status = STATUS_SUCCESS; + } NtClose(event); }