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 } 465