ReactOS 0.4.15-dev-7994-gb388cb6
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
10static
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
20C_ASSERT(sizeof(DISPATCHER_HEADER) == 8 + 2 * sizeof(PVOID));
21C_ASSERT(sizeof(KMUTANT) == sizeof(DISPATCHER_HEADER) + 3 * sizeof(PVOID) + sizeof(PVOID));
22C_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
71static
72VOID
73TestMutant(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);
93 CheckMutex(&Mutant, 1L, FALSE, 0);
95
96 /* Acquire and release */
100 FALSE,
101 NULL);
103 CheckMutex(&Mutant, 0L, TRUE, 0);
105
106 State = KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
107 ok_eq_long(State, 0L);
108 CheckMutex(&Mutant, 1L, FALSE, 0);
110
111 /* Acquire recursively */
112 for (i = 0; i < 8; i++)
113 {
116 Executive,
118 FALSE,
119 NULL);
122 CheckMutex(&Mutant, -i, FALSE, 0);
124 }
125
126 for (i = 0; i < 7; i++)
127 {
129 State = KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
131 ok_eq_long(State, -7L + i);
132 CheckMutex(&Mutant, -6L + i, FALSE, 0);
134 }
135
136 State = KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
137 ok_eq_long(State, 0L);
138 CheckMutex(&Mutant, 1L, FALSE, 0);
140
141 /* Pretend to acquire it recursively -MINLONG times */
144 Executive,
146 FALSE,
147 NULL);
150 CheckMutex(&Mutant, 0L, FALSE, 0);
152
153 Mutant.Header.SignalState = MINLONG + 1;
156 Executive,
158 FALSE,
159 NULL);
162 CheckMutex(&Mutant, (LONG)MINLONG, FALSE, 0);
164
166 KeWaitForSingleObject(&Mutant,
167 Executive,
169 FALSE,
170 NULL);
172 CheckMutex(&Mutant, (LONG)MINLONG, FALSE, 0);
174
175 State = KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
177 CheckMutex(&Mutant, (LONG)MINLONG + 1L, FALSE, 0);
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);
185
186 State = KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
187 ok_eq_long(State, 0L);
188 CheckMutex(&Mutant, 1L, FALSE, 0);
190
191 /* Now release it once too often */
193 KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
195 CheckMutex(&Mutant, 1L, FALSE, 0);
197}
198
199static
200VOID
202{
205 LONG State;
206 LONG i;
208
210 RtlFillMemory(&Mutex, sizeof(Mutex), 0x55);
212 CheckMutex(&Mutex, 1L, TRUE, 1);
214
215 RtlFillMemory(&Mutex, sizeof(Mutex), 0x55);
217 CheckMutex(&Mutex, 1L, TRUE, 1);
219
220 /* Acquire and release */
222 Executive,
224 FALSE,
225 NULL);
227 CheckMutex(&Mutex, 0L, FALSE, 1);
229
231 ok_eq_long(State, 0L);
232 CheckMutex(&Mutex, 1L, FALSE, 1);
234
235 /* Acquire recursively */
236 for (i = 0; i < 8; i++)
237 {
240 Executive,
242 FALSE,
243 NULL);
246 CheckMutex(&Mutex, -i, FALSE, 1);
248 }
249
250 for (i = 0; i < 7; i++)
251 {
255 ok_eq_long(State, -7L + i);
256 CheckMutex(&Mutex, -6L + i, FALSE, 1);
258 }
259
261 ok_eq_long(State, 0L);
262 CheckMutex(&Mutex, 1L, FALSE, 1);
264
265 /* Pretend to acquire it recursively -MINLONG times */
268 Executive,
270 FALSE,
271 NULL);
274 CheckMutex(&Mutex, 0L, FALSE, 1);
276
277 Mutex.Header.SignalState = MINLONG + 1;
280 Executive,
282 FALSE,
283 NULL);
288
291 Executive,
293 FALSE,
294 NULL);
298
301 CheckMutex(&Mutex, (LONG)MINLONG + 1L, FALSE, 1);
303
304 Mutex.Header.SignalState = -1;
306 ok_eq_long(State, -1L);
307 CheckMutex(&Mutex, 0L, FALSE, 1);
309
311 ok_eq_long(State, 0L);
312 CheckMutex(&Mutex, 1L, FALSE, 1);
314
315 /* Now release it once too often */
319 CheckMutex(&Mutex, 1L, FALSE, 1);
321}
322
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}
#define CheckMutex(Mutex, State, New, ExpectedApcDisable)
static VOID TestMutex(VOID)
Definition: KeMutex.c:201
#define MUTANT_SIZE
#define CheckApcs(KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, Irql)
#define VOID
Definition: acefi.h:82
#define ok_eq_hex(value, expected)
Definition: apitest.h:77
#define ok_eq_long(value, expected)
Definition: apitest.h:62
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
Definition: Header.h:9
Definition: Mutex.h:16
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define _IRQL_requires_min_(irql)
Definition: driverspecs.h:231
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
Status
Definition: gdiplustypes.h:25
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
#define KeGetCurrentThread
Definition: hal.h:55
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:599
#define C_ASSERT(e)
Definition: intsafe.h:73
#define KmtStartSeh()
Definition: kmt_test.h:282
#define KmtEndSeh(ExpectedStatus)
Definition: kmt_test.h:288
PVOID KmtGetSystemRoutineAddress(IN PCWSTR RoutineName)
#define for
Definition: utility.h:88
#define KernelMode
Definition: asm.h:34
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
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_LIMIT_EXCEEDED
Definition: ntstatus.h:634
#define STATUS_MUTANT_NOT_OWNED
Definition: ntstatus.h:306
#define L(x)
Definition: ntvdm.h:50
#define BOOLEAN
Definition: pedump.c:73
long LONG
Definition: pedump.c:60
#define STATUS_SUCCESS
Definition: shellext.h:65
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG
Definition: typedefs.h:59
#define MINLONG
Definition: umtypes.h:115
@ Executive
Definition: ketypes.h:415