Commit 9db6037d authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

- implemented TIME_KILL_SYCHRONOUS timer flags

- timeKillTimer is now thread safe - replaced some iData attributes by global variables
parent 370a18f7
...@@ -2529,7 +2529,7 @@ MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16 lpTime, UINT16 wSize) ...@@ -2529,7 +2529,7 @@ MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16 lpTime, UINT16 wSize)
if (wSize >= sizeof(*lpTime)) { if (wSize >= sizeof(*lpTime)) {
lpTime->wType = TIME_MS; lpTime->wType = TIME_MS;
TIME_MMTimeStart(); TIME_MMTimeStart();
lpTime->u.ms = WINMM_IData->mmSysTimeMS; lpTime->u.ms = WINMM_SysTimeMS;
TRACE("=> %lu\n", lpTime->u.ms); TRACE("=> %lu\n", lpTime->u.ms);
} }
......
...@@ -42,6 +42,11 @@ ...@@ -42,6 +42,11 @@
WINE_DEFAULT_DEBUG_CHANNEL(mmtime); WINE_DEFAULT_DEBUG_CHANNEL(mmtime);
static HANDLE TIME_hMMTimer;
static LPWINE_TIMERENTRY TIME_TimersList;
static HANDLE TIME_hKillEvent;
DWORD WINMM_SysTimeMS;
/* /*
* FIXME * FIXME
* We're using "1" as the mininum resolution to the timer, * We're using "1" as the mininum resolution to the timer,
...@@ -90,15 +95,18 @@ static void TIME_TriggerCallBack(LPWINE_TIMERENTRY lpTimer) ...@@ -90,15 +95,18 @@ static void TIME_TriggerCallBack(LPWINE_TIMERENTRY lpTimer)
*/ */
static void CALLBACK TIME_MMSysTimeCallback(LPWINE_MM_IDATA iData) static void CALLBACK TIME_MMSysTimeCallback(LPWINE_MM_IDATA iData)
{ {
LPWINE_TIMERENTRY lpTimer, lpNextTimer; static int nSizeLpTimers;
DWORD delta = GetTickCount() - iData->mmSysTimeMS; static LPWINE_TIMERENTRY lpTimers;
LPWINE_TIMERENTRY timer, *ptimer, *next_ptimer;
DWORD delta = GetTickCount() - WINMM_SysTimeMS;
int idx; int idx;
TRACE("Time delta: %ld\n", delta); TRACE("Time delta: %ld\n", delta);
while (delta >= MMSYSTIME_MININTERVAL) { while (delta >= MMSYSTIME_MININTERVAL) {
delta -= MMSYSTIME_MININTERVAL; delta -= MMSYSTIME_MININTERVAL;
iData->mmSysTimeMS += MMSYSTIME_MININTERVAL; WINMM_SysTimeMS += MMSYSTIME_MININTERVAL;
/* since timeSetEvent() and timeKillEvent() can be called /* since timeSetEvent() and timeKillEvent() can be called
* from 16 bit code, there are cases where win16 lock is * from 16 bit code, there are cases where win16 lock is
...@@ -109,48 +117,52 @@ static void CALLBACK TIME_MMSysTimeCallback(LPWINE_MM_IDATA iData) ...@@ -109,48 +117,52 @@ static void CALLBACK TIME_MMSysTimeCallback(LPWINE_MM_IDATA iData)
* situation). * situation).
* To cope with that, we just copy the WINE_TIMERENTRY struct * To cope with that, we just copy the WINE_TIMERENTRY struct
* that need to trigger the callback, and call it without the * that need to trigger the callback, and call it without the
* mm timer crit sect locked. The bad side of this * mm timer crit sect locked.
* implementation is that, in some cases, the callback may be * the hKillTimeEvent is used to mark the section where we
* invoked *after* a timer has been destroyed... * handle the callbacks so we can do synchronous kills.
* EPP 99/07/13 * EPP 99/07/13, updated 04/01/10
*/ */
idx = 0; idx = 0;
EnterCriticalSection(&iData->cs); EnterCriticalSection(&iData->cs);
for (lpTimer = iData->lpTimerList; lpTimer != NULL; ) { for (ptimer = &TIME_TimersList; *ptimer != NULL; ) {
lpNextTimer = lpTimer->lpNext; timer = *ptimer;
if (lpTimer->uCurTime < MMSYSTIME_MININTERVAL) { next_ptimer = &timer->lpNext;
if (timer->uCurTime < MMSYSTIME_MININTERVAL) {
/* since lpTimer->wDelay is >= MININTERVAL, wCurTime value /* since lpTimer->wDelay is >= MININTERVAL, wCurTime value
* shall be correct (>= 0) * shall be correct (>= 0)
*/ */
lpTimer->uCurTime += lpTimer->wDelay - MMSYSTIME_MININTERVAL; timer->uCurTime += timer->wDelay - MMSYSTIME_MININTERVAL;
if (lpTimer->lpFunc) { if (timer->lpFunc) {
if (idx == iData->nSizeLpTimers) { if (idx == nSizeLpTimers) {
if (iData->lpTimers) if (lpTimers)
iData->lpTimers = (LPWINE_TIMERENTRY) lpTimers = (LPWINE_TIMERENTRY)
HeapReAlloc(GetProcessHeap(), 0, HeapReAlloc(GetProcessHeap(), 0, lpTimers,
iData->lpTimers, ++nSizeLpTimers * sizeof(WINE_TIMERENTRY));
++iData->nSizeLpTimers * sizeof(WINE_TIMERENTRY));
else else
iData->lpTimers = (LPWINE_TIMERENTRY) lpTimers = (LPWINE_TIMERENTRY)
HeapAlloc(GetProcessHeap(), 0, 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 */ /* TIME_ONESHOT is defined as 0 */
if (!(lpTimer->wFlags & TIME_PERIODIC)) if (!(timer->wFlags & TIME_PERIODIC))
timeKillEvent(lpTimer->wTimerID); {
/* unlink timer from timers list */
*ptimer = *next_ptimer;
HeapFree(GetProcessHeap(), 0, timer);
}
} else { } else {
lpTimer->uCurTime -= MMSYSTIME_MININTERVAL; timer->uCurTime -= MMSYSTIME_MININTERVAL;
} }
lpTimer = lpNextTimer; ptimer = next_ptimer;
} }
if (TIME_hKillEvent) ResetEvent(TIME_hKillEvent);
LeaveCriticalSection(&iData->cs); LeaveCriticalSection(&iData->cs);
while (idx > 0) { while (idx > 0) TIME_TriggerCallBack(&lpTimers[--idx]);
TIME_TriggerCallBack(&iData->lpTimers[--idx]); if (TIME_hKillEvent) SetEvent(TIME_hKillEvent);
}
} }
} }
...@@ -160,7 +172,7 @@ static void CALLBACK TIME_MMSysTimeCallback(LPWINE_MM_IDATA iData) ...@@ -160,7 +172,7 @@ static void CALLBACK TIME_MMSysTimeCallback(LPWINE_MM_IDATA iData)
static DWORD CALLBACK TIME_MMSysTimeThread(LPVOID arg) static DWORD CALLBACK TIME_MMSysTimeThread(LPVOID arg)
{ {
LPWINE_MM_IDATA iData = (LPWINE_MM_IDATA)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; DWORD last_time, cur_time;
usleep(MMSYSTIME_STDINTERVAL * 1000); usleep(MMSYSTIME_STDINTERVAL * 1000);
...@@ -184,10 +196,10 @@ void TIME_MMTimeStart(void) ...@@ -184,10 +196,10 @@ void TIME_MMTimeStart(void)
* mm timers are active, but this would require to keep mmSysTimeMS up-to-date * mm timers are active, but this would require to keep mmSysTimeMS up-to-date
* without being incremented within the service thread callback. * without being incremented within the service thread callback.
*/ */
if (!WINMM_IData->hMMTimer) { if (!TIME_hMMTimer) {
WINMM_IData->mmSysTimeMS = GetTickCount(); WINMM_SysTimeMS = GetTickCount();
WINMM_IData->lpTimerList = NULL; TIME_TimersList = NULL;
WINMM_IData->hMMTimer = CreateThread(NULL, 0, TIME_MMSysTimeThread, WINMM_IData, 0, NULL); TIME_hMMTimer = CreateThread(NULL, 0, TIME_MMSysTimeThread, WINMM_IData, 0, NULL);
} }
} }
...@@ -196,9 +208,10 @@ void TIME_MMTimeStart(void) ...@@ -196,9 +208,10 @@ void TIME_MMTimeStart(void)
*/ */
void TIME_MMTimeStop(void) void TIME_MMTimeStop(void)
{ {
if (WINMM_IData->hMMTimer) { /* FIXME: in the worst case, we're going to wait 65 seconds here :-( */
HANDLE hMMTimer = WINMM_IData->hMMTimer; if (TIME_hMMTimer) {
WINMM_IData->hMMTimer = 0; HANDLE hMMTimer = TIME_hMMTimer;
TIME_hMMTimer = 0;
WaitForSingleObject(hMMTimer, INFINITE); WaitForSingleObject(hMMTimer, INFINITE);
CloseHandle(hMMTimer); CloseHandle(hMMTimer);
} }
...@@ -214,7 +227,7 @@ MMRESULT WINAPI timeGetSystemTime(LPMMTIME lpTime, UINT wSize) ...@@ -214,7 +227,7 @@ MMRESULT WINAPI timeGetSystemTime(LPMMTIME lpTime, UINT wSize)
if (wSize >= sizeof(*lpTime)) { if (wSize >= sizeof(*lpTime)) {
TIME_MMTimeStart(); TIME_MMTimeStart();
lpTime->wType = TIME_MS; lpTime->wType = TIME_MS;
lpTime->u.ms = WINMM_IData->mmSysTimeMS; lpTime->u.ms = WINMM_SysTimeMS;
TRACE("=> %lu\n", lpTime->u.ms); TRACE("=> %lu\n", lpTime->u.ms);
} }
...@@ -252,12 +265,15 @@ WORD TIME_SetEventInternal(UINT wDelay, UINT wResol, ...@@ -252,12 +265,15 @@ WORD TIME_SetEventInternal(UINT wDelay, UINT wResol,
EnterCriticalSection(&WINMM_IData->cs); 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); wNewID = max(wNewID, lpTimer->wTimerID);
} }
lpNewTimer->lpNext = WINMM_IData->lpTimerList; lpNewTimer->lpNext = TIME_TimersList;
WINMM_IData->lpTimerList = lpNewTimer; TIME_TimersList = lpNewTimer;
lpNewTimer->wTimerID = wNewID + 1; lpNewTimer->wTimerID = wNewID + 1;
LeaveCriticalSection(&WINMM_IData->cs); LeaveCriticalSection(&WINMM_IData->cs);
...@@ -285,31 +301,30 @@ MMRESULT WINAPI timeSetEvent(UINT wDelay, UINT wResol, LPTIMECALLBACK lpFunc, ...@@ -285,31 +301,30 @@ MMRESULT WINAPI timeSetEvent(UINT wDelay, UINT wResol, LPTIMECALLBACK lpFunc,
*/ */
MMRESULT WINAPI timeKillEvent(UINT wID) MMRESULT WINAPI timeKillEvent(UINT wID)
{ {
LPWINE_TIMERENTRY* lpTimer; LPWINE_TIMERENTRY lpSelf = NULL, *lpTimer;
MMRESULT ret = MMSYSERR_INVALPARAM;
TRACE("(%u)\n", wID); TRACE("(%u)\n", wID);
EnterCriticalSection(&WINMM_IData->cs); EnterCriticalSection(&WINMM_IData->cs);
/* remove WINE_TIMERENTRY from list */ /* 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) { if (wID == (*lpTimer)->wTimerID) {
lpSelf = *lpTimer;
/* unlink timer of id 'wID' */
*lpTimer = (*lpTimer)->lpNext;
break; break;
} }
} }
LeaveCriticalSection(&WINMM_IData->cs); LeaveCriticalSection(&WINMM_IData->cs);
if (*lpTimer) { if (!lpSelf)
LPWINE_TIMERENTRY lpTemp = *lpTimer; {
WARN("wID=%u is not a valid timer ID\n", wID);
/* unlink timer of id 'wID' */ return MMSYSERR_INVALPARAM;
*lpTimer = (*lpTimer)->lpNext;
HeapFree(GetProcessHeap(), 0, lpTemp);
ret = TIMERR_NOERROR;
} else {
WARN("wID=%u is not a valid timer ID\n", wID);
} }
if (lpSelf->wFlags & TIME_KILL_SYNCHRONOUS)
return ret; WaitForSingleObject(TIME_hKillEvent, INFINITE);
HeapFree(GetProcessHeap(), 0, lpSelf);
return TIMERR_NOERROR;
} }
/************************************************************************** /**************************************************************************
...@@ -361,5 +376,5 @@ DWORD WINAPI timeGetTime(void) ...@@ -361,5 +376,5 @@ DWORD WINAPI timeGetTime(void)
if (pFnReleaseThunkLock) pFnReleaseThunkLock(&count); if (pFnReleaseThunkLock) pFnReleaseThunkLock(&count);
TIME_MMTimeStart(); TIME_MMTimeStart();
if (pFnRestoreThunkLock) pFnRestoreThunkLock(count); if (pFnRestoreThunkLock) pFnRestoreThunkLock(count);
return WINMM_IData->mmSysTimeMS; return WINMM_SysTimeMS;
} }
...@@ -201,12 +201,6 @@ typedef struct tagWINE_MM_IDATA { ...@@ -201,12 +201,6 @@ typedef struct tagWINE_MM_IDATA {
HANDLE hWinMM32Instance; HANDLE hWinMM32Instance;
HANDLE hWinMM16Instance; HANDLE hWinMM16Instance;
CRITICAL_SECTION cs; CRITICAL_SECTION cs;
/* mm timer part */
HANDLE hMMTimer;
DWORD mmSysTimeMS;
LPWINE_TIMERENTRY lpTimerList;
int nSizeLpTimers;
LPWINE_TIMERENTRY lpTimers;
/* mci part */ /* mci part */
LPWINE_MCIDRIVER lpMciDrvs; LPWINE_MCIDRIVER lpMciDrvs;
/* low level drivers (unused yet) */ /* low level drivers (unused yet) */
...@@ -242,7 +236,7 @@ DWORD MMDRV_Open(LPWINE_MLD mld, UINT wMsg, DWORD dwParam1, DWORD dwParam2); ...@@ -242,7 +236,7 @@ DWORD MMDRV_Open(LPWINE_MLD mld, UINT wMsg, DWORD dwParam1, DWORD dwParam2);
DWORD MMDRV_Close(LPWINE_MLD mld, UINT wMsg); DWORD MMDRV_Close(LPWINE_MLD mld, UINT wMsg);
LPWINE_MLD MMDRV_Get(HANDLE hndl, UINT type, BOOL bCanBeID); LPWINE_MLD MMDRV_Get(HANDLE hndl, UINT type, BOOL bCanBeID);
LPWINE_MLD MMDRV_GetRelated(HANDLE hndl, UINT srcType, BOOL bSrcCanBeID, UINT dstTyped); 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); UINT MMDRV_PhysicalFeatures(LPWINE_MLD mld, UINT uMsg, DWORD dwParam1, DWORD dwParam2);
BOOL MMDRV_Is32(unsigned int); BOOL MMDRV_Is32(unsigned int);
void MMDRV_InstallMap(unsigned int, MMDRV_MAPFUNC, MMDRV_UNMAPFUNC, void MMDRV_InstallMap(unsigned int, MMDRV_MAPFUNC, MMDRV_UNMAPFUNC,
...@@ -290,6 +284,7 @@ void TIME_MMTimeStop(void); ...@@ -290,6 +284,7 @@ void TIME_MMTimeStop(void);
/* Global variables */ /* Global variables */
extern LPWINE_MM_IDATA WINMM_IData; extern LPWINE_MM_IDATA WINMM_IData;
extern DWORD WINMM_SysTimeMS;
/* pointers to 16 bit functions (if sibling MMSYSTEM.DLL is loaded /* pointers to 16 bit functions (if sibling MMSYSTEM.DLL is loaded
* NULL otherwise * NULL otherwise
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment