[KMTESTS]
[reactos.git] / rostests / kmtests / ntos_ke / KeGuardedMutex.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Guarded Mutex test
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include <kmt_test.h>
9
10 #define NDEBUG
11 #include <debug.h>
12
13 static
14 _IRQL_requires_min_(PASSIVE_LEVEL)
15 _IRQL_requires_max_(DISPATCH_LEVEL)
16 BOOLEAN
17 (NTAPI
18 *pKeAreAllApcsDisabled)(VOID);
19
20 static
21 _Acquires_lock_(_Global_critical_region_)
22 _Requires_lock_not_held_(*Mutex)
23 _Acquires_lock_(*Mutex)
24 _IRQL_requires_max_(APC_LEVEL)
25 _IRQL_requires_min_(PASSIVE_LEVEL)
26 VOID
27 (FASTCALL
28 *pKeAcquireGuardedMutex)(
29 _Inout_ PKGUARDED_MUTEX GuardedMutex);
30
31 static
32 _Requires_lock_not_held_(*FastMutex)
33 _Acquires_lock_(*FastMutex)
34 _IRQL_requires_max_(APC_LEVEL)
35 _IRQL_requires_min_(PASSIVE_LEVEL)
36 VOID
37 (FASTCALL
38 *pKeAcquireGuardedMutexUnsafe)(
39 _Inout_ PKGUARDED_MUTEX GuardedMutex);
40
41 static
42 _Acquires_lock_(_Global_critical_region_)
43 _IRQL_requires_max_(APC_LEVEL)
44 VOID
45 (NTAPI
46 *pKeEnterGuardedRegion)(VOID);
47
48 static
49 _Releases_lock_(_Global_critical_region_)
50 _IRQL_requires_max_(APC_LEVEL)
51 VOID
52 (NTAPI
53 *pKeLeaveGuardedRegion)(VOID);
54
55 static
56 _IRQL_requires_max_(APC_LEVEL)
57 _IRQL_requires_min_(PASSIVE_LEVEL)
58 VOID
59 (FASTCALL
60 *pKeInitializeGuardedMutex)(
61 _Out_ PKGUARDED_MUTEX GuardedMutex);
62
63 static
64 _Requires_lock_held_(*FastMutex)
65 _Releases_lock_(*FastMutex)
66 _IRQL_requires_max_(APC_LEVEL)
67 VOID
68 (FASTCALL
69 *pKeReleaseGuardedMutexUnsafe)(
70 _Inout_ PKGUARDED_MUTEX GuardedMutex);
71
72 static
73 _Releases_lock_(_Global_critical_region_)
74 _Requires_lock_held_(*Mutex)
75 _Releases_lock_(*Mutex)
76 _IRQL_requires_max_(APC_LEVEL)
77 VOID
78 (FASTCALL
79 *pKeReleaseGuardedMutex)(
80 _Inout_ PKGUARDED_MUTEX GuardedMutex);
81
82 static
83 _Must_inspect_result_
84 _Success_(return != FALSE)
85 _IRQL_requires_max_(APC_LEVEL)
86 _Post_satisfies_(return == 1 || return == 0)
87 BOOLEAN
88 (FASTCALL
89 *pKeTryToAcquireGuardedMutex)(
90 _When_ (return, _Requires_lock_not_held_(*_Curr_) _Acquires_exclusive_lock_(*_Curr_)) _Acquires_lock_(_Global_critical_region_)
91 _Inout_ PKGUARDED_MUTEX GuardedMutex);
92
93 #define CheckMutex(Mutex, ExpectedCount, ExpectedOwner, ExpectedContention, \
94 ExpectedKernelApcDisable, ExpectedSpecialApcDisable, \
95 KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, \
96 ExpectedIrql) do \
97 { \
98 ok_eq_long((Mutex)->Count, ExpectedCount); \
99 ok_eq_pointer((Mutex)->Owner, ExpectedOwner); \
100 ok_eq_ulong((Mutex)->Contention, ExpectedContention); \
101 ok_eq_int((Mutex)->KernelApcDisable, ExpectedKernelApcDisable); \
102 if (KmtIsCheckedBuild) \
103 ok_eq_int((Mutex)->SpecialApcDisable, ExpectedSpecialApcDisable); \
104 else \
105 ok_eq_int((Mutex)->SpecialApcDisable, 0x5555); \
106 ok_eq_bool(KeAreApcsDisabled(), KernelApcsDisabled || SpecialApcsDisabled); \
107 ok_eq_int(Thread->KernelApcDisable, KernelApcsDisabled); \
108 ok_eq_bool(pKeAreAllApcsDisabled(), AllApcsDisabled); \
109 ok_eq_int(Thread->SpecialApcDisable, SpecialApcsDisabled); \
110 ok_irql(ExpectedIrql); \
111 } while (0)
112
113 static
114 VOID
115 TestGuardedMutex(
116 PKGUARDED_MUTEX Mutex,
117 SHORT KernelApcsDisabled,
118 SHORT SpecialApcsDisabled,
119 SHORT AllApcsDisabled,
120 KIRQL OriginalIrql)
121 {
122 PKTHREAD Thread = KeGetCurrentThread();
123
124 ok_irql(OriginalIrql);
125 CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, 0x5555, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql);
126
127 /* these ASSERT */
128 if (!KmtIsCheckedBuild || OriginalIrql <= APC_LEVEL)
129 {
130 /* acquire/release normally */
131 pKeAcquireGuardedMutex(Mutex);
132 CheckMutex(Mutex, 0L, Thread, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled - 1, TRUE, OriginalIrql);
133 ok_bool_false(pKeTryToAcquireGuardedMutex(Mutex), "KeTryToAcquireGuardedMutex returned");
134 CheckMutex(Mutex, 0L, Thread, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled - 1, TRUE, OriginalIrql);
135 pKeReleaseGuardedMutex(Mutex);
136 CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql);
137
138 /* try to acquire */
139 ok_bool_true(pKeTryToAcquireGuardedMutex(Mutex), "KeTryToAcquireGuardedMutex returned");
140 CheckMutex(Mutex, 0L, Thread, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled - 1, TRUE, OriginalIrql);
141 pKeReleaseGuardedMutex(Mutex);
142 CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql);
143 }
144 else
145 /* Make the following test happy */
146 Mutex->SpecialApcDisable = SpecialApcsDisabled - 1;
147
148 /* ASSERT */
149 if (!KmtIsCheckedBuild || OriginalIrql == APC_LEVEL || SpecialApcsDisabled < 0)
150 {
151 /* acquire/release unsafe */
152 pKeAcquireGuardedMutexUnsafe(Mutex);
153 CheckMutex(Mutex, 0L, Thread, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql);
154 pKeReleaseGuardedMutexUnsafe(Mutex);
155 CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql);
156 }
157
158 /* Bugchecks >= DISPATCH_LEVEL */
159 if (!KmtIsCheckedBuild)
160 {
161 /* mismatched acquire/release */
162 pKeAcquireGuardedMutex(Mutex);
163 CheckMutex(Mutex, 0L, Thread, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled - 1, TRUE, OriginalIrql);
164 pKeReleaseGuardedMutexUnsafe(Mutex);
165 CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled - 1, TRUE, OriginalIrql);
166 pKeLeaveGuardedRegion();
167 CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql);
168
169 pKeAcquireGuardedMutexUnsafe(Mutex);
170 CheckMutex(Mutex, 0L, Thread, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql);
171 pKeReleaseGuardedMutex(Mutex);
172 CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled + 1, OriginalIrql >= APC_LEVEL || SpecialApcsDisabled != -1, OriginalIrql);
173 pKeEnterGuardedRegion();
174 CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql);
175
176 /* release without acquire */
177 pKeReleaseGuardedMutexUnsafe(Mutex);
178 CheckMutex(Mutex, 0L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql);
179 pKeReleaseGuardedMutex(Mutex);
180 CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled, KernelApcsDisabled, SpecialApcsDisabled + 1, OriginalIrql >= APC_LEVEL || SpecialApcsDisabled != -1, OriginalIrql);
181 pKeReleaseGuardedMutex(Mutex);
182 /* TODO: here we see that Mutex->Count isn't actually just a count. Test the bits correctly! */
183 CheckMutex(Mutex, 0L, NULL, 0LU, 0x5555, SpecialApcsDisabled, KernelApcsDisabled, SpecialApcsDisabled + 2, OriginalIrql >= APC_LEVEL || SpecialApcsDisabled != -2, OriginalIrql);
184 pKeReleaseGuardedMutex(Mutex);
185 CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled, KernelApcsDisabled, SpecialApcsDisabled + 3, OriginalIrql >= APC_LEVEL || SpecialApcsDisabled != -3, OriginalIrql);
186 Thread->SpecialApcDisable -= 3;
187 }
188
189 /* make sure we survive this in case of error */
190 ok_eq_long(Mutex->Count, 1L);
191 Mutex->Count = 1;
192 ok_eq_int(Thread->KernelApcDisable, KernelApcsDisabled);
193 Thread->KernelApcDisable = KernelApcsDisabled;
194 ok_eq_int(Thread->SpecialApcDisable, SpecialApcsDisabled);
195 Thread->SpecialApcDisable = SpecialApcsDisabled;
196 ok_irql(OriginalIrql);
197 }
198
199 typedef VOID (FASTCALL *PMUTEX_FUNCTION)(PKGUARDED_MUTEX);
200 typedef BOOLEAN (FASTCALL *PMUTEX_TRY_FUNCTION)(PKGUARDED_MUTEX);
201
202 typedef struct
203 {
204 HANDLE Handle;
205 PKTHREAD Thread;
206 KIRQL Irql;
207 PKGUARDED_MUTEX Mutex;
208 PMUTEX_FUNCTION Acquire;
209 PMUTEX_TRY_FUNCTION TryAcquire;
210 PMUTEX_FUNCTION Release;
211 BOOLEAN Try;
212 BOOLEAN RetExpected;
213 KEVENT InEvent;
214 KEVENT OutEvent;
215 } THREAD_DATA, *PTHREAD_DATA;
216
217 static
218 VOID
219 NTAPI
220 AcquireMutexThread(
221 PVOID Parameter)
222 {
223 PTHREAD_DATA ThreadData = Parameter;
224 KIRQL Irql;
225 BOOLEAN Ret = FALSE;
226 NTSTATUS Status;
227
228 DPRINT("Thread starting\n");
229 KeRaiseIrql(ThreadData->Irql, &Irql);
230
231 if (ThreadData->Try)
232 {
233 Ret = ThreadData->TryAcquire(ThreadData->Mutex);
234 ok_eq_bool(Ret, ThreadData->RetExpected);
235 }
236 else
237 ThreadData->Acquire(ThreadData->Mutex);
238
239 ok_bool_false(KeSetEvent(&ThreadData->OutEvent, 0, TRUE), "KeSetEvent returned");
240 DPRINT("Thread now waiting\n");
241 Status = KeWaitForSingleObject(&ThreadData->InEvent, Executive, KernelMode, FALSE, NULL);
242 DPRINT("Thread done waiting\n");
243 ok_eq_hex(Status, STATUS_SUCCESS);
244
245 if (!ThreadData->Try || Ret)
246 ThreadData->Release(ThreadData->Mutex);
247
248 KeLowerIrql(Irql);
249 DPRINT("Thread exiting\n");
250 }
251
252 static
253 VOID
254 InitThreadData(
255 PTHREAD_DATA ThreadData,
256 PKGUARDED_MUTEX Mutex,
257 PMUTEX_FUNCTION Acquire,
258 PMUTEX_TRY_FUNCTION TryAcquire,
259 PMUTEX_FUNCTION Release)
260 {
261 ThreadData->Mutex = Mutex;
262 KeInitializeEvent(&ThreadData->InEvent, NotificationEvent, FALSE);
263 KeInitializeEvent(&ThreadData->OutEvent, NotificationEvent, FALSE);
264 ThreadData->Acquire = Acquire;
265 ThreadData->TryAcquire = TryAcquire;
266 ThreadData->Release = Release;
267 }
268
269 static
270 NTSTATUS
271 StartThread(
272 PTHREAD_DATA ThreadData,
273 PLARGE_INTEGER Timeout,
274 KIRQL Irql,
275 BOOLEAN Try,
276 BOOLEAN RetExpected)
277 {
278 NTSTATUS Status = STATUS_SUCCESS;
279 OBJECT_ATTRIBUTES Attributes;
280
281 ThreadData->Try = Try;
282 ThreadData->Irql = Irql;
283 ThreadData->RetExpected = RetExpected;
284 InitializeObjectAttributes(&Attributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
285 Status = PsCreateSystemThread(&ThreadData->Handle, GENERIC_ALL, &Attributes, NULL, NULL, AcquireMutexThread, ThreadData);
286 ok_eq_hex(Status, STATUS_SUCCESS);
287 Status = ObReferenceObjectByHandle(ThreadData->Handle, SYNCHRONIZE, *PsThreadType, KernelMode, (PVOID *)&ThreadData->Thread, NULL);
288 ok_eq_hex(Status, STATUS_SUCCESS);
289
290 return KeWaitForSingleObject(&ThreadData->OutEvent, Executive, KernelMode, FALSE, Timeout);
291 }
292
293 static
294 VOID
295 FinishThread(
296 PTHREAD_DATA ThreadData)
297 {
298 NTSTATUS Status = STATUS_SUCCESS;
299
300 KeSetEvent(&ThreadData->InEvent, 0, TRUE);
301 Status = KeWaitForSingleObject(ThreadData->Thread, Executive, KernelMode, FALSE, NULL);
302 ok_eq_hex(Status, STATUS_SUCCESS);
303
304 ObDereferenceObject(ThreadData->Thread);
305 Status = ZwClose(ThreadData->Handle);
306 ok_eq_hex(Status, STATUS_SUCCESS);
307 KeClearEvent(&ThreadData->InEvent);
308 KeClearEvent(&ThreadData->OutEvent);
309 }
310
311 static
312 VOID
313 TestGuardedMutexConcurrent(
314 PKGUARDED_MUTEX Mutex)
315 {
316 NTSTATUS Status;
317 THREAD_DATA ThreadData;
318 THREAD_DATA ThreadData2;
319 THREAD_DATA ThreadDataUnsafe;
320 THREAD_DATA ThreadDataTry;
321 PKTHREAD Thread = KeGetCurrentThread();
322 LARGE_INTEGER Timeout;
323 Timeout.QuadPart = -50 * 1000 * 10; /* 50 ms */
324
325 InitThreadData(&ThreadData, Mutex, pKeAcquireGuardedMutex, NULL, pKeReleaseGuardedMutex);
326 InitThreadData(&ThreadData2, Mutex, pKeAcquireGuardedMutex, NULL, pKeReleaseGuardedMutex);
327 InitThreadData(&ThreadDataUnsafe, Mutex, pKeAcquireGuardedMutexUnsafe, NULL, pKeReleaseGuardedMutexUnsafe);
328 InitThreadData(&ThreadDataTry, Mutex, NULL, pKeTryToAcquireGuardedMutex, pKeReleaseGuardedMutex);
329
330 /* have a thread acquire the mutex */
331 Status = StartThread(&ThreadData, NULL, PASSIVE_LEVEL, FALSE, FALSE);
332 ok_eq_hex(Status, STATUS_SUCCESS);
333 CheckMutex(Mutex, 0L, ThreadData.Thread, 0LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
334 /* have a second thread try to acquire it -- should fail */
335 Status = StartThread(&ThreadDataTry, NULL, PASSIVE_LEVEL, TRUE, FALSE);
336 ok_eq_hex(Status, STATUS_SUCCESS);
337 CheckMutex(Mutex, 0L, ThreadData.Thread, 0LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
338 FinishThread(&ThreadDataTry);
339
340 /* have another thread acquire it -- should block */
341 Status = StartThread(&ThreadData2, &Timeout, APC_LEVEL, FALSE, FALSE);
342 ok_eq_hex(Status, STATUS_TIMEOUT);
343 CheckMutex(Mutex, 4L, ThreadData.Thread, 1LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
344
345 /* finish the first thread -- now the second should become available */
346 FinishThread(&ThreadData);
347 Status = KeWaitForSingleObject(&ThreadData2.OutEvent, Executive, KernelMode, FALSE, NULL);
348 ok_eq_hex(Status, STATUS_SUCCESS);
349 CheckMutex(Mutex, 0L, ThreadData2.Thread, 1LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
350
351 /* block two more threads */
352 Status = StartThread(&ThreadDataUnsafe, &Timeout, APC_LEVEL, FALSE, FALSE);
353 ok_eq_hex(Status, STATUS_TIMEOUT);
354 CheckMutex(Mutex, 4L, ThreadData2.Thread, 2LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
355
356 Status = StartThread(&ThreadData, &Timeout, PASSIVE_LEVEL, FALSE, FALSE);
357 ok_eq_hex(Status, STATUS_TIMEOUT);
358 CheckMutex(Mutex, 8L, ThreadData2.Thread, 3LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
359
360 /* finish 1 */
361 FinishThread(&ThreadData2);
362 Status = KeWaitForSingleObject(&ThreadDataUnsafe.OutEvent, Executive, KernelMode, FALSE, NULL);
363 ok_eq_hex(Status, STATUS_SUCCESS);
364 CheckMutex(Mutex, 4L, ThreadDataUnsafe.Thread, 3LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
365
366 /* finish 2 */
367 FinishThread(&ThreadDataUnsafe);
368 Status = KeWaitForSingleObject(&ThreadData.OutEvent, Executive, KernelMode, FALSE, NULL);
369 ok_eq_hex(Status, STATUS_SUCCESS);
370 CheckMutex(Mutex, 0L, ThreadData.Thread, 3LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
371
372 /* finish 3 */
373 FinishThread(&ThreadData);
374
375 CheckMutex(Mutex, 1L, NULL, 3LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
376 }
377
378 START_TEST(KeGuardedMutex)
379 {
380 KGUARDED_MUTEX Mutex;
381 KIRQL OldIrql;
382 PKTHREAD Thread = KeGetCurrentThread();
383 struct {
384 KIRQL Irql;
385 SHORT KernelApcsDisabled;
386 SHORT SpecialApcsDisabled;
387 BOOLEAN AllApcsDisabled;
388 } TestIterations[] =
389 {
390 { PASSIVE_LEVEL, 0, 0, FALSE },
391 { PASSIVE_LEVEL, -1, 0, FALSE },
392 { PASSIVE_LEVEL, -3, 0, FALSE },
393 { PASSIVE_LEVEL, 0, -1, TRUE },
394 { PASSIVE_LEVEL, -1, -1, TRUE },
395 { PASSIVE_LEVEL, -3, -2, TRUE },
396 // 6
397 { APC_LEVEL, 0, 0, TRUE },
398 { APC_LEVEL, -1, 0, TRUE },
399 { APC_LEVEL, -3, 0, TRUE },
400 { APC_LEVEL, 0, -1, TRUE },
401 { APC_LEVEL, -1, -1, TRUE },
402 { APC_LEVEL, -3, -2, TRUE },
403 // 12
404 { DISPATCH_LEVEL, 0, 0, TRUE },
405 { DISPATCH_LEVEL, -1, 0, TRUE },
406 { DISPATCH_LEVEL, -3, 0, TRUE },
407 { DISPATCH_LEVEL, 0, -1, TRUE },
408 { DISPATCH_LEVEL, -1, -1, TRUE },
409 { DISPATCH_LEVEL, -3, -2, TRUE },
410 // 18
411 { HIGH_LEVEL, 0, 0, TRUE },
412 { HIGH_LEVEL, -1, 0, TRUE },
413 { HIGH_LEVEL, -3, 0, TRUE },
414 { HIGH_LEVEL, 0, -1, TRUE },
415 { HIGH_LEVEL, -1, -1, TRUE },
416 { HIGH_LEVEL, -3, -2, TRUE },
417 };
418 int i;
419
420 pKeAreAllApcsDisabled = KmtGetSystemRoutineAddress(L"KeAreAllApcsDisabled");
421 pKeInitializeGuardedMutex = KmtGetSystemRoutineAddress(L"KeInitializeGuardedMutex");
422 pKeAcquireGuardedMutex = KmtGetSystemRoutineAddress(L"KeAcquireGuardedMutex");
423 pKeAcquireGuardedMutexUnsafe = KmtGetSystemRoutineAddress(L"KeAcquireGuardedMutexUnsafe");
424 pKeEnterGuardedRegion = KmtGetSystemRoutineAddress(L"KeEnterGuardedRegion");
425 pKeLeaveGuardedRegion = KmtGetSystemRoutineAddress(L"KeLeaveGuardedRegion");
426 pKeReleaseGuardedMutex = KmtGetSystemRoutineAddress(L"KeReleaseGuardedMutex");
427 pKeReleaseGuardedMutexUnsafe = KmtGetSystemRoutineAddress(L"KeReleaseGuardedMutexUnsafe");
428 pKeTryToAcquireGuardedMutex = KmtGetSystemRoutineAddress(L"KeTryToAcquireGuardedMutex");
429
430 if (skip(pKeAreAllApcsDisabled &&
431 pKeInitializeGuardedMutex &&
432 pKeAcquireGuardedMutex &&
433 pKeAcquireGuardedMutexUnsafe &&
434 pKeEnterGuardedRegion &&
435 pKeLeaveGuardedRegion &&
436 pKeReleaseGuardedMutex &&
437 pKeReleaseGuardedMutexUnsafe &&
438 pKeTryToAcquireGuardedMutex, "No guarded mutexes\n"))
439 {
440 return;
441 }
442
443 for (i = 0; i < sizeof TestIterations / sizeof TestIterations[0]; ++i)
444 {
445 trace("Run %d\n", i);
446 KeRaiseIrql(TestIterations[i].Irql, &OldIrql);
447 Thread->KernelApcDisable = TestIterations[i].KernelApcsDisabled;
448 Thread->SpecialApcDisable = TestIterations[i].SpecialApcsDisabled;
449
450 RtlFillMemory(&Mutex, sizeof Mutex, 0x55);
451 pKeInitializeGuardedMutex(&Mutex);
452 CheckMutex(&Mutex, 1L, NULL, 0LU, 0x5555, 0x5555, TestIterations[i].KernelApcsDisabled, TestIterations[i].SpecialApcsDisabled, TestIterations[i].AllApcsDisabled, TestIterations[i].Irql);
453 TestGuardedMutex(&Mutex, TestIterations[i].KernelApcsDisabled, TestIterations[i].SpecialApcsDisabled, TestIterations[i].AllApcsDisabled, TestIterations[i].Irql);
454
455 Thread->SpecialApcDisable = 0;
456 Thread->KernelApcDisable = 0;
457 KeLowerIrql(OldIrql);
458 }
459
460 trace("Concurrent test\n");
461 RtlFillMemory(&Mutex, sizeof Mutex, 0x55);
462 pKeInitializeGuardedMutex(&Mutex);
463 TestGuardedMutexConcurrent(&Mutex);
464 }