10#define PUSH_LOCK_TIMEOUT_MS 5000
11#define PUSH_LOCK_POLL_INTERVAL_MS 1
13#define PUSH_LOCK_RELATIVE_TIMEOUT(Milliseconds) (-((LONGLONG)(Milliseconds) * 10 * 1000))
15#define PUSH_LOCK_MAX_WAITERS 4
17#define PUSH_LOCK_RACE_ITERATIONS 64
18#define PUSH_LOCK_CONTENTION_THREADS 6
19#define PUSH_LOCK_CONTENTION_ITERATIONS 2048
21#define PUSH_LOCK_CHECKSUM_XOR 0xA5A5A5A5UL
156 WaitBlockAddress =
Value.Value & ~EX_PUSH_LOCK_PTR_BITS;
157 if (WaitBlockAddress == 0)
250 if (
State->ActiveWriters != 0)
257 if (
State->ActiveWriters != 0)
298 ULONG SequenceInverse;
304 Sequence =
State->Sequence;
305 SequenceInverse =
State->SequenceInverse;
306 Checksum =
State->Checksum;
308 if (SequenceInverse != ~Sequence ||
325 Sequence =
State->Sequence + 1;
326 State->Sequence = Sequence;
330 State->SequenceInverse = ~Sequence;
357 Context->ReleaseKind = ReleaseKind;
443 ok(
FALSE,
"Could not create push-lock test thread\n");
544 goto CheckForConcurrentChange;
574 for (SeenIndex = 0; SeenIndex < ActualCount; SeenIndex++)
576 if (Seen[SeenIndex] == Current)
582 Seen[ActualCount] = Current;
587 if (Current->Previous != Previous)
589 goto CheckForConcurrentChange;
592 Flags = Current->Flags;
614 Current = Current->Next;
631 if (ActualCount < ExpectedCount)
636 if (ActualCount > ExpectedCount)
645 if (ActualNewestFirst[
Index] != ExpectedNewestFirst[
Index])
651 if (OldestWaitBlock !=
NULL)
653 *OldestWaitBlock = Last;
658CheckForConcurrentChange:
840 "Wait chain did not stabilize after waiter %lu\n",
Index);
861 "Reader wait chain is invalid while the writer owns the lock\n");
944 ExclusiveThread =
NULL;
946 OldestWaitBlock =
NULL;
976 ok(
Success,
"Exclusive waiter did not reach a stable wait state\n");
993 ok(
Success,
"Exclusive/shared wait chain did not stabilize\n");
1000 ok(
Value.Locked,
"Push lock is not locked\n");
1001 ok(
Value.Waiting,
"Push lock has no waiters\n");
1002 ok(!
Value.Waking,
"Push lock is waking\n");
1003 ok(
Value.MultipleShared,
"MultipleShared is not set\n");
1005 if (OldestWaitBlock !=
NULL)
1017 if (OldestWaitBlock !=
NULL)
1023 ok(
Value.Locked,
"Push lock is not locked while shares remain\n");
1024 ok(
Value.Waiting,
"Push lock has no waiters while shares remain\n");
1025 ok(
Value.MultipleShared,
"MultipleShared is not set while shares remain\n");
1062 ok(
Success,
"Shared waiter did not remain queued behind the exclusive owner\n");
1066 ExclusiveThread =
NULL;
1078 SharedThread =
NULL;
1091 if (ExclusiveThread !=
NULL)
1096 if (SharedThread !=
NULL)
1135 OldestThread =
NULL;
1136 NewestThread =
NULL;
1156 "Oldest waiter did not stabilize at iteration %lu\n",
1182 ReleaseKind = (Iteration & 1)
1239 for (Iteration = 0; Iteration <
Context->Iterations; Iteration++)
1243 ReleaseKind = ((Iteration +
Context->Index) & 1)
1271 if ((Iteration & 0x3f) == 0)
1330 ok(
FALSE,
"Could not create contention thread %lu\n",
Index);
static VOID TestPushLockSharedOwnerDrain(_In_ PUSH_LOCK_RELEASE_KIND ReleaseKind)
#define PUSH_LOCK_CONTENTION_ITERATIONS
struct PUSH_LOCK_TEST_STATE * PPUSH_LOCK_TEST_STATE
static VOID TestPushLockWaiterSelection(VOID)
static VOID PushLockEnterProtectedRegion(_Inout_ PPUSH_LOCK_TEST_STATE State, _In_ PUSH_LOCK_MODE Mode)
static PUSH_LOCK_WAIT_CHAIN_STATE PushLockValidateWaitChain(_In_ PEX_PUSH_LOCK PushLock, _In_reads_(ExpectedCount) const PUSH_LOCK_MODE *ExpectedNewestFirst, _In_ ULONG ExpectedCount, _Out_opt_ PEX_PUSH_LOCK_WAIT_BLOCK *OldestWaitBlock)
static VOID TestPushLockUncontended(_In_ PUSH_LOCK_RELEASE_KIND ReleaseKind)
static VOID PushLockReleaseAndFinishThread(_In_opt_ PKTHREAD Thread, _Inout_ PPUSH_LOCK_THREAD_CONTEXT Context)
static EX_PUSH_LOCK PushLockReadValue(_In_ PEX_PUSH_LOCK PushLock)
static VOID TestPushLockContention(VOID)
static BOOLEAN PushLockStartControlledThread(_Inout_ PPUSH_LOCK_THREAD_CONTEXT Context, _Out_ PKTHREAD *Thread)
#define PUSH_LOCK_MAX_WAITERS
#define PUSH_LOCK_CONTENTION_THREADS
@ PushLockReleaseSpecific
static VOID PushLockSampleState(_Inout_ PPUSH_LOCK_TEST_STATE State)
static VOID PushLockReadProtectedValue(_Inout_ PPUSH_LOCK_TEST_STATE State)
struct PUSH_LOCK_THREAD_CONTEXT * PPUSH_LOCK_THREAD_CONTEXT
static VOID PushLockInitializeThreadContext(_Out_ PPUSH_LOCK_THREAD_CONTEXT Context, _Inout_ PPUSH_LOCK_TEST_STATE State, _In_ PUSH_LOCK_MODE Mode, _In_ PUSH_LOCK_RELEASE_KIND ReleaseKind)
static VOID PushLockWriteProtectedValue(_Inout_ PPUSH_LOCK_TEST_STATE State)
FORCEINLINE NTSTATUS PushLockWaitForEvent(_In_ PKEVENT Event)
static VOID PushLockAcquire(_Inout_ PEX_PUSH_LOCK PushLock, _In_ PUSH_LOCK_MODE Mode)
#define PUSH_LOCK_RELATIVE_TIMEOUT(Milliseconds)
static VOID NTAPI PushLockContentionThread(_In_ PVOID Parameter)
#define PUSH_LOCK_RACE_ITERATIONS
static VOID PushLockLeaveProtectedRegion(_Inout_ PPUSH_LOCK_TEST_STATE State, _In_ PUSH_LOCK_MODE Mode)
static VOID TestPushLockWaiterArrivalDuringRelease(VOID)
static BOOLEAN PushLockValueIsPlausible(_In_ EX_PUSH_LOCK Value)
static VOID PushLockInitializeState(_Out_ PPUSH_LOCK_TEST_STATE State)
static VOID PushLockRelease(_Inout_ PEX_PUSH_LOCK PushLock, _In_ PUSH_LOCK_MODE Mode, _In_ PUSH_LOCK_RELEASE_KIND ReleaseKind)
FORCEINLINE VOID PushLockRecordViolation(_Inout_ PPUSH_LOCK_TEST_STATE State)
static VOID NTAPI PushLockControlledThread(_In_ PVOID Parameter)
#define PUSH_LOCK_CHECKSUM_XOR
#define PUSH_LOCK_TIMEOUT_MS
FORCEINLINE VOID PushLockDelay(VOID)
#define PUSH_LOCK_POLL_INTERVAL_MS
static BOOLEAN PushLockWaitForStableWaitChain(_In_ PEX_PUSH_LOCK PushLock, _In_reads_(ExpectedCount) const PUSH_LOCK_MODE *ExpectedNewestFirst, _In_ ULONG ExpectedCount, _Out_opt_ PEX_PUSH_LOCK_WAIT_BLOCK *OldestWaitBlock)
PUSH_LOCK_WAIT_CHAIN_STATE
@ PushLockWaitChainInProgress
@ PushLockWaitChainInvalid
@ PushLockWaitChainStable
#define EX_PUSH_LOCK_PTR_BITS
#define EX_PUSH_LOCK_SHARE_INC
#define EX_PUSH_LOCK_LOCK
#define ok_eq_hex(value, expected)
#define ok_eq_long(value, expected)
#define ok_eq_ulongptr(value, expected)
#define InterlockedIncrement
#define InterlockedDecrement
static const WCHAR Cleanup[]
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
#define KeInitializeEvent(pEvt, foo, foo2)
#define KeSetEvent(pEvt, foo, foo2)
#define KeDelayExecutionThread(mode, foo, t)
LONG NTAPI KeReadStateEvent(IN PKEVENT Event)
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
#define InterlockedCompareExchangePointer
#define KeLeaveCriticalRegion()
#define KeEnterCriticalRegion()
PKTHREAD KmtStartThread(IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext OPTIONAL)
VOID KmtFinishThread(IN PKTHREAD Thread OPTIONAL, IN PKEVENT Event OPTIONAL)
static PFLT_CONTEXT_REGISTRATION Contexts
BOOLEAN NTAPI MmIsAddressValid(IN PVOID VirtualAddress)
* PEX_PUSH_LOCK_WAIT_BLOCK
#define EX_PUSH_LOCK_FLAGS_EXCLUSIVE
#define EX_PUSH_LOCK_FLAGS_WAIT
VOID FASTCALL ExfReleasePushLock(PEX_PUSH_LOCK PushLock)
VOID FASTCALL ExfReleasePushLockShared(PEX_PUSH_LOCK PushLock)
VOID FASTCALL ExfReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
VOID FASTCALL ExfAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
VOID FASTCALL ExfAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
FORCEINLINE VOID KeMemoryBarrier(VOID)
volatile LONG SharedAcquisitions
volatile LONG ActiveReaders
volatile LONG ActiveWriters
volatile LONG ExclusiveAcquisitions
volatile LONG CompletedOperations
volatile ULONG SequenceInverse
PPUSH_LOCK_TEST_STATE State
PUSH_LOCK_RELEASE_KIND ReleaseKind
State(char *beg, char *end)
static const VBE_MODE Modes[VBE_MODE_COUNT]
#define RtlZeroMemory(Destination, Length)
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
_Must_inspect_result_ _In_ ULONG Flags
_Inout_opt_ PVOID Parameter