diff --git a/reactos/include/ddk/winddk.h b/reactos/include/ddk/winddk.h index 3e43a6095d1..4bdd4d8c53c 100644 --- a/reactos/include/ddk/winddk.h +++ b/reactos/include/ddk/winddk.h @@ -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; diff --git a/reactos/ntoskrnl/include/internal/i386/ke.h b/reactos/ntoskrnl/include/internal/i386/ke.h index c1c7a6727e6..62c496163eb 100644 --- a/reactos/ntoskrnl/include/internal/i386/ke.h +++ b/reactos/ntoskrnl/include/internal/i386/ke.h @@ -124,7 +124,6 @@ KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine, #define LOCK "lock ; " #else #define LOCK "" -#define KeGetCurrentIrql() (((PKPCR)KPCR_BASE)->Irql) #endif #if defined(__GNUC__) diff --git a/reactos/ntoskrnl/include/internal/ke_x.h b/reactos/ntoskrnl/include/internal/ke_x.h index 8db34413bf9..f9580053cc3 100644 --- a/reactos/ntoskrnl/include/internal/ke_x.h +++ b/reactos/ntoskrnl/include/internal/ke_x.h @@ -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 diff --git a/reactos/ntoskrnl/ke/exception.c b/reactos/ntoskrnl/ke/exception.c index 4f762dd7b65..1caf27f660a 100644 --- a/reactos/ntoskrnl/ke/exception.c +++ b/reactos/ntoskrnl/ke/exception.c @@ -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 #define NDEBUG #include -/* 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 */ diff --git a/reactos/ntoskrnl/ke/kqueue.c b/reactos/ntoskrnl/ke/kqueue.c index 954f3811a09..a3a408a2238 100644 --- a/reactos/ntoskrnl/ke/kqueue.c +++ b/reactos/ntoskrnl/ke/kqueue.c @@ -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 #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; }