Made the timer code thread safe.

This commit is contained in:
Stephane Lussier 1999-03-25 13:23:26 +00:00 committed by Alexandre Julliard
parent f91e6d037e
commit 35ffc5d8c0
3 changed files with 98 additions and 11 deletions

View file

@ -18,6 +18,7 @@ extern BOOL MSG_InternalGetMessage( MSG *msg, HWND hwnd,
WORD flags, BOOL sendIdle ); WORD flags, BOOL sendIdle );
/* timer.c */ /* timer.c */
extern BOOL TIMER_Init( void );
extern void TIMER_RemoveWindowTimers( HWND hwnd ); extern void TIMER_RemoveWindowTimers( HWND hwnd );
extern void TIMER_RemoveQueueTimers( HQUEUE16 hqueue ); extern void TIMER_RemoveQueueTimers( HQUEUE16 hqueue );
extern void TIMER_SwitchQueue( HQUEUE16 hOldQueue, HQUEUE16 hNewQueue ); extern void TIMER_SwitchQueue( HQUEUE16 hOldQueue, HQUEUE16 hNewQueue );

View file

@ -210,6 +210,9 @@ BOOL WINAPI MAIN_UserInit(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserve
/* Create the DCEs */ /* Create the DCEs */
DCE_Init(); DCE_Init();
/* Initialize timers */
if (!TIMER_Init()) return FALSE;
/* Initialize window procedures */ /* Initialize window procedures */
if (!WINPROC_Init()) return FALSE; if (!WINPROC_Init()) return FALSE;

View file

@ -30,11 +30,27 @@ static TIMER TimersArray[NB_TIMERS];
static TIMER * pNextTimer = NULL; /* Next timer to expire */ static TIMER * pNextTimer = NULL; /* Next timer to expire */
static CRITICAL_SECTION csTimer;
/* Duration from 'time' until expiration of the timer */ /* Duration from 'time' until expiration of the timer */
#define EXPIRE_TIME(pTimer,time) \ #define EXPIRE_TIME(pTimer,time) \
(((pTimer)->expires <= (time)) ? 0 : (pTimer)->expires - (time)) (((pTimer)->expires <= (time)) ? 0 : (pTimer)->expires - (time))
/***********************************************************************
* TIMER_Init
*
* Initialize critical section for the timer.
*/
BOOL TIMER_Init( void )
{
InitializeCriticalSection( &csTimer );
MakeCriticalSectionGlobal( &csTimer );
return TRUE;
}
/*********************************************************************** /***********************************************************************
* TIMER_InsertTimer * TIMER_InsertTimer
* *
@ -42,6 +58,8 @@ static TIMER * pNextTimer = NULL; /* Next timer to expire */
*/ */
static void TIMER_InsertTimer( TIMER * pTimer ) static void TIMER_InsertTimer( TIMER * pTimer )
{ {
EnterCriticalSection( &csTimer );
if (!pNextTimer || (pTimer->expires < pNextTimer->expires)) if (!pNextTimer || (pTimer->expires < pNextTimer->expires))
{ {
pTimer->next = pNextTimer; pTimer->next = pNextTimer;
@ -55,6 +73,8 @@ static void TIMER_InsertTimer( TIMER * pTimer )
pTimer->next = ptr->next; pTimer->next = ptr->next;
ptr->next = pTimer; ptr->next = pTimer;
} }
LeaveCriticalSection( &csTimer );
} }
@ -67,9 +87,14 @@ static void TIMER_RemoveTimer( TIMER * pTimer )
{ {
TIMER **ppTimer = &pNextTimer; TIMER **ppTimer = &pNextTimer;
EnterCriticalSection( &csTimer );
while (*ppTimer && (*ppTimer != pTimer)) ppTimer = &(*ppTimer)->next; while (*ppTimer && (*ppTimer != pTimer)) ppTimer = &(*ppTimer)->next;
if (*ppTimer) *ppTimer = pTimer->next; if (*ppTimer) *ppTimer = pTimer->next;
pTimer->next = NULL; pTimer->next = NULL;
LeaveCriticalSection( &csTimer );
if (!pTimer->expires) QUEUE_DecTimerCount( pTimer->hq ); if (!pTimer->expires) QUEUE_DecTimerCount( pTimer->hq );
} }
@ -95,13 +120,18 @@ static void TIMER_ClearTimer( TIMER * pTimer )
*/ */
void TIMER_SwitchQueue( HQUEUE16 old, HQUEUE16 new ) void TIMER_SwitchQueue( HQUEUE16 old, HQUEUE16 new )
{ {
TIMER * pT = pNextTimer; TIMER * pT;
EnterCriticalSection( &csTimer );
pT = pNextTimer;
while (pT) while (pT)
{ {
if (pT->hq == old) pT->hq = new; if (pT->hq == old) pT->hq = new;
pT = pT->next; pT = pT->next;
} }
LeaveCriticalSection( &csTimer );
} }
@ -115,9 +145,13 @@ void TIMER_RemoveWindowTimers( HWND hwnd )
int i; int i;
TIMER *pTimer; TIMER *pTimer;
EnterCriticalSection( &csTimer );
for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++) for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
if ((pTimer->hwnd == hwnd) && pTimer->timeout) if ((pTimer->hwnd == hwnd) && pTimer->timeout)
TIMER_ClearTimer( pTimer ); TIMER_ClearTimer( pTimer );
LeaveCriticalSection( &csTimer );
} }
@ -131,9 +165,13 @@ void TIMER_RemoveQueueTimers( HQUEUE16 hqueue )
int i; int i;
TIMER *pTimer; TIMER *pTimer;
EnterCriticalSection( &csTimer );
for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++) for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
if ((pTimer->hq == hqueue) && pTimer->timeout) if ((pTimer->hq == hqueue) && pTimer->timeout)
TIMER_ClearTimer( pTimer ); TIMER_ClearTimer( pTimer );
LeaveCriticalSection( &csTimer );
} }
@ -157,7 +195,13 @@ static void TIMER_RestartTimer( TIMER * pTimer, DWORD curTime )
*/ */
LONG TIMER_GetNextExpiration(void) LONG TIMER_GetNextExpiration(void)
{ {
return pNextTimer ? EXPIRE_TIME( pNextTimer, GetTickCount() ) : -1; LONG retValue;
EnterCriticalSection( &csTimer );
retValue = pNextTimer ? EXPIRE_TIME( pNextTimer, GetTickCount() ) : -1;
LeaveCriticalSection( &csTimer );
return retValue;
} }
@ -168,9 +212,13 @@ LONG TIMER_GetNextExpiration(void)
*/ */
void TIMER_ExpireTimers(void) void TIMER_ExpireTimers(void)
{ {
TIMER *pTimer = pNextTimer; TIMER *pTimer;
DWORD curTime = GetTickCount(); DWORD curTime = GetTickCount();
EnterCriticalSection( &csTimer );
pTimer = pNextTimer;
while (pTimer && !pTimer->expires) /* Skip already expired timers */ while (pTimer && !pTimer->expires) /* Skip already expired timers */
pTimer = pTimer->next; pTimer = pTimer->next;
while (pTimer && (pTimer->expires <= curTime)) while (pTimer && (pTimer->expires <= curTime))
@ -179,6 +227,8 @@ void TIMER_ExpireTimers(void)
QUEUE_IncTimerCount( pTimer->hq ); QUEUE_IncTimerCount( pTimer->hq );
pTimer = pTimer->next; pTimer = pTimer->next;
} }
LeaveCriticalSection( &csTimer );
} }
@ -190,15 +240,24 @@ void TIMER_ExpireTimers(void)
BOOL TIMER_GetTimerMsg( MSG *msg, HWND hwnd, BOOL TIMER_GetTimerMsg( MSG *msg, HWND hwnd,
HQUEUE16 hQueue, BOOL remove ) HQUEUE16 hQueue, BOOL remove )
{ {
TIMER *pTimer = pNextTimer; TIMER *pTimer;
DWORD curTime = GetTickCount(); DWORD curTime = GetTickCount();
EnterCriticalSection( &csTimer );
pTimer = pNextTimer;
if (hwnd) /* Find first timer for this window */ if (hwnd) /* Find first timer for this window */
while (pTimer && (pTimer->hwnd != hwnd)) pTimer = pTimer->next; while (pTimer && (pTimer->hwnd != hwnd)) pTimer = pTimer->next;
else /* Find first timer for this queue */ else /* Find first timer for this queue */
while (pTimer && (pTimer->hq != hQueue)) pTimer = pTimer->next; while (pTimer && (pTimer->hq != hQueue)) pTimer = pTimer->next;
if (!pTimer || (pTimer->expires > curTime)) return FALSE; /* No timer */ if (!pTimer || (pTimer->expires > curTime))
{
LeaveCriticalSection( &csTimer );
return FALSE; /* No timer */
}
if (remove) TIMER_RestartTimer( pTimer, curTime ); /* Restart it */ if (remove) TIMER_RestartTimer( pTimer, curTime ); /* Restart it */
TRACE(timer, "Timer expired: %04x, %04x, %04x, %08lx\n", TRACE(timer, "Timer expired: %04x, %04x, %04x, %08lx\n",
@ -210,6 +269,9 @@ BOOL TIMER_GetTimerMsg( MSG *msg, HWND hwnd,
msg->wParam = pTimer->id; msg->wParam = pTimer->id;
msg->lParam = (LONG)pTimer->proc; msg->lParam = (LONG)pTimer->proc;
msg->time = curTime; msg->time = curTime;
LeaveCriticalSection( &csTimer );
return TRUE; return TRUE;
} }
@ -225,6 +287,8 @@ static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
if (!timeout) return 0; if (!timeout) return 0;
EnterCriticalSection( &csTimer );
/* Check if there's already a timer with the same hwnd and id */ /* Check if there's already a timer with the same hwnd and id */
for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++) for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
@ -240,6 +304,7 @@ static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
type, WIN_PROC_TIMER ); type, WIN_PROC_TIMER );
pTimer->expires = GetTickCount() + timeout; pTimer->expires = GetTickCount() + timeout;
TIMER_InsertTimer( pTimer ); TIMER_InsertTimer( pTimer );
LeaveCriticalSection( &csTimer );
return id; return id;
} }
@ -248,8 +313,13 @@ static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++) for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
if (!pTimer->timeout) break; if (!pTimer->timeout) break;
if (i >= NB_TIMERS) return 0; if ( (i >= NB_TIMERS) ||
if (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) return 0; (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) )
{
LeaveCriticalSection( &csTimer );
return 0;
}
if (!hwnd) id = i + 1; if (!hwnd) id = i + 1;
/* Add the timer */ /* Add the timer */
@ -267,6 +337,9 @@ static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
pTimer, pTimer->hwnd, pTimer->msg, pTimer->id, pTimer, pTimer->hwnd, pTimer->msg, pTimer->id,
(DWORD)pTimer->proc ); (DWORD)pTimer->proc );
TIMER_InsertTimer( pTimer ); TIMER_InsertTimer( pTimer );
LeaveCriticalSection( &csTimer );
if (!id) return TRUE; if (!id) return TRUE;
else return id; else return id;
} }
@ -280,19 +353,29 @@ static BOOL TIMER_KillTimer( HWND hwnd, UINT id, BOOL sys )
int i; int i;
TIMER * pTimer; TIMER * pTimer;
EnterCriticalSection( &csTimer );
/* Find the timer */ /* Find the timer */
for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++) for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
if ((pTimer->hwnd == hwnd) && (pTimer->id == id) && if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
(pTimer->timeout != 0)) break; (pTimer->timeout != 0)) break;
if (i >= NB_TIMERS) return FALSE;
if (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) return FALSE; if ( (i >= NB_TIMERS) ||
if (!sys && (pTimer->msg != WM_TIMER)) return FALSE; (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) ||
else if (sys && (pTimer->msg != WM_SYSTIMER)) return FALSE; (!sys && (pTimer->msg != WM_TIMER)) ||
(sys && (pTimer->msg != WM_SYSTIMER)) )
{
LeaveCriticalSection( &csTimer );
return FALSE;
}
/* Delete the timer */ /* Delete the timer */
TIMER_ClearTimer( pTimer ); TIMER_ClearTimer( pTimer );
LeaveCriticalSection( &csTimer );
return TRUE; return TRUE;
} }