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