1*c2c66affSColin Finck /* 2*c2c66affSColin Finck * PROJECT: ReactOS Kernel 3*c2c66affSColin Finck * LICENSE: GPL - See COPYING in the top level directory 4*c2c66affSColin Finck * FILE: ntoskrnl/io/iomgr/iotimer.c 5*c2c66affSColin Finck * PURPOSE: I/O Wrappers for Executive Timers 6*c2c66affSColin Finck * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7*c2c66affSColin Finck */ 8*c2c66affSColin Finck 9*c2c66affSColin Finck /* INCLUDES *****************************************************************/ 10*c2c66affSColin Finck 11*c2c66affSColin Finck #include <ntoskrnl.h> 12*c2c66affSColin Finck #define NDEBUG 13*c2c66affSColin Finck #include <debug.h> 14*c2c66affSColin Finck 15*c2c66affSColin Finck /* GLOBALS *******************************************************************/ 16*c2c66affSColin Finck 17*c2c66affSColin Finck /* Timer Database */ 18*c2c66affSColin Finck KSPIN_LOCK IopTimerLock; 19*c2c66affSColin Finck LIST_ENTRY IopTimerQueueHead; 20*c2c66affSColin Finck 21*c2c66affSColin Finck /* Timer Firing */ 22*c2c66affSColin Finck KDPC IopTimerDpc; 23*c2c66affSColin Finck KTIMER IopTimer; 24*c2c66affSColin Finck 25*c2c66affSColin Finck /* Keep count of how many timers we have */ 26*c2c66affSColin Finck ULONG IopTimerCount = 0; 27*c2c66affSColin Finck 28*c2c66affSColin Finck /* PRIVATE FUNCTIONS *********************************************************/ 29*c2c66affSColin Finck 30*c2c66affSColin Finck VOID 31*c2c66affSColin Finck NTAPI 32*c2c66affSColin Finck IopTimerDispatch(IN PKDPC Dpc, 33*c2c66affSColin Finck IN PVOID DeferredContext, 34*c2c66affSColin Finck IN PVOID SystemArgument1, 35*c2c66affSColin Finck IN PVOID SystemArgument2) 36*c2c66affSColin Finck { 37*c2c66affSColin Finck KIRQL OldIrql; 38*c2c66affSColin Finck PLIST_ENTRY TimerEntry; 39*c2c66affSColin Finck PIO_TIMER Timer; 40*c2c66affSColin Finck ULONG i; 41*c2c66affSColin Finck 42*c2c66affSColin Finck /* Check if any Timers are actualyl enabled as of now */ 43*c2c66affSColin Finck if (IopTimerCount) 44*c2c66affSColin Finck { 45*c2c66affSColin Finck /* Lock the Timers */ 46*c2c66affSColin Finck KeAcquireSpinLock(&IopTimerLock, &OldIrql); 47*c2c66affSColin Finck 48*c2c66affSColin Finck /* Call the Timer Routine of each enabled Timer */ 49*c2c66affSColin Finck for (TimerEntry = IopTimerQueueHead.Flink, i = IopTimerCount; 50*c2c66affSColin Finck (TimerEntry != &IopTimerQueueHead) && i; 51*c2c66affSColin Finck TimerEntry = TimerEntry->Flink) 52*c2c66affSColin Finck { 53*c2c66affSColin Finck /* Get the timer and check if it's enabled */ 54*c2c66affSColin Finck Timer = CONTAINING_RECORD(TimerEntry, IO_TIMER, IoTimerList); 55*c2c66affSColin Finck if (Timer->TimerEnabled) 56*c2c66affSColin Finck { 57*c2c66affSColin Finck /* Call the timer routine */ 58*c2c66affSColin Finck Timer->TimerRoutine(Timer->DeviceObject, Timer->Context); 59*c2c66affSColin Finck i--; 60*c2c66affSColin Finck } 61*c2c66affSColin Finck } 62*c2c66affSColin Finck 63*c2c66affSColin Finck /* Unlock the Timers */ 64*c2c66affSColin Finck KeReleaseSpinLock(&IopTimerLock, OldIrql); 65*c2c66affSColin Finck } 66*c2c66affSColin Finck } 67*c2c66affSColin Finck 68*c2c66affSColin Finck VOID 69*c2c66affSColin Finck NTAPI 70*c2c66affSColin Finck IopRemoveTimerFromTimerList(IN PIO_TIMER Timer) 71*c2c66affSColin Finck { 72*c2c66affSColin Finck KIRQL OldIrql; 73*c2c66affSColin Finck 74*c2c66affSColin Finck /* Lock Timers */ 75*c2c66affSColin Finck KeAcquireSpinLock(&IopTimerLock, &OldIrql); 76*c2c66affSColin Finck 77*c2c66affSColin Finck /* Remove Timer from the List and Drop the Timer Count if Enabled */ 78*c2c66affSColin Finck RemoveEntryList(&Timer->IoTimerList); 79*c2c66affSColin Finck if (Timer->TimerEnabled) IopTimerCount--; 80*c2c66affSColin Finck 81*c2c66affSColin Finck /* Unlock the Timers */ 82*c2c66affSColin Finck KeReleaseSpinLock(&IopTimerLock, OldIrql); 83*c2c66affSColin Finck } 84*c2c66affSColin Finck 85*c2c66affSColin Finck /* PUBLIC FUNCTIONS **********************************************************/ 86*c2c66affSColin Finck 87*c2c66affSColin Finck /* 88*c2c66affSColin Finck * @implemented 89*c2c66affSColin Finck */ 90*c2c66affSColin Finck NTSTATUS 91*c2c66affSColin Finck NTAPI 92*c2c66affSColin Finck IoInitializeTimer(IN PDEVICE_OBJECT DeviceObject, 93*c2c66affSColin Finck IN PIO_TIMER_ROUTINE TimerRoutine, 94*c2c66affSColin Finck IN PVOID Context) 95*c2c66affSColin Finck { 96*c2c66affSColin Finck PIO_TIMER IoTimer = DeviceObject->Timer; 97*c2c66affSColin Finck PAGED_CODE(); 98*c2c66affSColin Finck 99*c2c66affSColin Finck /* Check if we don't have a timer yet */ 100*c2c66affSColin Finck if (!IoTimer) 101*c2c66affSColin Finck { 102*c2c66affSColin Finck /* Allocate Timer */ 103*c2c66affSColin Finck IoTimer = ExAllocatePoolWithTag(NonPagedPool, 104*c2c66affSColin Finck sizeof(IO_TIMER), 105*c2c66affSColin Finck TAG_IO_TIMER); 106*c2c66affSColin Finck if (!IoTimer) return STATUS_INSUFFICIENT_RESOURCES; 107*c2c66affSColin Finck 108*c2c66affSColin Finck /* Set up the Timer Structure */ 109*c2c66affSColin Finck RtlZeroMemory(IoTimer, sizeof(IO_TIMER)); 110*c2c66affSColin Finck IoTimer->Type = IO_TYPE_TIMER; 111*c2c66affSColin Finck IoTimer->DeviceObject = DeviceObject; 112*c2c66affSColin Finck DeviceObject->Timer = IoTimer; 113*c2c66affSColin Finck } 114*c2c66affSColin Finck 115*c2c66affSColin Finck /* Setup the timer routine and context */ 116*c2c66affSColin Finck IoTimer->TimerRoutine = TimerRoutine; 117*c2c66affSColin Finck IoTimer->Context = Context; 118*c2c66affSColin Finck 119*c2c66affSColin Finck /* Add it to the Timer List */ 120*c2c66affSColin Finck ExInterlockedInsertTailList(&IopTimerQueueHead, 121*c2c66affSColin Finck &IoTimer->IoTimerList, 122*c2c66affSColin Finck &IopTimerLock); 123*c2c66affSColin Finck 124*c2c66affSColin Finck /* Return Success */ 125*c2c66affSColin Finck return STATUS_SUCCESS; 126*c2c66affSColin Finck } 127*c2c66affSColin Finck 128*c2c66affSColin Finck /* 129*c2c66affSColin Finck * @implemented 130*c2c66affSColin Finck */ 131*c2c66affSColin Finck VOID 132*c2c66affSColin Finck NTAPI 133*c2c66affSColin Finck IoStartTimer(IN PDEVICE_OBJECT DeviceObject) 134*c2c66affSColin Finck { 135*c2c66affSColin Finck KIRQL OldIrql; 136*c2c66affSColin Finck PIO_TIMER IoTimer = DeviceObject->Timer; 137*c2c66affSColin Finck 138*c2c66affSColin Finck /* Make sure the device isn't unloading */ 139*c2c66affSColin Finck if (!(((PEXTENDED_DEVOBJ_EXTENSION)(DeviceObject->DeviceObjectExtension))-> 140*c2c66affSColin Finck ExtensionFlags & (DOE_UNLOAD_PENDING | 141*c2c66affSColin Finck DOE_DELETE_PENDING | 142*c2c66affSColin Finck DOE_REMOVE_PENDING | 143*c2c66affSColin Finck DOE_REMOVE_PROCESSED))) 144*c2c66affSColin Finck { 145*c2c66affSColin Finck /* Lock Timers */ 146*c2c66affSColin Finck KeAcquireSpinLock(&IopTimerLock, &OldIrql); 147*c2c66affSColin Finck 148*c2c66affSColin Finck /* Check if the timer isn't already enabled */ 149*c2c66affSColin Finck if (!IoTimer->TimerEnabled) 150*c2c66affSColin Finck { 151*c2c66affSColin Finck /* Enable it and increase the timer count */ 152*c2c66affSColin Finck IoTimer->TimerEnabled = TRUE; 153*c2c66affSColin Finck IopTimerCount++; 154*c2c66affSColin Finck } 155*c2c66affSColin Finck 156*c2c66affSColin Finck /* Unlock Timers */ 157*c2c66affSColin Finck KeReleaseSpinLock(&IopTimerLock, OldIrql); 158*c2c66affSColin Finck } 159*c2c66affSColin Finck } 160*c2c66affSColin Finck 161*c2c66affSColin Finck /* 162*c2c66affSColin Finck * @implemented 163*c2c66affSColin Finck */ 164*c2c66affSColin Finck VOID 165*c2c66affSColin Finck NTAPI 166*c2c66affSColin Finck IoStopTimer(PDEVICE_OBJECT DeviceObject) 167*c2c66affSColin Finck { 168*c2c66affSColin Finck KIRQL OldIrql; 169*c2c66affSColin Finck PIO_TIMER IoTimer = DeviceObject->Timer; 170*c2c66affSColin Finck 171*c2c66affSColin Finck /* Lock Timers */ 172*c2c66affSColin Finck KeAcquireSpinLock(&IopTimerLock, &OldIrql); 173*c2c66affSColin Finck 174*c2c66affSColin Finck /* Check if the timer is enabled */ 175*c2c66affSColin Finck if (IoTimer->TimerEnabled) 176*c2c66affSColin Finck { 177*c2c66affSColin Finck /* Disable it and decrease the timer count */ 178*c2c66affSColin Finck IoTimer->TimerEnabled = FALSE; 179*c2c66affSColin Finck IopTimerCount--; 180*c2c66affSColin Finck } 181*c2c66affSColin Finck 182*c2c66affSColin Finck /* Unlock Timers */ 183*c2c66affSColin Finck KeReleaseSpinLock(&IopTimerLock, OldIrql); 184*c2c66affSColin Finck } 185*c2c66affSColin Finck 186*c2c66affSColin Finck /* EOF */ 187