From 313b147b5f124e897ceaa2be8bc36c9488340597 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Tue, 4 Aug 2009 23:51:39 +0000 Subject: [PATCH] - Partial rewrite of recursive mutex code - Makes the recursive mutex faster and smaller - Fixes several unprotected accesses to recursive mutex svn path=/trunk/; revision=42400 --- reactos/drivers/network/tcpip/include/lock.h | 2 +- .../drivers/network/tcpip/recmutex/recmutex.c | 74 +++++++------------ .../drivers/network/tcpip/recmutex/recmutex.h | 12 +-- reactos/drivers/network/tcpip/tcpip/lock.c | 6 +- 4 files changed, 30 insertions(+), 64 deletions(-) diff --git a/reactos/drivers/network/tcpip/include/lock.h b/reactos/drivers/network/tcpip/include/lock.h index 99f50a27681..f5c15f5aefa 100644 --- a/reactos/drivers/network/tcpip/include/lock.h +++ b/reactos/drivers/network/tcpip/include/lock.h @@ -13,7 +13,7 @@ extern VOID TcpipInterlockedInsertTailList( PLIST_ENTRY ListHead, extern VOID TcpipAcquireFastMutex( PFAST_MUTEX Mutex ); extern VOID TcpipReleaseFastMutex( PFAST_MUTEX Mutex ); extern VOID TcpipRecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ); -extern UINT TcpipRecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, +extern VOID TcpipRecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, BOOLEAN ToWrite ); extern VOID TcpipRecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ); diff --git a/reactos/drivers/network/tcpip/recmutex/recmutex.c b/reactos/drivers/network/tcpip/recmutex/recmutex.c index 72e889fbd77..7c7a60a4304 100644 --- a/reactos/drivers/network/tcpip/recmutex/recmutex.c +++ b/reactos/drivers/network/tcpip/recmutex/recmutex.c @@ -3,7 +3,6 @@ VOID RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) { RtlZeroMemory( RecMutex, sizeof(*RecMutex) ); - KeInitializeSpinLock( &RecMutex->SpinLock ); ExInitializeFastMutex( &RecMutex->Mutex ); KeInitializeEvent( &RecMutex->StateLockedEvent, NotificationEvent, FALSE ); @@ -11,76 +10,53 @@ VOID RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) { /* NOTE: When we leave, the FAST_MUTEX must have been released. The result * is that we always exit in the same irql as entering */ -SIZE_T RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, BOOLEAN ToWrite ) { +VOID RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex ) { NTSTATUS Status = STATUS_SUCCESS; PVOID CurrentThread = KeGetCurrentThread(); - KIRQL CurrentIrql; + KIRQL CurrentIrql = KeGetCurrentIrql(); + + ASSERT(RecMutex); + ASSERT(CurrentIrql <= APC_LEVEL); /* 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 * time we get the event whether somebody still has the state locked */ - if( !RecMutex ) return FALSE; + ExAcquireFastMutex( &RecMutex->Mutex ); - if( CurrentThread == RecMutex->CurrentThread || - (!ToWrite && !RecMutex->Writer) ) { + if( CurrentThread == RecMutex->CurrentThread ) { RecMutex->LockCount++; - return TRUE; - } - - CurrentIrql = KeGetCurrentIrql(); - - ASSERT(CurrentIrql <= DISPATCH_LEVEL); - - if( CurrentIrql <= APC_LEVEL ) { - ExAcquireFastMutex( &RecMutex->Mutex ); - while( RecMutex->Locked ) { ExReleaseFastMutex( &RecMutex->Mutex ); - Status = KeWaitForSingleObject( &RecMutex->StateLockedEvent, - UserRequest, - KernelMode, - FALSE, - NULL ); - ExAcquireFastMutex( &RecMutex->Mutex ); - } - RecMutex->OldIrql = CurrentIrql; - RecMutex->Locked = TRUE; - RecMutex->Writer = ToWrite; - RecMutex->CurrentThread = CurrentThread; - RecMutex->LockCount++; - ExReleaseFastMutex( &RecMutex->Mutex ); - } else { - KeAcquireSpinLockAtDpcLevel( &RecMutex->SpinLock ); - RecMutex->OldIrql = DISPATCH_LEVEL; - RecMutex->Locked = TRUE; - RecMutex->Writer = ToWrite; - RecMutex->CurrentThread = CurrentThread; - RecMutex->LockCount++; + return; } - return TRUE; + while( RecMutex->LockCount != 0 ) { + ExReleaseFastMutex( &RecMutex->Mutex ); + Status = KeWaitForSingleObject( &RecMutex->StateLockedEvent, + UserRequest, + KernelMode, + FALSE, + NULL ); + ExAcquireFastMutex( &RecMutex->Mutex ); + } + RecMutex->CurrentThread = CurrentThread; + RecMutex->LockCount++; + ExReleaseFastMutex( &RecMutex->Mutex ); } VOID RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ) { + ASSERT(RecMutex); + + ExAcquireFastMutex( &RecMutex->Mutex ); ASSERT(RecMutex->LockCount > 0); RecMutex->LockCount--; if( !RecMutex->LockCount ) { - RecMutex->CurrentThread = NULL; - if( RecMutex->OldIrql <= APC_LEVEL ) { - ExAcquireFastMutex( &RecMutex->Mutex ); - RecMutex->Locked = FALSE; - RecMutex->Writer = FALSE; - ExReleaseFastMutex( &RecMutex->Mutex ); - } else { - RecMutex->Locked = FALSE; - RecMutex->Writer = FALSE; - KeReleaseSpinLockFromDpcLevel( &RecMutex->SpinLock ); - } - KePulseEvent( &RecMutex->StateLockedEvent, IO_NETWORK_INCREMENT, FALSE ); } + + ExReleaseFastMutex( &RecMutex->Mutex ); } diff --git a/reactos/drivers/network/tcpip/recmutex/recmutex.h b/reactos/drivers/network/tcpip/recmutex/recmutex.h index b4e068a1606..3479268e3bd 100644 --- a/reactos/drivers/network/tcpip/recmutex/recmutex.h +++ b/reactos/drivers/network/tcpip/recmutex/recmutex.h @@ -10,20 +10,12 @@ typedef struct _RECURSIVE_MUTEX { PVOID CurrentThread; /* Notification event which signals that another thread can take over */ KEVENT StateLockedEvent; - /* IRQL from spin lock */ - KIRQL OldIrql; - /* Is Locked */ - BOOLEAN Locked; - /* Is reader or writer phase */ - BOOLEAN Writer; - /* Spin lock needed for */ - KSPIN_LOCK SpinLock; } RECURSIVE_MUTEX, *PRECURSIVE_MUTEX; extern VOID RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ); -extern SIZE_T RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, BOOLEAN ToRead ); +extern VOID RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex ); extern VOID RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ); -#define ASSERT_LOCKED(x) ASSERT((x)->Locked) +#define ASSERT_LOCKED(x) #endif/*_ROSRTL_RECMUTEX_H*/ diff --git a/reactos/drivers/network/tcpip/tcpip/lock.c b/reactos/drivers/network/tcpip/tcpip/lock.c index d642d1accd9..db8ef244f33 100644 --- a/reactos/drivers/network/tcpip/tcpip/lock.c +++ b/reactos/drivers/network/tcpip/tcpip/lock.c @@ -48,11 +48,9 @@ VOID TcpipRecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) { RecursiveMutexInit( RecMutex ); } -UINT TcpipRecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, BOOLEAN ToWrite ) { - UINT Ret; +VOID TcpipRecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, BOOLEAN ToWrite ) { //TI_DbgPrint(DEBUG_LOCK,("Locking\n")); - Ret = RecursiveMutexEnter( RecMutex, ToWrite ); - return Ret; + RecursiveMutexEnter( RecMutex ); } VOID TcpipRecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ) {