ReactOS  0.4.14-dev-552-g2fad488
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); \
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)
#define ok_eq_int(value, expected)
Definition: kmt_test.h:238
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
Definition: Mutex.h:15
BOOLEAN KmtIsCheckedBuild
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
BOOLEAN NTAPI KeAreApcsDisabled(VOID)
Definition: apc.c:958
_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:1557

◆ 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 
113 static
114 VOID
115 TestGuardedMutex(
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 */
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 }
#define TRUE
Definition: types.h:120
#define ok_eq_int(value, expected)
Definition: kmt_test.h:238
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
#define CheckMutex(Mutex, ExpectedCount, ExpectedOwner, ExpectedContention, ExpectedKernelApcDisable, ExpectedSpecialApcDisable, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, ExpectedIrql)
Definition: Mutex.h:15
#define ok_bool_false(value, desc)
Definition: kmt_test.h:257
UCHAR KIRQL
Definition: env_spec_w32.h:591
BOOLEAN KmtIsCheckedBuild
#define ok_bool_true(value, desc)
Definition: kmt_test.h:256
short SHORT
Definition: pedump.c:59
smooth NULL
Definition: ftsmooth.c:416
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
static const WCHAR L[]
Definition: oid.c:1250
BOOLEAN NTAPI KeAreApcsDisabled(VOID)
Definition: apc.c:958
_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:1557
#define KeGetCurrentThread
Definition: hal.h:44
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define ok_eq_long(value, expected)
Definition: kmt_test.h:240

◆ 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 
248  KeLowerIrql(Irql);
249  DPRINT("Thread exiting\n");
250 }
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define TRUE
Definition: types.h:120
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
LONG NTSTATUS
Definition: precomp.h:26
_In_ PVOID Parameter
Definition: ldrtypes.h:241
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
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
_Out_ PKIRQL Irql
Definition: csq.h:179
#define ok_bool_false(value, desc)
Definition: kmt_test.h:257
UCHAR KIRQL
Definition: env_spec_w32.h:591
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
#define ok_eq_bool(value, expected)
Definition: kmt_test.h:258
Status
Definition: gdiplustypes.h:24
#define ok_eq_hex(value, expected)
return STATUS_SUCCESS
Definition: btrfs.c:2938

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 }
#define TRUE
Definition: types.h:120
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
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
smooth NULL
Definition: ftsmooth.c:416
HANDLE Handle
Definition: drwtsn32.h:25
Status
Definition: gdiplustypes.h:24
#define ok_eq_hex(value, expected)
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
return STATUS_SUCCESS
Definition: btrfs.c:2938

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: classpnp.h:929
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
static PFAST_MUTEX Mutex
Definition: timer.c:22

Referenced by TestGuardedMutexConcurrent().

◆ START_TEST()

START_TEST ( KeGuardedMutex  )

Definition at line 378 of file KeGuardedMutex.c.

379 {
381  KIRQL OldIrql;
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 }
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define TRUE
Definition: types.h:120
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define CheckMutex(Mutex, ExpectedCount, ExpectedOwner, ExpectedContention, ExpectedKernelApcDisable, ExpectedSpecialApcDisable, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, ExpectedIrql)
_Out_ PKIRQL Irql
Definition: csq.h:179
Definition: Mutex.h:15
UCHAR KIRQL
Definition: env_spec_w32.h:591
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
short SHORT
Definition: pedump.c:59
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define trace
Definition: atltest.h:70
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
PVOID KmtGetSystemRoutineAddress(IN PCWSTR RoutineName)
static const WCHAR L[]
Definition: oid.c:1250
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
static VOID TestGuardedMutexConcurrent(PKGUARDED_MUTEX Mutex)
static PFAST_MUTEX Mutex
Definition: timer.c:22
#define skip(...)
Definition: atltest.h:64
#define KeGetCurrentThread
Definition: hal.h:44
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
#define APC_LEVEL
Definition: env_spec_w32.h:695

◆ 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 }
#define GENERIC_ALL
Definition: nt_native.h:92
LONG NTSTATUS
Definition: precomp.h:26
static VOID NTAPI AcquireMutexThread(PVOID Parameter)
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
_Out_ PKIRQL Irql
Definition: csq.h:179
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:496
smooth NULL
Definition: ftsmooth.c:416
HANDLE Handle
Definition: drwtsn32.h:25
POBJECT_TYPE PsThreadType
Definition: thread.c:20
#define SYNCHRONIZE
Definition: nt_native.h:61
Status
Definition: gdiplustypes.h:24
_Must_inspect_result_ _In_ USHORT _In_ PHIDP_PREPARSED_DATA _Out_writes_to_ LengthAttributes PHIDP_EXTENDED_ATTRIBUTES Attributes
Definition: hidpi.h:348
static ULONG Timeout
Definition: ping.c:61
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
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define ok_eq_hex(value, expected)
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231

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 }
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
#define CheckMutex(Mutex, ExpectedCount, ExpectedOwner, ExpectedContention, ExpectedKernelApcDisable, ExpectedSpecialApcDisable, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, ExpectedIrql)
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
Definition: Mutex.h:15
PKTHREAD Thread
Definition: ExFastMutex.c:143
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
KEVENT OutEvent
Definition: ExFastMutex.c:152
smooth NULL
Definition: ftsmooth.c:416
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)
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
static const WCHAR L[]
Definition: oid.c:1250
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
Status
Definition: gdiplustypes.h:24
static ULONG Timeout
Definition: ping.c:61
static NTSTATUS StartThread(PTHREAD_DATA ThreadData, PLARGE_INTEGER Timeout, KIRQL Irql, BOOLEAN Try, BOOLEAN RetExpected)
#define ok_eq_hex(value, expected)
#define KeGetCurrentThread
Definition: hal.h:44
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define APC_LEVEL
Definition: env_spec_w32.h:695

Referenced by START_TEST().