Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

devquobj.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 devquobj.c 00008 00009 Abstract: 00010 00011 This module implements the kernel device queue object. Functions are 00012 provided to initialize a device queue object and to insert and remove 00013 device queue entries in a device queue object. 00014 00015 Author: 00016 00017 David N. Cutler (davec) 1-Apr-1989 00018 00019 Environment: 00020 00021 Kernel mode only. 00022 00023 Revision History: 00024 00025 --*/ 00026 00027 #include "ki.h" 00028 00029 // 00030 // The following assert macro is used to check that an input device queue 00031 // is really a kdevice_queue and not something else, like deallocated pool. 00032 // 00033 00034 #define ASSERT_DEVICE_QUEUE(E) { \ 00035 ASSERT((E)->Type == DeviceQueueObject); \ 00036 } 00037 00038 00039 VOID 00040 KeInitializeDeviceQueue ( 00041 IN PKDEVICE_QUEUE DeviceQueue 00042 ) 00043 00044 /*++ 00045 00046 Routine Description: 00047 00048 This function initializes a kernel device queue object. 00049 00050 Arguments: 00051 00052 DeviceQueue - Supplies a pointer to a control object of type device 00053 queue. 00054 00055 SpinLock - Supplies a pointer to an executive spin lock. 00056 00057 Return Value: 00058 00059 None. 00060 00061 --*/ 00062 00063 { 00064 00065 // 00066 // Initialize standard control object header. 00067 // 00068 00069 DeviceQueue->Type = DeviceQueueObject; 00070 DeviceQueue->Size = sizeof(KDEVICE_QUEUE); 00071 00072 // 00073 // Initialize the device queue list head, spin lock, and busy indicator. 00074 // 00075 00076 InitializeListHead(&DeviceQueue->DeviceListHead); 00077 KeInitializeSpinLock(&DeviceQueue->Lock); 00078 DeviceQueue->Busy = FALSE; 00079 return; 00080 } 00081 00082 BOOLEAN 00083 KeInsertDeviceQueue ( 00084 IN PKDEVICE_QUEUE DeviceQueue, 00085 IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry 00086 ) 00087 00088 /*++ 00089 00090 Routine Description: 00091 00092 This function inserts a device queue entry at the tail of the specified 00093 device queue. If the device is not busy, then it is set busy and the entry 00094 is not placed in the device queue. Otherwise the specified entry is placed 00095 at the end of the device queue. 00096 00097 N.B. This function can only be called from DISPATCH_LEVEL. 00098 00099 Arguments: 00100 00101 DeviceQueue - Supplies a pointer to a control object of type device queue. 00102 00103 DeviceQueueEntry - Supplies a pointer to a device queue entry. 00104 00105 Return Value: 00106 00107 If the device is not busy, then a value of FALSE is returned. Otherwise a 00108 value of TRUE is returned. 00109 00110 --*/ 00111 00112 { 00113 00114 BOOLEAN Inserted; 00115 00116 ASSERT_DEVICE_QUEUE(DeviceQueue); 00117 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 00118 00119 // 00120 // Lock specified device queue. 00121 // 00122 00123 KiAcquireSpinLock(&DeviceQueue->Lock); 00124 00125 // 00126 // Insert the specified device queue entry at the end of the device queue 00127 // if the device queue is busy. Otherwise set the device queue busy and 00128 // don't insert the device queue entry. 00129 // 00130 00131 if (DeviceQueue->Busy == TRUE) { 00132 Inserted = TRUE; 00133 InsertTailList(&DeviceQueue->DeviceListHead, 00134 &DeviceQueueEntry->DeviceListEntry); 00135 } else { 00136 DeviceQueue->Busy = TRUE; 00137 Inserted = FALSE; 00138 } 00139 DeviceQueueEntry->Inserted = Inserted; 00140 KiReleaseSpinLock(&DeviceQueue->Lock); 00141 return Inserted; 00142 } 00143 00144 BOOLEAN 00145 KeInsertByKeyDeviceQueue ( 00146 IN PKDEVICE_QUEUE DeviceQueue, 00147 IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry, 00148 IN ULONG SortKey 00149 ) 00150 00151 /*++ 00152 00153 Routine Description: 00154 00155 This function inserts a device queue entry into the specified device 00156 queue according to a sort key. If the device is not busy, then it is 00157 set busy and the entry is not placed in the device queue. Otherwise 00158 the specified entry is placed in the device queue at a position such 00159 that the specified sort key is greater than or equal to its predecessor 00160 and less than its successor. 00161 00162 N.B. This function can only be called from DISPATCH_LEVEL. 00163 00164 Arguments: 00165 00166 DeviceQueue - Supplies a pointer to a control object of type device queue. 00167 00168 DeviceQueueEntry - Supplies a pointer to a device queue entry. 00169 00170 SortKey - Supplies the sort key by which the position to insert the device 00171 queue entry is to be determined. 00172 00173 Return Value: 00174 00175 If the device is not busy, then a value of FALSE is returned. Otherwise a 00176 value of TRUE is returned. 00177 00178 --*/ 00179 00180 { 00181 00182 BOOLEAN Inserted; 00183 PLIST_ENTRY NextEntry; 00184 PKDEVICE_QUEUE_ENTRY QueueEntry; 00185 00186 ASSERT_DEVICE_QUEUE(DeviceQueue); 00187 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 00188 00189 // 00190 // Lock specified device queue. 00191 // 00192 00193 KiAcquireSpinLock(&DeviceQueue->Lock); 00194 00195 // 00196 // Insert the specified device queue entry in the device queue at the 00197 // position specified by the sort key if the device queue is busy. 00198 // Otherwise set the device queue busy an don't insert the device queue 00199 // entry. 00200 // 00201 00202 DeviceQueueEntry->SortKey = SortKey; 00203 if (DeviceQueue->Busy == TRUE) { 00204 Inserted = TRUE; 00205 NextEntry = DeviceQueue->DeviceListHead.Flink; 00206 while (NextEntry != &DeviceQueue->DeviceListHead) { 00207 QueueEntry = CONTAINING_RECORD(NextEntry, KDEVICE_QUEUE_ENTRY, 00208 DeviceListEntry); 00209 if (SortKey < QueueEntry->SortKey) { 00210 break; 00211 } 00212 NextEntry = NextEntry->Flink; 00213 } 00214 NextEntry = NextEntry->Blink; 00215 InsertHeadList(NextEntry, &DeviceQueueEntry->DeviceListEntry); 00216 } else { 00217 DeviceQueue->Busy = TRUE; 00218 Inserted = FALSE; 00219 } 00220 DeviceQueueEntry->Inserted = Inserted; 00221 KiReleaseSpinLock(&DeviceQueue->Lock); 00222 return Inserted; 00223 } 00224 00225 PKDEVICE_QUEUE_ENTRY 00226 KeRemoveDeviceQueue ( 00227 IN PKDEVICE_QUEUE DeviceQueue 00228 ) 00229 00230 /*++ 00231 00232 Routine Description: 00233 00234 This function removes an entry from the head of the specified device 00235 queue. If the device queue is empty, then the device is set Not-Busy 00236 and a NULL pointer is returned. Otherwise the next entry is removed 00237 from the head of the device queue and the address of device queue entry 00238 is returned. 00239 00240 N.B. This function can only be called from DISPATCH_LEVEL. 00241 00242 Arguments: 00243 00244 DeviceQueue - Supplies a pointer to a control object of type device queue. 00245 00246 Return Value: 00247 00248 A NULL pointer is returned if the device queue is empty. Otherwise a 00249 pointer to a device queue entry is returned. 00250 00251 --*/ 00252 00253 { 00254 00255 PKDEVICE_QUEUE_ENTRY DeviceQueueEntry; 00256 PLIST_ENTRY NextEntry; 00257 00258 ASSERT_DEVICE_QUEUE(DeviceQueue); 00259 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 00260 00261 // 00262 // Lock specified device queue. 00263 // 00264 00265 KiAcquireSpinLock(&DeviceQueue->Lock); 00266 00267 ASSERT(DeviceQueue->Busy == TRUE); 00268 00269 // 00270 // If the device queue is not empty, then remove the first entry from 00271 // the queue. Otherwise set the device queue not busy. 00272 // 00273 00274 if (IsListEmpty(&DeviceQueue->DeviceListHead) == TRUE) { 00275 DeviceQueue->Busy = FALSE; 00276 DeviceQueueEntry = (PKDEVICE_QUEUE_ENTRY)NULL; 00277 } else { 00278 NextEntry = RemoveHeadList(&DeviceQueue->DeviceListHead); 00279 DeviceQueueEntry = CONTAINING_RECORD(NextEntry, KDEVICE_QUEUE_ENTRY, 00280 DeviceListEntry); 00281 DeviceQueueEntry->Inserted = FALSE; 00282 } 00283 00284 // 00285 // Release device queue spin lock and return address of device queue 00286 // entry. 00287 // 00288 00289 KiReleaseSpinLock(&DeviceQueue->Lock); 00290 return DeviceQueueEntry; 00291 } 00292 00293 PKDEVICE_QUEUE_ENTRY 00294 KeRemoveByKeyDeviceQueue ( 00295 IN PKDEVICE_QUEUE DeviceQueue, 00296 IN ULONG SortKey 00297 ) 00298 00299 /*++ 00300 00301 Routine Description: 00302 00303 This function removes an entry from the specified device 00304 queue. If the device queue is empty, then the device is set Not-Busy 00305 and a NULL pointer is returned. Otherwise the an entry is removed 00306 from the device queue and the address of device queue entry 00307 is returned. The queue is search for the first entry which has a value 00308 greater than or equal to the SortKey. If no such entry is found then the 00309 first entry of the queue is returned. 00310 00311 N.B. This function can only be called from DISPATCH_LEVEL. 00312 00313 Arguments: 00314 00315 DeviceQueue - Supplies a pointer to a control object of type device queue. 00316 00317 SortKey - Supplies the sort key by which the position to remove the device 00318 queue entry is to be determined. 00319 00320 Return Value: 00321 00322 A NULL pointer is returned if the device queue is empty. Otherwise a 00323 pointer to a device queue entry is returned. 00324 00325 --*/ 00326 00327 { 00328 00329 PKDEVICE_QUEUE_ENTRY DeviceQueueEntry; 00330 PLIST_ENTRY NextEntry; 00331 00332 ASSERT_DEVICE_QUEUE(DeviceQueue); 00333 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 00334 00335 // 00336 // Lock specified device queue. 00337 // 00338 00339 KiAcquireSpinLock(&DeviceQueue->Lock); 00340 00341 ASSERT(DeviceQueue->Busy == TRUE); 00342 00343 // 00344 // If the device queue is not empty, then remove the first entry from 00345 // the queue. Otherwise set the device queue not busy. 00346 // 00347 00348 if (IsListEmpty(&DeviceQueue->DeviceListHead) == TRUE) { 00349 DeviceQueue->Busy = FALSE; 00350 DeviceQueueEntry = (PKDEVICE_QUEUE_ENTRY)NULL; 00351 } else { 00352 NextEntry = DeviceQueue->DeviceListHead.Flink; 00353 while (NextEntry != &DeviceQueue->DeviceListHead) { 00354 DeviceQueueEntry = CONTAINING_RECORD(NextEntry, KDEVICE_QUEUE_ENTRY, 00355 DeviceListEntry); 00356 if (SortKey <= DeviceQueueEntry->SortKey) { 00357 break; 00358 } 00359 NextEntry = NextEntry->Flink; 00360 } 00361 00362 if (NextEntry != &DeviceQueue->DeviceListHead) { 00363 RemoveEntryList(&DeviceQueueEntry->DeviceListEntry); 00364 00365 } else { 00366 NextEntry = RemoveHeadList(&DeviceQueue->DeviceListHead); 00367 DeviceQueueEntry = CONTAINING_RECORD(NextEntry, KDEVICE_QUEUE_ENTRY, 00368 DeviceListEntry); 00369 } 00370 00371 DeviceQueueEntry->Inserted = FALSE; 00372 } 00373 00374 // 00375 // Release device queue spin lock and return address of device queue 00376 // entry. 00377 // 00378 00379 KiReleaseSpinLock(&DeviceQueue->Lock); 00380 return DeviceQueueEntry; 00381 } 00382 00383 BOOLEAN 00384 KeRemoveEntryDeviceQueue ( 00385 IN PKDEVICE_QUEUE DeviceQueue, 00386 IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry 00387 ) 00388 00389 /*++ 00390 00391 Routine Description: 00392 00393 This function removes a specified entry from the the specified device 00394 queue. If the device queue entry is not in the device queue, then no 00395 operation is performed. Otherwise the specified device queue entry is 00396 removed from the device queue and its inserted status is set to FALSE. 00397 00398 Arguments: 00399 00400 DeviceQueue - Supplies a pointer to a control object of type device queue. 00401 00402 DeviceQueueEntry - Supplies a pointer to a device queue entry which is to 00403 be removed from its device queue. 00404 00405 Return Value: 00406 00407 A value of TRUE is returned if the device queue entry is removed from its 00408 device queue. Otherwise a value of FALSE is returned. 00409 00410 --*/ 00411 00412 { 00413 00414 KIRQL OldIrql; 00415 BOOLEAN Removed; 00416 00417 ASSERT_DEVICE_QUEUE(DeviceQueue); 00418 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 00419 00420 // 00421 // Raise IRQL to dispatcher level and lock specified device queue. 00422 // 00423 00424 ExAcquireSpinLock(&DeviceQueue->Lock, &OldIrql); 00425 00426 // 00427 // If the device queue entry is not in a device queue, then no operation 00428 // is performed. Otherwise remove the specified device queue entry from its 00429 // device queue. 00430 // 00431 00432 Removed = DeviceQueueEntry->Inserted; 00433 if (Removed == TRUE) { 00434 DeviceQueueEntry->Inserted = FALSE; 00435 RemoveEntryList(&DeviceQueueEntry->DeviceListEntry); 00436 } 00437 00438 // 00439 // Unlock specified device queue, lower IRQL to its previous level, and 00440 // return whether the device queue entry was removed from its queue. 00441 // 00442 00443 ExReleaseSpinLock(&DeviceQueue->Lock, OldIrql); 00444 return Removed; 00445 }

Generated on Sat May 15 19:39:44 2004 for test by doxygen 1.3.7