Author: tfaber
Date: Fri Aug 5 21:12:11 2011
New Revision: 53091
URL:
http://svn.reactos.org/svn/reactos?rev=53091&view=rev
Log:
[KMTESTS]
- KeEvent: a little concurrent testing (part 2/x)
- ExFastMutex: concurrent testing (part 2/2)
- Fix copypasta
Modified:
branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_platform.h
branches/GSoC_2011/KMTestSuite/kmtests/ntos_ex/ExFastMutex.c
branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeEvent.c
Modified: branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_platform.h
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/i…
==============================================================================
--- branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_platform.h [iso-8859-1] (original)
+++ branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_platform.h [iso-8859-1] Fri Aug 5
21:12:11 2011
@@ -41,7 +41,7 @@
#define ExAllocatePoolWithTag(type, size, tag) HeapAlloc(GetProcessHeap(), 0, size)
#define ExFreePool(p) HeapFree(GetProcessHeap(), 0, p)
#define ExFreePoolWithTag(p, tag) HeapFree(GetProcessHeap(), 0, p)
-#define RtlCopyMemoryNonTemporal(d, s, l)
+#define RtlCopyMemoryNonTemporal RtlCopyMemory
#define RtlPrefetchMemoryNonTemporal(s, l)
#endif /* defined KMT_EMULATE_KERNEL */
Modified: branches/GSoC_2011/KMTestSuite/kmtests/ntos_ex/ExFastMutex.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/n…
==============================================================================
--- branches/GSoC_2011/KMTestSuite/kmtests/ntos_ex/ExFastMutex.c [iso-8859-1] (original)
+++ branches/GSoC_2011/KMTestSuite/kmtests/ntos_ex/ExFastMutex.c [iso-8859-1] Fri Aug 5
21:12:11 2011
@@ -104,6 +104,180 @@
KmtSetIrql(OriginalIrql);
}
+typedef VOID (FASTCALL *PMUTEX_FUNCTION)(PFAST_MUTEX);
+typedef BOOLEAN (FASTCALL *PMUTEX_TRY_FUNCTION)(PFAST_MUTEX);
+
+typedef struct
+{
+ HANDLE Handle;
+ PKTHREAD Thread;
+ KIRQL Irql;
+ PFAST_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;
+
+ 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");
+ Status = KeWaitForSingleObject(&ThreadData->InEvent, Executive, KernelMode,
FALSE, NULL);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+
+ if (!ThreadData->Try || Ret)
+ ThreadData->Release(ThreadData->Mutex);
+
+ KeLowerIrql(Irql);
+}
+
+static
+VOID
+InitThreadData(
+ PTHREAD_DATA ThreadData,
+ PFAST_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
+TestFastMutexConcurrent(
+ PFAST_MUTEX Mutex)
+{
+ NTSTATUS Status;
+ THREAD_DATA ThreadData;
+ THREAD_DATA ThreadData2;
+ THREAD_DATA ThreadDataUnsafe;
+ THREAD_DATA ThreadDataTry;
+ LARGE_INTEGER Timeout;
+ Timeout.QuadPart = -10 * 1000 * 10; /* 10 ms */
+
+ InitThreadData(&ThreadData, Mutex, ExAcquireFastMutex, NULL,
ExReleaseFastMutex);
+ InitThreadData(&ThreadData2, Mutex, ExAcquireFastMutex, NULL,
ExReleaseFastMutex);
+ InitThreadData(&ThreadDataUnsafe, Mutex, ExAcquireFastMutexUnsafe, NULL,
ExReleaseFastMutexUnsafe);
+ InitThreadData(&ThreadDataTry, Mutex, NULL, ExTryToAcquireFastMutex,
ExReleaseFastMutex);
+
+ /* 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, PASSIVE_LEVEL, 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, PASSIVE_LEVEL, 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, -1L, ThreadData.Thread, 1LU, PASSIVE_LEVEL, 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, APC_LEVEL, PASSIVE_LEVEL);
+
+ /* block two more threads */
+ Status = StartThread(&ThreadDataUnsafe, &Timeout, APC_LEVEL, FALSE, FALSE);
+ ok_eq_hex(Status, STATUS_TIMEOUT);
+ CheckMutex(Mutex, -1L, ThreadData2.Thread, 2LU, APC_LEVEL, PASSIVE_LEVEL);
+
+ Status = StartThread(&ThreadData, &Timeout, PASSIVE_LEVEL, FALSE, FALSE);
+ ok_eq_hex(Status, STATUS_TIMEOUT);
+ CheckMutex(Mutex, -2L, ThreadData2.Thread, 3LU, APC_LEVEL, PASSIVE_LEVEL);
+
+ /* finish 1 */
+ FinishThread(&ThreadData2);
+ Status = KeWaitForSingleObject(&ThreadDataUnsafe.OutEvent, Executive, KernelMode,
FALSE, NULL);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ CheckMutex(Mutex, -1L, ThreadDataUnsafe.Thread, 3LU, APC_LEVEL, 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, PASSIVE_LEVEL, PASSIVE_LEVEL);
+
+ /* finish 3 */
+ FinishThread(&ThreadData);
+
+ CheckMutex(Mutex, 1L, NULL, 3LU, PASSIVE_LEVEL, PASSIVE_LEVEL);
+}
+
START_TEST(ExFastMutex)
{
FAST_MUTEX Mutex;
@@ -124,4 +298,6 @@
TestFastMutex(&Mutex, HIGH_LEVEL);
}
KeLowerIrql(PASSIVE_LEVEL);
-}
+
+ TestFastMutexConcurrent(&Mutex);
+}
Modified: branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeEvent.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/n…
==============================================================================
--- branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeEvent.c [iso-8859-1] (original)
+++ branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeEvent.c [iso-8859-1] Fri Aug 5
21:12:11 2011
@@ -7,7 +7,7 @@
#include <kmt_test.h>
-/* TODO: thread testing, exports vs macros */
+/* TODO: more thread testing, exports vs macros */
#define CheckEvent(Event, ExpectedType, State, ExpectedWaitNext, Irql) do \
{ \
@@ -96,6 +96,95 @@
KmtSetIrql(OriginalIrql);
}
+typedef struct
+{
+ HANDLE Handle;
+ PKTHREAD Thread;
+ PKEVENT Event1;
+ PKEVENT Event2;
+ volatile BOOLEAN Signal;
+} THREAD_DATA, *PTHREAD_DATA;
+
+static
+VOID
+NTAPI
+WaitForEventThread(
+ IN OUT PVOID Context)
+{
+ NTSTATUS Status;
+ PTHREAD_DATA ThreadData = Context;
+
+ ok_irql(PASSIVE_LEVEL);
+ ThreadData->Signal = TRUE;
+ Status = KeWaitForSingleObject(ThreadData->Event1, Executive, KernelMode, FALSE,
NULL);
+ ok_irql(PASSIVE_LEVEL);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ ThreadData->Signal = TRUE;
+ Status = KeWaitForSingleObject(ThreadData->Event2, Executive, KernelMode, FALSE,
NULL);
+ ok_irql(PASSIVE_LEVEL);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ ok_irql(PASSIVE_LEVEL);
+}
+
+static
+VOID
+TestEventThreads(
+ IN PKEVENT Event,
+ IN EVENT_TYPE Type,
+ IN KIRQL OriginalIrql)
+{
+ NTSTATUS Status;
+ THREAD_DATA Threads[5];
+ LARGE_INTEGER Timeout;
+ KPRIORITY Priority;
+ KEVENT WaitEvent;
+ KEVENT TerminateEvent;
+ int i;
+ Timeout.QuadPart = -1000 * 10;
+
+ KeInitializeEvent(Event, Type, FALSE);
+ KeInitializeEvent(&WaitEvent, NotificationEvent, FALSE);
+ KeInitializeEvent(&TerminateEvent, SynchronizationEvent, FALSE);
+
+ for (i = 0; i < sizeof Threads / sizeof Threads[0]; ++i)
+ {
+ Threads[i].Event1 = Event;
+ Threads[i].Event2 = &TerminateEvent;
+ Threads[i].Signal = FALSE;
+ Status = PsCreateSystemThread(&Threads[i].Handle, GENERIC_ALL, NULL, NULL,
NULL, WaitForEventThread, &Threads[i]);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ Status = ObReferenceObjectByHandle(Threads[i].Handle, SYNCHRONIZE, PsThreadType,
KernelMode, (PVOID *)&Threads[i].Thread, NULL);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ Priority = KeQueryPriorityThread(Threads[i].Thread);
+ ok_eq_long(Priority, 8L);
+ while (!Threads[i].Signal)
+ {
+ Status = KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE,
&Timeout);
+ ok_eq_hex(Status, STATUS_TIMEOUT);
+ }
+ Threads[i].Signal = FALSE;
+ }
+
+ for (i = 0; i < sizeof Threads / sizeof Threads[0]; ++i)
+ {
+ KeSetEvent(Event, 1, FALSE);
+ while (!Threads[i].Signal)
+ {
+ Status = KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE,
&Timeout);
+ ok_eq_hex(Status, STATUS_TIMEOUT);
+ }
+ Priority = KeQueryPriorityThread(Threads[i].Thread);
+ ok_eq_long(Priority, 9L);
+ KeSetEvent(&TerminateEvent, 0, FALSE);
+ Status = KeWaitForSingleObject(Threads[i].Thread, Executive, KernelMode, FALSE,
NULL);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+
+ ObDereferenceObject(Threads[i].Thread);
+ Status = ZwClose(Threads[i].Handle);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ }
+}
+
START_TEST(KeEvent)
{
KEVENT Event;
@@ -111,6 +200,8 @@
KeLowerIrql(Irql);
}
+ TestEventThreads(&Event, NotificationEvent, PASSIVE_LEVEL);
+
ok_irql(PASSIVE_LEVEL);
KmtSetIrql(PASSIVE_LEVEL);
}