- 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:
Alex Ionescu 2006-09-13 00:20:46 +00:00
parent c0cda24302
commit d99f96a295
5 changed files with 200 additions and 130 deletions

View file

@ -1093,6 +1093,9 @@ typedef struct _KLOCK_QUEUE_HANDLE {
((Object)->Type == DpcObject) || \
((Object)->Type == ThreadedDpcObject))
#define ASSERT_DEVICE_QUEUE(Object) \
ASSERT((Object)->Type == DeviceQueueObject)
typedef struct _KDPC
{
UCHAR Type;

View file

@ -124,7 +124,6 @@ KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
#define LOCK "lock ; "
#else
#define LOCK ""
#define KeGetCurrentIrql() (((PKPCR)KPCR_BASE)->Irql)
#endif
#if defined(__GNUC__)

View file

@ -696,6 +696,44 @@ KiReleaseProcessLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE 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.
// If this thread cannot currently run on this CPU, then the thread is

View file

@ -1,18 +1,18 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ke/exception.c
* PURPOSE: Platform independent exception handling
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES *****************************************************************/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS ****************************************************************/
/* INCLUDES ******************************************************************/
VOID
NTAPI
@ -46,11 +46,7 @@ KiContinue(IN PCONTEXT Context,
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
/* Raise to APC_LEVEL, only if needed */
if (KeGetCurrentIrql() < APC_LEVEL)
{
/* Raise to APC_LEVEL */
KeRaiseIrql(APC_LEVEL, &OldIrql);
}
if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
/* Set up SEH to validate the context */
_SEH_TRY
@ -75,6 +71,7 @@ KiContinue(IN PCONTEXT Context,
}
_SEH_HANDLE
{
/* Save the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
@ -88,18 +85,17 @@ KiContinue(IN PCONTEXT Context,
NTSTATUS
NTAPI
KiRaiseException(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context,
PKEXCEPTION_FRAME ExceptionFrame,
PKTRAP_FRAME TrapFrame,
BOOLEAN SearchFrames)
KiRaiseException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PKTRAP_FRAME TrapFrame,
IN BOOLEAN SearchFrames)
{
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
CONTEXT LocalContext;
EXCEPTION_RECORD LocalExceptionRecord;
ULONG ParameterCount, Size;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT1("KiRaiseException\n");
/* Set up SEH */
_SEH_TRY
@ -143,10 +139,12 @@ KiRaiseException(PEXCEPTION_RECORD ExceptionRecord,
}
_SEH_HANDLE
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* Make sure we didn't crash in SEH */
if (NT_SUCCESS(Status))
{
/* Convert the context record */

View file

@ -1,16 +1,12 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PURPOSE: ReactOS kernel
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ke/kqueue.c
* PURPOSE: Implement device queues
*
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Several optimizations and implement
* usage of Inserted flag + reformat and
* add debug output.
* David Welch (welch@mcmail.com)
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ****************************************************************/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
@ -20,16 +16,11 @@
/*
* @implemented
*
* FUNCTION: Intializes a device queue
* ARGUMENTS:
* DeviceQueue = Device queue to initialize
*/
VOID
STDCALL
NTAPI
KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
{
/* Initialize the Header */
DeviceQueue->Type = DeviceQueueObject;
DeviceQueue->Size = sizeof(KDEVICE_QUEUE);
@ -44,48 +35,41 @@ KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
/*
* @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
STDCALL
NTAPI
KeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
{
KLOCK_QUEUE_HANDLE DeviceLock;
BOOLEAN Inserted;
ASSERT_DEVICE_QUEUE(DeviceQueue);
DPRINT("KeInsertDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
/* Lock the Queue */
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
if (!DeviceQueue->Busy) {
/* 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 {
}
else
{
/* Insert it into the list */
Inserted = TRUE;
InsertTailList(&DeviceQueue->DeviceListHead,
&DeviceQueueEntry->DeviceListEntry);
}
/* Sert the Insert state into the entry */
DeviceQueueEntry->Inserted = Inserted;
/* Release lock and return */
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
/* Release the lock */
KiReleaseDeviceQueueLock(&DeviceLock);
/* Return the state */
return Inserted;
}
@ -93,29 +77,30 @@ KeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
* @implemented
*/
BOOLEAN
STDCALL
NTAPI
KeInsertByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry,
IN ULONG SortKey)
{
KLOCK_QUEUE_HANDLE DeviceLock;
BOOLEAN Inserted;
ASSERT_DEVICE_QUEUE(DeviceQueue);
DPRINT("KeInsertByKeyDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
/* Acquire the Lock */
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
/* Lock the queue */
KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock);
/* Set the Sort Key */
DeviceQueueEntry->SortKey=SortKey;
DeviceQueueEntry->SortKey = SortKey;
if (!DeviceQueue->Busy) {
DeviceQueue->Busy=TRUE;
/* Check if it's not busy */
if (!DeviceQueue->Busy)
{
/* Set it as busy */
Inserted = FALSE;
} else {
DeviceQueue->Busy = TRUE;
}
else
{
/* Insert new entry after the last entry with SortKey less or equal to passed-in SortKey */
InsertAscendingListFIFO(&DeviceQueue->DeviceListHead,
DeviceQueueEntry,
@ -125,43 +110,38 @@ KeInsertByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
Inserted = TRUE;
}
/* Reset the Inserted State */
DeviceQueueEntry->Inserted = Inserted;
/* Release the lock */
KiReleaseDeviceQueueLock(&DeviceLock);
/* Release Lock and Return */
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
/* Return the state */
return Inserted;
}
/*
* @implemented
*
* FUNCTION: Removes an entry from a device queue
* ARGUMENTS:
* DeviceQueue = Queue to remove the entry
* RETURNS: The removed entry
*/
PKDEVICE_QUEUE_ENTRY
STDCALL
NTAPI
KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
{
PLIST_ENTRY ListEntry;
PKDEVICE_QUEUE_ENTRY ReturnEntry;
KLOCK_QUEUE_HANDLE DeviceLock;
ASSERT_DEVICE_QUEUE(DeviceQueue);
DPRINT("KeRemoveDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
/* Acquire the Lock */
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
/* Lock the queue */
KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock);
ASSERT(DeviceQueue->Busy);
/* An attempt to remove an entry from an empty (and busy) queue sets the queue idle */
if (IsListEmpty(&DeviceQueue->DeviceListHead)) {
/* Check if this is an empty queue */
if (IsListEmpty(&DeviceQueue->DeviceListHead))
{
/* Set it to idle and return nothing*/
DeviceQueue->Busy = FALSE;
ReturnEntry = NULL;
} else {
}
else
{
/* Remove the Entry from the List */
ListEntry = RemoveHeadList(&DeviceQueue->DeviceListHead);
ReturnEntry = CONTAINING_RECORD(ListEntry,
@ -172,8 +152,10 @@ KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
ReturnEntry->Inserted = FALSE;
}
/* Release lock and Return */
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
/* Release the lock */
KiReleaseDeviceQueueLock(&DeviceLock);
/* Return the entry */
return ReturnEntry;
}
@ -181,33 +163,34 @@ KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
* @implemented
*/
PKDEVICE_QUEUE_ENTRY
STDCALL
KeRemoveByKeyDeviceQueue (IN PKDEVICE_QUEUE DeviceQueue,
IN ULONG SortKey)
NTAPI
KeRemoveByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
IN ULONG SortKey)
{
PLIST_ENTRY ListEntry;
PKDEVICE_QUEUE_ENTRY ReturnEntry;
KLOCK_QUEUE_HANDLE DeviceLock;
ASSERT_DEVICE_QUEUE(DeviceQueue);
DPRINT("KeRemoveByKeyDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
/* Acquire the Lock */
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
/* Lock the queue */
KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock);
ASSERT(DeviceQueue->Busy);
/* An attempt to remove an entry from an empty (and busy) queue sets the queue idle */
if (IsListEmpty(&DeviceQueue->DeviceListHead)) {
/* Check if this is an empty queue */
if (IsListEmpty(&DeviceQueue->DeviceListHead))
{
/* Set it to idle and return nothing*/
DeviceQueue->Busy = FALSE;
ReturnEntry = NULL;
} else {
}
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) {
if (ReturnEntry->SortKey >= SortKey)
{
/* We found it, so just remove it */
RemoveEntryList(&ReturnEntry->DeviceListEntry);
break;
@ -215,61 +198,110 @@ KeRemoveByKeyDeviceQueue (IN PKDEVICE_QUEUE DeviceQueue,
}
/* Check if we found something */
if (!ReturnEntry) {
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 lock and Return */
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
return ReturnEntry;
}
/* Release the lock */
KiReleaseDeviceQueueLock(&DeviceLock);
/*
* @unimplemented
*/
PKDEVICE_QUEUE_ENTRY
STDCALL
KeRemoveByKeyDeviceQueueIfBusy(IN PKDEVICE_QUEUE DeviceQueue,
IN ULONG SortKey)
{
UNIMPLEMENTED;
return 0;
/* Return the entry */
return ReturnEntry;
}
/*
* @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,
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
{
KIRQL OldIrql;
BOOLEAN OldState;
KLOCK_QUEUE_HANDLE DeviceLock;
ASSERT_DEVICE_QUEUE(DeviceQueue);
DPRINT("KeRemoveEntryDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
/* Acquire the Lock */
KeAcquireSpinLock(&DeviceQueue->Lock, &OldIrql);
/* Check/Set Old State */
if ((OldState = DeviceQueueEntry->Inserted)) {
/* 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 */
KeReleaseSpinLock(&DeviceQueue->Lock, OldIrql);
KiReleaseDeviceQueueLock(&DeviceLock);
return OldState;
}