mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-03 04:13:31 +00:00
- 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:
@@ -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*/
|
||||
|
||||
@@ -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 ) {
|
||||
|
||||
Reference in New Issue
Block a user