ReactOS  0.4.14-dev-614-gbfd8a84
KeMutex.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS kernel-mode tests
3  * LICENSE: GPLv2+ - See COPYING in the top level directory
4  * PURPOSE: Kernel-Mode Test Suite Mutant/Mutex test
5  * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include <kmt_test.h>
9 
10 static
13 BOOLEAN
14 (NTAPI
15 *pKeAreAllApcsDisabled)(VOID);
16 
17 #define ULONGS_PER_POINTER (sizeof(PVOID) / sizeof(ULONG))
18 #define MUTANT_SIZE (2 + 6 * ULONGS_PER_POINTER)
19 
20 C_ASSERT(sizeof(DISPATCHER_HEADER) == 8 + 2 * sizeof(PVOID));
21 C_ASSERT(sizeof(KMUTANT) == sizeof(DISPATCHER_HEADER) + 3 * sizeof(PVOID) + sizeof(PVOID));
22 C_ASSERT(sizeof(KMUTANT) == MUTANT_SIZE * sizeof(ULONG));
23 
24 #define CheckMutex(Mutex, State, New, ExpectedApcDisable) do { \
25  PKTHREAD Thread = KeGetCurrentThread(); \
26  ok_eq_uint((Mutex)->Header.Type, MutantObject); \
27  ok_eq_uint((Mutex)->Header.Abandoned, 0x55); \
28  ok_eq_uint((Mutex)->Header.Size, MUTANT_SIZE); \
29  ok_eq_uint((Mutex)->Header.DpcActive, 0x55); \
30  ok_eq_pointer((Mutex)->Header.WaitListHead.Flink, \
31  &(Mutex)->Header.WaitListHead); \
32  ok_eq_pointer((Mutex)->Header.WaitListHead.Blink, \
33  &(Mutex)->Header.WaitListHead); \
34  if ((State) <= 0) \
35  { \
36  ok_eq_long((Mutex)->Header.SignalState, State); \
37  ok_eq_pointer((Mutex)->MutantListEntry.Flink, &Thread->MutantListHead); \
38  ok_eq_pointer((Mutex)->MutantListEntry.Blink, &Thread->MutantListHead); \
39  ok_eq_pointer(Thread->MutantListHead.Flink, &(Mutex)->MutantListEntry); \
40  ok_eq_pointer(Thread->MutantListHead.Blink, &(Mutex)->MutantListEntry); \
41  ok_eq_pointer((Mutex)->OwnerThread, Thread); \
42  } \
43  else \
44  { \
45  ok_eq_long((Mutex)->Header.SignalState, State); \
46  if (New) \
47  { \
48  ok_eq_pointer((Mutex)->MutantListEntry.Flink, \
49  (PVOID)0x5555555555555555ULL); \
50  ok_eq_pointer((Mutex)->MutantListEntry.Blink, \
51  (PVOID)0x5555555555555555ULL); \
52  } \
53  ok_eq_pointer(Thread->MutantListHead.Flink, &Thread->MutantListHead); \
54  ok_eq_pointer(Thread->MutantListHead.Blink, &Thread->MutantListHead); \
55  ok_eq_pointer((Mutex)->OwnerThread, NULL); \
56  } \
57  ok_eq_uint((Mutex)->Abandoned, 0); \
58  ok_eq_uint((Mutex)->ApcDisable, ExpectedApcDisable); \
59 } while (0)
60 
61 #define CheckApcs(KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, Irql) do \
62 { \
63  ok_eq_bool(KeAreApcsDisabled(), KernelApcsDisabled || SpecialApcsDisabled); \
64  ok_eq_int(Thread->KernelApcDisable, KernelApcsDisabled); \
65  if (pKeAreAllApcsDisabled) \
66  ok_eq_bool(pKeAreAllApcsDisabled(), AllApcsDisabled); \
67  ok_eq_int(Thread->SpecialApcDisable, SpecialApcsDisabled); \
68  ok_irql(Irql); \
69 } while (0)
70 
71 static
72 VOID
73 TestMutant(VOID)
74 {
76  KMUTANT Mutant;
77  LONG State;
78  LONG i;
80 
82  RtlFillMemory(&Mutant, sizeof(Mutant), 0x55);
83  KeInitializeMutant(&Mutant, FALSE);
84  CheckMutex(&Mutant, 1L, TRUE, 0);
86 
87  RtlFillMemory(&Mutant, sizeof(Mutant), 0x55);
88  KeInitializeMutant(&Mutant, TRUE);
90  CheckMutex(&Mutant, 0L, TRUE, 0);
91  State = KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
92  ok_eq_long(State, 0L);
93  CheckMutex(&Mutant, 1L, FALSE, 0);
95 
96  /* Acquire and release */
97  Status = KeWaitForSingleObject(&Mutant,
98  Executive,
99  KernelMode,
100  FALSE,
101  NULL);
103  CheckMutex(&Mutant, 0L, TRUE, 0);
104  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
105 
106  State = KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
107  ok_eq_long(State, 0L);
108  CheckMutex(&Mutant, 1L, FALSE, 0);
109  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
110 
111  /* Acquire recursively */
112  for (i = 0; i < 8; i++)
113  {
114  KmtStartSeh()
115  Status = KeWaitForSingleObject(&Mutant,
116  Executive,
117  KernelMode,
118  FALSE,
119  NULL);
122  CheckMutex(&Mutant, -i, FALSE, 0);
123  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
124  }
125 
126  for (i = 0; i < 7; i++)
127  {
128  KmtStartSeh()
129  State = KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
131  ok_eq_long(State, -7L + i);
132  CheckMutex(&Mutant, -6L + i, FALSE, 0);
133  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
134  }
135 
136  State = KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
137  ok_eq_long(State, 0L);
138  CheckMutex(&Mutant, 1L, FALSE, 0);
139  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
140 
141  /* Pretend to acquire it recursively -MINLONG times */
142  KmtStartSeh()
143  Status = KeWaitForSingleObject(&Mutant,
144  Executive,
145  KernelMode,
146  FALSE,
147  NULL);
150  CheckMutex(&Mutant, 0L, FALSE, 0);
151  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
152 
153  Mutant.Header.SignalState = MINLONG + 1;
154  KmtStartSeh()
155  Status = KeWaitForSingleObject(&Mutant,
156  Executive,
157  KernelMode,
158  FALSE,
159  NULL);
162  CheckMutex(&Mutant, (LONG)MINLONG, FALSE, 0);
163  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
164 
165  KmtStartSeh()
166  KeWaitForSingleObject(&Mutant,
167  Executive,
168  KernelMode,
169  FALSE,
170  NULL);
172  CheckMutex(&Mutant, (LONG)MINLONG, FALSE, 0);
173  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
174 
175  State = KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
177  CheckMutex(&Mutant, (LONG)MINLONG + 1L, FALSE, 0);
178  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
179 
180  Mutant.Header.SignalState = -1;
181  State = KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
182  ok_eq_long(State, -1L);
183  CheckMutex(&Mutant, 0L, FALSE, 0);
184  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
185 
186  State = KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
187  ok_eq_long(State, 0L);
188  CheckMutex(&Mutant, 1L, FALSE, 0);
189  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
190 
191  /* Now release it once too often */
192  KmtStartSeh()
193  KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
195  CheckMutex(&Mutant, 1L, FALSE, 0);
196  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
197 }
198 
199 static
200 VOID
202 {
204  KMUTEX Mutex;
205  LONG State;
206  LONG i;
208 
209  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
210  RtlFillMemory(&Mutex, sizeof(Mutex), 0x55);
212  CheckMutex(&Mutex, 1L, TRUE, 1);
213  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
214 
215  RtlFillMemory(&Mutex, sizeof(Mutex), 0x55);
216  KeInitializeMutex(&Mutex, 123);
217  CheckMutex(&Mutex, 1L, TRUE, 1);
218  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
219 
220  /* Acquire and release */
222  Executive,
223  KernelMode,
224  FALSE,
225  NULL);
227  CheckMutex(&Mutex, 0L, FALSE, 1);
228  CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
229 
231  ok_eq_long(State, 0L);
232  CheckMutex(&Mutex, 1L, FALSE, 1);
233  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
234 
235  /* Acquire recursively */
236  for (i = 0; i < 8; i++)
237  {
238  KmtStartSeh()
240  Executive,
241  KernelMode,
242  FALSE,
243  NULL);
246  CheckMutex(&Mutex, -i, FALSE, 1);
247  CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
248  }
249 
250  for (i = 0; i < 7; i++)
251  {
252  KmtStartSeh()
255  ok_eq_long(State, -7L + i);
256  CheckMutex(&Mutex, -6L + i, FALSE, 1);
257  CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
258  }
259 
261  ok_eq_long(State, 0L);
262  CheckMutex(&Mutex, 1L, FALSE, 1);
263  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
264 
265  /* Pretend to acquire it recursively -MINLONG times */
266  KmtStartSeh()
268  Executive,
269  KernelMode,
270  FALSE,
271  NULL);
274  CheckMutex(&Mutex, 0L, FALSE, 1);
275  CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
276 
277  Mutex.Header.SignalState = MINLONG + 1;
278  KmtStartSeh()
280  Executive,
281  KernelMode,
282  FALSE,
283  NULL);
287  CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
288 
289  KmtStartSeh()
291  Executive,
292  KernelMode,
293  FALSE,
294  NULL);
297  CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
298 
301  CheckMutex(&Mutex, (LONG)MINLONG + 1L, FALSE, 1);
302  CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
303 
304  Mutex.Header.SignalState = -1;
306  ok_eq_long(State, -1L);
307  CheckMutex(&Mutex, 0L, FALSE, 1);
308  CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
309 
311  ok_eq_long(State, 0L);
312  CheckMutex(&Mutex, 1L, FALSE, 1);
313  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
314 
315  /* Now release it once too often */
316  KmtStartSeh()
319  CheckMutex(&Mutex, 1L, FALSE, 1);
320  CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
321 }
322 
323 START_TEST(KeMutex)
324 {
325  pKeAreAllApcsDisabled = KmtGetSystemRoutineAddress(L"KeAreAllApcsDisabled");
326  if (skip(pKeAreAllApcsDisabled != NULL, "KeAreAllApcsDisabled unavailable\n"))
327  {
328  /* We can live without this function here */
329  }
330 
331  TestMutant();
332  TestMutex();
333 }
static _IRQL_requires_min_(PASSIVE_LEVEL)
Definition: KeMutex.c:11
#define CheckMutex(Mutex, State, New, ExpectedApcDisable)
#define TRUE
Definition: types.h:120
#define _IRQL_requires_max_(irql)
Definition: no_sal2.h:650
VOID NTAPI KeInitializeMutant(IN PKMUTANT Mutant, IN BOOLEAN InitialOwner)
Definition: mutex.c:22
LONG NTSTATUS
Definition: precomp.h:26
#define KmtEndSeh(ExpectedStatus)
Definition: kmt_test.h:283
#define CheckApcs(KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, Irql)
LONG NTAPI KeReleaseMutex(IN PKMUTEX Mutex, IN BOOLEAN Wait)
Definition: mutex.c:189
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define STATUS_MUTANT_NOT_OWNED
Definition: ntstatus.h:292
Definition: Mutex.h:15
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
Definition: Header.h:8
long LONG
Definition: pedump.c:60
START_TEST(KeMutex)
Definition: KeMutex.c:323
smooth NULL
Definition: ftsmooth.c:416
#define C_ASSERT(e)
Definition: intsafe.h:79
#define for
Definition: utility.h:88
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
PVOID KmtGetSystemRoutineAddress(IN PCWSTR RoutineName)
LONG NTAPI KeReleaseMutant(IN PKMUTANT Mutant, IN KPRIORITY Increment, IN BOOLEAN Abandon, IN BOOLEAN Wait)
Definition: mutex.c:98
VOID NTAPI KeInitializeMutex(IN PKMUTEX Mutex, IN ULONG Level)
Definition: mutex.c:67
static const WCHAR L[]
Definition: oid.c:1250
#define MINLONG
Definition: umtypes.h:115
#define VOID
Definition: acefi.h:82
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define KmtStartSeh()
Definition: kmt_test.h:277
Status
Definition: gdiplustypes.h:24
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
enum State_ State
Definition: pofuncs.h:54
static PFAST_MUTEX Mutex
Definition: timer.c:22
#define skip(...)
Definition: atltest.h:64
#define BOOLEAN
Definition: pedump.c:73
unsigned int ULONG
Definition: retypes.h:1
#define ok_eq_hex(value, expected)
static VOID TestMutex(VOID)
Definition: KeMutex.c:201
#define KeGetCurrentThread
Definition: hal.h:44
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define MUTANT_SIZE
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
#define ok_eq_long(value, expected)
Definition: kmt_test.h:240
#define STATUS_MUTANT_LIMIT_EXCEEDED
Definition: ntstatus.h:620