winmm: Use unix fd's instead of win32 events to sync internal events in timer.

Maarten Lankhorst m.b.lankhorst at gmail.com
Tue Jun 5 12:48:32 CDT 2007


This will allow the winmm to get better scheduling by sleeping more,
using win32 events causes expensive server calls in a timer that should
block as much as it can to get more favorable scheduling by kernel.
-------------- next part --------------
>From c316f7228ecb6fcca780bed4293e592589a30467 Mon Sep 17 00:00:00 2001
From: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date: Tue, 5 Jun 2007 19:32:20 +0200
Subject: [PATCH] winmm: Use fd's instead of events to sync internally

---
 dlls/winmm/time.c |   76 +++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 54 insertions(+), 22 deletions(-)

diff --git a/dlls/winmm/time.c b/dlls/winmm/time.c
index 7ecbf52..351788a 100644
--- a/dlls/winmm/time.c
+++ b/dlls/winmm/time.c
@@ -31,6 +31,14 @@
 # include <unistd.h>
 #endif
 
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#endif
+#include <errno.h>
+
 #include "windef.h"
 #include "winbase.h"
 #include "mmsystem.h"
@@ -43,10 +51,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(mmtime);
 
 static    HANDLE                TIME_hMMTimer;
 static    LPWINE_TIMERENTRY 	TIME_TimersList;
-static    HANDLE                TIME_hWakeEvent;
 static    CRITICAL_SECTION      TIME_cbcrst;
 static    BOOL                  TIME_TimeToDie = TRUE;
 static    UINT16                TIME_wTimerID;
+static    int                   TIME_fdWake[2] = { -1, -1 };
 
 /*
  * Some observations on the behavior of winmm on Windows.
@@ -80,11 +88,12 @@ static    UINT16                wTimerID;
 /**************************************************************************
  *           TIME_MMSysTimeCallback
  */
