- Patch by rafalh <rafalh1992 at o2 dor pl>, see bug 5835. Fix timers implementation.


svn path=/trunk/; revision=50547
This commit is contained in:
James Tabor 2011-01-29 09:03:25 +00:00
parent 3ade810715
commit ac10b13f14

View file

@ -19,7 +19,7 @@
/* GLOBALS *******************************************************************/ /* GLOBALS *******************************************************************/
static PTIMER FirstpTmr = NULL; static LIST_ENTRY TimersListHead;
static LONG TimeLast = 0; static LONG TimeLast = 0;
#define MAX_ELAPSE_TIME 0x7FFFFFFF #define MAX_ELAPSE_TIME 0x7FFFFFFF
@ -62,26 +62,13 @@ CreateTimer(VOID)
HANDLE Handle; HANDLE Handle;
PTIMER Ret = NULL; PTIMER Ret = NULL;
if (!FirstpTmr) Ret = UserCreateObject(gHandleTable, NULL, &Handle, otTimer, sizeof(TIMER));
if (Ret)
{ {
ExInitializeResourceLite(&TimerLock); Ret->head.h = Handle;
FirstpTmr = UserCreateObject(gHandleTable, NULL, &Handle, otTimer, sizeof(TIMER)); InsertTailList(&TimersListHead, &Ret->ptmrList);
if (FirstpTmr)
{
FirstpTmr->head.h = Handle;
InitializeListHead(&FirstpTmr->ptmrList);
}
Ret = FirstpTmr;
}
else
{
Ret = UserCreateObject(gHandleTable, NULL, &Handle, otTimer, sizeof(TIMER));
if (Ret)
{
Ret->head.h = Handle;
InsertTailList(&FirstpTmr->ptmrList, &Ret->ptmrList);
}
} }
return Ret; return Ret;
} }
@ -118,12 +105,13 @@ FindTimer(PWND Window,
UINT_PTR nID, UINT_PTR nID,
UINT flags) UINT flags)
{ {
PLIST_ENTRY pLE; PLIST_ENTRY pLE = TimersListHead.Flink;
PTIMER pTmr = FirstpTmr, RetTmr = NULL; PTIMER pTmr, RetTmr = NULL;
TimerEnterExclusive(); TimerEnterExclusive();
do while (pLE != &TimersListHead)
{ {
if (!pTmr) break; pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
if ( pTmr->nID == nID && if ( pTmr->nID == nID &&
pTmr->pWnd == Window && pTmr->pWnd == Window &&
@ -133,9 +121,8 @@ FindTimer(PWND Window,
break; break;
} }
pLE = pTmr->ptmrList.Flink; pLE = pLE->Flink;
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList); }
} while (pTmr != FirstpTmr);
TimerLeave(); TimerLeave();
return RetTmr; return RetTmr;
@ -145,20 +132,20 @@ PTIMER
FASTCALL FASTCALL
FindSystemTimer(PMSG pMsg) FindSystemTimer(PMSG pMsg)
{ {
PLIST_ENTRY pLE; PLIST_ENTRY pLE = TimersListHead.Flink;
PTIMER pTmr = FirstpTmr; PTIMER pTmr = NULL;
TimerEnterExclusive(); TimerEnterExclusive();
do while (pLE != &TimersListHead)
{ {
if (!pTmr) break; pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
if ( pMsg->lParam == (LPARAM)pTmr->pfn && if ( pMsg->lParam == (LPARAM)pTmr->pfn &&
(pTmr->flags & TMRF_SYSTEM) ) (pTmr->flags & TMRF_SYSTEM) )
break; break;
pLE = pTmr->ptmrList.Flink; pLE = pLE->Flink;
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList); }
} while (pTmr != FirstpTmr);
TimerLeave(); TimerLeave();
return pTmr; return pTmr;
@ -169,15 +156,14 @@ FASTCALL
ValidateTimerCallback(PTHREADINFO pti, ValidateTimerCallback(PTHREADINFO pti,
LPARAM lParam) LPARAM lParam)
{ {
PLIST_ENTRY pLE; PLIST_ENTRY pLE = TimersListHead.Flink;
BOOL Ret = FALSE; BOOL Ret = FALSE;
PTIMER pTmr = FirstpTmr; PTIMER pTmr;
if (!pTmr) return FALSE;
TimerEnterExclusive(); TimerEnterExclusive();
do while (pLE != &TimersListHead)
{ {
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
if ( (lParam == (LPARAM)pTmr->pfn) && if ( (lParam == (LPARAM)pTmr->pfn) &&
!(pTmr->flags & (TMRF_SYSTEM|TMRF_RIT)) && !(pTmr->flags & (TMRF_SYSTEM|TMRF_RIT)) &&
(pTmr->pti->ppi == pti->ppi) ) (pTmr->pti->ppi == pti->ppi) )
@ -185,9 +171,8 @@ ValidateTimerCallback(PTHREADINFO pti,
Ret = TRUE; Ret = TRUE;
break; break;
} }
pLE = pTmr->ptmrList.Flink; pLE = pLE->Flink;
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList); }
} while (pTmr != FirstpTmr);
TimerLeave(); TimerLeave();
return Ret; return Ret;
@ -286,7 +271,7 @@ IntSetTimer( PWND Window,
ASSERT(MasterTimer != NULL); ASSERT(MasterTimer != NULL);
// Start the timer thread! // Start the timer thread!
if (pTmr == FirstpTmr) if (TimersListHead.Flink == TimersListHead.Blink) // There is only one timer
KeSetTimer(MasterTimer, DueTime, NULL); KeSetTimer(MasterTimer, DueTime, NULL);
return Ret; return Ret;
@ -334,22 +319,21 @@ BOOL
FASTCALL FASTCALL
PostTimerMessages(PWND Window) PostTimerMessages(PWND Window)
{ {
PLIST_ENTRY pLE; PLIST_ENTRY pLE = TimersListHead.Flink;
PUSER_MESSAGE_QUEUE ThreadQueue; PUSER_MESSAGE_QUEUE ThreadQueue;
MSG Msg; MSG Msg;
PTHREADINFO pti; PTHREADINFO pti;
BOOL Hit = FALSE; BOOL Hit = FALSE;
PTIMER pTmr = FirstpTmr; PTIMER pTmr;
if (!pTmr) return FALSE;
pti = PsGetCurrentThreadWin32Thread(); pti = PsGetCurrentThreadWin32Thread();
ThreadQueue = pti->MessageQueue; ThreadQueue = pti->MessageQueue;
TimerEnterExclusive(); TimerEnterExclusive();
do while(pLE != &TimersListHead)
{ {
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
if ( (pTmr->flags & TMRF_READY) && if ( (pTmr->flags & TMRF_READY) &&
(pTmr->pti == pti) && (pTmr->pti == pti) &&
((pTmr->pWnd == Window) || (Window == NULL)) ) ((pTmr->pWnd == Window) || (Window == NULL)) )
@ -366,9 +350,8 @@ PostTimerMessages(PWND Window)
break; break;
} }
pLE = pTmr->ptmrList.Flink; pLE = pLE->Flink;
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList); }
} while (pTmr != FirstpTmr);
TimerLeave(); TimerLeave();
@ -381,12 +364,10 @@ ProcessTimers(VOID)
{ {
LARGE_INTEGER TickCount, DueTime; LARGE_INTEGER TickCount, DueTime;
LONG Time; LONG Time;
PLIST_ENTRY pLE; PLIST_ENTRY pLE = TimersListHead.Flink;
PTIMER pTmr = FirstpTmr; PTIMER pTmr;
LONG TimerCount = 0; LONG TimerCount = 0;
if (!pTmr) return;
TimerEnterExclusive(); TimerEnterExclusive();
KeQueryTickCount(&TickCount); KeQueryTickCount(&TickCount);
@ -394,8 +375,9 @@ ProcessTimers(VOID)
DueTime.QuadPart = (LONGLONG)(-500000); DueTime.QuadPart = (LONGLONG)(-500000);
do while(pLE != &TimersListHead)
{ {
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
TimerCount++; TimerCount++;
if (pTmr->flags & TMRF_WAITING) if (pTmr->flags & TMRF_WAITING)
{ {
@ -440,9 +422,8 @@ ProcessTimers(VOID)
pTmr->cmsCountdown -= Time - TimeLast; pTmr->cmsCountdown -= Time - TimeLast;
} }
pLE = pTmr->ptmrList.Flink; pLE = pLE->Flink;
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList); }
} while (pTmr != FirstpTmr);
// Restart the timer thread! // Restart the timer thread!
ASSERT(MasterTimer != NULL); ASSERT(MasterTimer != NULL);
@ -457,24 +438,24 @@ ProcessTimers(VOID)
BOOL FASTCALL BOOL FASTCALL
DestroyTimersForWindow(PTHREADINFO pti, PWND Window) DestroyTimersForWindow(PTHREADINFO pti, PWND Window)
{ {
PLIST_ENTRY pLE; PLIST_ENTRY pLE = TimersListHead.Flink;
PTIMER pTmr = FirstpTmr; PTIMER pTmr;
BOOL TimersRemoved = FALSE; BOOL TimersRemoved = FALSE;
if ((FirstpTmr == NULL) || (Window == NULL)) if ((Window == NULL))
return FALSE; return FALSE;
TimerEnterExclusive(); TimerEnterExclusive();
do while(pLE != &TimersListHead)
{ {
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
pLE = pLE->Flink; /* get next timer list entry before current timer is removed */
if ((pTmr) && (pTmr->pti == pti) && (pTmr->pWnd == Window)) if ((pTmr) && (pTmr->pti == pti) && (pTmr->pWnd == Window))
{ {
TimersRemoved = RemoveTimer(pTmr); TimersRemoved = RemoveTimer(pTmr);
} }
pLE = pTmr->ptmrList.Flink; }
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
} while (pTmr != FirstpTmr);
TimerLeave(); TimerLeave();
@ -484,24 +465,21 @@ DestroyTimersForWindow(PTHREADINFO pti, PWND Window)
BOOL FASTCALL BOOL FASTCALL
DestroyTimersForThread(PTHREADINFO pti) DestroyTimersForThread(PTHREADINFO pti)
{ {
PLIST_ENTRY pLE; PLIST_ENTRY pLE = TimersListHead.Flink;
PTIMER pTmr = FirstpTmr; PTIMER pTmr;
BOOL TimersRemoved = FALSE; BOOL TimersRemoved = FALSE;
if (FirstpTmr == NULL)
return FALSE;
TimerEnterExclusive(); TimerEnterExclusive();
do while(pLE != &TimersListHead)
{ {
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
pLE = pLE->Flink; /* get next timer list entry before current timer is removed */
if ((pTmr) && (pTmr->pti == pti)) if ((pTmr) && (pTmr->pti == pti))
{ {
TimersRemoved = RemoveTimer(pTmr); TimersRemoved = RemoveTimer(pTmr);
} }
pLE = pTmr->ptmrList.Flink; }
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
} while (pTmr != FirstpTmr);
TimerLeave(); TimerLeave();
@ -550,6 +528,9 @@ InitTimerImpl(VOID)
/* yes we need this, since ExAllocatePoolWithTag isn't supposed to zero out allocated memory */ /* yes we need this, since ExAllocatePoolWithTag isn't supposed to zero out allocated memory */
RtlClearAllBits(&WindowLessTimersBitMap); RtlClearAllBits(&WindowLessTimersBitMap);
ExInitializeResourceLite(&TimerLock);
InitializeListHead(&TimersListHead);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }