ReactOS 0.4.16-dev-334-g4d9f67c
mutex.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/mutex.c
5 * PURPOSE: Implements the Mutant Dispatcher Object
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include <ntoskrnl.h>
12#define NDEBUG
13#include <debug.h>
14
15/* FUNCTIONS *****************************************************************/
16
17/*
18 * @implemented
19 */
20VOID
24{
25 PKTHREAD CurrentThread;
27
28 /* Check if we have an initial owner */
29 if (InitialOwner)
30 {
31 /* We also need to associate a thread */
32 CurrentThread = KeGetCurrentThread();
33 Mutant->OwnerThread = CurrentThread;
34
35 /* We're about to touch the Thread, so lock the Dispatcher */
37
38 /* And insert it into its list */
39 InsertTailList(&CurrentThread->MutantListHead,
40 &Mutant->MutantListEntry);
41
42 /* Release Dispatcher Lock */
44 }
45 else
46 {
47 /* In this case, we don't have an owner yet */
48 Mutant->OwnerThread = NULL;
49 }
50
51 /* Now we set up the Dispatcher Header */
52 Mutant->Header.Type = MutantObject;
53 Mutant->Header.Size = sizeof(KMUTANT) / sizeof(ULONG);
54 Mutant->Header.SignalState = InitialOwner ? 0 : 1;
55 InitializeListHead(&(Mutant->Header.WaitListHead));
56
57 /* Initialize the default data */
58 Mutant->Abandoned = FALSE;
59 Mutant->ApcDisable = 0;
60}
61
62/*
63 * @implemented
64 */
65VOID
69{
70 /* Set up the Dispatcher Header */
71 Mutex->Header.Type = MutantObject;
72 Mutex->Header.Size = sizeof(KMUTEX) / sizeof(ULONG);
73 Mutex->Header.SignalState = 1;
74 InitializeListHead(&(Mutex->Header.WaitListHead));
75
76 /* Initialize the default data */
77 Mutex->OwnerThread = NULL;
78 Mutex->Abandoned = FALSE;
79 Mutex->ApcDisable = 1;
80}
81
82/*
83 * @implemented
84 */
85LONG
88{
89 /* Return the Signal State */
90 return Mutant->Header.SignalState;
91}
92
93/*
94 * @implemented
95 */
96LONG
100 IN BOOLEAN Abandon,
102{
105 PKTHREAD CurrentThread = KeGetCurrentThread();
106 BOOLEAN EnableApc = FALSE;
107 ASSERT_MUTANT(Mutant);
109
110 /* Lock the Dispatcher Database */
112
113 /* Save the Previous State */
114 PreviousState = Mutant->Header.SignalState;
115
116 /* Check if it is to be abandonned */
117 if (Abandon == FALSE)
118 {
119 /* Make sure that the Owner Thread is the current Thread */
120 if (Mutant->OwnerThread != CurrentThread)
121 {
122 /* Release the lock */
124
125 /* Raise an exception */
126 ExRaiseStatus(Mutant->Abandoned ? STATUS_ABANDONED :
128 }
129
130 /* If the thread owns it, then increase the signal state */
131 Mutant->Header.SignalState++;
132 }
133 else
134 {
135 /* It's going to be abandonned */
136 Mutant->Header.SignalState = 1;
137 Mutant->Abandoned = TRUE;
138 }
139
140 /* Check if the signal state is only single */
141 if (Mutant->Header.SignalState == 1)
142 {
143 /* Check if it's below 0 now */
144 if (PreviousState <= 0)
145 {
146 /* Remove the mutant from the list */
147 RemoveEntryList(&Mutant->MutantListEntry);
148
149 /* Save if we need to re-enable APCs */
150 EnableApc = Mutant->ApcDisable;
151 }
152
153 /* Remove the Owning Thread and wake it */
154 Mutant->OwnerThread = NULL;
155
156 /* Check if the Wait List isn't empty */
157 if (!IsListEmpty(&Mutant->Header.WaitListHead))
158 {
159 /* Wake the Mutant */
160 KiWaitTest(&Mutant->Header, Increment);
161 }
162 }
163
164 /* Check if the caller wants to wait after this release */
165 if (Wait == FALSE)
166 {
167 /* Release the Lock */
169 }
170 else
171 {
172 /* Set a wait */
173 CurrentThread->WaitNext = TRUE;
174 CurrentThread->WaitIrql = OldIrql;
175 }
176
177 /* Check if we need to re-enable APCs */
178 if (EnableApc) KeLeaveCriticalRegion();
179
180 /* Return the previous state */
181 return PreviousState;
182}
183
184/*
185 * @implemented
186 */
187LONG
188NTAPI
191{
193
194 /* There's no difference at this level between the two */
196}
197
198/* EOF */
unsigned char BOOLEAN
Definition: Mutex.h:16
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LONG KPRIORITY
Definition: compat.h:803
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG Increment
Definition: CrNtStubs.h:46
#define KeGetCurrentThread
Definition: hal.h:55
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:157
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
FORCEINLINE KIRQL KiAcquireDispatcherLock(VOID)
Definition: ke_x.h:149
#define MUTANT_INCREMENT
Definition: extypes.h:84
@ MutantObject
Definition: ketypes.h:408
VOID FASTCALL KiWaitTest(PVOID Object, KPRIORITY Increment)
#define ExRaiseStatus
Definition: ntoskrnl.h:114
LONG NTAPI KeReleaseMutant(IN PKMUTANT Mutant, IN KPRIORITY Increment, IN BOOLEAN Abandon, IN BOOLEAN Wait)
Definition: mutex.c:98
VOID NTAPI KeInitializeMutant(IN PKMUTANT Mutant, IN BOOLEAN InitialOwner)
Definition: mutex.c:22
LONG NTAPI KeReadStateMutant(IN PKMUTANT Mutant)
Definition: mutex.c:87
VOID NTAPI KeInitializeMutex(IN PKMUTEX Mutex, IN ULONG Level)
Definition: mutex.c:67
LONG NTAPI KeReleaseMutex(IN PKMUTEX Mutex, IN BOOLEAN Wait)
Definition: mutex.c:189
#define STATUS_MUTANT_NOT_OWNED
Definition: ntstatus.h:306
#define STATUS_ABANDONED
Definition: ntstatus.h:75
long LONG
Definition: pedump.c:60
#define ASSERT_IRQL_LESS_OR_EQUAL(x)
Definition: debug.h:251
LIST_ENTRY MutantListHead
Definition: ketypes.h:2009
KIRQL WaitIrql
Definition: ketypes.h:1795
ULONG WaitNext
Definition: ketypes.h:1696
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDF_POWER_DEVICE_STATE PreviousState
Definition: wdfdevice.h:829
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:56
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
_In_ BOOLEAN InitialOwner
Definition: kefuncs.h:565
struct _KMUTANT KMUTANT
#define ASSERT_MUTANT(Object)
struct _KMUTANT KMUTEX