Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 1 + include/ddk/wdm.h | 1 + 2 files changed, 2 insertions(+)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 3c7a9d1950..c4ddfb2830 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -546,6 +546,7 @@ @ stub KeFindConfigurationNextEntry @ stub KeFlushEntireTb @ stdcall KeFlushQueuedDpcs() +@ stdcall KeGetCurrentProcessorNumber() NtGetCurrentProcessorNumber @ stdcall KeGetCurrentThread() @ stub KeGetPreviousMode @ stub KeGetRecommendedSharedDataAlignment diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index b0ad0e70d3..c1d083ef01 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1686,6 +1686,7 @@ BOOLEAN WINAPI KeCancelTimer(KTIMER*); void WINAPI KeClearEvent(PRKEVENT); NTSTATUS WINAPI KeDelayExecutionThread(KPROCESSOR_MODE,BOOLEAN,LARGE_INTEGER*); void WINAPI KeEnterCriticalRegion(void); +ULONG WINAPI KeGetCurrentProcessorNumber(void); PKTHREAD WINAPI KeGetCurrentThread(void); void WINAPI KeInitializeEvent(PRKEVENT,EVENT_TYPE,BOOLEAN); void WINAPI KeInitializeMutex(PRKMUTEX,ULONG);
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 5 +++++ dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 1 + include/ddk/wdm.h | 1 + 3 files changed, 7 insertions(+)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index c4f2180c4c..2291842a67 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -4011,3 +4011,8 @@ BOOLEAN WINAPI KdRefreshDebuggerNotPresent(void)
return !KdDebuggerEnabled; } + +void WINAPI KeSignalCallDpcDone(void *barrier) +{ + InterlockedDecrement((LONG *)barrier); +} diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index c4ddfb2830..28f8d5e4cd 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -59,6 +59,7 @@ @ stub KeSetTimeUpdateNotifyRoutine @ stub KefAcquireSpinLockAtDpcLevel @ stub KefReleaseSpinLockFromDpcLevel +@ stdcall KeSignalCallDpcDone(ptr) @ stub KiAcquireSpinLock @ stub KiReleaseSpinLock @ stdcall -fastcall ObfDereferenceObject(ptr) diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index c1d083ef01..b11f4d239d 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1713,6 +1713,7 @@ KPRIORITY WINAPI KeSetPriorityThread(PKTHREAD,KPRIORITY); void WINAPI KeSetSystemAffinityThread(KAFFINITY); KAFFINITY WINAPI KeSetSystemAffinityThreadEx(KAFFINITY affinity); BOOLEAN WINAPI KeSetTimerEx(KTIMER*,LARGE_INTEGER,LONG,KDPC*); +void WINAPI KeSignalCallDpcDone(void*); NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG,void*[],WAIT_TYPE,KWAIT_REASON,KPROCESSOR_MODE,BOOLEAN,LARGE_INTEGER*,KWAIT_BLOCK*); NTSTATUS WINAPI KeWaitForSingleObject(void*,KWAIT_REASON,KPROCESSOR_MODE,BOOLEAN,LARGE_INTEGER*);
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 113 ++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 1 + include/ddk/wdm.h | 7 ++ 3 files changed, 121 insertions(+)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 2291842a67..1a0cf1c5c2 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -72,6 +72,10 @@ KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[4] = { { 0 } };
#define MAX_SERVICE_NAME 260
+static TP_POOL *dpc_call_tp; +static TP_CALLBACK_ENVIRON dpc_call_tpe; +DECLARE_CRITICAL_SECTION(dpc_call_cs); + /* tid of the thread running client request */ static DWORD request_thread;
@@ -3160,6 +3164,10 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved ) break; case DLL_PROCESS_DETACH: if (reserved) break; + + if (dpc_call_tp) + CloseThreadpool(dpc_call_tp); + HeapDestroy( ntoskrnl_heap ); RtlRemoveVectoredExceptionHandler( handler ); break; @@ -4012,6 +4020,111 @@ BOOLEAN WINAPI KdRefreshDebuggerNotPresent(void) return !KdDebuggerEnabled; }
+struct generic_call_dpc_context +{ + DEFERRED_REVERSE_BARRIER *reverse_barrier; + PKDEFERRED_ROUTINE routine; + ULONG *cpu_count_barrier; + void *context; + ULONG cpu_index; +}; + +static void WINAPI generic_call_dpc_callback(TP_CALLBACK_INSTANCE *instance, void *context) +{ + struct generic_call_dpc_context *c = context; + GROUP_AFFINITY old, new; + + TRACE("instance %p, context %p.\n", instance, context); + + NtQueryInformationThread(GetCurrentThread(), ThreadGroupInformation, + &old, sizeof(old), NULL); + + memset(&new, 0, sizeof(new)); + + new.Mask = 1 << c->cpu_index; + NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation, &new, sizeof(new)); + + c->routine((PKDPC)0xdeadbeef, c->context, c->cpu_count_barrier, c->reverse_barrier); + NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation, &old, sizeof(old)); +} + +void WINAPI KeGenericCallDpc(PKDEFERRED_ROUTINE routine, void *context) +{ + ULONG cpu_count = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS); + static struct generic_call_dpc_context *contexts; + DEFERRED_REVERSE_BARRIER reverse_barrier; + static ULONG last_cpu_count; + ULONG cpu_count_barrier; + ULONG i; + + TRACE("routine %p, context %p.\n", routine, context); + + EnterCriticalSection(&dpc_call_cs); + + if (!dpc_call_tp) + { + if (!(dpc_call_tp = CreateThreadpool(NULL))) + { + ERR("Could not create thread pool.\n"); + LeaveCriticalSection(&dpc_call_cs); + return; + } + + SetThreadpoolThreadMinimum(dpc_call_tp, cpu_count); + SetThreadpoolThreadMaximum(dpc_call_tp, cpu_count); + + memset(&dpc_call_tpe, 0, sizeof(dpc_call_tpe)); + dpc_call_tpe.Version = 1; + dpc_call_tpe.Pool = dpc_call_tp; + } + + reverse_barrier.Barrier = cpu_count; + reverse_barrier.TotalProcessors = cpu_count; + cpu_count_barrier = cpu_count; + + if (contexts) + { + if (last_cpu_count < cpu_count) + { + static struct generic_call_dpc_context *new_contexts; + if (!(new_contexts = heap_realloc(contexts, sizeof(*contexts) * cpu_count))) + { + ERR("No memory.\n"); + LeaveCriticalSection(&dpc_call_cs); + return; + } + contexts = new_contexts; + SetThreadpoolThreadMinimum(dpc_call_tp, cpu_count); + SetThreadpoolThreadMaximum(dpc_call_tp, cpu_count); + } + } + else if (!(contexts = heap_alloc(sizeof(*contexts) * cpu_count))) + { + ERR("No memory.\n"); + LeaveCriticalSection(&dpc_call_cs); + return; + } + + memset(contexts, 0, sizeof(*contexts) * cpu_count); + last_cpu_count = cpu_count; + + for (i = 0; i < cpu_count; ++i) + { + contexts[i].reverse_barrier = &reverse_barrier; + contexts[i].cpu_count_barrier = &cpu_count_barrier; + contexts[i].routine = routine; + contexts[i].context = context; + contexts[i].cpu_index = i; + + TrySubmitThreadpoolCallback(generic_call_dpc_callback, &contexts[i], &dpc_call_tpe); + } + + while (InterlockedCompareExchange((LONG *)&cpu_count_barrier, 0, 0)) + SwitchToThread(); + + LeaveCriticalSection(&dpc_call_cs); +} + void WINAPI KeSignalCallDpcDone(void *barrier) { InterlockedDecrement((LONG *)barrier); diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 28f8d5e4cd..923ba22529 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -59,6 +59,7 @@ @ stub KeSetTimeUpdateNotifyRoutine @ stub KefAcquireSpinLockAtDpcLevel @ stub KefReleaseSpinLockFromDpcLevel +@ stdcall KeGenericCallDpc(ptr ptr) @ stdcall KeSignalCallDpcDone(ptr) @ stub KiAcquireSpinLock @ stub KiReleaseSpinLock diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index b11f4d239d..1b001d7424 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -122,6 +122,12 @@ typedef struct _KMUTANT { UCHAR ApcDisable; } KMUTANT, *PKMUTANT, *RESTRICTED_POINTER PRKMUTANT, KMUTEX, *PKMUTEX, *RESTRICTED_POINTER PRKMUTEX;
+typedef struct _DEFERRED_REVERSE_BARRIER +{ + ULONG Barrier; + ULONG TotalProcessors; +} DEFERRED_REVERSE_BARRIER; + typedef enum _KWAIT_REASON { Executive, @@ -1686,6 +1692,7 @@ BOOLEAN WINAPI KeCancelTimer(KTIMER*); void WINAPI KeClearEvent(PRKEVENT); NTSTATUS WINAPI KeDelayExecutionThread(KPROCESSOR_MODE,BOOLEAN,LARGE_INTEGER*); void WINAPI KeEnterCriticalRegion(void); +void WINAPI KeGenericCallDpc(PKDEFERRED_ROUTINE,PVOID); ULONG WINAPI KeGetCurrentProcessorNumber(void); PKTHREAD WINAPI KeGetCurrentThread(void); void WINAPI KeInitializeEvent(PRKEVENT,EVENT_TYPE,BOOLEAN);
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 46 +++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 1 + include/ddk/wdm.h | 1 + 3 files changed, 48 insertions(+)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 1a0cf1c5c2..bfac397011 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -75,6 +75,7 @@ KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[4] = { { 0 } }; static TP_POOL *dpc_call_tp; static TP_CALLBACK_ENVIRON dpc_call_tpe; DECLARE_CRITICAL_SECTION(dpc_call_cs); +static DWORD dpc_call_tls_index;
/* tid of the thread running client request */ static DWORD request_thread; @@ -3161,6 +3162,7 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved ) KeQueryTickCount( &count ); /* initialize the global KeTickCount */ NtBuildNumber = NtCurrentTeb()->Peb->OSBuildNumber; ntoskrnl_heap = HeapCreate( HEAP_CREATE_ENABLE_EXECUTE, 0, 0 ); + dpc_call_tls_index = TlsAlloc(); break; case DLL_PROCESS_DETACH: if (reserved) break; @@ -4027,6 +4029,8 @@ struct generic_call_dpc_context ULONG *cpu_count_barrier; void *context; ULONG cpu_index; + ULONG current_barrier_flag; + LONG *barrier_passed_count; };
static void WINAPI generic_call_dpc_callback(TP_CALLBACK_INSTANCE *instance, void *context) @@ -4044,7 +4048,9 @@ static void WINAPI generic_call_dpc_callback(TP_CALLBACK_INSTANCE *instance, voi new.Mask = 1 << c->cpu_index; NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation, &new, sizeof(new));
+ TlsSetValue(dpc_call_tls_index, context); c->routine((PKDPC)0xdeadbeef, c->context, c->cpu_count_barrier, c->reverse_barrier); + TlsSetValue(dpc_call_tls_index, NULL); NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation, &old, sizeof(old)); }
@@ -4054,6 +4060,7 @@ void WINAPI KeGenericCallDpc(PKDEFERRED_ROUTINE routine, void *context) static struct generic_call_dpc_context *contexts; DEFERRED_REVERSE_BARRIER reverse_barrier; static ULONG last_cpu_count; + LONG barrier_passed_count; ULONG cpu_count_barrier; ULONG i;
@@ -4107,6 +4114,7 @@ void WINAPI KeGenericCallDpc(PKDEFERRED_ROUTINE routine, void *context)
memset(contexts, 0, sizeof(*contexts) * cpu_count); last_cpu_count = cpu_count; + barrier_passed_count = 0;
for (i = 0; i < cpu_count; ++i) { @@ -4115,6 +4123,7 @@ void WINAPI KeGenericCallDpc(PKDEFERRED_ROUTINE routine, void *context) contexts[i].routine = routine; contexts[i].context = context; contexts[i].cpu_index = i; + contexts[i].barrier_passed_count = &barrier_passed_count;
TrySubmitThreadpoolCallback(generic_call_dpc_callback, &contexts[i], &dpc_call_tpe); } @@ -4125,6 +4134,43 @@ void WINAPI KeGenericCallDpc(PKDEFERRED_ROUTINE routine, void *context) LeaveCriticalSection(&dpc_call_cs); }
+ +BOOLEAN WINAPI KeSignalCallDpcSynchronize(void *barrier) +{ + struct generic_call_dpc_context *context = TlsGetValue(dpc_call_tls_index); + DEFERRED_REVERSE_BARRIER *b = barrier; + LONG curr_flag, comp, done_value; + BOOL first; + + TRACE("barrier %p, context %p.\n", barrier, context); + + if (!context) + { + WARN("Called outside of DPC context.\n"); + return FALSE; + } + + context->current_barrier_flag ^= 0x80000000; + curr_flag = context->current_barrier_flag; + + first = !context->cpu_index; + comp = curr_flag + context->cpu_index; + done_value = curr_flag + b->TotalProcessors; + + if (first) + InterlockedExchange((LONG *)&b->Barrier, comp); + + while (InterlockedCompareExchange((LONG *)&b->Barrier, comp + 1, comp) != done_value) + ; + + InterlockedIncrement(context->barrier_passed_count); + + while (first && InterlockedCompareExchange(context->barrier_passed_count, 0, b->TotalProcessors)) + ; + + return first; +} + void WINAPI KeSignalCallDpcDone(void *barrier) { InterlockedDecrement((LONG *)barrier); diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 923ba22529..331b03ba9f 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -61,6 +61,7 @@ @ stub KefReleaseSpinLockFromDpcLevel @ stdcall KeGenericCallDpc(ptr ptr) @ stdcall KeSignalCallDpcDone(ptr) +@ stdcall KeSignalCallDpcSynchronize(ptr) @ stub KiAcquireSpinLock @ stub KiReleaseSpinLock @ stdcall -fastcall ObfDereferenceObject(ptr) diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 1b001d7424..8368f8c6e9 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1721,6 +1721,7 @@ void WINAPI KeSetSystemAffinityThread(KAFFINITY); KAFFINITY WINAPI KeSetSystemAffinityThreadEx(KAFFINITY affinity); BOOLEAN WINAPI KeSetTimerEx(KTIMER*,LARGE_INTEGER,LONG,KDPC*); void WINAPI KeSignalCallDpcDone(void*); +BOOLEAN WINAPI KeSignalCallDpcSynchronize(void*); NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG,void*[],WAIT_TYPE,KWAIT_REASON,KPROCESSOR_MODE,BOOLEAN,LARGE_INTEGER*,KWAIT_BLOCK*); NTSTATUS WINAPI KeWaitForSingleObject(void*,KWAIT_REASON,KPROCESSOR_MODE,BOOLEAN,LARGE_INTEGER*);
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntoskrnl.exe/tests/driver.c | 115 +++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+)
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 356c60a2e7..89a352f46d 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -1779,6 +1779,120 @@ 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, done_barrier_end_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); + + data->done_barrier_end_value = *(volatile LONG *)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); + ok(!data.done_barrier_end_value, "Got unexpected done_barrier_end_value %d.\n", data.done_barrier_end_value); + + KeRevertToUserAffinityThread(); +} + static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack) { ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; @@ -1833,6 +1947,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;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=72313
Your paranoid android.
=== debiant (32 bit WoW report) ===
ntoskrnl.exe: driver.c:1891: Test failed: Got unexpected done_barrier_end_value 1.