mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Added simple recursive mutex adapted from my afd one. Works both above
and below DISPATCH_LEVEL. svn path=/trunk/; revision=11056
This commit is contained in:
parent
3a4c09d746
commit
1eb1e27110
3 changed files with 116 additions and 3 deletions
27
reactos/include/rosrtl/recmutex.h
Normal file
27
reactos/include/rosrtl/recmutex.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef _ROSRTL_RECMUTEX_H
|
||||||
|
#define _ROSRTL_RECMUTEX_H
|
||||||
|
|
||||||
|
typedef struct _RECURSIVE_MUTEX {
|
||||||
|
/* Lock. */
|
||||||
|
FAST_MUTEX Mutex;
|
||||||
|
/* Number of times this object was locked */
|
||||||
|
UINT LockCount;
|
||||||
|
/* CurrentThread */
|
||||||
|
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 UINT RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, BOOL ToRead );
|
||||||
|
extern VOID RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex );
|
||||||
|
|
||||||
|
#endif/*_ROSRTL_RECMUTEX_H*/
|
|
@ -1,4 +1,4 @@
|
||||||
# $Id: makefile,v 1.16 2004/09/15 18:57:01 weiden Exp $
|
# $Id: makefile,v 1.17 2004/09/25 21:32:17 arty Exp $
|
||||||
|
|
||||||
PATH_TO_TOP = ../..
|
PATH_TO_TOP = ../..
|
||||||
|
|
||||||
|
@ -32,6 +32,8 @@ MISC_OBJECTS = \
|
||||||
FILE_OBJECTS = \
|
FILE_OBJECTS = \
|
||||||
file/sparse.o
|
file/sparse.o
|
||||||
|
|
||||||
|
RECMUTEX_OBJECTS = recmutex/recmutex.o
|
||||||
|
|
||||||
include $(PATH_TO_TOP)/config
|
include $(PATH_TO_TOP)/config
|
||||||
|
|
||||||
include makefile.$(ARCH)
|
include makefile.$(ARCH)
|
||||||
|
@ -43,8 +45,8 @@ TARGET_NAME = rosrtl
|
||||||
TARGET_CFLAGS = -D__USE_W32API -Wall -Werror
|
TARGET_CFLAGS = -D__USE_W32API -Wall -Werror
|
||||||
|
|
||||||
TARGET_OBJECTS = $(THREAD_OBJECTS) $(MISC_OBJECTS) $(STRING_OBJECTS) \
|
TARGET_OBJECTS = $(THREAD_OBJECTS) $(MISC_OBJECTS) $(STRING_OBJECTS) \
|
||||||
$(REGISTRY_OBJECTS) $(FILE_OBJECTS)
|
$(REGISTRY_OBJECTS) $(FILE_OBJECTS) $(RECMUTEX_OBJECTS)
|
||||||
|
|
||||||
DEP_OBJECTS = $(TARGET_OBJECTS)
|
DEP_OBJECTS = $(TARGET_OBJECTS)
|
||||||
|
|
||||||
include $(PATH_TO_TOP)/rules.mak
|
include $(PATH_TO_TOP)/rules.mak
|
||||||
|
|
84
reactos/lib/rosrtl/recmutex/recmutex.c
Normal file
84
reactos/lib/rosrtl/recmutex/recmutex.c
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#define NTOS_MODE_USER
|
||||||
|
#include <ntos.h>
|
||||||
|
#include <rosrtl/recmutex.h>
|
||||||
|
|
||||||
|
VOID RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) {
|
||||||
|
RtlZeroMemory( RecMutex, sizeof(*RecMutex) );
|
||||||
|
KeInitializeSpinLock( &RecMutex->SpinLock );
|
||||||
|
ExInitializeFastMutex( &RecMutex->Mutex );
|
||||||
|
KeInitializeEvent( &RecMutex->StateLockedEvent,
|
||||||
|
NotificationEvent, FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: When we leave, the FAST_MUTEX must have been released. The result
|
||||||
|
* is that we always exit in the same irql as entering */
|
||||||
|
UINT RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, BOOL ToWrite ) {
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
PVOID CurrentThread = KeGetCurrentThread();
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
if( CurrentThread == RecMutex->CurrentThread ||
|
||||||
|
(!ToWrite && !RecMutex->Writer) ) {
|
||||||
|
RecMutex->LockCount++;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( KeGetCurrentIrql() == PASSIVE_LEVEL ) {
|
||||||
|
ExAcquireFastMutex( &RecMutex->Mutex );
|
||||||
|
RecMutex->OldIrql = PASSIVE_LEVEL;
|
||||||
|
while( RecMutex->Locked ) {
|
||||||
|
ExReleaseFastMutex( &RecMutex->Mutex );
|
||||||
|
Status = KeWaitForSingleObject( &RecMutex->StateLockedEvent,
|
||||||
|
UserRequest,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL );
|
||||||
|
ExAcquireFastMutex( &RecMutex->Mutex );
|
||||||
|
if( Status == STATUS_SUCCESS ) break;
|
||||||
|
}
|
||||||
|
RecMutex->Locked = TRUE;
|
||||||
|
RecMutex->Writer = ToWrite;
|
||||||
|
RecMutex->CurrentThread = CurrentThread;
|
||||||
|
RecMutex->LockCount++;
|
||||||
|
ExReleaseFastMutex( &RecMutex->Mutex );
|
||||||
|
} else {
|
||||||
|
KeAcquireSpinLock( &RecMutex->SpinLock, &RecMutex->OldIrql );
|
||||||
|
RecMutex->Locked = TRUE;
|
||||||
|
RecMutex->Writer = ToWrite;
|
||||||
|
RecMutex->CurrentThread = CurrentThread;
|
||||||
|
RecMutex->LockCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ) {
|
||||||
|
if( RecMutex->LockCount == 0 ) {
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
RecMutex->LockCount--;
|
||||||
|
|
||||||
|
if( !RecMutex->LockCount ) {
|
||||||
|
RecMutex->CurrentThread = NULL;
|
||||||
|
if( RecMutex->OldIrql == PASSIVE_LEVEL ) {
|
||||||
|
ExAcquireFastMutex( &RecMutex->Mutex );
|
||||||
|
RecMutex->Locked = FALSE;
|
||||||
|
RecMutex->Writer = FALSE;
|
||||||
|
ExReleaseFastMutex( &RecMutex->Mutex );
|
||||||
|
} else {
|
||||||
|
RecMutex->Locked = FALSE;
|
||||||
|
RecMutex->Writer = FALSE;
|
||||||
|
KeReleaseSpinLock( &RecMutex->SpinLock, RecMutex->OldIrql );
|
||||||
|
}
|
||||||
|
|
||||||
|
RecMutex->OldIrql = PASSIVE_LEVEL;
|
||||||
|
KePulseEvent( &RecMutex->StateLockedEvent, IO_NETWORK_INCREMENT,
|
||||||
|
FALSE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue