3450ab8567fbaebc9864274c9f632c543d91e5a5
[reactos.git] / reactos / drivers / network / tcpip / recmutex / recmutex.c
1 #include <ntddk.h>
2 #include "recmutex.h"
3
4 VOID RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) {
5 RtlZeroMemory( RecMutex, sizeof(*RecMutex) );
6 ExInitializeFastMutex( &RecMutex->Mutex );
7 KeInitializeEvent( &RecMutex->StateLockedEvent,
8 NotificationEvent, FALSE );
9 }
10
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();
16
17 ASSERT(RecMutex);
18 ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
19
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 */
23
24 ExAcquireFastMutex( &RecMutex->Mutex );
25
26 if( CurrentThread == RecMutex->CurrentThread ) {
27 RecMutex->LockCount++;
28 ExReleaseFastMutex( &RecMutex->Mutex );
29 return;
30 }
31
32 while( RecMutex->LockCount != 0 ) {
33 ExReleaseFastMutex( &RecMutex->Mutex );
34 Status = KeWaitForSingleObject( &RecMutex->StateLockedEvent,
35 UserRequest,
36 KernelMode,
37 FALSE,
38 NULL );
39 ExAcquireFastMutex( &RecMutex->Mutex );
40 }
41 RecMutex->CurrentThread = CurrentThread;
42 RecMutex->LockCount++;
43 ExReleaseFastMutex( &RecMutex->Mutex );
44 }
45
46 VOID RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ) {
47 ASSERT(RecMutex);
48
49 ExAcquireFastMutex( &RecMutex->Mutex );
50
51 ASSERT(RecMutex->LockCount > 0);
52 RecMutex->LockCount--;
53
54 if( !RecMutex->LockCount ) {
55 KePulseEvent( &RecMutex->StateLockedEvent, IO_NETWORK_INCREMENT,
56 FALSE );
57 }
58
59 ExReleaseFastMutex( &RecMutex->Mutex );
60 }
61