- 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
This commit is contained in:
Cameron Gutman
2009-08-04 23:51:39 +00:00
parent 083150d2cd
commit 313b147b5f
4 changed files with 30 additions and 64 deletions
+1 -1
View File
@@ -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 );
@@ -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 );
}
@@ -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*/
+2 -4
View File
@@ -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 ) {