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

Alexandre Julliard julliard at wine.codeweavers.com
Thu Jun 7 16:26:37 CDT 2007


Module: wine
Branch: master
Commit: 0383e4e4990e414a7dcaba51e6b81bf60499944a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=0383e4e4990e414a7dcaba51e6b81bf60499944a

Author: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date:   Tue Jun  5 19:32:20 2007 +0200

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

---

 dlls/winmm/time.c |   67 ++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 46 insertions(+), 21 deletions(-)

diff --git a/dlls/winmm/time.c b/dlls/winmm/time.c
index d392786..9329b27 100644
--- a/dlls/winmm/time.c
+++ b/dlls/winmm/time.c
@@ -24,6 +24,7 @@
 #include "wine/port.h"
 
 #include <stdarg.h>
+#include <errno.h>
 #include <time.h>
 #ifdef HAVE_SYS_TIME_H
 # include <sys/time.h>
@@ -31,6 +32,12 @@
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#endif
 
 #include "windef.h"
 #include "winbase.h"
@@ -44,9 +51,9 @@ 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    int                   TIME_fdWake[2] = { -1, -1 };
 
 /*
  * Some observations on the behavior of winmm on Windows.
@@ -219,7 +226,12 @@ static    LPWINE_TIMERENTRY		lpTimers;
 static DWORD CALLBACK TIME_MMSysTimeThread(LPVOID arg)
 {
     LPWINE_MM_IDATA iData = (LPWINE_MM_IDATA)arg;
-    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");
 
@@ -231,17 +243,21 @@ static DWORD CALLBACK TIME_MMSysTimeThread(LPVOID arg)
 
     while (! TIME_TimeToDie) 
     {
-        int sleep_time = TIME_MMSysTimeCallback(iData);
+        sleep_time = TIME_MMSysTimeCallback(iData);
 
         if (sleep_time == 0)
             continue;
 
-        rc = WaitForSingleObject(TIME_hWakeEvent, (sleep_time == -1) ? INFINITE : (DWORD)sleep_time);
-        if (rc != WAIT_TIMEOUT && rc != WAIT_OBJECT_0)
-        {   
-            FIXME("Unexpected error %d(%d) in timer thread\n", rc, GetLastError());
-            break;
-        }
+        if ((ret = poll(&pfd, 1, sleep_time)) < 0)
+        {
+            if (errno != EINTR && errno != EAGAIN)
+            {
+                ERR("Unexpected error in poll: %s(%d)\n", strerror(errno), errno);
+                break;
+            }
+         }
+
+        while (ret > 0) ret = read(TIME_fdWake[0], readme, sizeof(readme));
     }
     TRACE("Exiting main winmm thread\n");
     return 0;
@@ -253,10 +269,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");
@@ -269,16 +292,17 @@ void	TIME_MMTimeStart(void)
 void	TIME_MMTimeStop(void)
 {
     if (TIME_hMMTimer) {
+        const char a='a';
 
         TIME_TimeToDie = TRUE;
-        SetEvent(TIME_hWakeEvent);
-
-        /* FIXME: in the worst case, we're going to wait 65 seconds here :-( */
-	WaitForSingleObject(TIME_hMMTimer, INFINITE);
-
-	CloseHandle(TIME_hMMTimer);
-	CloseHandle(TIME_hWakeEvent);
-	TIME_hMMTimer = 0;
+        write(TIME_fdWake[1], &a, sizeof(a));
+
+        WaitForSingleObject(TIME_hMMTimer, INFINITE);
+        close(TIME_fdWake[0]);
+        close(TIME_fdWake[1]);
+        TIME_fdWake[0] = TIME_fdWake[1] = -1;
+        CloseHandle(TIME_hMMTimer);
+        TIME_hMMTimer = 0;
         TIME_cbcrst.DebugInfo->Spare[0] = 0;
         DeleteCriticalSection(&TIME_cbcrst);
         TIME_TimersList = NULL;
@@ -309,6 +333,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);
 
@@ -344,7 +369,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);
 




More information about the wine-cvs mailing list