4 VOID
RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex
) {
5 RtlZeroMemory( RecMutex
, sizeof(*RecMutex
) );
6 ExInitializeFastMutex( &RecMutex
->Mutex
);
7 KeInitializeEvent( &RecMutex
->StateLockedEvent
,
8 NotificationEvent
, FALSE
);
11 /* NOTE: When we leave, the FAST_MUTEX must have been released. The result
12 * is that we always exit in the same irql as entering */
13 VOID
RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex
) {
14 NTSTATUS Status
= STATUS_SUCCESS
;
15 PVOID CurrentThread
= KeGetCurrentThread();
18 ASSERT(KeGetCurrentIrql() <= APC_LEVEL
);
20 /* Wait for the previous user to unlock the RecMutex state. There might be
21 * multiple waiters waiting to change the state. We need to check each
22 * time we get the event whether somebody still has the state locked */
24 ExAcquireFastMutex( &RecMutex
->Mutex
);
26 if( CurrentThread
== RecMutex
->CurrentThread
) {
27 RecMutex
->LockCount
++;
28 ExReleaseFastMutex( &RecMutex
->Mutex
);
32 while( RecMutex
->LockCount
!= 0 ) {
33 ExReleaseFastMutex( &RecMutex
->Mutex
);
34 Status
= KeWaitForSingleObject( &RecMutex
->StateLockedEvent
,
39 ExAcquireFastMutex( &RecMutex
->Mutex
);
41 RecMutex
->CurrentThread
= CurrentThread
;
42 RecMutex
->LockCount
++;
43 ExReleaseFastMutex( &RecMutex
->Mutex
);
46 VOID
RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex
) {
49 ExAcquireFastMutex( &RecMutex
->Mutex
);
51 ASSERT(RecMutex
->LockCount
> 0);
52 RecMutex
->LockCount
--;
54 if( !RecMutex
->LockCount
) {
55 KePulseEvent( &RecMutex
->StateLockedEvent
, IO_NETWORK_INCREMENT
,
59 ExReleaseFastMutex( &RecMutex
->Mutex
);