[ros-diffs] [tfaber] 53367: [KMTESTS/KE] - Add concurrent testing to KeGuardedMutex test (part 2/2)

tfaber at svn.reactos.org tfaber at svn.reactos.org
Mon Aug 22 10:02:13 UTC 2011


Author: tfaber
Date: Mon Aug 22 10:02:12 2011
New Revision: 53367

URL: http://svn.reactos.org/svn/reactos?rev=53367&view=rev
Log:
[KMTESTS/KE]
- Add concurrent testing to KeGuardedMutex test (part 2/2)

Modified:
    branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeGuardedMutex.c

Modified: branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeGuardedMutex.c
URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeGuardedMutex.c?rev=53367&r1=53366&r2=53367&view=diff
==============================================================================
--- branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeGuardedMutex.c [iso-8859-1] (original)
+++ branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeGuardedMutex.c [iso-8859-1] Mon Aug 22 10:02:12 2011
@@ -114,6 +114,185 @@
     ok_eq_int(Thread->SpecialApcDisable, SpecialApcsDisabled);
     Thread->SpecialApcDisable = SpecialApcsDisabled;
     ok_irql(OriginalIrql);
+}
+
+typedef VOID (FASTCALL *PMUTEX_FUNCTION)(PKGUARDED_MUTEX);
+typedef BOOLEAN (FASTCALL *PMUTEX_TRY_FUNCTION)(PKGUARDED_MUTEX);
+
+typedef struct
+{
+    HANDLE Handle;
+    PKTHREAD Thread;
+    KIRQL Irql;
+    PKGUARDED_MUTEX Mutex;
+    PMUTEX_FUNCTION Acquire;
+    PMUTEX_TRY_FUNCTION TryAcquire;
+    PMUTEX_FUNCTION Release;
+    BOOLEAN Try;
+    BOOLEAN RetExpected;
+    KEVENT InEvent;
+    KEVENT OutEvent;
+} THREAD_DATA, *PTHREAD_DATA;
+
+static
+VOID
+NTAPI
+AcquireMutexThread(
+    PVOID Parameter)
+{
+    PTHREAD_DATA ThreadData = Parameter;
+    KIRQL Irql;
+    BOOLEAN Ret = FALSE;
+    NTSTATUS Status;
+
+    DPRINT("Thread starting\n");
+    KeRaiseIrql(ThreadData->Irql, &Irql);
+
+    if (ThreadData->Try)
+    {
+        Ret = ThreadData->TryAcquire(ThreadData->Mutex);
+        ok_eq_bool(Ret, ThreadData->RetExpected);
+    }
+    else
+        ThreadData->Acquire(ThreadData->Mutex);
+
+    ok_bool_false(KeSetEvent(&ThreadData->OutEvent, 0, TRUE), "KeSetEvent returned");
+    DPRINT("Thread now waiting\n");
+    Status = KeWaitForSingleObject(&ThreadData->InEvent, Executive, KernelMode, FALSE, NULL);
+    DPRINT("Thread done waiting\n");
+    ok_eq_hex(Status, STATUS_SUCCESS);
+
+    if (!ThreadData->Try || Ret)
+        ThreadData->Release(ThreadData->Mutex);
+
+    KeLowerIrql(Irql);
+    DPRINT("Thread exiting\n");
+}
+
+static
+VOID
+InitThreadData(
+    PTHREAD_DATA ThreadData,
+    PKGUARDED_MUTEX Mutex,
+    PMUTEX_FUNCTION Acquire,
+    PMUTEX_TRY_FUNCTION TryAcquire,
+    PMUTEX_FUNCTION Release)
+{
+    ThreadData->Mutex = Mutex;
+    KeInitializeEvent(&ThreadData->InEvent, NotificationEvent, FALSE);
+    KeInitializeEvent(&ThreadData->OutEvent, NotificationEvent, FALSE);
+    ThreadData->Acquire = Acquire;
+    ThreadData->TryAcquire = TryAcquire;
+    ThreadData->Release = Release;
+}
+
+static
+NTSTATUS
+StartThread(
+    PTHREAD_DATA ThreadData,
+    PLARGE_INTEGER Timeout,
+    KIRQL Irql,
+    BOOLEAN Try,
+    BOOLEAN RetExpected)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    OBJECT_ATTRIBUTES Attributes;
+
+    ThreadData->Try = Try;
+    ThreadData->Irql = Irql;
+    ThreadData->RetExpected = RetExpected;
+    InitializeObjectAttributes(&Attributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
+    Status = PsCreateSystemThread(&ThreadData->Handle, GENERIC_ALL, &Attributes, NULL, NULL, AcquireMutexThread, ThreadData);
+    ok_eq_hex(Status, STATUS_SUCCESS);
+    Status = ObReferenceObjectByHandle(ThreadData->Handle, SYNCHRONIZE, PsThreadType, KernelMode, (PVOID *)&ThreadData->Thread, NULL);
+    ok_eq_hex(Status, STATUS_SUCCESS);
+
+    return KeWaitForSingleObject(&ThreadData->OutEvent, Executive, KernelMode, FALSE, Timeout);
+}
+
+static
+VOID
+FinishThread(
+    PTHREAD_DATA ThreadData)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    KeSetEvent(&ThreadData->InEvent, 0, TRUE);
+    Status = KeWaitForSingleObject(ThreadData->Thread, Executive, KernelMode, FALSE, NULL);
+    ok_eq_hex(Status, STATUS_SUCCESS);
+
+    ObDereferenceObject(ThreadData->Thread);
+    Status = ZwClose(ThreadData->Handle);
+    ok_eq_hex(Status, STATUS_SUCCESS);
+    KeClearEvent(&ThreadData->InEvent);
+    KeClearEvent(&ThreadData->OutEvent);
+}
+
+static
+VOID
+TestGuardedMutexConcurrent(
+    PKGUARDED_MUTEX Mutex)
+{
+    NTSTATUS Status;
+    THREAD_DATA ThreadData;
+    THREAD_DATA ThreadData2;
+    THREAD_DATA ThreadDataUnsafe;
+    THREAD_DATA ThreadDataTry;
+    PKTHREAD Thread = KeGetCurrentThread();
+    LARGE_INTEGER Timeout;
+    Timeout.QuadPart = -10 * 1000 * 10; /* 10 ms */
+
+    InitThreadData(&ThreadData, Mutex, KeAcquireGuardedMutex, NULL, KeReleaseGuardedMutex);
+    InitThreadData(&ThreadData2, Mutex, KeAcquireGuardedMutex, NULL, KeReleaseGuardedMutex);
+    InitThreadData(&ThreadDataUnsafe, Mutex, KeAcquireGuardedMutexUnsafe, NULL, KeReleaseGuardedMutexUnsafe);
+    InitThreadData(&ThreadDataTry, Mutex, NULL, KeTryToAcquireGuardedMutex, KeReleaseGuardedMutex);
+
+    /* have a thread acquire the mutex */
+    Status = StartThread(&ThreadData, NULL, PASSIVE_LEVEL, FALSE, FALSE);
+    ok_eq_hex(Status, STATUS_SUCCESS);
+    CheckMutex(Mutex, 0L, ThreadData.Thread, 0LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
+    /* have a second thread try to acquire it -- should fail */
+    Status = StartThread(&ThreadDataTry, NULL, PASSIVE_LEVEL, TRUE, FALSE);
+    ok_eq_hex(Status, STATUS_SUCCESS);
+    CheckMutex(Mutex, 0L, ThreadData.Thread, 0LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
+    FinishThread(&ThreadDataTry);
+
+    /* have another thread acquire it -- should block */
+    Status = StartThread(&ThreadData2, &Timeout, APC_LEVEL, FALSE, FALSE);
+    ok_eq_hex(Status, STATUS_TIMEOUT);
+    CheckMutex(Mutex, 4L, ThreadData.Thread, 1LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
+
+    /* finish the first thread -- now the second should become available */
+    FinishThread(&ThreadData);
+    Status = KeWaitForSingleObject(&ThreadData2.OutEvent, Executive, KernelMode, FALSE, NULL);
+    ok_eq_hex(Status, STATUS_SUCCESS);
+    CheckMutex(Mutex, 0L, ThreadData2.Thread, 1LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
+
+    /* block two more threads */
+    Status = StartThread(&ThreadDataUnsafe, &Timeout, APC_LEVEL, FALSE, FALSE);
+    ok_eq_hex(Status, STATUS_TIMEOUT);
+    CheckMutex(Mutex, 4L, ThreadData2.Thread, 2LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
+
+    Status = StartThread(&ThreadData, &Timeout, PASSIVE_LEVEL, FALSE, FALSE);
+    ok_eq_hex(Status, STATUS_TIMEOUT);
+    CheckMutex(Mutex, 8L, ThreadData2.Thread, 3LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
+
+    /* finish 1 */
+    FinishThread(&ThreadData2);
+    Status = KeWaitForSingleObject(&ThreadDataUnsafe.OutEvent, Executive, KernelMode, FALSE, NULL);
+    ok_eq_hex(Status, STATUS_SUCCESS);
+    CheckMutex(Mutex, 4L, ThreadDataUnsafe.Thread, 3LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
+
+    /* finish 2 */
+    FinishThread(&ThreadDataUnsafe);
+    Status = KeWaitForSingleObject(&ThreadData.OutEvent, Executive, KernelMode, FALSE, NULL);
+    ok_eq_hex(Status, STATUS_SUCCESS);
+    CheckMutex(Mutex, 0L, ThreadData.Thread, 3LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
+
+    /* finish 3 */
+    FinishThread(&ThreadData);
+
+    CheckMutex(Mutex, 1L, NULL, 3LU, 0x5555, -1, 0, 0, FALSE, PASSIVE_LEVEL);
 }
 
 START_TEST(KeGuardedMutex)
@@ -174,4 +353,9 @@
         Thread->KernelApcDisable = 0;
         KeLowerIrql(OldIrql);
     }
-}
+
+    trace("Concurrent test\n");
+    RtlFillMemory(&Mutex, sizeof Mutex, 0x55);
+    KeInitializeGuardedMutex(&Mutex);
+    TestGuardedMutexConcurrent(&Mutex);
+}




More information about the Ros-diffs mailing list