Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374/* * PROJECT: ReactOS Kernel * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/ke/devqueue.c * PURPOSE: Implement device queues * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>#define NDEBUG#include <debug.h>
/* FUNCTIONS *****************************************************************/
/* * @implemented */VOIDNTAPIKeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue){ /* Initialize the Header */ DeviceQueue->Type = DeviceQueueObject; DeviceQueue->Size = sizeof(KDEVICE_QUEUE);
/* Initialize the Listhead and Spinlock */ InitializeListHead(&DeviceQueue->DeviceListHead); KeInitializeSpinLock(&DeviceQueue->Lock);
/* Set it as busy */ DeviceQueue->Busy=FALSE;}
/* * @implemented */BOOLEANNTAPIKeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry){ KLOCK_QUEUE_HANDLE DeviceLock; BOOLEAN Inserted; ASSERT_DEVICE_QUEUE(DeviceQueue);
DPRINT("KeInsertDeviceQueue() DevQueue %p, Entry %p\n", DeviceQueue, DeviceQueueEntry);
/* Lock the queue */ KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock);
/* Check if it's not busy */ if (!DeviceQueue->Busy) { /* Set it as busy */ Inserted = FALSE; DeviceQueue->Busy = TRUE; } else { /* Insert it into the list */ Inserted = TRUE; InsertTailList(&DeviceQueue->DeviceListHead, &DeviceQueueEntry->DeviceListEntry); }
/* Set the Insert state into the entry */ DeviceQueueEntry->Inserted = Inserted;
/* Release the lock */ KiReleaseDeviceQueueLock(&DeviceLock);
/* Return the state */ return Inserted;}
/* * @implemented */BOOLEANNTAPIKeInsertByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry, IN ULONG SortKey){ KLOCK_QUEUE_HANDLE DeviceLock; BOOLEAN Inserted; PLIST_ENTRY NextEntry; PKDEVICE_QUEUE_ENTRY LastEntry; ASSERT_DEVICE_QUEUE(DeviceQueue);
DPRINT("KeInsertByKeyDeviceQueue() DevQueue %p, Entry %p, SortKey 0x%x\n", DeviceQueue, DeviceQueueEntry, SortKey);
/* Lock the queue */ KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock);
/* Set the Sort Key */ DeviceQueueEntry->SortKey = SortKey;
/* Check if it's not busy */ if (!DeviceQueue->Busy) { /* Set it as busy */ Inserted = FALSE; DeviceQueue->Busy = TRUE; } else { /* Make sure the list isn't empty */ NextEntry = &DeviceQueue->DeviceListHead; if (!IsListEmpty(NextEntry)) { /* Get the last entry */ LastEntry = CONTAINING_RECORD(NextEntry->Blink, KDEVICE_QUEUE_ENTRY, DeviceListEntry);
/* Check if our sort key is lower */ if (SortKey < LastEntry->SortKey) { /* Loop each sort key */ do { /* Get the next entry */ NextEntry = NextEntry->Flink; LastEntry = CONTAINING_RECORD(NextEntry, KDEVICE_QUEUE_ENTRY, DeviceListEntry);
/* Keep looping until we find a place to insert */ } while (SortKey >= LastEntry->SortKey); } }
/* Now insert us */ InsertTailList(NextEntry, &DeviceQueueEntry->DeviceListEntry); Inserted = TRUE; }
/* Release the lock */ KiReleaseDeviceQueueLock(&DeviceLock);
/* Return the state */ return Inserted;}
/* * @implemented */PKDEVICE_QUEUE_ENTRYNTAPIKeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue){ PLIST_ENTRY ListEntry; PKDEVICE_QUEUE_ENTRY ReturnEntry; KLOCK_QUEUE_HANDLE DeviceLock; ASSERT_DEVICE_QUEUE(DeviceQueue);
DPRINT("KeRemoveDeviceQueue() DevQueue %p\n", DeviceQueue);
/* Lock the queue */ KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock); ASSERT(DeviceQueue->Busy);
/* Check if this is an empty queue */ if (IsListEmpty(&DeviceQueue->DeviceListHead)) { /* Set it to idle and return nothing*/ DeviceQueue->Busy = FALSE; ReturnEntry = NULL; } else { /* Remove the Entry from the List */ ListEntry = RemoveHeadList(&DeviceQueue->DeviceListHead); ReturnEntry = CONTAINING_RECORD(ListEntry, KDEVICE_QUEUE_ENTRY, DeviceListEntry);
/* Set it as non-inserted */ ReturnEntry->Inserted = FALSE; }
/* Release the lock */ KiReleaseDeviceQueueLock(&DeviceLock);
/* Return the entry */ return ReturnEntry;}
/* * @implemented */PKDEVICE_QUEUE_ENTRYNTAPIKeRemoveByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, IN ULONG SortKey){ PLIST_ENTRY NextEntry; PKDEVICE_QUEUE_ENTRY ReturnEntry; KLOCK_QUEUE_HANDLE DeviceLock; ASSERT_DEVICE_QUEUE(DeviceQueue);
DPRINT("KeRemoveByKeyDeviceQueue() DevQueue %p, SortKey 0x%x\n", DeviceQueue, SortKey);
/* Lock the queue */ KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock); ASSERT(DeviceQueue->Busy);
/* Check if this is an empty queue */ if (IsListEmpty(&DeviceQueue->DeviceListHead)) { /* Set it to idle and return nothing*/ DeviceQueue->Busy = FALSE; ReturnEntry = NULL; } else { /* If SortKey is greater than the last key, then return the first entry right away */ NextEntry = &DeviceQueue->DeviceListHead; ReturnEntry = CONTAINING_RECORD(NextEntry->Blink, KDEVICE_QUEUE_ENTRY, DeviceListEntry);
/* Check if we can just get the first entry */ if (ReturnEntry->SortKey <= SortKey) { /* Get the first entry */ ReturnEntry = CONTAINING_RECORD(NextEntry->Flink, KDEVICE_QUEUE_ENTRY, DeviceListEntry); } else { /* Loop the list */ NextEntry = DeviceQueue->DeviceListHead.Flink; while (TRUE) { /* Make sure we don't go beyond the end of the queue */ ASSERT(NextEntry != &DeviceQueue->DeviceListHead);
/* Get the next entry and check if the key is low enough */ ReturnEntry = CONTAINING_RECORD(NextEntry, KDEVICE_QUEUE_ENTRY, DeviceListEntry); if (SortKey <= ReturnEntry->SortKey) break;
/* Try the next one */ NextEntry = NextEntry->Flink; } }
/* We have an entry, remove it now */ RemoveEntryList(&ReturnEntry->DeviceListEntry);
/* Set it as non-inserted */ ReturnEntry->Inserted = FALSE; }
/* Release the lock */ KiReleaseDeviceQueueLock(&DeviceLock);
/* Return the entry */ return ReturnEntry;}
/* * @implemented */PKDEVICE_QUEUE_ENTRYNTAPIKeRemoveByKeyDeviceQueueIfBusy(IN PKDEVICE_QUEUE DeviceQueue, IN ULONG SortKey){ PLIST_ENTRY NextEntry; PKDEVICE_QUEUE_ENTRY ReturnEntry; KLOCK_QUEUE_HANDLE DeviceLock; ASSERT_DEVICE_QUEUE(DeviceQueue);
DPRINT("KeRemoveByKeyDeviceQueueIfBusy() DevQueue %p, SortKey 0x%x\n", DeviceQueue, SortKey);
/* Lock the queue */ KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock);
/* Check if this is an empty or idle queue */ if (!(DeviceQueue->Busy) || (IsListEmpty(&DeviceQueue->DeviceListHead))) { /* Set it to idle and return nothing*/ DeviceQueue->Busy = FALSE; ReturnEntry = NULL; } else { /* If SortKey is greater than the last key, then return the first entry right away */ NextEntry = &DeviceQueue->DeviceListHead; ReturnEntry = CONTAINING_RECORD(NextEntry->Blink, KDEVICE_QUEUE_ENTRY, DeviceListEntry);
/* Check if we can just get the first entry */ if (ReturnEntry->SortKey <= SortKey) { /* Get the first entry */ ReturnEntry = CONTAINING_RECORD(NextEntry->Flink, KDEVICE_QUEUE_ENTRY, DeviceListEntry); } else { /* Loop the list */ NextEntry = DeviceQueue->DeviceListHead.Flink; while (TRUE) { /* Make sure we don't go beyond the end of the queue */ ASSERT(NextEntry != &DeviceQueue->DeviceListHead);
/* Get the next entry and check if the key is low enough */ ReturnEntry = CONTAINING_RECORD(NextEntry, KDEVICE_QUEUE_ENTRY, DeviceListEntry); if (SortKey <= ReturnEntry->SortKey) break;
/* Try the next one */ NextEntry = NextEntry->Flink; } }
/* We have an entry, remove it now */ RemoveEntryList(&ReturnEntry->DeviceListEntry);
/* Set it as non-inserted */ ReturnEntry->Inserted = FALSE; }
/* Release the lock */ KiReleaseDeviceQueueLock(&DeviceLock);
/* Return the entry */ return ReturnEntry;}
/* * @implemented */BOOLEANNTAPIKeRemoveEntryDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry){ BOOLEAN OldState; KLOCK_QUEUE_HANDLE DeviceLock; ASSERT_DEVICE_QUEUE(DeviceQueue);
DPRINT("KeRemoveEntryDeviceQueue() DevQueue %p, Entry %p\n", DeviceQueue, DeviceQueueEntry);
/* Lock the queue */ KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock); ASSERT(DeviceQueue->Busy);
/* Check the insertion state */ OldState = DeviceQueueEntry->Inserted; if (OldState) { /* Remove it */ DeviceQueueEntry->Inserted = FALSE; RemoveEntryList(&DeviceQueueEntry->DeviceListEntry); }
/* Unlock and return old state */ KiReleaseDeviceQueueLock(&DeviceLock); return OldState;}