Paul Gofman : ntoskrnl.exe: Reimplement KeSetTimerEx() on top of thread pool.

Alexandre Julliard julliard at winehq.org
Thu May 28 17:11:11 CDT 2020


Module: wine
Branch: master
Commit: 68a03b6393220a8f24f862da9db2369349042d50
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=68a03b6393220a8f24f862da9db2369349042d50

Author: Paul Gofman <pgofman at codeweavers.com>
Date:   Thu May 28 12:15:16 2020 +0300

ntoskrnl.exe: Reimplement KeSetTimerEx() on top of thread pool.

This is needed to call the DPC callbacks later as SetWaitableTimer()
will call the callback only when the thread is in alertable
wait state.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntoskrnl.exe/sync.c | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c
index d5a635efad..1954b8befb 100644
--- a/dlls/ntoskrnl.exe/sync.c
+++ b/dlls/ntoskrnl.exe/sync.c
@@ -388,6 +388,15 @@ LONG WINAPI KeReleaseMutex( PRKMUTEX mutex, BOOLEAN wait )
     return ret;
 }
 
+static void CALLBACK ke_timer_complete_proc(PTP_CALLBACK_INSTANCE instance, void *timer_, PTP_TIMER tp_timer)
+{
+    KTIMER *timer = timer_;
+
+    TRACE("instance %p, timer %p, tp_timer %p.\n", instance, timer, tp_timer);
+
+    SetEvent(timer->Header.WaitListHead.Blink);
+}
+
 /***********************************************************************
  *           KeInitializeTimerEx   (NTOSKRNL.EXE.@)
  */
@@ -431,9 +440,18 @@ BOOLEAN WINAPI KeSetTimerEx( KTIMER *timer, LARGE_INTEGER duetime, LONG period,
 
     ret = timer->Header.Inserted;
     timer->Header.Inserted = TRUE;
-    timer->Header.WaitListHead.Blink = CreateWaitableTimerW( NULL, timer->Header.Type == TYPE_MANUAL_TIMER, NULL );
-    SetWaitableTimer( timer->Header.WaitListHead.Blink, &duetime, period, NULL, NULL, FALSE );
+    timer->Header.WaitListHead.Blink = CreateEventW( NULL, timer->Header.Type == TYPE_MANUAL_TIMER, FALSE, NULL );
 
+    if (!timer->TimerListEntry.Blink)
+        timer->TimerListEntry.Blink = (void *)CreateThreadpoolTimer(ke_timer_complete_proc, timer, NULL);
+
+    if (!timer->TimerListEntry.Blink)
+        ERR("Could not create thread pool timer.\n");
+
+    timer->DueTime.QuadPart = duetime.QuadPart;
+    timer->Period = period;
+
+    SetThreadpoolTimer((TP_TIMER *)timer->TimerListEntry.Blink, (FILETIME *)&duetime, period, 0);
     LeaveCriticalSection( &sync_cs );
 
     return ret;
@@ -446,6 +464,21 @@ BOOLEAN WINAPI KeCancelTimer( KTIMER *timer )
     TRACE("timer %p.\n", timer);
 
     EnterCriticalSection( &sync_cs );
+    if (timer->TimerListEntry.Blink)
+    {
+        SetThreadpoolTimer((TP_TIMER *)timer->TimerListEntry.Blink, NULL, 0, 0);
+
+        LeaveCriticalSection( &sync_cs );
+        WaitForThreadpoolTimerCallbacks((TP_TIMER *)timer->TimerListEntry.Blink, TRUE);
+        EnterCriticalSection( &sync_cs );
+
+        if (timer->TimerListEntry.Blink)
+        {
+            CloseThreadpoolTimer((TP_TIMER *)timer->TimerListEntry.Blink);
+            timer->TimerListEntry.Blink = NULL;
+        }
+    }
+
     ret = timer->Header.Inserted;
     timer->Header.Inserted = FALSE;
     CloseHandle(timer->Header.WaitListHead.Blink);




More information about the wine-cvs mailing list