ReactOS 0.4.15-dev-8100-g1887773
KeGuardedMutex.c File Reference
#include <kmt_test.h>
#include <debug.h>
Include dependency graph for KeGuardedMutex.c:

Go to the source code of this file.

Classes

struct  THREAD_DATA
 

Macros

#define NDEBUG
 
#define CheckMutex(Mutex, ExpectedCount, ExpectedOwner, ExpectedContention, ExpectedKernelApcDisable, ExpectedSpecialApcDisable, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, ExpectedIrql)
 

Typedefs

typedef VOID(FASTCALLPMUTEX_FUNCTION) (PKGUARDED_MUTEX)
 
typedef BOOLEAN(FASTCALLPMUTEX_TRY_FUNCTION) (PKGUARDED_MUTEX)
 
typedef struct THREAD_DATAPTHREAD_DATA
 

Functions

static _IRQL_requires_min_ (PASSIVE_LEVEL)
 
static VOID NTAPI AcquireMutexThread (PVOID Parameter)
 
static VOID InitThreadData (PTHREAD_DATA ThreadData, PKGUARDED_MUTEX Mutex, PMUTEX_FUNCTION Acquire, PMUTEX_TRY_FUNCTION TryAcquire, PMUTEX_FUNCTION Release)
 
static NTSTATUS StartThread (PTHREAD_DATA ThreadData, PLARGE_INTEGER Timeout, KIRQL Irql, BOOLEAN Try, BOOLEAN RetExpected)
 
static VOID FinishThread (PTHREAD_DATA ThreadData)
 
static VOID TestGuardedMutexConcurrent (PKGUARDED_MUTEX Mutex)
 
 START_TEST (KeGuardedMutex)
 

Macro Definition Documentation

◆ CheckMutex

#define CheckMutex (   Mutex,
  ExpectedCount,
  ExpectedOwner,
  ExpectedContention,
  ExpectedKernelApcDisable,
  ExpectedSpecialApcDisable,
  KernelApcsDisabled,
  SpecialApcsDisabled,
  AllApcsDisabled,
  ExpectedIrql 
)
Value:
do \
{ \
ok_eq_long((Mutex)->Count, ExpectedCount); \
ok_eq_pointer((Mutex)->Owner, ExpectedOwner); \
ok_eq_ulong((Mutex)->Contention, ExpectedContention); \
ok_eq_int((Mutex)->KernelApcDisable, ExpectedKernelApcDisable); \
ok_eq_int((Mutex)->SpecialApcDisable, ExpectedSpecialApcDisable); \
else \
ok_eq_int((Mutex)->SpecialApcDisable, 0x5555); \
ok_eq_bool(KeAreApcsDisabled(), KernelApcsDisabled || SpecialApcsDisabled); \
ok_eq_int(Thread->KernelApcDisable, KernelApcsDisabled); \
ok_eq_bool(pKeAreAllApcsDisabled(), AllApcsDisabled); \
ok_eq_int(Thread->SpecialApcDisable, SpecialApcsDisabled); \
ok_irql(ExpectedIrql); \
} while (0)
Definition: Mutex.h:16
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
BOOLEAN KmtIsCheckedBuild
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID Owner
Definition: rtlfuncs.h:1597
int Count
Definition: noreturn.cpp:7
BOOLEAN NTAPI KeAreApcsDisabled(VOID)
Definition: apc.c:958

◆ NDEBUG

#define NDEBUG

Definition at line 10 of file KeGuardedMutex.c.

Typedef Documentation

◆ PMUTEX_FUNCTION

typedef VOID(FASTCALL * PMUTEX_FUNCTION) (PKGUARDED_MUTEX)

Definition at line 199 of file KeGuardedMutex.c.

◆ PMUTEX_TRY_FUNCTION

typedef BOOLEAN(FASTCALL * PMUTEX_TRY_FUNCTION) (PKGUARDED_MUTEX)

Definition at line 200 of file KeGuardedMutex.c.

◆ PTHREAD_DATA

Function Documentation

◆ _IRQL_requires_min_()

static _IRQL_requires_min_ ( PASSIVE_LEVEL  )
static

Definition at line 14 of file KeGuardedMutex.c.

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
113static
114VOID
115TestGuardedMutex(
117 SHORT KernelApcsDisabled,
118 SHORT SpecialApcsDisabled,
119 SHORT AllApcsDisabled,
120 KIRQL OriginalIrql)
121{
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 */
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}
#define CheckMutex(Mutex, ExpectedCount, ExpectedOwner, ExpectedContention, ExpectedKernelApcDisable, ExpectedSpecialApcDisable, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, ExpectedIrql)
#define ok_eq_long(value, expected)
Definition: apitest.h:62
#define ok_bool_false(value, desc)
Definition: apitest.h:79
#define ok_bool_true(value, desc)
Definition: apitest.h:78
#define ok_eq_int(value, expected)
Definition: apitest.h:60
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeGetCurrentThread
Definition: hal.h:55
#define L(x)
Definition: ntvdm.h:50
short SHORT
Definition: pedump.c:59

◆ AcquireMutexThread()

static VOID NTAPI AcquireMutexThread ( PVOID  Parameter)
static

Definition at line 220 of file KeGuardedMutex.c.

