2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iocomp.c
5 * PURPOSE: I/O Wrappers for Executive Timers
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES *****************************************************************/
15 /* GLOBALS *******************************************************************/
18 KSPIN_LOCK IopTimerLock
;
19 LIST_ENTRY IopTimerQueueHead
;
25 /* Keep count of how many timers we have */
26 ULONG IopTimerCount
= 0;
28 /* PRIVATE FUNCTIONS *********************************************************/
32 IopTimerDispatch(IN PKDPC Dpc
,
33 IN PVOID DeferredContext
,
34 IN PVOID SystemArgument1
,
35 IN PVOID SystemArgument2
)
38 PLIST_ENTRY TimerEntry
;
42 /* Check if any Timers are actualyl enabled as of now */
46 KeAcquireSpinLock(&IopTimerLock
, &OldIrql
);
48 /* Call the Timer Routine of each enabled Timer */
49 for (TimerEntry
= IopTimerQueueHead
.Flink
, i
= IopTimerCount
;
50 (TimerEntry
!= &IopTimerQueueHead
) && i
;
51 TimerEntry
= TimerEntry
->Flink
)
53 /* Get the timer and check if it's enabled */
54 Timer
= CONTAINING_RECORD(TimerEntry
, IO_TIMER
, IoTimerList
);
55 if (Timer
->TimerEnabled
)
57 /* Call the timer routine */
58 Timer
->TimerRoutine(Timer
->DeviceObject
, Timer
->Context
);
63 /* Unlock the Timers */
64 KeReleaseSpinLock(&IopTimerLock
, OldIrql
);
70 IopRemoveTimerFromTimerList(IN PIO_TIMER Timer
)
75 KeAcquireSpinLock(&IopTimerLock
, &OldIrql
);
77 /* Remove Timer from the List and Drop the Timer Count if Enabled */
78 RemoveEntryList(&Timer
->IoTimerList
);
79 if (Timer
->TimerEnabled
) IopTimerCount
--;
81 /* Unlock the Timers */
82 KeReleaseSpinLock(&IopTimerLock
, OldIrql
);
85 /* PUBLIC FUNCTIONS **********************************************************/
92 IoInitializeTimer(IN PDEVICE_OBJECT DeviceObject
,
93 IN PIO_TIMER_ROUTINE TimerRoutine
,
96 PIO_TIMER IoTimer
= DeviceObject
->Timer
;
99 /* Check if we don't have a timer yet */
103 IoTimer
= ExAllocatePoolWithTag(NonPagedPool
,
106 if (!IoTimer
) return STATUS_INSUFFICIENT_RESOURCES
;
108 /* Set up the Timer Structure */
109 RtlZeroMemory(IoTimer
, sizeof(IO_TIMER
));
110 IoTimer
->Type
= IO_TYPE_TIMER
;
111 IoTimer
->DeviceObject
= DeviceObject
;
112 DeviceObject
->Timer
= IoTimer
;
115 /* Setup the timer routine and context */
116 IoTimer
->TimerRoutine
= TimerRoutine
;
117 IoTimer
->Context
= Context
;
119 /* Add it to the Timer List */
120 ExInterlockedInsertTailList(&IopTimerQueueHead
,
121 &IoTimer
->IoTimerList
,
125 return STATUS_SUCCESS
;
133 IoStartTimer(IN PDEVICE_OBJECT DeviceObject
)
136 PIO_TIMER IoTimer
= DeviceObject
->Timer
;
138 /* Make sure the device isn't unloading */
139 if (!(((PEXTENDED_DEVOBJ_EXTENSION
)(DeviceObject
->DeviceObjectExtension
))->
140 ExtensionFlags
& (DOE_UNLOAD_PENDING
|
143 DOE_REMOVE_PROCESSED
)))
146 KeAcquireSpinLock(&IopTimerLock
, &OldIrql
);
148 /* Check if the timer isn't already enabled */
149 if (!IoTimer
->TimerEnabled
)
151 /* Enable it and increase the timer count */
152 IoTimer
->TimerEnabled
= TRUE
;
157 KeReleaseSpinLock(&IopTimerLock
, OldIrql
);
166 IoStopTimer(PDEVICE_OBJECT DeviceObject
)
169 PIO_TIMER IoTimer
= DeviceObject
->Timer
;
172 KeAcquireSpinLock(&IopTimerLock
, &OldIrql
);
174 /* Check if the timer is enabled */
175 if (IoTimer
->TimerEnabled
)
177 /* Disable it and decrease the timer count */
178 IoTimer
->TimerEnabled
= FALSE
;
183 KeReleaseSpinLock(&IopTimerLock
, OldIrql
);