- 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 *****************************************************************/
#include <ntoskrnl.h>
#include <internal/debug.h>
#define NDEBUG
#include <debug.h>
VOID
FASTCALL
KiAcquireFastMutex(IN PFAST_MUTEX FastMutex);
KiAcquireFastMutex(
IN PFAST_MUTEX FastMutex
);
/* FUNCTIONS *****************************************************************/
/* PRIVATE FUNCTIONS *********************************************************/
/*
* @implemented
*/
VOID
FASTCALL
ExEnterCriticalRegionAndAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
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,26 +47,16 @@ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
FastMutex->Owner = Thread;
}
/*
* @implemented
*/
VOID
FASTCALL
ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(PFAST_MUTEX FastMutex)
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(FastMutex->Owner == KeGetCurrentThread());
ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
(KeGetCurrentThread() == NULL) ||
(KeGetCurrentThread()->CombinedApcDisable != 0));
ASSERT(FastMutex->Owner == KeGetCurrentThread());
/* Erase the owner */
FastMutex->Owner = NULL;
@ -79,8 +64,35 @@ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(PFAST_MUTEX FastMutex)
if (InterlockedIncrement(&FastMutex->Count) <= 0)
{
/* 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 */
KeLeaveCriticalRegion();
@ -91,16 +103,16 @@ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(PFAST_MUTEX FastMutex)
*/
VOID
FASTCALL
ExAcquireFastMutex(PFAST_MUTEX FastMutex)
ExAcquireFastMutex(IN OUT PFAST_MUTEX FastMutex)
{
KIRQL OldIrql;
ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL);
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
/* Raise IRQL to APC */
OldIrql = KfRaiseIrql(APC_LEVEL);
/* Decrease the count */
if (InterlockedDecrement(&FastMutex->Count))
if (InterlockedDecrement(&FastMutex->Count) != 0)
{
/* Someone is still holding it, use slow path */
KiAcquireFastMutex(FastMutex);
@ -116,7 +128,7 @@ ExAcquireFastMutex(PFAST_MUTEX FastMutex)
*/
VOID
FASTCALL
ExReleaseFastMutex (PFAST_MUTEX FastMutex)
ExReleaseFastMutex(IN OUT PFAST_MUTEX FastMutex)
{
KIRQL OldIrql;
ASSERT_IRQL(APC_LEVEL);
@ -141,25 +153,10 @@ ExReleaseFastMutex (PFAST_MUTEX FastMutex)
*/
VOID
FASTCALL
ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
ExAcquireFastMutexUnsafe(IN OUT 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;
/* Acquire the mutex unsafely */
ExiAcquireFastMutexUnsafe(FastMutex);
}
/*
@ -167,24 +164,10 @@ ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
*/
VOID
FASTCALL
ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex)
ExReleaseFastMutexUnsafe(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(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);
}
/* Release the mutex unsafely */
ExiReleaseFastMutexUnsafe(FastMutex);
}
/*
@ -192,10 +175,10 @@ ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex)
*/
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);

View file

@ -572,7 +572,6 @@ IoWriteErrorLogEntry(IN PVOID ElEntry)
KIRQL Irql;
/* Get the main header */
KEBUGCHECK(0);
LogEntry = (PERROR_LOG_ENTRY)((ULONG_PTR)ElEntry -
sizeof(ERROR_LOG_ENTRY));
@ -586,12 +585,14 @@ IoWriteErrorLogEntry(IN PVOID ElEntry)
/* 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 */

View file

@ -141,12 +141,21 @@ IopStartDevice(
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))
{
DPRINT("IopInitiatePnpIrp() failed\n");