222{
224 KIRQL Irql;
225 BOOLEAN Ret = FALSE;
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");
242 DPRINT("Thread done waiting\n");
244
245 if (!ThreadData->Try || Ret)
246 ThreadData->Release(ThreadData->Mutex);
247
249 DPRINT("Thread exiting\n");
250}
unsigned char BOOLEAN
#define ok_eq_hex(value, expected)
Definition: apitest.h:77
#define ok_eq_bool(value, expected)
Definition: apitest.h:80
LONG NTSTATUS
Definition: precomp.h:26
_Out_ PKIRQL Irql
Definition: csq.h:179
#define FALSE
Definition: types.h:117
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
Status
Definition: gdiplustypes.h:25
#define KernelMode
Definition: asm.h:34
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
@ Executive
Definition: ketypes.h:415
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:323

Referenced by StartThread().

◆ FinishThread()

static VOID FinishThread ( PTHREAD_DATA  ThreadData)
static

Definition at line 295 of file KeGuardedMutex.c.

297{
299
300 KeSetEvent(&ThreadData->InEvent, 0, TRUE);
303
307 KeClearEvent(&ThreadData->InEvent);
308 KeClearEvent(&ThreadData->OutEvent);
309}
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
HANDLE Handle
Definition: drwtsn32.h:25
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by TestGuardedMutexConcurrent().

◆ InitThreadData()

static VOID InitThreadData ( PTHREAD_DATA  ThreadData,
PKGUARDED_MUTEX  Mutex,
PMUTEX_FUNCTION  Acquire,
PMUTEX_TRY_FUNCTION  TryAcquire,
PMUTEX_FUNCTION  Release 
)
static

Definition at line 254 of file KeGuardedMutex.c.

260{
261 ThreadData->Mutex = Mutex;
264 ThreadData->Acquire = Acquire;
265 ThreadData->TryAcquire = TryAcquire;
266 ThreadData->Release = Release;
267}
_In_ BOOLEAN Release
Definition: cdrom.h:920
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
@ NotificationEvent

Referenced by TestGuardedMutexConcurrent().

◆ START_TEST()

START_TEST ( KeGuardedMutex  )

Definition at line 378 of file KeGuardedMutex.c.

379{
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;
458 }
459
460 trace("Concurrent test\n");
461 RtlFillMemory(&Mutex, sizeof Mutex, 0x55);
462 pKeInitializeGuardedMutex(&Mutex);
464}
static VOID TestGuardedMutexConcurrent(PKGUARDED_MUTEX Mutex)
#define trace
Definition: atltest.h:70
#define skip(...)
Definition: atltest.h:64
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
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 RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:599
PVOID KmtGetSystemRoutineAddress(IN PCWSTR RoutineName)
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

◆ StartThread()

static NTSTATUS StartThread ( PTHREAD_DATA  ThreadData,
PLARGE_INTEGER  Timeout,
KIRQL  Irql,
BOOLEAN  Try,
BOOLEAN  RetExpected 
)
static

Definition at line 271 of file KeGuardedMutex.c.

277{
280
281 ThreadData->Try = Try;
282 ThreadData->Irql = Irql;
283 ThreadData->RetExpected = RetExpected;
289
291}
static VOID NTAPI AcquireMutexThread(PVOID Parameter)
int Try(int arg)
Definition: ehframes.cpp:53
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define SYNCHRONIZE
Definition: nt_native.h:61
#define GENERIC_ALL
Definition: nt_native.h:92
POBJECT_TYPE PsThreadType
Definition: thread.c:20
NTSTATUS NTAPI PsCreateSystemThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, IN PCLIENT_ID ClientId, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext)
Definition: thread.c:602
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
static ULONG Timeout
Definition: ping.c:61
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes

Referenced by TestGuardedMutexConcurrent().

◆ TestGuardedMutexConcurrent()

static VOID TestGuardedMutexConcurrent ( PKGUARDED_MUTEX  Mutex)
static

Definition at line 313 of file KeGuardedMutex.c.

315{
318 THREAD_DATA ThreadData2;
319 THREAD_DATA ThreadDataUnsafe;
320 THREAD_DATA ThreadDataTry;
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 */
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);
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);
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 */
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);
354 CheckMutex(Mutex, 4L, ThreadData2.Thread, 2LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
355
358 CheckMutex(Mutex, 8L, ThreadData2.Thread, 3LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
359
360 /* finish 1 */
361 FinishThread(&ThreadData2);
364 CheckMutex(Mutex, 4L, ThreadDataUnsafe.Thread, 3LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
365
366 /* finish 2 */
367 FinishThread(&ThreadDataUnsafe);
370 CheckMutex(Mutex, 0L, ThreadData.Thread, 3LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
371
372 /* finish 3 */
374
375 CheckMutex(Mutex, 1L, NULL, 3LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
376}
static NTSTATUS StartThread(PTHREAD_DATA ThreadData, PLARGE_INTEGER Timeout, KIRQL Irql, BOOLEAN Try, BOOLEAN RetExpected)
static VOID InitThreadData(PTHREAD_DATA ThreadData, PKGUARDED_MUTEX Mutex, PMUTEX_FUNCTION Acquire, PMUTEX_TRY_FUNCTION TryAcquire, PMUTEX_FUNCTION Release)
static VOID FinishThread(PTHREAD_DATA ThreadData)
#define U(x)
Definition: wordpad.c:45
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
PKTHREAD Thread
Definition: ExFastMutex.c:143
KEVENT OutEvent
Definition: ExFastMutex.c:152

Referenced by START_TEST().