2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/devqueue.c
5 * PURPOSE: Implement device queues
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
13 #include <internal/debug.h>
15 /* FUNCTIONS *****************************************************************/
22 KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue
)
24 /* Initialize the Header */
25 DeviceQueue
->Type
= DeviceQueueObject
;
26 DeviceQueue
->Size
= sizeof(KDEVICE_QUEUE
);
28 /* Initialize the Listhead and Spinlock */
29 InitializeListHead(&DeviceQueue
->DeviceListHead
);
30 KeInitializeSpinLock(&DeviceQueue
->Lock
);
33 DeviceQueue
->Busy
=FALSE
;
41 KeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue
,
42 IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry
)
44 KLOCK_QUEUE_HANDLE DeviceLock
;
46 ASSERT_DEVICE_QUEUE(DeviceQueue
);
49 KiAcquireDeviceQueueLock(DeviceQueue
, &DeviceLock
);
51 /* Check if it's not busy */
52 if (!DeviceQueue
->Busy
)
56 DeviceQueue
->Busy
= TRUE
;
60 /* Insert it into the list */
62 InsertTailList(&DeviceQueue
->DeviceListHead
,
63 &DeviceQueueEntry
->DeviceListEntry
);
66 /* Sert the Insert state into the entry */
67 DeviceQueueEntry
->Inserted
= Inserted
;
69 /* Release the lock */
70 KiReleaseDeviceQueueLock(&DeviceLock
);
72 /* Return the state */
81 KeInsertByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue
,
82 IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry
,
85 KLOCK_QUEUE_HANDLE DeviceLock
;
87 ASSERT_DEVICE_QUEUE(DeviceQueue
);
90 KiAcquireDeviceQueueLock(DeviceQueue
, &DeviceLock
);
92 /* Set the Sort Key */
93 DeviceQueueEntry
->SortKey
= SortKey
;
95 /* Check if it's not busy */
96 if (!DeviceQueue
->Busy
)
100 DeviceQueue
->Busy
= TRUE
;
104 /* Insert new entry after the last entry with SortKey less or equal to passed-in SortKey */
105 InsertAscendingListFIFO(&DeviceQueue
->DeviceListHead
,
113 /* Release the lock */
114 KiReleaseDeviceQueueLock(&DeviceLock
);
116 /* Return the state */
125 KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue
)
127 PLIST_ENTRY ListEntry
;
128 PKDEVICE_QUEUE_ENTRY ReturnEntry
;
129 KLOCK_QUEUE_HANDLE DeviceLock
;
130 ASSERT_DEVICE_QUEUE(DeviceQueue
);
133 KiAcquireDeviceQueueLock(DeviceQueue
, &DeviceLock
);
134 ASSERT(DeviceQueue
->Busy
);
136 /* Check if this is an empty queue */
137 if (IsListEmpty(&DeviceQueue
->DeviceListHead
))
139 /* Set it to idle and return nothing*/
140 DeviceQueue
->Busy
= FALSE
;
145 /* Remove the Entry from the List */
146 ListEntry
= RemoveHeadList(&DeviceQueue
->DeviceListHead
);
147 ReturnEntry
= CONTAINING_RECORD(ListEntry
,
151 /* Set it as non-inserted */
152 ReturnEntry
->Inserted
= FALSE
;
155 /* Release the lock */
156 KiReleaseDeviceQueueLock(&DeviceLock
);
158 /* Return the entry */
167 KeRemoveByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue
,
170 PLIST_ENTRY ListEntry
;
171 PKDEVICE_QUEUE_ENTRY ReturnEntry
;
172 KLOCK_QUEUE_HANDLE DeviceLock
;
173 ASSERT_DEVICE_QUEUE(DeviceQueue
);
176 KiAcquireDeviceQueueLock(DeviceQueue
, &DeviceLock
);
177 ASSERT(DeviceQueue
->Busy
);
179 /* Check if this is an empty queue */
180 if (IsListEmpty(&DeviceQueue
->DeviceListHead
))
182 /* Set it to idle and return nothing*/
183 DeviceQueue
->Busy
= FALSE
;
188 /* Find entry with SortKey greater than or equal to the passed-in SortKey */
189 LIST_FOR_EACH(ReturnEntry
, &DeviceQueue
->DeviceListHead
, KDEVICE_QUEUE_ENTRY
, DeviceListEntry
)
191 /* Check if keys match */
192 if (ReturnEntry
->SortKey
>= SortKey
)
194 /* We found it, so just remove it */
195 RemoveEntryList(&ReturnEntry
->DeviceListEntry
);
200 /* Check if we found something */
203 /* Not found, return the first entry */
204 ListEntry
= RemoveHeadList(&DeviceQueue
->DeviceListHead
);
205 ReturnEntry
= CONTAINING_RECORD(ListEntry
,
210 /* Set it as non-inserted */
211 ReturnEntry
->Inserted
= FALSE
;
214 /* Release the lock */
215 KiReleaseDeviceQueueLock(&DeviceLock
);
217 /* Return the entry */
226 KeRemoveByKeyDeviceQueueIfBusy(IN PKDEVICE_QUEUE DeviceQueue
,
229 PLIST_ENTRY ListEntry
;
230 PKDEVICE_QUEUE_ENTRY ReturnEntry
;
231 KLOCK_QUEUE_HANDLE DeviceLock
;
232 ASSERT_DEVICE_QUEUE(DeviceQueue
);
235 KiAcquireDeviceQueueLock(DeviceQueue
, &DeviceLock
);
237 /* Check if this is an empty or idle queue */
238 if (!(DeviceQueue
->Busy
) || (IsListEmpty(&DeviceQueue
->DeviceListHead
)))
240 /* Set it to idle and return nothing*/
241 DeviceQueue
->Busy
= FALSE
;
246 /* Find entry with SortKey greater than or equal to the passed-in SortKey */
247 LIST_FOR_EACH(ReturnEntry
, &DeviceQueue
->DeviceListHead
, KDEVICE_QUEUE_ENTRY
, DeviceListEntry
)
249 /* Check if keys match */
250 if (ReturnEntry
->SortKey
>= SortKey
)
252 /* We found it, so just remove it */
253 RemoveEntryList(&ReturnEntry
->DeviceListEntry
);
258 /* Check if we found something */
261 /* Not found, return the first entry */
262 ListEntry
= RemoveHeadList(&DeviceQueue
->DeviceListHead
);
263 ReturnEntry
= CONTAINING_RECORD(ListEntry
,
268 /* Set it as non-inserted */
269 ReturnEntry
->Inserted
= FALSE
;
272 /* Release the lock */
273 KiReleaseDeviceQueueLock(&DeviceLock
);
275 /* Return the entry */
284 KeRemoveEntryDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue
,
285 IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry
)
288 KLOCK_QUEUE_HANDLE DeviceLock
;
289 ASSERT_DEVICE_QUEUE(DeviceQueue
);
292 KiAcquireDeviceQueueLock(DeviceQueue
, &DeviceLock
);
293 ASSERT(DeviceQueue
->Busy
);
295 /* Check the insertion state */
296 OldState
= DeviceQueueEntry
->Inserted
;
300 DeviceQueueEntry
->Inserted
= FALSE
;
301 RemoveEntryList(&DeviceQueueEntry
->DeviceListEntry
);
304 /* Unlock and return old state */
305 KiReleaseDeviceQueueLock(&DeviceLock
);