-static DWORD CALLBACK TIME_MMSysTimeCallback(LPWINE_MM_IDATA iData)
+static int CALLBACK TIME_MMSysTimeCallback(LPWINE_MM_IDATA iData)
 {
     LPWINE_TIMERENTRY   timer, *ptimer;
     WINE_TIMERENTRY ftime;
-    DWORD cur_time, delta_time, adjust_time, ret_time = INFINITE;
+    DWORD cur_time, delta_time, adjust_time;
+    int ret_time = -1;
 
     /* optimize for the most frequent case  - no events */
     if (!TIME_TimersList)
@@ -176,7 +185,7 @@ static DWORD CALLBACK TIME_MMSysTimeCallback(LPWINE_MM_IDATA iData)
 
     /* We return the amount of time our caller should sleep
        before needing to check in on us again       */
-    return(ret_time);
+    return ret_time;
 }
 
 /**************************************************************************
@@ -185,8 +194,12 @@ static DWORD CALLBACK TIME_MMSysTimeCallback(LPWINE_MM_IDATA iData)
 static DWORD CALLBACK TIME_MMSysTimeThread(LPVOID arg)
 {
     LPWINE_MM_IDATA iData = (LPWINE_MM_IDATA)arg;
-    DWORD sleep_time;
-    DWORD rc;
+    int sleep_time, ret;
+    char readme[16];
+
+    struct pollfd pfd;
+    pfd.fd = TIME_fdWake[0];
+    pfd.events = POLLIN;
 
     TRACE("Starting main winmm thread\n");
 
@@ -198,18 +211,27 @@ static DWORD CALLBACK TIME_MMSysTimeThread(LPVOID arg)
 
     while (! TIME_TimeToDie) 
     {
-	sleep_time = TIME_MMSysTimeCallback(iData);
+        sleep_time = TIME_MMSysTimeCallback(iData);
 
         if (sleep_time == 0)
             continue;
 
-        rc = WaitForSingleObject(TIME_hWakeEvent, sleep_time);
-        if (rc != WAIT_TIMEOUT && rc != WAIT_OBJECT_0)
-        {   
-            FIXME("Unexpected error %d(%d) in timer thread\n", rc, GetLastError());
-            break;
+        while ((ret = poll(&pfd, 1, sleep_time)) < 0)
+        {
+            if (errno != EINTR && errno != EAGAIN)
+            {
+                ERR("Unexpected error in poll: %s(%d)\n", strerror(errno), errno);
+                goto end;
+            }
         }
+
+        if (ret > 0) 
+            do {
+                ret = read(TIME_fdWake[0], readme, sizeof(*readme));
+            } while (ret > 0);
     }
+
+    end:
     TRACE("Exiting main winmm thread\n");
     return 0;
 }
@@ -220,10 +242,17 @@ static DWORD CALLBACK TIME_MMSysTimeThread(LPVOID arg)
 void	TIME_MMTimeStart(void)
 {
     if (!TIME_hMMTimer) {
-	TIME_TimersList = NULL;
-        TIME_hWakeEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+        TIME_TimersList = NULL;
+        if (pipe(TIME_fdWake) < 0)
+        {
+            TIME_fdWake[0] = TIME_fdWake[1] = -1;
+            ERR("Cannot create pipe: %s\n", strerror(errno));
+        } else {
+            fcntl(TIME_fdWake[0], F_SETFL, O_NONBLOCK);
+            fcntl(TIME_fdWake[1], F_SETFL, O_NONBLOCK);
+        }
         TIME_TimeToDie = FALSE;
-	TIME_hMMTimer = CreateThread(NULL, 0, TIME_MMSysTimeThread, &WINMM_IData, 0, NULL);
+        TIME_hMMTimer = CreateThread(NULL, 0, TIME_MMSysTimeThread, &WINMM_IData, 0, NULL);
         SetThreadPriority(TIME_hMMTimer, THREAD_PRIORITY_TIME_CRITICAL);
         InitializeCriticalSection(&TIME_cbcrst);
         TIME_cbcrst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": WINMM.TIME_cbcrst");
@@ -237,16 +266,18 @@ void	TIME_MMTimeStart(void)
 void	TIME_MMTimeStop(void)
 {
     if (TIME_hMMTimer) {
-
+        const char a='a';
         TIME_TimeToDie = TRUE;
-        SetEvent(TIME_hWakeEvent);
+        write(TIME_fdWake[1], &a, sizeof(a));
 
         /* FIXME: in the worst case, we're going to wait 65 seconds here :-( */
-	WaitForSingleObject(TIME_hMMTimer, INFINITE);
+        WaitForSingleObject(TIME_hMMTimer, INFINITE);
+        close(TIME_fdWake[0]);
+        close(TIME_fdWake[1]);
+        TIME_fdWake[0] = TIME_fdWake[1] = -1;
 
-	CloseHandle(TIME_hMMTimer);
-	CloseHandle(TIME_hWakeEvent);
-	TIME_hMMTimer = 0;
+        CloseHandle(TIME_hMMTimer);
+        TIME_hMMTimer = 0;
     }
 }
 
@@ -274,6 +305,7 @@ WORD	TIME_SetEventInternal(UINT wDelay, UINT wResol,
     WORD 		wNewID = 0;
     LPWINE_TIMERENTRY	lpNewTimer;
     LPWINE_TIMERENTRY	lpTimer;
+    const char c = 'c';
 
     TRACE("(%u, %u, %p, %08X, %04X);\n", wDelay, wResol, lpFunc, dwUser, wFlags);
 
@@ -309,7 +341,7 @@ WORD	TIME_SetEventInternal(UINT wDelay, UINT wResol,
     LeaveCriticalSection(&WINMM_IData.cs);
 
     /* Wake the service thread in case there is work to be done */
-    SetEvent(TIME_hWakeEvent);
+    write(TIME_fdWake[1], &c, sizeof(c));
 
     TRACE("=> %u\n", wNewID + 1);
 
-- 
1.4.4.2



More information about the wine-patches mailing list