Paul Gofman : ntoskrnl.exe/tests: Add basic test for DPC call.
Alexandre Julliard
julliard at winehq.org
Wed May 27 15:19:30 CDT 2020
Module: wine
Branch: master
Commit: 4c81f499a632726b111473730c413d3cce537938
URL: https://source.winehq.org/git/wine.git/?a=commit;h=4c81f499a632726b111473730c413d3cce537938
Author: Paul Gofman <pgofman at codeweavers.com>
Date: Wed May 27 13:23:22 2020 +0300
ntoskrnl.exe/tests: Add basic test for DPC call.
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntoskrnl.exe/tests/driver.c | 112 +++++++++++++++++++++++++++++++++++++++
1 file changed, 112 insertions(+)
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c
index 356c60a2e7..dc576bfb1b 100644
--- a/dlls/ntoskrnl.exe/tests/driver.c
+++ b/dlls/ntoskrnl.exe/tests/driver.c
@@ -1779,6 +1779,117 @@ static void test_affinity(void)
KeRevertToUserAffinityThread();
}
+struct test_dpc_func_context
+{
+ volatile LONG call_count;
+ volatile LONG selected_count;
+ volatile DEFERRED_REVERSE_BARRIER sync_barrier_start_value, sync_barrier_mid_value, sync_barrier_end_value;
+ volatile LONG done_barrier_start_value;
+};
+
+static BOOLEAN (WINAPI *pKeSignalCallDpcSynchronize)(void *barrier);
+static void (WINAPI *pKeSignalCallDpcDone)(void *barrier);
+
+static void WINAPI test_dpc_func(PKDPC Dpc, void *context, void *cpu_count,
+ void *reverse_barrier)
+{
+ DEFERRED_REVERSE_BARRIER *barrier = reverse_barrier;
+ struct test_dpc_func_context *data = context;
+
+ InterlockedIncrement(&data->call_count);
+
+ InterlockedCompareExchange((volatile LONG*)&data->sync_barrier_start_value.Barrier,
+ *(volatile LONG *)&barrier->Barrier, 0);
+ InterlockedCompareExchange((volatile LONG*)&data->sync_barrier_start_value.TotalProcessors,
+ *(volatile LONG *)&barrier->TotalProcessors, 0);
+
+ if (pKeSignalCallDpcSynchronize(reverse_barrier))
+ InterlockedIncrement(&data->selected_count);
+
+ InterlockedCompareExchange((volatile LONG*)&data->sync_barrier_mid_value.Barrier,
+ *(volatile LONG *)&barrier->Barrier, 0);
+ InterlockedCompareExchange((volatile LONG*)&data->sync_barrier_mid_value.TotalProcessors,
+ *(volatile LONG *)&barrier->TotalProcessors, 0);
+
+ data->done_barrier_start_value = *(volatile LONG *)cpu_count;
+
+ if (pKeSignalCallDpcSynchronize(reverse_barrier))
+ InterlockedIncrement(&data->selected_count);
+
+ pKeSignalCallDpcSynchronize(reverse_barrier);
+ pKeSignalCallDpcSynchronize(reverse_barrier);
+
+ InterlockedCompareExchange((volatile LONG*)&data->sync_barrier_end_value.Barrier,
+ *(volatile LONG *)&barrier->Barrier, 0);
+ InterlockedCompareExchange((volatile LONG*)&data->sync_barrier_end_value.TotalProcessors,
+ *(volatile LONG *)&barrier->TotalProcessors, 0);
+
+ pKeSignalCallDpcDone(cpu_count);
+}
+
+static void test_dpc(void)
+{
+ void (WINAPI *pKeGenericCallDpc)(PKDEFERRED_ROUTINE routine, void *context);
+ struct test_dpc_func_context data;
+ KAFFINITY cpu_mask;
+ ULONG cpu_count;
+
+ pKeGenericCallDpc = get_proc_address("KeGenericCallDpc");
+ if (!pKeGenericCallDpc)
+ {
+ win_skip("KeGenericCallDpc is not available.\n");
+ return;
+ }
+
+ pKeSignalCallDpcDone = get_proc_address("KeSignalCallDpcDone");
+ ok(!!pKeSignalCallDpcDone, "KeSignalCallDpcDone is not available.\n");
+ pKeSignalCallDpcSynchronize = get_proc_address("KeSignalCallDpcSynchronize");
+ ok(!!pKeSignalCallDpcSynchronize, "KeSignalCallDpcSynchronize is not available.\n");
+
+
+ cpu_mask = KeQueryActiveProcessors();
+ cpu_count = 0;
+ while (cpu_mask)
+ {
+ if (cpu_mask & 1)
+ ++cpu_count;
+
+ cpu_mask >>= 1;
+ }
+
+ memset(&data, 0, sizeof(data));
+
+ KeSetSystemAffinityThread(0x1);
+
+ pKeGenericCallDpc(test_dpc_func, &data);
+ ok(data.call_count == cpu_count, "Got unexpected call_count %u.\n", data.call_count);
+ ok(data.selected_count == 2, "Got unexpected selected_count %u.\n", data.selected_count);
+ ok(data.sync_barrier_start_value.Barrier == cpu_count,
+ "Got unexpected sync_barrier_start_value.Barrier %d.\n",
+ data.sync_barrier_start_value.Barrier);
+ ok(data.sync_barrier_start_value.TotalProcessors == cpu_count,
+ "Got unexpected sync_barrier_start_value.TotalProcessors %d.\n",
+ data.sync_barrier_start_value.TotalProcessors);
+
+ ok(data.sync_barrier_mid_value.Barrier == (0x80000000 | cpu_count),
+ "Got unexpected sync_barrier_mid_value.Barrier %d.\n",
+ data.sync_barrier_mid_value.Barrier);
+ ok(data.sync_barrier_mid_value.TotalProcessors == cpu_count,
+ "Got unexpected sync_barrier_mid_value.TotalProcessors %d.\n",
+ data.sync_barrier_mid_value.TotalProcessors);
+
+ ok(data.sync_barrier_end_value.Barrier == cpu_count,
+ "Got unexpected sync_barrier_end_value.Barrier %d.\n",
+ data.sync_barrier_end_value.Barrier);
+ ok(data.sync_barrier_end_value.TotalProcessors == cpu_count,
+ "Got unexpected sync_barrier_end_value.TotalProcessors %d.\n",
+ data.sync_barrier_end_value.TotalProcessors);
+
+ ok(data.done_barrier_start_value == cpu_count, "Got unexpected done_barrier_start_value %d.\n", data.done_barrier_start_value);
+
+ KeRevertToUserAffinityThread();
+}
+
static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack)
{
ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength;
@@ -1833,6 +1944,7 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st
test_executable_pool();
#endif
test_affinity();
+ test_dpc();
if (main_test_work_item) return STATUS_UNEXPECTED_IO_ERROR;
More information about the wine-cvs
mailing list