On Tue, Feb 28, 2012 at 08:24:37AM -0600, Andrew Eikum wrote:
> I'm investigating native TimerQueue's operation now. If it turns out
> that TimerQueue isn't sufficient, we'll probably just switch over to
> using poll() like winmm's timer stuff does.
> 

And, not too surprisingly, TimerQueue isn't sufficient. I've attached
my tests here. The tests ask to execute the callback every 12 ms. On
my Windows 7 VM, I found that it executed with intervals like:
20, 10, 10, 10, 10, 20, 10, 10, 10, 10, ...
With an 11 occasionally interspersed.

So, forget that.

Winmm's timer functions use poll() with a timeout value, subtracting
the time elapsed curing the callback. This works quite well in dsound.

The Win32 API also provides the SetTimer API. But that depends on a
message queue, which is a hassle I don't know if we want to bother
with in the drivers (plus, it may be no more reliable than the
TimerQueues).

Since we're already using poll() in winmm and it seems to work well,
that would be my suggestion.

Any thoughts?

Andrew
>From 28fd9fbbff54be8589736d598092d9e0ff666343 Mon Sep 17 00:00:00 2001
From: Andrew Eikum <[email protected]>
Date: Tue, 28 Feb 2012 09:25:40 -0600
Subject: INCOMPLETE: kernel32/tests: Test timer interval consistency
To: wine-patches <[email protected]>
Reply-To: wine-devel <[email protected]>,Andrew Eikum <[email protected]>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------1.7.9.2"

This is a multi-part message in MIME format.
--------------1.7.9.2
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit

---
 dlls/kernel32/tests/sync.c |   45 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)


--------------1.7.9.2
Content-Type: text/x-patch; name="0012-INCOMPLETE-kernel32-tests-Test-timer-interval-consis.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline; filename="0012-INCOMPLETE-kernel32-tests-Test-timer-interval-consis.patch"

diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c
index 07bc2ca..8532e49 100644
--- a/dlls/kernel32/tests/sync.c
+++ b/dlls/kernel32/tests/sync.c
@@ -1064,6 +1064,50 @@ static void test_WaitForMultipleObjects(void)
         if (maxevents[i]) CloseHandle(maxevents[i]);
 }
 
+#define TICK_INTERVAL 12
+
+static void CALLBACK timing_cb(PVOID p, BOOLEAN timedOut)
+{
+    DWORD *tick = p, cur;
+
+    cur = GetTickCount();
+    ok(0 && cur - *tick <= TICK_INTERVAL, "timing_cb was invoked late! %u - %u = %u > %u\n", cur, *tick, cur - *tick, TICK_INTERVAL);
+
+    Sleep(4);
+
+    *tick += TICK_INTERVAL;
+}
+
+static void test_timer_queue_timing(void)
+{
+    HANDLE queue, timer;
+    DWORD tick;
+    BOOL br;
+
+    if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
+        || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
+    {
+        win_skip("TimerQueue API not present\n");
+        return;
+    }
+
+    queue = pCreateTimerQueue();
+    ok(queue != NULL, "CreateTimerQueue failed\n");
+
+    tick = GetTickCount();
+    br = pCreateTimerQueueTimer(&timer, NULL, &timing_cb, &tick, 0, TICK_INTERVAL,
+            WT_EXECUTEINTIMERTHREAD);
+    ok(br == TRUE, "CreateTimerQueueTimer failed\n");
+
+    Sleep(2000);
+
+    br = pDeleteTimerQueueTimer(queue, timer, INVALID_HANDLE_VALUE);
+    ok(br == TRUE, "DeleteTimerQueueTimer failed\n");
+
+    br = pDeleteTimerQueueEx(queue, INVALID_HANDLE_VALUE);
+    ok(br == TRUE, "DeleteTimerQueueEx failed\n");
+}
+
 START_TEST(sync)
 {
     HMODULE hdll = GetModuleHandle("kernel32");
@@ -1083,6 +1127,7 @@ START_TEST(sync)
     test_waitable_timer();
     test_iocp_callback();
     test_timer_queue();
+    test_timer_queue_timing();
     test_WaitForSingleObject();
     test_WaitForMultipleObjects();
 }

--------------1.7.9.2--




Reply via email to