3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/timer.c
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 * Alex Ionescu (alex@relsoft.net)
12 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
18 /* GLOBALS *******************************************************************/
20 #define TAG_IO_TIMER TAG('I', 'O', 'T', 'M')
23 KSPIN_LOCK IopTimerLock
;
24 LIST_ENTRY IopTimerQueueHead
;
30 /* Keep count of how many timers we have */
31 ULONG IopTimerCount
= 0;
33 /* FUNCTIONS *****************************************************************/
36 IopTimerDispatch(IN PKDPC Dpc
,
37 IN PVOID DeferredContext
,
38 IN PVOID SystemArgument1
,
39 IN PVOID SystemArgument2
)
42 PLIST_ENTRY TimerEntry
;
46 DPRINT("Dispatching IO Timers. There are: %x \n", IopTimerCount
);
48 /* Check if any Timers are actualyl enabled as of now */
52 KeAcquireSpinLock(&IopTimerLock
, &OldIrql
);
54 /* Call the Timer Routine of each enabled Timer */
55 for(TimerEntry
= IopTimerQueueHead
.Flink
, i
= IopTimerCount
;
56 (TimerEntry
!= &IopTimerQueueHead
) && i
;
57 TimerEntry
= TimerEntry
->Flink
) {
59 Timer
= CONTAINING_RECORD(TimerEntry
, IO_TIMER
, IoTimerList
);
60 if (Timer
->TimerEnabled
) {
61 DPRINT("Dispatching a Timer Routine: %x for Device Object: %x \n",
64 Timer
->TimerRoutine(Timer
->DeviceObject
, Timer
->Context
);
69 /* Unlock the Timers */
70 KeReleaseSpinLock(&IopTimerLock
, OldIrql
);
76 IopRemoveTimerFromTimerList(
83 KeAcquireSpinLock(&IopTimerLock
, &OldIrql
);
85 /* Remove Timer from the List and Drop the Timer Count if Enabled */
86 RemoveEntryList(&Timer
->IoTimerList
);
87 if (Timer
->TimerEnabled
) IopTimerCount
--;
89 /* Unlock the Timers */
90 KeReleaseSpinLock(&IopTimerLock
, OldIrql
);
95 IopInitTimerImplementation(VOID
)
96 /* FUNCTION: Initializes the IO Timer Object Implementation
100 LARGE_INTEGER ExpireTime
;
102 /* Initialize Timer List Lock */
103 KeInitializeSpinLock(&IopTimerLock
);
105 /* Initialize Timer List */
106 InitializeListHead(&IopTimerQueueHead
);
108 /* Initialize the DPC/Timer which will call the other Timer Routines */
109 ExpireTime
.QuadPart
= -10000000;
110 KeInitializeDpc(&IopTimerDpc
, IopTimerDispatch
, NULL
);
111 KeInitializeTimerEx(&IopTimer
, SynchronizationTimer
);
112 KeSetTimerEx(&IopTimer
, ExpireTime
, 1000, &IopTimerDpc
);
120 IoInitializeTimer(PDEVICE_OBJECT DeviceObject
,
121 PIO_TIMER_ROUTINE TimerRoutine
,
124 * FUNCTION: Sets up a driver-supplied IoTimer routine associated with a given
127 * DeviceObject = Device object whose timer is be initialized
128 * TimerRoutine = Driver supplied routine which will be called once per
129 * second if the timer is active
130 * Context = Driver supplied context to be passed to the TimerRoutine
134 DPRINT("IoInitializeTimer() called for Device Object: %x with Routine: %x \n", DeviceObject
, TimerRoutine
);
137 if (!DeviceObject
->Timer
) {
138 DeviceObject
->Timer
= ExAllocatePoolWithTag(NonPagedPool
,
141 if (!DeviceObject
->Timer
) return STATUS_INSUFFICIENT_RESOURCES
;
143 /* Set up the Timer Structure */
144 DeviceObject
->Timer
->Type
= IO_TYPE_TIMER
;
145 DeviceObject
->Timer
->DeviceObject
= DeviceObject
;
148 DeviceObject
->Timer
->TimerRoutine
= TimerRoutine
;
149 DeviceObject
->Timer
->Context
= Context
;
150 DeviceObject
->Timer
->TimerEnabled
= FALSE
;
152 /* Add it to the Timer List */
153 ExInterlockedInsertTailList(&IopTimerQueueHead
,
154 &DeviceObject
->Timer
->IoTimerList
,
158 DPRINT("IoInitializeTimer() Completed\n");
159 return(STATUS_SUCCESS
);
167 IoStartTimer(PDEVICE_OBJECT DeviceObject
)
169 * FUNCTION: Starts a timer so the driver-supplied IoTimer routine will be
170 * called once per second
172 * DeviceObject = Device whose timer is to be started
177 DPRINT("IoStartTimer for Device Object: %x\n", DeviceObject
);
180 KeAcquireSpinLock(&IopTimerLock
, &OldIrql
);
182 /* If the timer isn't already enabled, enable it and increase IO Timer Count*/
183 if (!DeviceObject
->Timer
->TimerEnabled
) {
184 DeviceObject
->Timer
->TimerEnabled
= TRUE
;
189 KeReleaseSpinLock(&IopTimerLock
, OldIrql
);
190 DPRINT("IoStartTimer Completed for Device Object: %x New Count: %x \n", DeviceObject
, IopTimerCount
);
198 IoStopTimer(PDEVICE_OBJECT DeviceObject
)
200 * FUNCTION: Disables for a specified device object so the driver-supplied
201 * IoTimer is not called
203 * DeviceObject = Device whose timer is to be stopped
208 DPRINT("IoStopTimer for Device Object: %x\n", DeviceObject
);
211 KeAcquireSpinLock(&IopTimerLock
, &OldIrql
);
213 /* If the timer is enabled, disable it and decrease IO Timer Count*/
214 if (DeviceObject
->Timer
->TimerEnabled
) {
215 DeviceObject
->Timer
->TimerEnabled
= FALSE
;
220 KeReleaseSpinLock(&IopTimerLock
, OldIrql
);
221 DPRINT("IoStopTimer Completed for Device Object: %x New Count: %x \n", DeviceObject
, IopTimerCount
);