mirror of
https://github.com/reactos/reactos.git
synced 2025-07-04 06:21:23 +00:00
- Implement KiAcquireDeviceQueueLock/KiReleaseDeviceQueueLock for locking KDEVICE_QUEUEs, since they can be used from Threaded DPCs which don't execute at DISPATCH_LEVEL, so the lock needs to be acquired differently.
- Add ASSERT_DEVICE_QUEUE and ASSERTify + reformat kqueue.c. - Implement KeRemoveByKeyDeviceQueueIfBusy. - Cleanup exception.c - Remove dangerous/broken KeGetCurrentIrql() define. svn path=/trunk/; revision=24087
This commit is contained in:
parent
c0cda24302
commit
d99f96a295
5 changed files with 200 additions and 130 deletions
|
@ -1093,6 +1093,9 @@ typedef struct _KLOCK_QUEUE_HANDLE {
|
||||||
((Object)->Type == DpcObject) || \
|
((Object)->Type == DpcObject) || \
|
||||||
((Object)->Type == ThreadedDpcObject))
|
((Object)->Type == ThreadedDpcObject))
|
||||||
|
|
||||||
|
#define ASSERT_DEVICE_QUEUE(Object) \
|
||||||
|
ASSERT((Object)->Type == DeviceQueueObject)
|
||||||
|
|
||||||
typedef struct _KDPC
|
typedef struct _KDPC
|
||||||
{
|
{
|
||||||
UCHAR Type;
|
UCHAR Type;
|
||||||
|
|
|
@ -124,7 +124,6 @@ KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
|
||||||
#define LOCK "lock ; "
|
#define LOCK "lock ; "
|
||||||
#else
|
#else
|
||||||
#define LOCK ""
|
#define LOCK ""
|
||||||
#define KeGetCurrentIrql() (((PKPCR)KPCR_BASE)->Irql)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
|
|
|
@ -696,6 +696,44 @@ KiReleaseProcessLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE Handle)
|
||||||
KeReleaseInStackQueuedSpinLockFromDpcLevel(Handle);
|
KeReleaseInStackQueuedSpinLockFromDpcLevel(Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
KiAcquireDeviceQueueLock(IN PKDEVICE_QUEUE DeviceQueue,
|
||||||
|
IN PKLOCK_QUEUE_HANDLE DeviceLock)
|
||||||
|
{
|
||||||
|
/* Check if we were called from a threaded DPC */
|
||||||
|
if (KeGetCurrentPrcb()->DpcThreadActive)
|
||||||
|
{
|
||||||
|
/* Lock the Queue, we're not at DPC level */
|
||||||
|
KeAcquireInStackQueuedSpinLock(&DeviceQueue->Lock, DeviceLock);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We must be at DPC level, acquire the lock safely */
|
||||||
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
|
KeAcquireInStackQueuedSpinLockAtDpcLevel(&DeviceQueue->Lock,
|
||||||
|
DeviceLock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
KiReleaseDeviceQueueLock(IN PKLOCK_QUEUE_HANDLE DeviceLock)
|
||||||
|
{
|
||||||
|
/* Check if we were called from a threaded DPC */
|
||||||
|
if (KeGetCurrentPrcb()->DpcThreadActive)
|
||||||
|
{
|
||||||
|
/* Unlock the Queue, we're not at DPC level */
|
||||||
|
KeReleaseInStackQueuedSpinLock(DeviceLock);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We must be at DPC level, release the lock safely */
|
||||||
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
|
KeReleaseInStackQueuedSpinLockFromDpcLevel(DeviceLock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// This routine queues a thread that is ready on the PRCB's ready lists.
|
// This routine queues a thread that is ready on the PRCB's ready lists.
|
||||||
// If this thread cannot currently run on this CPU, then the thread is
|
// If this thread cannot currently run on this CPU, then the thread is
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/ke/exception.c
|
* FILE: ntoskrnl/ke/exception.c
|
||||||
* PURPOSE: Platform independent exception handling
|
* PURPOSE: Platform independent exception handling
|
||||||
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include <ntoskrnl.h>
|
#include <ntoskrnl.h>
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -46,11 +46,7 @@ KiContinue(IN PCONTEXT Context,
|
||||||
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
|
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
|
||||||
|
|
||||||
/* Raise to APC_LEVEL, only if needed */
|
/* Raise to APC_LEVEL, only if needed */
|
||||||
if (KeGetCurrentIrql() < APC_LEVEL)
|
if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
|
||||||
{
|
|
||||||
/* Raise to APC_LEVEL */
|
|
||||||
KeRaiseIrql(APC_LEVEL, &OldIrql);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set up SEH to validate the context */
|
/* Set up SEH to validate the context */
|
||||||
_SEH_TRY
|
_SEH_TRY
|
||||||
|
@ -75,6 +71,7 @@ KiContinue(IN PCONTEXT Context,
|
||||||
}
|
}
|
||||||
_SEH_HANDLE
|
_SEH_HANDLE
|
||||||
{
|
{
|
||||||
|
/* Save the exception code */
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
}
|
||||||
_SEH_END;
|
_SEH_END;
|
||||||
|
@ -88,18 +85,17 @@ KiContinue(IN PCONTEXT Context,
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
KiRaiseException(PEXCEPTION_RECORD ExceptionRecord,
|
KiRaiseException(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||||
PCONTEXT Context,
|
IN PCONTEXT Context,
|
||||||
PKEXCEPTION_FRAME ExceptionFrame,
|
IN PKEXCEPTION_FRAME ExceptionFrame,
|
||||||
PKTRAP_FRAME TrapFrame,
|
IN PKTRAP_FRAME TrapFrame,
|
||||||
BOOLEAN SearchFrames)
|
IN BOOLEAN SearchFrames)
|
||||||
{
|
{
|
||||||
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
|
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
|
||||||
CONTEXT LocalContext;
|
CONTEXT LocalContext;
|
||||||
EXCEPTION_RECORD LocalExceptionRecord;
|
EXCEPTION_RECORD LocalExceptionRecord;
|
||||||
ULONG ParameterCount, Size;
|
ULONG ParameterCount, Size;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
DPRINT1("KiRaiseException\n");
|
|
||||||
|
|
||||||
/* Set up SEH */
|
/* Set up SEH */
|
||||||
_SEH_TRY
|
_SEH_TRY
|
||||||
|
@ -143,10 +139,12 @@ KiRaiseException(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
}
|
}
|
||||||
_SEH_HANDLE
|
_SEH_HANDLE
|
||||||
{
|
{
|
||||||
|
/* Get the exception code */
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
}
|
||||||
_SEH_END;
|
_SEH_END;
|
||||||
|
|
||||||
|
/* Make sure we didn't crash in SEH */
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Convert the context record */
|
/* Convert the context record */
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* PROJECT: ReactOS Kernel
|
||||||
* PURPOSE: ReactOS kernel
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/ke/kqueue.c
|
* FILE: ntoskrnl/ke/kqueue.c
|
||||||
* PURPOSE: Implement device queues
|
* PURPOSE: Implement device queues
|
||||||
*
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Several optimizations and implement
|
|
||||||
* usage of Inserted flag + reformat and
|
|
||||||
* add debug output.
|
|
||||||
* David Welch (welch@mcmail.com)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ****************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include <ntoskrnl.h>
|
#include <ntoskrnl.h>
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
@ -20,16 +16,11 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*
|
|
||||||
* FUNCTION: Intializes a device queue
|
|
||||||
* ARGUMENTS:
|
|
||||||
* DeviceQueue = Device queue to initialize
|
|
||||||
*/
|
*/
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
NTAPI
|
||||||
KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
|
KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Initialize the Header */
|
/* Initialize the Header */
|
||||||
DeviceQueue->Type = DeviceQueueObject;
|
DeviceQueue->Type = DeviceQueueObject;
|
||||||
DeviceQueue->Size = sizeof(KDEVICE_QUEUE);
|
DeviceQueue->Size = sizeof(KDEVICE_QUEUE);
|
||||||
|
@ -44,48 +35,41 @@ KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*
|
|
||||||
* FUNCTION: Inserts an entry in a device queue
|
|
||||||
* ARGUMENTS:
|
|
||||||
* DeviceQueue = Queue to insert the entry in
|
|
||||||
* DeviceQueueEntry = Entry to insert
|
|
||||||
* RETURNS: False is the device queue wasn't busy
|
|
||||||
* True otherwise
|
|
||||||
*/
|
*/
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
STDCALL
|
NTAPI
|
||||||
KeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
|
KeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
|
||||||
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
|
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
|
||||||
{
|
{
|
||||||
|
KLOCK_QUEUE_HANDLE DeviceLock;
|
||||||
BOOLEAN Inserted;
|
BOOLEAN Inserted;
|
||||||
|
ASSERT_DEVICE_QUEUE(DeviceQueue);
|
||||||
|
|
||||||
DPRINT("KeInsertDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
|
/* Lock the queue */
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock);
|
||||||
|
|
||||||
/* Lock the Queue */
|
|
||||||
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
|
|
||||||
|
|
||||||
if (!DeviceQueue->Busy) {
|
|
||||||
|
|
||||||
|
/* Check if it's not busy */
|
||||||
|
if (!DeviceQueue->Busy)
|
||||||
|
{
|
||||||
/* Set it as busy */
|
/* Set it as busy */
|
||||||
Inserted = FALSE;
|
Inserted = FALSE;
|
||||||
DeviceQueue->Busy = TRUE;
|
DeviceQueue->Busy = TRUE;
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* Insert it into the list */
|
/* Insert it into the list */
|
||||||
Inserted = TRUE;
|
Inserted = TRUE;
|
||||||
InsertTailList(&DeviceQueue->DeviceListHead,
|
InsertTailList(&DeviceQueue->DeviceListHead,
|
||||||
&DeviceQueueEntry->DeviceListEntry);
|
&DeviceQueueEntry->DeviceListEntry);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sert the Insert state into the entry */
|
/* Sert the Insert state into the entry */
|
||||||
DeviceQueueEntry->Inserted = Inserted;
|
DeviceQueueEntry->Inserted = Inserted;
|
||||||
|
|
||||||
/* Release lock and return */
|
/* Release the lock */
|
||||||
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
|
KiReleaseDeviceQueueLock(&DeviceLock);
|
||||||
|
|
||||||
|
/* Return the state */
|
||||||
return Inserted;
|
return Inserted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,29 +77,30 @@ KeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
STDCALL
|
NTAPI
|
||||||
KeInsertByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
|
KeInsertByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
|
||||||
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry,
|
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry,
|
||||||
IN ULONG SortKey)
|
IN ULONG SortKey)
|
||||||
{
|
{
|
||||||
|
KLOCK_QUEUE_HANDLE DeviceLock;
|
||||||
BOOLEAN Inserted;
|
BOOLEAN Inserted;
|
||||||
|
ASSERT_DEVICE_QUEUE(DeviceQueue);
|
||||||
|
|
||||||
DPRINT("KeInsertByKeyDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
|
/* Lock the queue */
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock);
|
||||||
|
|
||||||
/* Acquire the Lock */
|
|
||||||
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
|
|
||||||
|
|
||||||
/* Set the Sort Key */
|
/* Set the Sort Key */
|
||||||
DeviceQueueEntry->SortKey = SortKey;
|
DeviceQueueEntry->SortKey = SortKey;
|
||||||
|
|
||||||
if (!DeviceQueue->Busy) {
|
/* Check if it's not busy */
|
||||||
|
if (!DeviceQueue->Busy)
|
||||||
DeviceQueue->Busy=TRUE;
|
{
|
||||||
|
/* Set it as busy */
|
||||||
Inserted = FALSE;
|
Inserted = FALSE;
|
||||||
|
DeviceQueue->Busy = TRUE;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Insert new entry after the last entry with SortKey less or equal to passed-in SortKey */
|
/* Insert new entry after the last entry with SortKey less or equal to passed-in SortKey */
|
||||||
InsertAscendingListFIFO(&DeviceQueue->DeviceListHead,
|
InsertAscendingListFIFO(&DeviceQueue->DeviceListHead,
|
||||||
DeviceQueueEntry,
|
DeviceQueueEntry,
|
||||||
|
@ -125,43 +110,38 @@ KeInsertByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
|
||||||
Inserted = TRUE;
|
Inserted = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the Inserted State */
|
/* Release the lock */
|
||||||
DeviceQueueEntry->Inserted = Inserted;
|
KiReleaseDeviceQueueLock(&DeviceLock);
|
||||||
|
|
||||||
/* Release Lock and Return */
|
/* Return the state */
|
||||||
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
|
|
||||||
return Inserted;
|
return Inserted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*
|
|
||||||
* FUNCTION: Removes an entry from a device queue
|
|
||||||
* ARGUMENTS:
|
|
||||||
* DeviceQueue = Queue to remove the entry
|
|
||||||
* RETURNS: The removed entry
|
|
||||||
*/
|
*/
|
||||||
PKDEVICE_QUEUE_ENTRY
|
PKDEVICE_QUEUE_ENTRY
|
||||||
STDCALL
|
NTAPI
|
||||||
KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
|
KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY ListEntry;
|
PLIST_ENTRY ListEntry;
|
||||||
PKDEVICE_QUEUE_ENTRY ReturnEntry;
|
PKDEVICE_QUEUE_ENTRY ReturnEntry;
|
||||||
|
KLOCK_QUEUE_HANDLE DeviceLock;
|
||||||
|
ASSERT_DEVICE_QUEUE(DeviceQueue);
|
||||||
|
|
||||||
DPRINT("KeRemoveDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
|
/* Lock the queue */
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock);
|
||||||
|
|
||||||
/* Acquire the Lock */
|
|
||||||
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
|
|
||||||
ASSERT(DeviceQueue->Busy);
|
ASSERT(DeviceQueue->Busy);
|
||||||
|
|
||||||
/* An attempt to remove an entry from an empty (and busy) queue sets the queue idle */
|
/* Check if this is an empty queue */
|
||||||
if (IsListEmpty(&DeviceQueue->DeviceListHead)) {
|
if (IsListEmpty(&DeviceQueue->DeviceListHead))
|
||||||
|
{
|
||||||
|
/* Set it to idle and return nothing*/
|
||||||
DeviceQueue->Busy = FALSE;
|
DeviceQueue->Busy = FALSE;
|
||||||
ReturnEntry = NULL;
|
ReturnEntry = NULL;
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* Remove the Entry from the List */
|
/* Remove the Entry from the List */
|
||||||
ListEntry = RemoveHeadList(&DeviceQueue->DeviceListHead);
|
ListEntry = RemoveHeadList(&DeviceQueue->DeviceListHead);
|
||||||
ReturnEntry = CONTAINING_RECORD(ListEntry,
|
ReturnEntry = CONTAINING_RECORD(ListEntry,
|
||||||
|
@ -172,8 +152,10 @@ KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
|
||||||
ReturnEntry->Inserted = FALSE;
|
ReturnEntry->Inserted = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release lock and Return */
|
/* Release the lock */
|
||||||
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
|
KiReleaseDeviceQueueLock(&DeviceLock);
|
||||||
|
|
||||||
|
/* Return the entry */
|
||||||
return ReturnEntry;
|
return ReturnEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,33 +163,34 @@ KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
PKDEVICE_QUEUE_ENTRY
|
PKDEVICE_QUEUE_ENTRY
|
||||||
STDCALL
|
NTAPI
|
||||||
KeRemoveByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
|
KeRemoveByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
|
||||||
IN ULONG SortKey)
|
IN ULONG SortKey)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY ListEntry;
|
PLIST_ENTRY ListEntry;
|
||||||
PKDEVICE_QUEUE_ENTRY ReturnEntry;
|
PKDEVICE_QUEUE_ENTRY ReturnEntry;
|
||||||
|
KLOCK_QUEUE_HANDLE DeviceLock;
|
||||||
|
ASSERT_DEVICE_QUEUE(DeviceQueue);
|
||||||
|
|
||||||
DPRINT("KeRemoveByKeyDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
|
/* Lock the queue */
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock);
|
||||||
|
|
||||||
/* Acquire the Lock */
|
|
||||||
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
|
|
||||||
ASSERT(DeviceQueue->Busy);
|
ASSERT(DeviceQueue->Busy);
|
||||||
|
|
||||||
/* An attempt to remove an entry from an empty (and busy) queue sets the queue idle */
|
/* Check if this is an empty queue */
|
||||||
if (IsListEmpty(&DeviceQueue->DeviceListHead)) {
|
if (IsListEmpty(&DeviceQueue->DeviceListHead))
|
||||||
|
{
|
||||||
|
/* Set it to idle and return nothing*/
|
||||||
DeviceQueue->Busy = FALSE;
|
DeviceQueue->Busy = FALSE;
|
||||||
ReturnEntry = NULL;
|
ReturnEntry = NULL;
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* Find entry with SortKey greater than or equal to the passed-in SortKey */
|
/* Find entry with SortKey greater than or equal to the passed-in SortKey */
|
||||||
LIST_FOR_EACH(ReturnEntry, &DeviceQueue->DeviceListHead, KDEVICE_QUEUE_ENTRY, DeviceListEntry)
|
LIST_FOR_EACH(ReturnEntry, &DeviceQueue->DeviceListHead, KDEVICE_QUEUE_ENTRY, DeviceListEntry)
|
||||||
{
|
{
|
||||||
/* Check if keys match */
|
/* Check if keys match */
|
||||||
if (ReturnEntry->SortKey >= SortKey) {
|
if (ReturnEntry->SortKey >= SortKey)
|
||||||
|
{
|
||||||
/* We found it, so just remove it */
|
/* We found it, so just remove it */
|
||||||
RemoveEntryList(&ReturnEntry->DeviceListEntry);
|
RemoveEntryList(&ReturnEntry->DeviceListEntry);
|
||||||
break;
|
break;
|
||||||
|
@ -215,8 +198,8 @@ KeRemoveByKeyDeviceQueue (IN PKDEVICE_QUEUE DeviceQueue,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we found something */
|
/* Check if we found something */
|
||||||
if (!ReturnEntry) {
|
if (!ReturnEntry)
|
||||||
|
{
|
||||||
/* Not found, return the first entry */
|
/* Not found, return the first entry */
|
||||||
ListEntry = RemoveHeadList(&DeviceQueue->DeviceListHead);
|
ListEntry = RemoveHeadList(&DeviceQueue->DeviceListHead);
|
||||||
ReturnEntry = CONTAINING_RECORD(ListEntry,
|
ReturnEntry = CONTAINING_RECORD(ListEntry,
|
||||||
|
@ -228,48 +211,97 @@ KeRemoveByKeyDeviceQueue (IN PKDEVICE_QUEUE DeviceQueue,
|
||||||
ReturnEntry->Inserted = FALSE;
|
ReturnEntry->Inserted = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release lock and Return */
|
/* Release the lock */
|
||||||
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
|
KiReleaseDeviceQueueLock(&DeviceLock);
|
||||||
return ReturnEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/* Return the entry */
|
||||||
* @unimplemented
|
return ReturnEntry;
|
||||||
*/
|
|
||||||
PKDEVICE_QUEUE_ENTRY
|
|
||||||
STDCALL
|
|
||||||
KeRemoveByKeyDeviceQueueIfBusy(IN PKDEVICE_QUEUE DeviceQueue,
|
|
||||||
IN ULONG SortKey)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOLEAN STDCALL
|
PKDEVICE_QUEUE_ENTRY
|
||||||
|
NTAPI
|
||||||
|
KeRemoveByKeyDeviceQueueIfBusy(IN PKDEVICE_QUEUE DeviceQueue,
|
||||||
|
IN ULONG SortKey)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY ListEntry;
|
||||||
|
PKDEVICE_QUEUE_ENTRY ReturnEntry;
|
||||||
|
KLOCK_QUEUE_HANDLE DeviceLock;
|
||||||
|
ASSERT_DEVICE_QUEUE(DeviceQueue);
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
{
|
||||||
|
/* Find entry with SortKey greater than or equal to the passed-in SortKey */
|
||||||
|
LIST_FOR_EACH(ReturnEntry, &DeviceQueue->DeviceListHead, KDEVICE_QUEUE_ENTRY, DeviceListEntry)
|
||||||
|
{
|
||||||
|
/* Check if keys match */
|
||||||
|
if (ReturnEntry->SortKey >= SortKey)
|
||||||
|
{
|
||||||
|
/* We found it, so just remove it */
|
||||||
|
RemoveEntryList(&ReturnEntry->DeviceListEntry);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we found something */
|
||||||
|
if (!ReturnEntry)
|
||||||
|
{
|
||||||
|
/* Not found, return the first entry */
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
KeRemoveEntryDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
|
KeRemoveEntryDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
|
||||||
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
|
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
|
||||||
BOOLEAN OldState;
|
BOOLEAN OldState;
|
||||||
|
KLOCK_QUEUE_HANDLE DeviceLock;
|
||||||
|
ASSERT_DEVICE_QUEUE(DeviceQueue);
|
||||||
|
|
||||||
DPRINT("KeRemoveEntryDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
|
/* Lock the queue */
|
||||||
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock);
|
||||||
|
ASSERT(DeviceQueue->Busy);
|
||||||
/* Acquire the Lock */
|
|
||||||
KeAcquireSpinLock(&DeviceQueue->Lock, &OldIrql);
|
|
||||||
|
|
||||||
/* Check/Set Old State */
|
|
||||||
if ((OldState = DeviceQueueEntry->Inserted)) {
|
|
||||||
|
|
||||||
|
/* Check the insertion state */
|
||||||
|
OldState = DeviceQueueEntry->Inserted;
|
||||||
|
if (OldState)
|
||||||
|
{
|
||||||
/* Remove it */
|
/* Remove it */
|
||||||
DeviceQueueEntry->Inserted = FALSE;
|
DeviceQueueEntry->Inserted = FALSE;
|
||||||
RemoveEntryList(&DeviceQueueEntry->DeviceListEntry);
|
RemoveEntryList(&DeviceQueueEntry->DeviceListEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock and return old state */
|
/* Unlock and return old state */
|
||||||
KeReleaseSpinLock(&DeviceQueue->Lock, OldIrql);
|
KiReleaseDeviceQueueLock(&DeviceLock);
|
||||||
return OldState;
|
return OldState;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue