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=230... ============================================================================== --- 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) {