- implemented TIME_KILL_SYCHRONOUS timer flags
- timeKillTimer is now thread safe - replaced some iData attributes by global variables
This commit is contained in:
parent
370a18f786
commit
9db6037de8
|
@ -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 @@
|
||||||
|
|
||||||
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)
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
* 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)
|
||||||
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)
|
||||||
* 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)
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
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 {
|
||||||
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);
|
||||||
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);
|
||||||
|
|
||||||
/* 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
|
||||||
|
|
Loading…
Reference in New Issue