mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 12:23:31 +00:00
[FORMATTING] - Cleanup timer.c
svn path=/trunk/; revision=23045
This commit is contained in:
+246
-313
@@ -1,256 +1,133 @@
|
||||
/*
|
||||
* 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 ([email protected]) - Reimplemented some parts, fixed many bugs.
|
||||
* David Welch ([email protected]) & Phillip Susi - Original Implementation.
|
||||
* PROGRAMMERS: Alex Ionescu ([email protected])
|
||||
* David Welch ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES ***************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* GLOBALS ****************************************************************/
|
||||
|
||||
LIST_ENTRY KiTimerListHead;
|
||||
|
||||
#define SYSTEM_TIME_UNITS_PER_MSEC (10000)
|
||||
|
||||
/* FUNCTIONS **************************************************************/
|
||||
/* PRIVATE 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)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
BOOLEAN Inserted = FALSE;
|
||||
|
||||
DPRINT("KeCancelTimer(Timer %x)\n",Timer);
|
||||
|
||||
/* 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");
|
||||
RemoveEntryList(&Timer->TimerListEntry);
|
||||
Timer->Header.Inserted = FALSE;
|
||||
|
||||
} else {
|
||||
|
||||
DPRINT("Timer was not inserted\n");
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
||||
NTAPI
|
||||
KiRemoveTimer(IN PKTIMER Timer)
|
||||
{
|
||||
/* Call the New Function */
|
||||
KeInitializeTimerEx(Timer, NotificationTimer);
|
||||
/* Remove the timer */
|
||||
Timer->Header.Inserted = FALSE;
|
||||
RemoveEntryList(&Timer->TimerListEntry);
|
||||
}
|
||||
|
||||
/*
|
||||
* @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);
|
||||
|
||||
/* Initialize the Dispatch Header */
|
||||
KeInitializeDispatcherHeader(&Timer->Header,
|
||||
TimerNotificationObject + Type,
|
||||
sizeof(KTIMER) / sizeof(ULONG),
|
||||
FALSE);
|
||||
|
||||
/* Initalize the Other data */
|
||||
Timer->DueTime.QuadPart = 0;
|
||||
Timer->Period = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
* Note: This function is called with the Dispatcher Lock held.
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeReadStateTimer (PKTIMER Timer)
|
||||
NTAPI
|
||||
KiInsertTimer(IN PKTIMER Timer,
|
||||
IN LARGE_INTEGER DueTime)
|
||||
{
|
||||
/* Return the Signal State */
|
||||
return (BOOLEAN)Timer->Header.SignalState;
|
||||
}
|
||||
LARGE_INTEGER SystemTime;
|
||||
LARGE_INTEGER DifferenceTime;
|
||||
ULONGLONG InterruptTime;
|
||||
|
||||
/*
|
||||
* @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)
|
||||
{
|
||||
/* Call the newer function and supply a period of 0 */
|
||||
return KeSetTimerEx(Timer, DueTime, 0, Dpc);
|
||||
}
|
||||
/* Set default data */
|
||||
Timer->Header.Inserted = TRUE;
|
||||
Timer->Header.Absolute = FALSE;
|
||||
if (!Timer->Period) Timer->Header.SignalState = FALSE;
|
||||
|
||||
/*
|
||||
* @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)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
BOOLEAN Inserted;
|
||||
|
||||
DPRINT("KeSetTimerEx(Timer %x, DueTime %I64d, Period %d, Dpc %x)\n", Timer, DueTime.QuadPart, Period, Dpc);
|
||||
ASSERT(KeGetCurrentIrql() <= 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");
|
||||
RemoveEntryList(&Timer->TimerListEntry);
|
||||
Timer->Header.Inserted = FALSE;
|
||||
}
|
||||
|
||||
/* Set Default Timer Data */
|
||||
Timer->Dpc = Dpc;
|
||||
Timer->Period = Period;
|
||||
Timer->Header.SignalState = FALSE;
|
||||
|
||||
/* Insert it */
|
||||
if (!KiInsertTimer(Timer, DueTime))
|
||||
/* Convert to relative time if needed */
|
||||
if (DueTime.HighPart >= 0)
|
||||
{
|
||||
/* Check if it has any waiters */
|
||||
if (!IsListEmpty(&Timer->Header.WaitListHead))
|
||||
/* 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)
|
||||
{
|
||||
/* Wake them */
|
||||
KiWaitTest(Timer, IO_NO_INCREMENT);
|
||||
/* Cancel everything */
|
||||
Timer->Header.SignalState = TRUE;
|
||||
Timer->Header.Inserted = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* 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));
|
||||
}
|
||||
/* Set the time as Absolute */
|
||||
Timer->Header.Absolute = TRUE;
|
||||
DueTime = DifferenceTime;
|
||||
}
|
||||
|
||||
/* Release Dispatcher Lock */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
/* Get the Interrupt Time */
|
||||
InterruptTime = KeQueryInterruptTime();
|
||||
|
||||
/* Return old state */
|
||||
DPRINT("Old State: %d\n", Inserted);
|
||||
return Inserted;
|
||||
/* 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
|
||||
STDCALL
|
||||
KiExpireTimers(PKDPC Dpc,
|
||||
PVOID DeferredContext,
|
||||
PVOID SystemArgument1,
|
||||
PVOID SystemArgument2)
|
||||
NTAPI
|
||||
KiExpireTimers(IN PKDPC Dpc,
|
||||
IN PVOID DeferredContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2)
|
||||
{
|
||||
PKTIMER Timer;
|
||||
ULONGLONG InterruptTime;
|
||||
@@ -293,8 +170,12 @@ KiExpireTimers(PKDPC Dpc,
|
||||
TimerListEntry);
|
||||
|
||||
/* Remove it */
|
||||
///
|
||||
// GCC IS A BRAINDEAD PIECE OF SHIT. WILL GIVE 5$ FOR EACH DEV KILLED.
|
||||
///
|
||||
Timer->Header.Inserted = FALSE;
|
||||
RemoveEntryList(&Timer->TimerListEntry);
|
||||
//KiRemoveTimer(Timer);
|
||||
|
||||
/* Expire it */
|
||||
KiHandleExpiredTimer(Timer);
|
||||
@@ -304,111 +185,163 @@ KiExpireTimers(PKDPC Dpc,
|
||||
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");
|
||||
}
|
||||
}
|
||||
/* PUBLIC FUNCTIONS **********************************************************/
|
||||
|
||||
/*
|
||||
* Note: This function is called with the Dispatcher Lock held.
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KiInsertTimer(PKTIMER Timer,
|
||||
LARGE_INTEGER DueTime)
|
||||
NTAPI
|
||||
KeCancelTimer(IN OUT PKTIMER Timer)
|
||||
{
|
||||
LARGE_INTEGER SystemTime;
|
||||
LARGE_INTEGER DifferenceTime;
|
||||
ULONGLONG InterruptTime;
|
||||
KIRQL OldIrql;
|
||||
BOOLEAN Inserted;
|
||||
ASSERT_TIMER(Timer);
|
||||
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||
|
||||
DPRINT("KiInsertTimer(Timer %x DueTime %I64d)\n", Timer, DueTime.QuadPart);
|
||||
/* Lock the Database and Raise IRQL */
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
/* 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;
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
/* Release Dispatcher Lock */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return Inserted;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
KeInitializeTimer(OUT PKTIMER Timer)
|
||||
{
|
||||
/* Call the New Function */
|
||||
KeInitializeTimerEx(Timer, NotificationTimer);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
KeInitializeTimerEx(OUT PKTIMER Timer,
|
||||
IN TIMER_TYPE Type)
|
||||
{
|
||||
/* Initialize the Dispatch Header */
|
||||
KeInitializeDispatcherHeader(&Timer->Header,
|
||||
TimerNotificationObject + Type,
|
||||
sizeof(KTIMER) / sizeof(ULONG),
|
||||
FALSE);
|
||||
|
||||
/* Initalize the Other data */
|
||||
Timer->DueTime.QuadPart = 0;
|
||||
Timer->Period = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
KeReadStateTimer(IN PKTIMER Timer)
|
||||
{
|
||||
/* Return the Signal State */
|
||||
ASSERT_TIMER(Timer);
|
||||
return (BOOLEAN)Timer->Header.SignalState;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
KeSetTimerEx(IN OUT PKTIMER Timer,
|
||||
IN LARGE_INTEGER DueTime,
|
||||
IN LONG Period,
|
||||
IN PKDPC Dpc OPTIONAL)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* Set Default Timer Data */
|
||||
Timer->Dpc = Dpc;
|
||||
Timer->Period = Period;
|
||||
Timer->Header.SignalState = FALSE;
|
||||
|
||||
/* Insert it */
|
||||
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);
|
||||
|
||||
/* Return old state */
|
||||
return Inserted;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
Reference in New Issue
Block a user