Module: wine Branch: master Commit: a148e190af1ad0c62190e8eb1299b78abc9a9cbf URL: http://source.winehq.org/git/wine.git/?a=commit;h=a148e190af1ad0c62190e8eb12...
Author: Dan Hipschman dsh@linux.ucla.edu Date: Tue Jul 29 14:36:41 2008 -0700
ntdll: Add support for a default timer queue.
---
dlls/kernel32/tests/sync.c | 14 ++++++++++++++ dlls/ntdll/threadpool.c | 44 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 5 deletions(-)
diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index dcf2b62..2a686ca 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -880,6 +880,20 @@ static void test_timer_queue(void) ok(!ret, "DeleteTimerQueueEx\n"); ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n"); ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n"); + + /* Test functions on the default timer queue. */ + t1 = NULL; + n1 = 0; + ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000, + 1000, 0); + ok(ret, "CreateTimerQueueTimer, default queue\n"); + ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n"); + + ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000); + ok(ret, "ChangeTimerQueueTimer, default queue\n"); + + ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE); + ok(ret, "DeleteTimerQueueTimer, default queue\n"); }
START_TEST(sync) diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c index e468cbe..18baeee 100644 --- a/dlls/ntdll/threadpool.c +++ b/dlls/ntdll/threadpool.c @@ -816,9 +816,14 @@ NTSTATUS WINAPI RtlDeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) { struct timer_queue *q = TimerQueue; struct queue_timer *t, *temp; - HANDLE thread = q->thread; + HANDLE thread; NTSTATUS status;
+ if (!q) + return STATUS_INVALID_HANDLE; + + thread = q->thread; + RtlEnterCriticalSection(&q->cs); q->quit = TRUE; if (list_head(&q->timers)) @@ -851,6 +856,31 @@ NTSTATUS WINAPI RtlDeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) return status; }
+static struct timer_queue *default_timer_queue; + +static struct timer_queue *get_timer_queue(HANDLE TimerQueue) +{ + if (TimerQueue) + return TimerQueue; + else + { + if (!default_timer_queue) + { + HANDLE q; + NTSTATUS status = RtlCreateTimerQueue(&q); + if (status == STATUS_SUCCESS) + { + PVOID p = interlocked_cmpxchg_ptr( + (void **) &default_timer_queue, q, NULL); + if (p) + /* Got beat to the punch. */ + RtlDeleteTimerQueueEx(p, NULL); + } + } + return default_timer_queue; + } +} + /*********************************************************************** * RtlCreateTimer (NTDLL.@) * @@ -882,8 +912,12 @@ NTSTATUS WINAPI RtlCreateTimer(PHANDLE NewTimer, HANDLE TimerQueue, ULONG Flags) { NTSTATUS status; - struct timer_queue *q = TimerQueue; - struct queue_timer *t = RtlAllocateHeap(GetProcessHeap(), 0, sizeof *t); + struct queue_timer *t; + struct timer_queue *q = get_timer_queue(TimerQueue); + if (!q) + return STATUS_NO_MEMORY; + + t = RtlAllocateHeap(GetProcessHeap(), 0, sizeof *t); if (!t) return STATUS_NO_MEMORY;
@@ -933,8 +967,8 @@ NTSTATUS WINAPI RtlCreateTimer(PHANDLE NewTimer, HANDLE TimerQueue, NTSTATUS WINAPI RtlUpdateTimer(HANDLE TimerQueue, HANDLE Timer, DWORD DueTime, DWORD Period) { - struct timer_queue *q = TimerQueue; struct queue_timer *t = Timer; + struct timer_queue *q = t->q;
RtlEnterCriticalSection(&q->cs); /* Can't change a timer if it was once-only or destroyed. */ @@ -969,8 +1003,8 @@ NTSTATUS WINAPI RtlUpdateTimer(HANDLE TimerQueue, HANDLE Timer, NTSTATUS WINAPI RtlDeleteTimer(HANDLE TimerQueue, HANDLE Timer, HANDLE CompletionEvent) { - struct timer_queue *q = TimerQueue; struct queue_timer *t = Timer; + struct timer_queue *q = t->q; NTSTATUS status = STATUS_PENDING; HANDLE event = NULL;