Author: cgutman
Date: Thu Jun 25 01:57:48 2009
New Revision: 41600
URL:
http://svn.reactos.org/svn/reactos?rev=41600&view=rev
Log:
- Fix a crash that happens when we are running at APC_LEVEL, acquire the recursive mutex
(which improperly handled APC_LEVEL), then attempt to access paged pool (or do anything
else that depends on Irql < DISPATCH_LEVEL)
- Optimize the code for acquiring and releasing the recursive mutex at DISPATCH_LEVEL
Modified:
trunk/reactos/drivers/network/tcpip/recmutex/recmutex.c
Modified: trunk/reactos/drivers/network/tcpip/recmutex/recmutex.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/recm…
==============================================================================
--- trunk/reactos/drivers/network/tcpip/recmutex/recmutex.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/tcpip/recmutex/recmutex.c [iso-8859-1] Thu Jun 25
01:57:48 2009
@@ -14,6 +14,7 @@
SIZE_T RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, BOOLEAN ToWrite ) {
NTSTATUS Status = STATUS_SUCCESS;
PVOID CurrentThread = KeGetCurrentThread();
+ KIRQL CurrentIrql;
/* Wait for the previous user to unlock the RecMutex state. There might be
* multiple waiters waiting to change the state. We need to check each
@@ -27,9 +28,13 @@
return TRUE;
}
- if( KeGetCurrentIrql() == PASSIVE_LEVEL ) {
+ CurrentIrql = KeGetCurrentIrql();
+
+ ASSERT(CurrentIrql <= DISPATCH_LEVEL);
+
+ if( CurrentIrql <= APC_LEVEL ) {
ExAcquireFastMutex( &RecMutex->Mutex );
- RecMutex->OldIrql = PASSIVE_LEVEL;
+ RecMutex->OldIrql = CurrentIrql;
while( RecMutex->Locked ) {
ExReleaseFastMutex( &RecMutex->Mutex );
Status = KeWaitForSingleObject( &RecMutex->StateLockedEvent,
@@ -45,7 +50,8 @@
RecMutex->LockCount++;
ExReleaseFastMutex( &RecMutex->Mutex );
} else {
- KeAcquireSpinLock( &RecMutex->SpinLock, &RecMutex->OldIrql );
+ KeAcquireSpinLockAtDpcLevel( &RecMutex->SpinLock );
+ RecMutex->OldIrql = DISPATCH_LEVEL;
RecMutex->Locked = TRUE;
RecMutex->Writer = ToWrite;
RecMutex->CurrentThread = CurrentThread;
@@ -56,14 +62,13 @@
}
VOID RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ) {
- if( RecMutex->LockCount == 0 ) {
- return;
- } else
- RecMutex->LockCount--;
+
+ ASSERT(RecMutex->LockCount > 0);
+ RecMutex->LockCount--;
if( !RecMutex->LockCount ) {
RecMutex->CurrentThread = NULL;
- if( RecMutex->OldIrql == PASSIVE_LEVEL ) {
+ if( RecMutex->OldIrql <= APC_LEVEL ) {
ExAcquireFastMutex( &RecMutex->Mutex );
RecMutex->Locked = FALSE;
RecMutex->Writer = FALSE;
@@ -71,10 +76,9 @@
} else {
RecMutex->Locked = FALSE;
RecMutex->Writer = FALSE;
- KeReleaseSpinLock( &RecMutex->SpinLock, RecMutex->OldIrql );
+ KeReleaseSpinLockFromDpcLevel( &RecMutex->SpinLock );
}
- RecMutex->OldIrql = PASSIVE_LEVEL;
KePulseEvent( &RecMutex->StateLockedEvent, IO_NETWORK_INCREMENT,
FALSE );
}