A+
Name: mmtime
ChangeLog:
- implemented TIME_KILL_SYCHRONOUS timer flags
- timeKillTimer is now thread safe
- replaced some iData attributes by global variables
License: X11
GenDate: 2004/01/10 16:30:57 UTC
ModifiedFiles: dlls/winmm/winemm.h dlls/winmm/mmsystem.c dlls/winmm/time.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/winmm/winemm.h,v
retrieving revision 1.53
diff -u -u -r1.53 winemm.h
--- dlls/winmm/winemm.h 6 Jan 2004 22:08:33 -0000 1.53
+++ dlls/winmm/winemm.h 10 Jan 2004 13:13:49 -0000
@@ -201,12 +201,6 @@
HANDLE hWinMM32Instance;
HANDLE hWinMM16Instance;
CRITICAL_SECTION cs;
- /* mm timer part */
- HANDLE hMMTimer;
- DWORD mmSysTimeMS;
- LPWINE_TIMERENTRY lpTimerList;
- int nSizeLpTimers;
- LPWINE_TIMERENTRY lpTimers;
/* mci part */
LPWINE_MCIDRIVER lpMciDrvs;
/* low level drivers (unused yet) */
@@ -242,7 +236,7 @@
DWORD MMDRV_Close(LPWINE_MLD mld, UINT wMsg);
LPWINE_MLD MMDRV_Get(HANDLE hndl, UINT type, BOOL bCanBeID);
LPWINE_MLD MMDRV_GetRelated(HANDLE hndl, UINT srcType, BOOL bSrcCanBeID, UINT dstTyped);
-DWORD MMDRV_Message(LPWINE_MLD mld, UINT wMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2, BOOL bFrom32);
+DWORD MMDRV_Message(LPWINE_MLD mld, UINT wMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2, BOOL bFrom32);
UINT MMDRV_PhysicalFeatures(LPWINE_MLD mld, UINT uMsg, DWORD dwParam1, DWORD dwParam2);
BOOL MMDRV_Is32(unsigned int);
void MMDRV_InstallMap(unsigned int, MMDRV_MAPFUNC, MMDRV_UNMAPFUNC,
@@ -290,6 +284,7 @@
/* Global variables */
extern LPWINE_MM_IDATA WINMM_IData;
+extern DWORD WINMM_SysTimeMS;
/* pointers to 16 bit functions (if sibling MMSYSTEM.DLL is loaded
* NULL otherwise
Index: dlls/winmm/mmsystem.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/winmm/mmsystem.c,v
retrieving revision 1.105
diff -u -u -r1.105 mmsystem.c
--- dlls/winmm/mmsystem.c 31 Dec 2003 23:49:45 -0000 1.105
+++ dlls/winmm/mmsystem.c 10 Jan 2004 13:05:08 -0000
@@ -2529,7 +2529,7 @@
if (wSize >= sizeof(*lpTime)) {
lpTime->wType = TIME_MS;
TIME_MMTimeStart();
- lpTime->u.ms = WINMM_IData->mmSysTimeMS;
+ lpTime->u.ms = WINMM_SysTimeMS;
TRACE("=> %lu\n", lpTime->u.ms);
}
Index: dlls/winmm/time.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/winmm/time.c,v
retrieving revision 1.25
diff -u -u -r1.25 time.c
--- dlls/winmm/time.c 31 Dec 2003 23:49:45 -0000 1.25
+++ dlls/winmm/time.c 10 Jan 2004 16:29:08 -0000
@@ -42,6 +42,11 @@
WINE_DEFAULT_DEBUG_CHANNEL(mmtime);
+static HANDLE TIME_hMMTimer;
+static LPWINE_TIMERENTRY TIME_TimersList;
+static HANDLE TIME_hKillEvent;
+DWORD WINMM_SysTimeMS;
+
/*
* FIXME
* We're using "1" as the mininum resolution to the timer,
@@ -90,15 +95,18 @@
*/
static void CALLBACK TIME_MMSysTimeCallback(LPWINE_MM_IDATA iData)
{
- LPWINE_TIMERENTRY lpTimer, lpNextTimer;
- DWORD delta = GetTickCount() - iData->mmSysTimeMS;
+static int nSizeLpTimers;
+static LPWINE_TIMERENTRY lpTimers;
+
+ LPWINE_TIMERENTRY timer, *ptimer, *next_ptimer;
+ DWORD delta = GetTickCount() - WINMM_SysTimeMS;
int idx;
TRACE("Time delta: %ld\n", delta);
while (delta >= MMSYSTIME_MININTERVAL) {
delta -= MMSYSTIME_MININTERVAL;
- iData->mmSysTimeMS += MMSYSTIME_MININTERVAL;
+ WINMM_SysTimeMS += MMSYSTIME_MININTERVAL;
/* since timeSetEvent() and timeKillEvent() can be called
* from 16 bit code, there are cases where win16 lock is
@@ -109,48 +117,52 @@
* situation).
* To cope with that, we just copy the WINE_TIMERENTRY struct
* that need to trigger the callback, and call it without the
- * mm timer crit sect locked. The bad side of this
- * implementation is that, in some cases, the callback may be
- * invoked *after* a timer has been destroyed...
- * EPP 99/07/13
+ * mm timer crit sect locked.
+ * the hKillTimeEvent is used to mark the section where we
+ * handle the callbacks so we can do synchronous kills.
+ * EPP 99/07/13, updated 04/01/10
*/
idx = 0;
EnterCriticalSection(&iData->cs);
- for (lpTimer = iData->lpTimerList; lpTimer != NULL; ) {
- lpNextTimer = lpTimer->lpNext;
- if (lpTimer->uCurTime < MMSYSTIME_MININTERVAL) {
+ for (ptimer = &TIME_TimersList; *ptimer != NULL; ) {
+ timer = *ptimer;
+ next_ptimer = &timer->lpNext;
+ if (timer->uCurTime < MMSYSTIME_MININTERVAL) {
/* since lpTimer->wDelay is >= MININTERVAL, wCurTime value
* shall be correct (>= 0)
*/
- lpTimer->uCurTime += lpTimer->wDelay - MMSYSTIME_MININTERVAL;
- if (lpTimer->lpFunc) {
- if (idx == iData->nSizeLpTimers) {
- if (iData->lpTimers)
- iData->lpTimers = (LPWINE_TIMERENTRY)
- HeapReAlloc(GetProcessHeap(), 0,
- iData->lpTimers,
- ++iData->nSizeLpTimers * sizeof(WINE_TIMERENTRY));
+ timer->uCurTime += timer->wDelay - MMSYSTIME_MININTERVAL;
+ if (timer->lpFunc) {
+ if (idx == nSizeLpTimers) {
+ if (lpTimers)
+ lpTimers = (LPWINE_TIMERENTRY)
+ HeapReAlloc(GetProcessHeap(), 0, lpTimers,
+ ++nSizeLpTimers * sizeof(WINE_TIMERENTRY));
else
- iData->lpTimers = (LPWINE_TIMERENTRY)
+ lpTimers = (LPWINE_TIMERENTRY)
HeapAlloc(GetProcessHeap(), 0,
- ++iData->nSizeLpTimers * sizeof(WINE_TIMERENTRY));
+ ++nSizeLpTimers * sizeof(WINE_TIMERENTRY));
}
- iData->lpTimers[idx++] = *lpTimer;
+ lpTimers[idx++] = *timer;
}
/* TIME_ONESHOT is defined as 0 */
- if (!(lpTimer->wFlags & TIME_PERIODIC))
- timeKillEvent(lpTimer->wTimerID);
+ if (!(timer->wFlags & TIME_PERIODIC))
+ {
+ /* unlink timer from timers list */
+ *ptimer = *next_ptimer;
+ HeapFree(GetProcessHeap(), 0, timer);
+ }
} else {
- lpTimer->uCurTime -= MMSYSTIME_MININTERVAL;
+ timer->uCurTime -= MMSYSTIME_MININTERVAL;
}
- lpTimer = lpNextTimer;
+ ptimer = next_ptimer;
}
+ if (TIME_hKillEvent) ResetEvent(TIME_hKillEvent);
LeaveCriticalSection(&iData->cs);
- while (idx > 0) {
- TIME_TriggerCallBack(&iData->lpTimers[--idx]);
- }
+ while (idx > 0) TIME_TriggerCallBack(&lpTimers[--idx]);
+ if (TIME_hKillEvent) SetEvent(TIME_hKillEvent);
}
}
@@ -160,7 +172,7 @@
static DWORD CALLBACK TIME_MMSysTimeThread(LPVOID arg)
{
LPWINE_MM_IDATA iData = (LPWINE_MM_IDATA)arg;
- volatile HANDLE *pActive = (volatile HANDLE *)&iData->hMMTimer;
+ volatile HANDLE *pActive = (volatile HANDLE *)&TIME_hMMTimer;
DWORD last_time, cur_time;
usleep(MMSYSTIME_STDINTERVAL * 1000);
@@ -184,10 +196,10 @@
* mm timers are active, but this would require to keep mmSysTimeMS up-to-date
* without being incremented within the service thread callback.
*/
- if (!WINMM_IData->hMMTimer) {
- WINMM_IData->mmSysTimeMS = GetTickCount();
- WINMM_IData->lpTimerList = NULL;
- WINMM_IData->hMMTimer = CreateThread(NULL, 0, TIME_MMSysTimeThread, WINMM_IData, 0, NULL);
+ if (!TIME_hMMTimer) {
+ WINMM_SysTimeMS = GetTickCount();
+ TIME_TimersList = NULL;
+ TIME_hMMTimer = CreateThread(NULL, 0, TIME_MMSysTimeThread, WINMM_IData, 0, NULL);
}
}
@@ -196,9 +208,10 @@
*/
void TIME_MMTimeStop(void)
{
- if (WINMM_IData->hMMTimer) {
- HANDLE hMMTimer = WINMM_IData->hMMTimer;
- WINMM_IData->hMMTimer = 0;
+ /* FIXME: in the worst case, we're going to wait 65 seconds here :-( */
+ if (TIME_hMMTimer) {
+ HANDLE hMMTimer = TIME_hMMTimer;
+ TIME_hMMTimer = 0;
WaitForSingleObject(hMMTimer, INFINITE);
CloseHandle(hMMTimer);
}
@@ -214,7 +227,7 @@
if (wSize >= sizeof(*lpTime)) {
TIME_MMTimeStart();
lpTime->wType = TIME_MS;
- lpTime->u.ms = WINMM_IData->mmSysTimeMS;
+ lpTime->u.ms = WINMM_SysTimeMS;
TRACE("=> %lu\n", lpTime->u.ms);
}
@@ -252,12 +265,15 @@
EnterCriticalSection(&WINMM_IData->cs);
- for (lpTimer = WINMM_IData->lpTimerList; lpTimer != NULL; lpTimer = lpTimer->lpNext) {
+ if ((wFlags & TIME_KILL_SYNCHRONOUS) && !TIME_hKillEvent)
+ TIME_hKillEvent = CreateEventW(NULL, TRUE, TRUE, NULL);
+
+ for (lpTimer = TIME_TimersList; lpTimer != NULL; lpTimer = lpTimer->lpNext) {
wNewID = max(wNewID, lpTimer->wTimerID);
}
- lpNewTimer->lpNext = WINMM_IData->lpTimerList;
- WINMM_IData->lpTimerList = lpNewTimer;
+ lpNewTimer->lpNext = TIME_TimersList;
+ TIME_TimersList = lpNewTimer;
lpNewTimer->wTimerID = wNewID + 1;
LeaveCriticalSection(&WINMM_IData->cs);
@@ -285,31 +301,30 @@
*/
MMRESULT WINAPI timeKillEvent(UINT wID)
{
- LPWINE_TIMERENTRY* lpTimer;
- MMRESULT ret = MMSYSERR_INVALPARAM;
+ LPWINE_TIMERENTRY lpSelf = NULL, *lpTimer;
TRACE("(%u)\n", wID);
EnterCriticalSection(&WINMM_IData->cs);
/* remove WINE_TIMERENTRY from list */
- for (lpTimer = &WINMM_IData->lpTimerList; *lpTimer; lpTimer = &(*lpTimer)->lpNext) {
+ for (lpTimer = &TIME_TimersList; *lpTimer; lpTimer = &(*lpTimer)->lpNext) {
if (wID == (*lpTimer)->wTimerID) {
+ lpSelf = *lpTimer;
+ /* unlink timer of id 'wID' */
+ *lpTimer = (*lpTimer)->lpNext;
break;
}
}
LeaveCriticalSection(&WINMM_IData->cs);
- if (*lpTimer) {
- LPWINE_TIMERENTRY lpTemp = *lpTimer;
-
- /* unlink timer of id 'wID' */
- *lpTimer = (*lpTimer)->lpNext;
- HeapFree(GetProcessHeap(), 0, lpTemp);
- ret = TIMERR_NOERROR;
- } else {
- WARN("wID=%u is not a valid timer ID\n", wID);
+ if (!lpSelf)
+ {
+ WARN("wID=%u is not a valid timer ID\n", wID);
+ return MMSYSERR_INVALPARAM;
}
-
- return ret;
+ if (lpSelf->wFlags & TIME_KILL_SYNCHRONOUS)
+ WaitForSingleObject(TIME_hKillEvent, INFINITE);
+ HeapFree(GetProcessHeap(), 0, lpSelf);
+ return TIMERR_NOERROR;
}
/**************************************************************************
@@ -361,5 +376,5 @@
if (pFnReleaseThunkLock) pFnReleaseThunkLock(&count);
TIME_MMTimeStart();
if (pFnRestoreThunkLock) pFnRestoreThunkLock(count);
- return WINMM_IData->mmSysTimeMS;
+ return WINMM_SysTimeMS;
}