test: devquobj.c Source File

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 }