- 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.

svn path=/trunk/; revision=26294
This commit is contained in:
Alex Ionescu 2007-04-09 13:00:38 +00:00
parent aa7e29c22e
commit 52041c5b65
3 changed files with 68 additions and 75 deletions

View file

@ -9,37 +9,32 @@
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include <ntoskrnl.h> #include <ntoskrnl.h>
#include <internal/debug.h> #define NDEBUG
#include <debug.h>
VOID VOID
FASTCALL FASTCALL
KiAcquireFastMutex(IN PFAST_MUTEX FastMutex); KiAcquireFastMutex(
IN PFAST_MUTEX FastMutex
);
/* FUNCTIONS *****************************************************************/ /* PRIVATE FUNCTIONS *********************************************************/
/*
* @implemented
*/
VOID VOID
FASTCALL FORCEINLINE
ExEnterCriticalRegionAndAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex) ExiAcquireFastMutexUnsafe(IN PFAST_MUTEX FastMutex)
{ {
PKTHREAD Thread = KeGetCurrentThread(); PKTHREAD Thread = KeGetCurrentThread();
/* Enter the Critical Region */ DPRINT("Sanity print: %d %d %p\n",
KeEnterCriticalRegion(); KeGetCurrentIrql(), Thread->CombinedApcDisable, Thread->Teb);
/* Sanity check */
ASSERT((KeGetCurrentIrql() == APC_LEVEL) || ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
(Thread == NULL) ||
(Thread->CombinedApcDisable != 0) || (Thread->CombinedApcDisable != 0) ||
(Thread->Teb == NULL) || (Thread->Teb == NULL) ||
(Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START)); (Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
ASSERT(FastMutex->Owner != Thread);
ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
(Thread == NULL) ||
(Thread->CombinedApcDisable != 0));
ASSERT((Thread == NULL) || (FastMutex->Owner != Thread));
/* Decrease the count */ /* Decrease the count */
if (InterlockedDecrement(&FastMutex->Count)) if (InterlockedDecrement(&FastMutex->Count))
@ -52,26 +47,16 @@ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
FastMutex->Owner = Thread; FastMutex->Owner = Thread;
} }
/*
* @implemented
*/
VOID VOID
FASTCALL FORCEINLINE
ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(PFAST_MUTEX FastMutex) ExiReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
{ {
ASSERT((KeGetCurrentIrql() == APC_LEVEL) || ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
(KeGetCurrentThread() == NULL) ||
(KeGetCurrentThread()->CombinedApcDisable != 0) || (KeGetCurrentThread()->CombinedApcDisable != 0) ||
(KeGetCurrentThread()->Teb == NULL) || (KeGetCurrentThread()->Teb == NULL) ||
(KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START)); (KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
ASSERT(FastMutex->Owner == KeGetCurrentThread());
ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
(KeGetCurrentThread() == NULL) ||
(KeGetCurrentThread()->CombinedApcDisable != 0));
ASSERT(FastMutex->Owner == KeGetCurrentThread());
/* Erase the owner */ /* Erase the owner */
FastMutex->Owner = NULL; FastMutex->Owner = NULL;
@ -79,8 +64,35 @@ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(PFAST_MUTEX FastMutex)
if (InterlockedIncrement(&FastMutex->Count) <= 0) if (InterlockedIncrement(&FastMutex->Count) <= 0)
{ {
/* Someone was waiting for it, signal the waiter */ /* Someone was waiting for it, signal the waiter */
KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT); 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 */ /* Leave the critical region */
KeLeaveCriticalRegion(); KeLeaveCriticalRegion();
@ -91,16 +103,16 @@ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(PFAST_MUTEX FastMutex)
*/ */
VOID VOID
FASTCALL FASTCALL
ExAcquireFastMutex(PFAST_MUTEX FastMutex) ExAcquireFastMutex(IN OUT PFAST_MUTEX FastMutex)
{ {
KIRQL OldIrql; KIRQL OldIrql;
ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL); ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
/* Raise IRQL to APC */ /* Raise IRQL to APC */
OldIrql = KfRaiseIrql(APC_LEVEL); OldIrql = KfRaiseIrql(APC_LEVEL);
/* Decrease the count */ /* Decrease the count */
if (InterlockedDecrement(&FastMutex->Count)) if (InterlockedDecrement(&FastMutex->Count) != 0)
{ {
/* Someone is still holding it, use slow path */ /* Someone is still holding it, use slow path */
KiAcquireFastMutex(FastMutex); KiAcquireFastMutex(FastMutex);
@ -116,7 +128,7 @@ ExAcquireFastMutex(PFAST_MUTEX FastMutex)
*/ */
VOID VOID
FASTCALL FASTCALL
ExReleaseFastMutex (PFAST_MUTEX FastMutex) ExReleaseFastMutex(IN OUT PFAST_MUTEX FastMutex)
{ {
KIRQL OldIrql; KIRQL OldIrql;
ASSERT_IRQL(APC_LEVEL); ASSERT_IRQL(APC_LEVEL);
@ -141,25 +153,10 @@ ExReleaseFastMutex (PFAST_MUTEX FastMutex)
*/ */
VOID VOID
FASTCALL FASTCALL
ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex) ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
{ {
PKTHREAD Thread = KeGetCurrentThread(); /* Acquire the mutex unsafely */
ASSERT((KeGetCurrentIrql() == APC_LEVEL) || ExiAcquireFastMutexUnsafe(FastMutex);
(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;
} }
/* /*
@ -167,24 +164,10 @@ ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
*/ */
VOID VOID
FASTCALL FASTCALL
ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex) ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
{ {
ASSERT((KeGetCurrentIrql() == APC_LEVEL) || /* Release the mutex unsafely */
(KeGetCurrentThread() == NULL) || ExiReleaseFastMutexUnsafe(FastMutex);
(KeGetCurrentThread()->CombinedApcDisable != 0) ||
(KeGetCurrentThread()->Teb == NULL) ||
(KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
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);
}
} }
/* /*
@ -192,10 +175,10 @@ ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex)
*/ */
BOOLEAN BOOLEAN
FASTCALL FASTCALL
ExTryToAcquireFastMutex(PFAST_MUTEX FastMutex) ExTryToAcquireFastMutex(IN OUT PFAST_MUTEX FastMutex)
{ {
KIRQL OldIrql; KIRQL OldIrql;
ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL); ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
/* Raise to APC_LEVEL */ /* Raise to APC_LEVEL */
OldIrql = KfRaiseIrql(APC_LEVEL); OldIrql = KfRaiseIrql(APC_LEVEL);

View file

@ -572,7 +572,6 @@ IoWriteErrorLogEntry(IN PVOID ElEntry)
KIRQL Irql; KIRQL Irql;
/* Get the main header */ /* Get the main header */
KEBUGCHECK(0);
LogEntry = (PERROR_LOG_ENTRY)((ULONG_PTR)ElEntry - LogEntry = (PERROR_LOG_ENTRY)((ULONG_PTR)ElEntry -
sizeof(ERROR_LOG_ENTRY)); sizeof(ERROR_LOG_ENTRY));
@ -586,12 +585,14 @@ IoWriteErrorLogEntry(IN PVOID ElEntry)
/* Check if the worker is runnign */ /* Check if the worker is runnign */
if (!IopLogWorkerRunning) if (!IopLogWorkerRunning)
{ {
#if 0
/* It's not, initialize it and queue it */ /* It's not, initialize it and queue it */
ExInitializeWorkItem(&IopErrorLogWorkItem, ExInitializeWorkItem(&IopErrorLogWorkItem,
IopLogWorker, IopLogWorker,
&IopErrorLogWorkItem); &IopErrorLogWorkItem);
ExQueueWorkItem(&IopErrorLogWorkItem, DelayedWorkQueue); ExQueueWorkItem(&IopErrorLogWorkItem, DelayedWorkQueue);
IopLogWorkerRunning = TRUE; IopLogWorkerRunning = TRUE;
#endif
} }
/* Release the lock and return */ /* Release the lock and return */

View file

@ -141,12 +141,21 @@ IopStartDevice(
Stack.Parameters.StartDevice.AllocatedResources = DeviceNode->ResourceList; Stack.Parameters.StartDevice.AllocatedResources = DeviceNode->ResourceList;
Stack.Parameters.StartDevice.AllocatedResourcesTranslated = DeviceNode->ResourceListTranslated; 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( Status = IopInitiatePnpIrp(
Fdo, Fdo,
&IoStatusBlock, &IoStatusBlock,
IRP_MN_START_DEVICE, IRP_MN_START_DEVICE,
&Stack); &Stack);
KeLeaveCriticalRegion();
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("IopInitiatePnpIrp() failed\n"); DPRINT("IopInitiatePnpIrp() failed\n");