ntoskrnl.exe/tests: Add basic test for DPC call.
Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
4921d24627
commit
4c81f499a6
|
@ -1779,6 +1779,117 @@ static void test_affinity(void)
|
||||||
KeRevertToUserAffinityThread();
|
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)
|
static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack)
|
||||||
{
|
{
|
||||||
ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength;
|
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();
|
test_executable_pool();
|
||||||
#endif
|
#endif
|
||||||
test_affinity();
|
test_affinity();
|
||||||
|
test_dpc();
|
||||||
|
|
||||||
if (main_test_work_item) return STATUS_UNEXPECTED_IO_ERROR;
|
if (main_test_work_item) return STATUS_UNEXPECTED_IO_ERROR;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue