[ros-diffs] [cgutman] 41600: - 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

cgutman at svn.reactos.org cgutman at svn.reactos.org
Wed Jun 24 23:57:49 CEST 2009


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/recmutex/recmutex.c?rev=41600&r1=41599&r2=41600&view=diff
==============================================================================
--- 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 );
     }



More information about the Ros-diffs mailing list