Author: ion Date: Mon Apr 9 17:00:38 2007 New Revision: 26294
URL: http://svn.reactos.org/svn/reactos?rev=26294&view=rev Log: - Call IRP_MN_START_DEVICE in a critical region, since NT drivers depend on this implementation detail (on NT, an ERESOURCE+CriticalRegion is always held when parsing a new device node, so all related IRP_MNs are actually received under a critical region. For now, I only made IRP_MN_START_DEVICE behave as such. i8042prt from the DDK depends on this behavior. - Cleaned up Fast Mutex Implementation. - Disabled a hard-coded bugcheck and instead disabled soem code.
Modified: trunk/reactos/ntoskrnl/ex/fmutex.c trunk/reactos/ntoskrnl/io/iomgr/error.c trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c
Modified: trunk/reactos/ntoskrnl/ex/fmutex.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/fmutex.c?rev=26... ============================================================================== --- trunk/reactos/ntoskrnl/ex/fmutex.c (original) +++ trunk/reactos/ntoskrnl/ex/fmutex.c Mon Apr 9 17:00:38 2007 @@ -9,37 +9,32 @@ /* INCLUDES *****************************************************************/
#include <ntoskrnl.h> -#include <internal/debug.h> - -VOID -FASTCALL -KiAcquireFastMutex(IN PFAST_MUTEX FastMutex); - -/* FUNCTIONS *****************************************************************/ - -/* - * @implemented - */ -VOID -FASTCALL -ExEnterCriticalRegionAndAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex) +#define NDEBUG +#include <debug.h> + +VOID +FASTCALL +KiAcquireFastMutex( + IN PFAST_MUTEX FastMutex +); + +/* PRIVATE FUNCTIONS *********************************************************/ + +VOID +FORCEINLINE +ExiAcquireFastMutexUnsafe(IN PFAST_MUTEX FastMutex) { PKTHREAD Thread = KeGetCurrentThread();
- /* Enter the Critical Region */ - KeEnterCriticalRegion(); - + DPRINT("Sanity print: %d %d %p\n", + KeGetCurrentIrql(), Thread->CombinedApcDisable, Thread->Teb); + + /* Sanity check */ ASSERT((KeGetCurrentIrql() == APC_LEVEL) || - (Thread == NULL) || (Thread->CombinedApcDisable != 0) || (Thread->Teb == NULL) || (Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START)); - - ASSERT((KeGetCurrentIrql() == APC_LEVEL) || - (Thread == NULL) || - (Thread->CombinedApcDisable != 0)); - - ASSERT((Thread == NULL) || (FastMutex->Owner != Thread)); + ASSERT(FastMutex->Owner != Thread);
/* Decrease the count */ if (InterlockedDecrement(&FastMutex->Count)) @@ -52,130 +47,16 @@ FastMutex->Owner = Thread; }
-/* - * @implemented - */ -VOID -FASTCALL -ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(PFAST_MUTEX FastMutex) -{ - +VOID +FORCEINLINE +ExiReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex) +{ ASSERT((KeGetCurrentIrql() == APC_LEVEL) || - (KeGetCurrentThread() == NULL) || - (KeGetCurrentThread()->CombinedApcDisable != 0) || - (KeGetCurrentThread()->Teb == NULL) || - (KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START)); - - - ASSERT((KeGetCurrentIrql() == APC_LEVEL) || - (KeGetCurrentThread() == NULL) || - (KeGetCurrentThread()->CombinedApcDisable != 0)); - ASSERT(FastMutex->Owner == KeGetCurrentThread()); - - /* Erase the owner */ - FastMutex->Owner = NULL; - - /* Increase the count */ - if (InterlockedIncrement(&FastMutex->Count) <= 0) - { - /* Someone was waiting for it, signal the waiter */ - KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT); - } - - /* Leave the critical region */ - KeLeaveCriticalRegion(); -} - -/* - * @implemented - */ -VOID -FASTCALL -ExAcquireFastMutex(PFAST_MUTEX FastMutex) -{ - KIRQL OldIrql; - ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL); - - /* Raise IRQL to APC */ - OldIrql = KfRaiseIrql(APC_LEVEL); - - /* Decrease the count */ - if (InterlockedDecrement(&FastMutex->Count)) - { - /* Someone is still holding it, use slow path */ - KiAcquireFastMutex(FastMutex); - } - - /* Set the owner and IRQL */ - FastMutex->Owner = KeGetCurrentThread(); - FastMutex->OldIrql = OldIrql; -} - -/* - * @implemented - */ -VOID -FASTCALL -ExReleaseFastMutex (PFAST_MUTEX FastMutex) -{ - KIRQL OldIrql; - ASSERT_IRQL(APC_LEVEL); - - /* Erase the owner */ - FastMutex->Owner = NULL; - OldIrql = FastMutex->OldIrql; - - /* Increase the count */ - if (InterlockedIncrement(&FastMutex->Count) <= 0) - { - /* Someone was waiting for it, signal the waiter */ - KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT); - } - - /* Lower IRQL back */ - KfLowerIrql(OldIrql); -} - -/* - * @implemented - */ -VOID -FASTCALL -ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex) -{ - PKTHREAD Thread = KeGetCurrentThread(); - ASSERT((KeGetCurrentIrql() == APC_LEVEL) || - (Thread == NULL) || - (Thread->CombinedApcDisable != 0) || - (Thread->Teb == NULL) || - (Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START)); - ASSERT((Thread == NULL) || (FastMutex->Owner != Thread)); - - /* Decrease the count */ - if (InterlockedDecrement(&FastMutex->Count)) - { - /* Someone is still holding it, use slow path */ - KiAcquireFastMutex(FastMutex); - } - - /* Set the owner */ - FastMutex->Owner = Thread; -} - -/* - * @implemented - */ -VOID -FASTCALL -ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex) -{ - ASSERT((KeGetCurrentIrql() == APC_LEVEL) || - (KeGetCurrentThread() == NULL) || (KeGetCurrentThread()->CombinedApcDisable != 0) || (KeGetCurrentThread()->Teb == NULL) || (KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START)); ASSERT(FastMutex->Owner == KeGetCurrentThread()); - + /* Erase the owner */ FastMutex->Owner = NULL;
@@ -183,8 +64,110 @@ if (InterlockedIncrement(&FastMutex->Count) <= 0) { /* Someone was waiting for it, signal the waiter */ + KeSetEventBoostPriority(&FastMutex->Gate, NULL); + } +} + +/* PUBLIC FUNCTIONS **********************************************************/ + +/* + * @implemented + */ +VOID +FASTCALL +ExEnterCriticalRegionAndAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex) +{ + /* Enter the Critical Region */ + KeEnterCriticalRegion(); + + /* Acquire the mutex unsafely */ + ExiAcquireFastMutexUnsafe(FastMutex); +} + +/* + * @implemented + */ +VOID +FASTCALL +ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(IN OUT PFAST_MUTEX FastMutex) +{ + /* Release the mutex unsafely */ + ExiReleaseFastMutexUnsafe(FastMutex); + + /* Leave the critical region */ + KeLeaveCriticalRegion(); +} + +/* + * @implemented + */ +VOID +FASTCALL +ExAcquireFastMutex(IN OUT PFAST_MUTEX FastMutex) +{ + KIRQL OldIrql; + ASSERT(KeGetCurrentIrql() <= APC_LEVEL); + + /* Raise IRQL to APC */ + OldIrql = KfRaiseIrql(APC_LEVEL); + + /* Decrease the count */ + if (InterlockedDecrement(&FastMutex->Count) != 0) + { + /* Someone is still holding it, use slow path */ + KiAcquireFastMutex(FastMutex); + } + + /* Set the owner and IRQL */ + FastMutex->Owner = KeGetCurrentThread(); + FastMutex->OldIrql = OldIrql; +} + +/* + * @implemented + */ +VOID +FASTCALL +ExReleaseFastMutex(IN OUT PFAST_MUTEX FastMutex) +{ + KIRQL OldIrql; + ASSERT_IRQL(APC_LEVEL); + + /* Erase the owner */ + FastMutex->Owner = NULL; + OldIrql = FastMutex->OldIrql; + + /* Increase the count */ + if (InterlockedIncrement(&FastMutex->Count) <= 0) + { + /* Someone was waiting for it, signal the waiter */ KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT); } + + /* Lower IRQL back */ + KfLowerIrql(OldIrql); +} + +/* + * @implemented + */ +VOID +FASTCALL +ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex) +{ + /* Acquire the mutex unsafely */ + ExiAcquireFastMutexUnsafe(FastMutex); +} + +/* + * @implemented + */ +VOID +FASTCALL +ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex) +{ + /* Release the mutex unsafely */ + ExiReleaseFastMutexUnsafe(FastMutex); }
/* @@ -192,10 +175,10 @@ */ BOOLEAN FASTCALL -ExTryToAcquireFastMutex(PFAST_MUTEX FastMutex) +ExTryToAcquireFastMutex(IN OUT PFAST_MUTEX FastMutex) { KIRQL OldIrql; - ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL); + ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
/* Raise to APC_LEVEL */ OldIrql = KfRaiseIrql(APC_LEVEL);
Modified: trunk/reactos/ntoskrnl/io/iomgr/error.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/error.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/error.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/error.c Mon Apr 9 17:00:38 2007 @@ -572,7 +572,6 @@ KIRQL Irql;
/* Get the main header */ - KEBUGCHECK(0); LogEntry = (PERROR_LOG_ENTRY)((ULONG_PTR)ElEntry - sizeof(ERROR_LOG_ENTRY));
@@ -586,12 +585,14 @@ /* Check if the worker is runnign */ if (!IopLogWorkerRunning) { +#if 0 /* It's not, initialize it and queue it */ ExInitializeWorkItem(&IopErrorLogWorkItem, IopLogWorker, &IopErrorLogWorkItem); ExQueueWorkItem(&IopErrorLogWorkItem, DelayedWorkQueue); IopLogWorkerRunning = TRUE; +#endif }
/* Release the lock and return */
Modified: trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c... ============================================================================== --- trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c (original) +++ trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c Mon Apr 9 17:00:38 2007 @@ -141,11 +141,20 @@ Stack.Parameters.StartDevice.AllocatedResources = DeviceNode->ResourceList; Stack.Parameters.StartDevice.AllocatedResourcesTranslated = DeviceNode->ResourceListTranslated;
+ /* + * Windows NT Drivers receive IRP_MN_START_DEVICE in a critical region and + * actually _depend_ on this!. This is because NT will lock the Device Node + * with an ERESOURCE, which of course requires APCs to be disabled. + */ + KeEnterCriticalRegion(); + Status = IopInitiatePnpIrp( Fdo, &IoStatusBlock, IRP_MN_START_DEVICE, &Stack); + + KeLeaveCriticalRegion();
if (!NT_SUCCESS(Status)) {