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 *******************************************************************/
21 KSPIN_LOCK IopTimerLock
;
22 LIST_ENTRY IopTimerQueueHead
;
28 /* Keep count of how many timers we have */
29 ULONG IopTimerCount
= 0;
31 /* FUNCTIONS *****************************************************************/
34 IopTimerDispatch(IN PKDPC Dpc
,
35 IN PVOID DeferredContext
,
36 IN PVOID SystemArgument1
,
37 IN PVOID SystemArgument2
)
40 PLIST_ENTRY TimerEntry
;
44 DPRINT("Dispatching IO Timers. There are: %x \n", IopTimerCount
);
46 /* Check if any Timers are actualyl enabled as of now */
50 KeAcquireSpinLock(&IopTimerLock
, &OldIrql
);
52 /* Call the Timer Routine of each enabled Timer */
53 for(TimerEntry
= IopTimerQueueHead
.Flink
, i
= IopTimerCount
;
54 (TimerEntry
!= &IopTimerQueueHead
) && i
;
55 TimerEntry
= TimerEntry
->Flink
) {
57 Timer
= CONTAINING_RECORD(TimerEntry
, IO_TIMER
, IoTimerList
);
58 if (Timer
->TimerEnabled
) {
59 DPRINT("Dispatching a Timer Routine: 0x%p for Device Object: 0x%p \n",
62 Timer
->TimerRoutine(Timer
->DeviceObject
, Timer
->Context
);
67 /* Unlock the Timers */
68 KeReleaseSpinLock(&IopTimerLock
, OldIrql
);
74 IopRemoveTimerFromTimerList(
81 KeAcquireSpinLock(&IopTimerLock
, &OldIrql
);
83 /* Remove Timer from the List and Drop the Timer Count if Enabled */
84 RemoveEntryList(&Timer
->IoTimerList
);
85 if (Timer
->TimerEnabled
) IopTimerCount
--;
87 /* Unlock the Timers */
88 KeReleaseSpinLock(&IopTimerLock
, OldIrql
);
93 IopInitTimerImplementation(VOID
)
94 /* FUNCTION: Initializes the IO Timer Object Implementation
98 LARGE_INTEGER ExpireTime
;
100 /* Initialize Timer List Lock */
101 KeInitializeSpinLock(&IopTimerLock
);
103 /* Initialize Timer List */
104 InitializeListHead(&IopTimerQueueHead
);
106 /* Initialize the DPC/Timer which will call the other Timer Routines */
107 ExpireTime
.QuadPart
= -10000000;
108 KeInitializeDpc(&IopTimerDpc
, IopTimerDispatch
, NULL
);
109 KeInitializeTimerEx(&IopTimer
, SynchronizationTimer
);
110 KeSetTimerEx(&IopTimer
, ExpireTime
, 1000, &IopTimerDpc
);
118 IoInitializeTimer(PDEVICE_OBJECT DeviceObject
,
119 PIO_TIMER_ROUTINE TimerRoutine
,
122 * FUNCTION: Sets up a driver-supplied IoTimer routine associated with a given
125 * DeviceObject = Device object whose timer is be initialized
126 * TimerRoutine = Driver supplied routine which will be called once per
127 * second if the timer is active
128 * Context = Driver supplied context to be passed to the TimerRoutine
132 DPRINT("IoInitializeTimer() called for Device Object: 0x%p with Routine: 0x%p \n", DeviceObject
, TimerRoutine
);
135 if (!DeviceObject
->Timer
) {
136 DeviceObject
->Timer
= ExAllocatePoolWithTag(NonPagedPool
,
139 if (!DeviceObject
->Timer
) return STATUS_INSUFFICIENT_RESOURCES
;
141 /* Set up the Timer Structure */
142 DeviceObject
->Timer
->Type
= IO_TYPE_TIMER
;
143 DeviceObject
->Timer
->DeviceObject
= DeviceObject
;
146 DeviceObject
->Timer
->TimerRoutine
= TimerRoutine
;
147 DeviceObject
->Timer
->Context
= Context
;
148 DeviceObject
->Timer
->TimerEnabled
= FALSE
;
150 /* Add it to the Timer List */
151 ExInterlockedInsertTailList(&IopTimerQueueHead
,
152 &DeviceObject
->Timer
->IoTimerList
,
156 DPRINT("IoInitializeTimer() Completed\n");
157 return(STATUS_SUCCESS
);
165 IoStartTimer(PDEVICE_OBJECT DeviceObject
)
167 * FUNCTION: Starts a timer so the driver-supplied IoTimer routine will be
168 * called once per second
170 * DeviceObject = Device whose timer is to be started
175 DPRINT("IoStartTimer for Device Object: 0x%p\n", DeviceObject
);
178 KeAcquireSpinLock(&IopTimerLock
, &OldIrql
);
180 /* If the timer isn't already enabled, enable it and increase IO Timer Count*/
181 if (!DeviceObject
->Timer
->TimerEnabled
) {
182 DeviceObject
->Timer
->TimerEnabled
= TRUE
;
187 KeReleaseSpinLock(&IopTimerLock
, OldIrql
);
188 DPRINT("IoStartTimer Completed for Device Object: 0x%p New Count: %x \n", DeviceObject
, IopTimerCount
);
196 IoStopTimer(PDEVICE_OBJECT DeviceObject
)
198 * FUNCTION: Disables for a specified device object so the driver-supplied
199 * IoTimer is not called
201 * DeviceObject = Device whose timer is to be stopped
206 DPRINT("IoStopTimer for Device Object: 0x%p\n", DeviceObject
);
209 KeAcquireSpinLock(&IopTimerLock
, &OldIrql
);
211 /* If the timer is enabled, disable it and decrease IO Timer Count*/
212 if (DeviceObject
->Timer
->TimerEnabled
) {
213 DeviceObject
->Timer
->TimerEnabled
= FALSE
;
218 KeReleaseSpinLock(&IopTimerLock
, OldIrql
);
219 DPRINT("IoStopTimer Completed for Device Object: 0x%p New Count: %x \n", DeviceObject
, IopTimerCount
);