4 VOID
RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex
) {
5 RtlZeroMemory( RecMutex
, sizeof(*RecMutex
) );
6 KeInitializeSpinLock( &RecMutex
->SpinLock
);
7 ExInitializeFastMutex( &RecMutex
->Mutex
);
8 KeInitializeEvent( &RecMutex
->StateLockedEvent
,
9 NotificationEvent
, FALSE
);
12 /* NOTE: When we leave, the FAST_MUTEX must have been released. The result
13 * is that we always exit in the same irql as entering */
14 UINT
RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex
, BOOL ToWrite
) {
15 NTSTATUS Status
= STATUS_SUCCESS
;
16 PVOID CurrentThread
= KeGetCurrentThread();
18 /* Wait for the previous user to unlock the RecMutex state. There might be
19 * multiple waiters waiting to change the state. We need to check each
20 * time we get the event whether somebody still has the state locked */
22 if( !RecMutex
) return FALSE
;
24 if( CurrentThread
== RecMutex
->CurrentThread
||
25 (!ToWrite
&& !RecMutex
->Writer
) ) {
26 RecMutex
->LockCount
++;
30 if( KeGetCurrentIrql() == PASSIVE_LEVEL
) {
31 ExAcquireFastMutex( &RecMutex
->Mutex
);
32 RecMutex
->OldIrql
= PASSIVE_LEVEL
;
33 while( RecMutex
->Locked
) {
34 ExReleaseFastMutex( &RecMutex
->Mutex
);
35 Status
= KeWaitForSingleObject( &RecMutex
->StateLockedEvent
,
40 ExAcquireFastMutex( &RecMutex
->Mutex
);
41 if( Status
== STATUS_SUCCESS
) break;
43 RecMutex
->Locked
= TRUE
;
44 RecMutex
->Writer
= ToWrite
;
45 RecMutex
->CurrentThread
= CurrentThread
;
46 RecMutex
->LockCount
++;
47 ExReleaseFastMutex( &RecMutex
->Mutex
);
49 KeAcquireSpinLock( &RecMutex
->SpinLock
, &RecMutex
->OldIrql
);
50 RecMutex
->Locked
= TRUE
;
51 RecMutex
->Writer
= ToWrite
;
52 RecMutex
->CurrentThread
= CurrentThread
;
53 RecMutex
->LockCount
++;
59 VOID
RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex
) {
60 if( RecMutex
->LockCount
== 0 ) {
63 RecMutex
->LockCount
--;
65 if( !RecMutex
->LockCount
) {
66 RecMutex
->CurrentThread
= NULL
;
67 if( RecMutex
->OldIrql
== PASSIVE_LEVEL
) {
68 ExAcquireFastMutex( &RecMutex
->Mutex
);
69 RecMutex
->Locked
= FALSE
;
70 RecMutex
->Writer
= FALSE
;
71 ExReleaseFastMutex( &RecMutex
->Mutex
);
73 RecMutex
->Locked
= FALSE
;
74 RecMutex
->Writer
= FALSE
;
75 KeReleaseSpinLock( &RecMutex
->SpinLock
, RecMutex
->OldIrql
);
78 RecMutex
->OldIrql
= PASSIVE_LEVEL
;
79 KePulseEvent( &RecMutex
->StateLockedEvent
, IO_NETWORK_INCREMENT
,