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