Author: ion Date: Thu Jul 13 23:43:10 2006 New Revision: 23045
URL: http://svn.reactos.org/svn/reactos?rev=23045&view=rev Log: [FORMATTING] - Cleanup timer.c
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:43:10 2006 @@ -1,98 +1,230 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/ke/timer.c * PURPOSE: Handle Kernel Timers (Kernel-part of Executive Timers) - * - * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Reimplemented some parts, fixed many bugs. - * David Welch (welch@mcmail.com) & Phillip Susi - Original Implementation. + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + * David Welch (welch@mcmail.com) */
/* INCLUDES ***************************************************************/
#include <ntoskrnl.h> - #define NDEBUG #include <internal/debug.h>
/* GLOBALS ****************************************************************/
LIST_ENTRY KiTimerListHead; - #define SYSTEM_TIME_UNITS_PER_MSEC (10000)
-/* FUNCTIONS **************************************************************/ - -BOOLEAN STDCALL KiInsertTimer(PKTIMER Timer, LARGE_INTEGER DueTime); -VOID STDCALL KiHandleExpiredTimer(PKTIMER Timer); - -/* - * @implemented - * - * FUNCTION: Removes a timer from the system timer list - * ARGUMENTS: - * Timer = timer to cancel - * RETURNS: True if the timer was running - * False otherwise - * - * DANGER! - * The statement in the DDK for KeCancelTimer that "if a DPC object is - * associated with the timer, it too is canceled" is wrong -- nothing is - * done with the DPC object when the timer is removed from the system - * queue. So its very likely that the DPC will run after you have canceled - * the timer! - * For what it's worth, calling KeRemoveQueueDpc after KeCancelTimer would - * be sufficient to prevent any problems associated with destroying the DPC - * object, at least as the OS is currently implemented. This is because the - * DPC dispatcher doesn't need access to the object once the DPC is - * dequeued, and the dequeuing happens before the DPC routine gets called." - * -Gunnar (article by Walter Oney) - */ -BOOLEAN -STDCALL -KeCancelTimer(PKTIMER Timer) -{ +/* PRIVATE FUNCTIONS ******************************************************/ + +VOID +NTAPI +KiRemoveTimer(IN PKTIMER Timer) +{ + /* Remove the timer */ + Timer->Header.Inserted = FALSE; + RemoveEntryList(&Timer->TimerListEntry); +} + +/* + * Note: This function is called with the Dispatcher Lock held. + */ +BOOLEAN +NTAPI +KiInsertTimer(IN PKTIMER Timer, + IN LARGE_INTEGER DueTime) +{ + LARGE_INTEGER SystemTime; + LARGE_INTEGER DifferenceTime; + ULONGLONG InterruptTime; + + /* Set default data */ + Timer->Header.Inserted = TRUE; + Timer->Header.Absolute = FALSE; + if (!Timer->Period) Timer->Header.SignalState = FALSE; + + /* Convert to relative time if needed */ + if (DueTime.HighPart >= 0) + { + /* Get System Time */ + KeQuerySystemTime(&SystemTime); + + /* Do the conversion */ + DifferenceTime.QuadPart = SystemTime.QuadPart - DueTime.QuadPart; + + /* Make sure it hasn't already expired */ + if (DifferenceTime.HighPart >= 0) + { + /* Cancel everything */ + Timer->Header.SignalState = TRUE; + Timer->Header.Inserted = FALSE; + return FALSE; + } + + /* Set the time as Absolute */ + Timer->Header.Absolute = TRUE; + DueTime = DifferenceTime; + } + + /* Get the Interrupt Time */ + InterruptTime = KeQueryInterruptTime(); + + /* Set the Final Due Time */ + Timer->DueTime.QuadPart = InterruptTime - DueTime.QuadPart; + + /* Now insert it into the Timer List */ + InsertAscendingList(&KiTimerListHead, + Timer, + KTIMER, + TimerListEntry, + DueTime.QuadPart); + return TRUE; +} + +/* + * We enter this function at IRQL DISPATCH_LEVEL, and with the + * Dispatcher Lock held! + */ +VOID +NTAPI +KiHandleExpiredTimer(IN PKTIMER Timer) +{ + LARGE_INTEGER DueTime; + + /* Set it as Signaled */ + Timer->Header.SignalState = TRUE; + + /* 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) + { + /* Reinsert the Timer */ + DueTime.QuadPart = Timer->Period * -SYSTEM_TIME_UNITS_PER_MSEC; + while (!KiInsertTimer(Timer, DueTime)); + } + + /* Check if the Timer has a DPC */ + if (Timer->Dpc) + { + /* Insert the DPC */ + KeInsertQueueDpc(Timer->Dpc, + NULL, + NULL); + } +} + +VOID +NTAPI +KiExpireTimers(IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +{ + PKTIMER Timer; + ULONGLONG InterruptTime; + LIST_ENTRY ExpiredTimerList; + PLIST_ENTRY ListHead, NextEntry; KIRQL OldIrql; - BOOLEAN Inserted = FALSE; - - DPRINT("KeCancelTimer(Timer %x)\n",Timer); + + /* Initialize the Expired Timer List */ + InitializeListHead(&ExpiredTimerList);
/* Lock the Database and Raise IRQL */ OldIrql = KeAcquireDispatcherDatabaseLock();
- /* Check if it's inserted, and remove it if it is */ - if ((Inserted = Timer->Header.Inserted)) { - - /* Remove from list */ - DPRINT("Timer was inserted, removing\n"); + /* Query Interrupt Times */ + InterruptTime = KeQueryInterruptTime(); + + /* Loop through the Timer List */ + ListHead = &KiTimerListHead; + NextEntry = ListHead->Flink; + while (NextEntry != ListHead) + { + /* Get the timer */ + Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry); + + /* Check if we have to Expire it */ + if (InterruptTime < Timer->DueTime.QuadPart) break; + + /* 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 (ExpiredTimerList.Flink != &ExpiredTimerList) + { + /* Get the Timer */ + Timer = CONTAINING_RECORD(ExpiredTimerList.Flink, + KTIMER, + TimerListEntry); + + /* Remove it */ + /// + // GCC IS A BRAINDEAD PIECE OF SHIT. WILL GIVE 5$ FOR EACH DEV KILLED. + /// Timer->Header.Inserted = FALSE; - - } else { - - DPRINT("Timer was not inserted\n"); + RemoveEntryList(&Timer->TimerListEntry); + //KiRemoveTimer(Timer); + + /* Expire it */ + KiHandleExpiredTimer(Timer); }
/* Release Dispatcher Lock */ KeReleaseDispatcherDatabaseLock(OldIrql); - - /* Return the old state */ - DPRINT("Old State: %d\n", Inserted); - return(Inserted); -} - -/* - * @implemented - * - * FUNCTION: Initalizes a kernel timer object - * ARGUMENTS: - * Timer = caller supplied storage for the timer - * NOTE: This function initializes a notification timer - */ -VOID -STDCALL -KeInitializeTimer (PKTIMER Timer) - +} + +/* PUBLIC FUNCTIONS **********************************************************/ + +/* + * @implemented + */ +BOOLEAN +NTAPI +KeCancelTimer(IN OUT PKTIMER Timer) +{ + KIRQL OldIrql; + BOOLEAN Inserted; + ASSERT_TIMER(Timer); + ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); + + /* Lock the Database and Raise IRQL */ + OldIrql = KeAcquireDispatcherDatabaseLock(); + + /* Check if it's inserted, and remove it if it is */ + Inserted = Timer->Header.Inserted; + if (Inserted) + { + /// + // GCC IS A BRAINDEAD PIECE OF SHIT. WILL GIVE 5$ FOR EACH DEV KILLED. + /// + Timer->Header.Inserted = FALSE; + RemoveEntryList(&Timer->TimerListEntry); + //KiRemoveTimer(Timer); + } + + /* Release Dispatcher Lock */ + KeReleaseDispatcherDatabaseLock(OldIrql); + return Inserted; +} + +/* + * @implemented + */ +VOID +NTAPI +KeInitializeTimer(OUT PKTIMER Timer) { /* Call the New Function */ KeInitializeTimerEx(Timer, NotificationTimer); @@ -100,24 +232,12 @@
/* * @implemented - * - * FUNCTION: Initializes a kernel timer object - * ARGUMENTS: - * Timer = caller supplied storage for the timer - * Type = the type of timer (notification or synchronization) - * NOTE: When a notification type expires all waiting threads are released - * and the timer remains signalled until it is explicitly reset. When a - * syncrhonization timer expires its state is set to signalled until a - * single waiting thread is released and then the timer is reset. - */ -VOID -STDCALL -KeInitializeTimerEx (PKTIMER Timer, - TIMER_TYPE Type) -{ - - DPRINT("KeInitializeTimerEx(%x, %d)\n", Timer, Type); - + */ +VOID +NTAPI +KeInitializeTimerEx(OUT PKTIMER Timer, + IN TIMER_TYPE Type) +{ /* Initialize the Dispatch Header */ KeInitializeDispatcherHeader(&Timer->Header, TimerNotificationObject + Type, @@ -129,37 +249,26 @@ Timer->Period = 0; }
- -/* - * @implemented - */ -BOOLEAN -STDCALL -KeReadStateTimer (PKTIMER Timer) +/* + * @implemented + */ +BOOLEAN +NTAPI +KeReadStateTimer(IN PKTIMER Timer) { /* Return the Signal State */ + ASSERT_TIMER(Timer); return (BOOLEAN)Timer->Header.SignalState; }
/* * @implemented - * - * FUNCTION: Sets the absolute or relative interval at which a timer object - * is to be set to the signaled state and optionally supplies a - * CustomTimerDpc to be executed when the timer expires. - * ARGUMENTS: - * Timer = Points to a previously initialized timer object - * DueTimer = If positive then absolute time to expire at - * If negative then the relative time to expire at - * Dpc = If non-NULL then a dpc to be called when the timer expires - * RETURNS: True if the timer was already in the system timer queue - * False otherwise - */ -BOOLEAN -STDCALL -KeSetTimer (PKTIMER Timer, - LARGE_INTEGER DueTime, - PKDPC Dpc) + */ +BOOLEAN +NTAPI +KeSetTimer(IN OUT PKTIMER Timer, + IN LARGE_INTEGER DueTime, + IN PKDPC Dpc OPTIONAL) { /* Call the newer function and supply a period of 0 */ return KeSetTimerEx(Timer, DueTime, 0, Dpc); @@ -167,41 +276,32 @@
/* * @implemented - * - * FUNCTION: Sets the absolute or relative interval at which a timer object - * is to be set to the signaled state and optionally supplies a - * CustomTimerDpc to be executed when the timer expires. - * ARGUMENTS: - * Timer = Points to a previously initialized timer object - * DueTimer = If positive then absolute time to expire at - * If negative then the relative time to expire at - * Dpc = If non-NULL then a dpc to be called when the timer expires - * RETURNS: True if the timer was already in the system timer queue - * False otherwise - */ -BOOLEAN -STDCALL -KeSetTimerEx (PKTIMER Timer, - LARGE_INTEGER DueTime, - LONG Period, - PKDPC Dpc) + */ +BOOLEAN +NTAPI +KeSetTimerEx(IN OUT PKTIMER Timer, + IN LARGE_INTEGER DueTime, + IN LONG Period, + IN PKDPC Dpc OPTIONAL) { KIRQL OldIrql; BOOLEAN Inserted; - - DPRINT("KeSetTimerEx(Timer %x, DueTime %I64d, Period %d, Dpc %x)\n", Timer, DueTime.QuadPart, Period, Dpc); - ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); + ASSERT_TIMER(Timer); + ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Lock the Database and Raise IRQL */ OldIrql = KeAcquireDispatcherDatabaseLock();
/* Check if it's inserted, and remove it if it is */ - if ((Inserted = Timer->Header.Inserted)) { - - /* Remove from list */ - DPRINT("Timer was already inserted\n"); + Inserted = Timer->Header.Inserted; + if (Inserted) + { + /// + // GCC IS A BRAINDEAD PIECE OF SHIT. WILL GIVE 5$ FOR EACH DEV KILLED. + /// + Timer->Header.Inserted = FALSE; RemoveEntryList(&Timer->TimerListEntry); - Timer->Header.Inserted = FALSE; + //KiRemoveTimer(Timer); }
/* Set Default Timer Data */ @@ -241,174 +341,7 @@ KeReleaseDispatcherDatabaseLock(OldIrql);
/* Return old state */ - DPRINT("Old State: %d\n", Inserted); return Inserted; }
-VOID -STDCALL -KiExpireTimers(PKDPC Dpc, - PVOID DeferredContext, - PVOID SystemArgument1, - PVOID SystemArgument2) -{ - PKTIMER Timer; - ULONGLONG InterruptTime; - LIST_ENTRY ExpiredTimerList; - PLIST_ENTRY ListHead, NextEntry; - KIRQL OldIrql; - - /* Initialize the Expired Timer List */ - InitializeListHead(&ExpiredTimerList); - - /* Lock the Database and Raise IRQL */ - OldIrql = KeAcquireDispatcherDatabaseLock(); - - /* Query Interrupt Times */ - InterruptTime = KeQueryInterruptTime(); - - /* Loop through the Timer List */ - ListHead = &KiTimerListHead; - NextEntry = ListHead->Flink; - while (NextEntry != ListHead) - { - /* Get the timer */ - Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry); - - /* Check if we have to Expire it */ - if (InterruptTime < Timer->DueTime.QuadPart) break; - - /* 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 (ExpiredTimerList.Flink != &ExpiredTimerList) - { - /* Get the Timer */ - Timer = CONTAINING_RECORD(ExpiredTimerList.Flink, - KTIMER, - TimerListEntry); - - /* Remove it */ - Timer->Header.Inserted = FALSE; - RemoveEntryList(&Timer->TimerListEntry); - - /* Expire it */ - KiHandleExpiredTimer(Timer); - } - - /* Release Dispatcher Lock */ - KeReleaseDispatcherDatabaseLock(OldIrql); -} - -/* - * We enter this function at IRQL DISPATCH_LEVEL, and with the - * Dispatcher Lock held! - */ -VOID -STDCALL -KiHandleExpiredTimer(PKTIMER Timer) -{ - LARGE_INTEGER DueTime; - - /* Set it as Signaled */ - Timer->Header.SignalState = TRUE; - - /* 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) { - - /* Reinsert the Timer */ - DueTime.QuadPart = Timer->Period * -SYSTEM_TIME_UNITS_PER_MSEC; - if (!KiInsertTimer(Timer, DueTime)) { - - /* FIXME: I will think about how to handle this and fix it ASAP -- Alex */ - DPRINT("CRITICAL UNHANDLED CASE: TIMER ALREADY EXPIRED!!!\n"); - }; - } - - /* Check if the Timer has a DPC */ - if (Timer->Dpc) { - - DPRINT("Timer->Dpc %x Timer->Dpc->DeferredRoutine %x\n", Timer->Dpc, Timer->Dpc->DeferredRoutine); - - /* Insert the DPC */ - KeInsertQueueDpc(Timer->Dpc, - NULL, - NULL); - - DPRINT("Finished dpc routine\n"); - } -} - -/* - * Note: This function is called with the Dispatcher Lock held. - */ -BOOLEAN -STDCALL -KiInsertTimer(PKTIMER Timer, - LARGE_INTEGER DueTime) -{ - LARGE_INTEGER SystemTime; - LARGE_INTEGER DifferenceTime; - ULONGLONG InterruptTime; - - DPRINT("KiInsertTimer(Timer %x DueTime %I64d)\n", Timer, DueTime.QuadPart); - - /* Set default data */ - Timer->Header.Inserted = TRUE; - Timer->Header.Absolute = FALSE; - if (!Timer->Period) Timer->Header.SignalState = FALSE; - - /* Convert to relative time if needed */ - if (DueTime.u.HighPart >= 0) { - - /* Get System Time */ - KeQuerySystemTime(&SystemTime); - - /* Do the conversion */ - DifferenceTime.QuadPart = SystemTime.QuadPart - DueTime.QuadPart; - DPRINT("Time Difference is: %I64d\n", DifferenceTime.QuadPart); - - /* Make sure it hasn't already expired */ - if (DifferenceTime.u.HighPart >= 0) { - - /* Cancel everything */ - DPRINT("Timer already expired: %d\n", DifferenceTime.u.HighPart); - Timer->Header.SignalState = TRUE; - Timer->Header.Inserted = FALSE; - return FALSE; - } - - /* Set the time as Absolute */ - Timer->Header.Absolute = TRUE; - DueTime = DifferenceTime; - } - - /* Get the Interrupt Time */ - InterruptTime = KeQueryInterruptTime(); - - /* Set the Final Due Time */ - Timer->DueTime.QuadPart = InterruptTime - DueTime.QuadPart; - DPRINT("Final Due Time is: %I64d\n", Timer->DueTime.QuadPart); - - /* Now insert it into the Timer List */ - DPRINT("Inserting Timer into list\n"); - InsertAscendingList(&KiTimerListHead, - Timer, - KTIMER, - TimerListEntry, - DueTime.QuadPart); - - return TRUE; -} /* EOF */