Author: ion
Date: Thu Jul 13 23:04:39 2006
New Revision: 23044
URL:
http://svn.reactos.org/svn/reactos?rev=23044&view=rev
Log:
- Don't make the timer signaled in KeSetTimerEx if it already expired.
- Only call KiWaitTest on timers if they have waiters.
- Fix list looping in KiExpireTimers.
Modified:
trunk/reactos/ntoskrnl/ke/timer.c
Modified: trunk/reactos/ntoskrnl/ke/timer.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/timer.c?rev=23…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/timer.c (original)
+++ trunk/reactos/ntoskrnl/ke/timer.c Thu Jul 13 23:04:39 2006
@@ -210,10 +210,32 @@
Timer->Header.SignalState = FALSE;
/* Insert it */
- if (!KiInsertTimer(Timer, DueTime)) {
-
- KiHandleExpiredTimer(Timer);
- };
+ if (!KiInsertTimer(Timer, DueTime))
+ {
+ /* Check if it has any waiters */
+ if (!IsListEmpty(&Timer->Header.WaitListHead))
+ {
+ /* Wake them */
+ KiWaitTest(Timer, IO_NO_INCREMENT);
+ }
+
+ /* Check if the Timer has a DPC */
+ if (Dpc)
+ {
+ /* Insert the DPC */
+ KeInsertQueueDpc(Timer->Dpc,
+ NULL,
+ NULL);
+ }
+
+ /* Check if the Timer is periodic */
+ if (Timer->Period)
+ {
+ /* Reinsert the Timer */
+ DueTime.QuadPart = Timer->Period * -SYSTEM_TIME_UNITS_PER_MSEC;
+ while (!KiInsertTimer(Timer, DueTime));
+ }
+ }
/* Release Dispatcher Lock */
KeReleaseDispatcherDatabaseLock(OldIrql);
@@ -230,13 +252,11 @@
PVOID SystemArgument1,
PVOID SystemArgument2)
{
- PKTIMER Timer, tmp;
+ PKTIMER Timer;
ULONGLONG InterruptTime;
LIST_ENTRY ExpiredTimerList;
- PLIST_ENTRY CurrentEntry = NULL;
+ PLIST_ENTRY ListHead, NextEntry;
KIRQL OldIrql;
-
- DPRINT("KiExpireTimers(Dpc: %x)\n", Dpc);
/* Initialize the Expired Timer List */
InitializeListHead(&ExpiredTimerList);
@@ -247,10 +267,13 @@
/* Query Interrupt Times */
InterruptTime = KeQueryInterruptTime();
- /* Loop through the Timer List and remove Expired Timers. Insert them into the
Expired Listhead */
- LIST_FOR_EACH_SAFE(Timer, tmp, &KiTimerListHead, KTIMER, TimerListEntry)
+ /* Loop through the Timer List */
+ ListHead = &KiTimerListHead;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
{
- DPRINT("Looping for Timer: %x. Duetime: %I64d. InterruptTime %I64d \n",
Timer, Timer->DueTime.QuadPart, InterruptTime);
+ /* Get the timer */
+ Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry);
/* Check if we have to Expire it */
if (InterruptTime < Timer->DueTime.QuadPart) break;
@@ -258,24 +281,25 @@
/* Remove it from the Timer List, add it to the Expired List */
RemoveEntryList(&Timer->TimerListEntry);
InsertTailList(&ExpiredTimerList, &Timer->TimerListEntry);
+ NextEntry = ListHead->Flink;
}
/* Expire the Timers */
- while (!IsListEmpty(&ExpiredTimerList)) {
-
- CurrentEntry = RemoveHeadList(&ExpiredTimerList);
-
+ while (ExpiredTimerList.Flink != &ExpiredTimerList)
+ {
/* Get the Timer */
- Timer = CONTAINING_RECORD(CurrentEntry, KTIMER, TimerListEntry);
+ Timer = CONTAINING_RECORD(ExpiredTimerList.Flink,
+ KTIMER,
+ TimerListEntry);
+
+ /* Remove it */
Timer->Header.Inserted = FALSE;
- DPRINT("Expiring Timer: %x\n", Timer);
+ RemoveEntryList(&Timer->TimerListEntry);
/* Expire it */
KiHandleExpiredTimer(Timer);
}
- DPRINT("Timers expired\n");
-
/* Release Dispatcher Lock */
KeReleaseDispatcherDatabaseLock(OldIrql);
}
@@ -288,21 +312,17 @@
STDCALL
KiHandleExpiredTimer(PKTIMER Timer)
{
-
LARGE_INTEGER DueTime;
- DPRINT("HandleExpiredTime(Timer %x)\n", Timer);
-
- if(Timer->Header.Inserted) {
-
- /* First of all, remove the Timer */
- Timer->Header.Inserted = FALSE;
- RemoveEntryList(&Timer->TimerListEntry);
- }
/* Set it as Signaled */
- DPRINT("Setting Timer as Signaled\n");
Timer->Header.SignalState = TRUE;
- KiWaitTest(&Timer->Header, IO_NO_INCREMENT);
+
+ /* Check if it has any waiters */
+ if (!IsListEmpty(&Timer->Header.WaitListHead))
+ {
+ /* Wake them */
+ KiWaitTest(Timer, IO_NO_INCREMENT);
+ }
/* If the Timer is periodic, reinsert the timer with the new due time */
if (Timer->Period) {