это правильный подход?
class TSingleProcessorMode2
{
volatile LONG Hub;
KDPC DpcArray[MAXIMUM_PROCESSORS];
static void DpcRoutine(KDPC* pDpc, void* pContext, void* pArg1, void* pArg2);
public:
void Initialize();
void Execute(void(__fastcall* Routine)(void*), void* pContext);
};
void TSingleProcessorMode2::Initialize()
{
RtlZeroMemory(this, sizeof(TSingleProcessorMode2));
if (KeQueryActiveProcessorCount(nullptr) > 1)
for (int i = 0; i < MAXIMUM_PROCESSORS; i++)
{
KeInitializeDpc(&DpcArray[i], DpcRoutine, this);
KeSetTargetProcessorDpc(&DpcArray[i], (CCHAR)i);
KeSetImportanceDpc(&DpcArray[i], HighImportance);
}
}
void TSingleProcessorMode2::DpcRoutine(KDPC* pDpc, void* pContext, void* pArg1, void* pArg2)
{
TSingleProcessorMode2* pThis = (TSingleProcessorMode2*)pContext;
#if _WIN32_WINNT < 0x0502
KeRaiseIrqlToSynchLevel();
#else
//KIRQL DummyIrql;
//KeRaiseIrql(12, &DummyIrql);
KeRaiseIrqlToSynchLevel();
#endif
while (true)
{
KIRQL DummyIrql;
KeRaiseIrql(HIGH_LEVEL, &DummyIrql);
LONG probe, level = InterlockedDecrement(&pThis->Hub) << 8;
if (level == 0)
{
((void(__fastcall*)(void*))pArg1)(pArg2);
InterlockedExchange(&pThis->Hub, -1);
exit:
KeLowerIrql(DISPATCH_LEVEL);
return;
}
do
{
PERFORMANCE_AUTO_COUNT;
__nop();
probe = pThis->Hub;
if (probe < 0)
goto exit;
} while (probe == 0 || --level >= 0
|| InterlockedCompareExchange(&pThis->Hub, probe + 1, probe) != probe);
KeLowerIrql(12);
PERFORMANCE_AUTO_COUNT;
__nop();
}
}
void TSingleProcessorMode2::Execute(void(__fastcall* pRoutine)(void*), void* pContext)
{
KeEnterCriticalRegion();
KeFlushQueuedDpcs();
if (KeQueryActiveProcessorCount(nullptr) > 1)
{
KAFFINITY ActiveProcessors = KeQueryActiveProcessors();
KIRQL Irql;
KeRaiseIrql(DISPATCH_LEVEL, &Irql);
KAFFINITY Mask = 1ul << 0; // Mask for core 0
if ((ActiveProcessors & Mask) != 0 && KeGetCurrentProcessorNumber() != 0)
{
ActiveProcessors &= ~Mask; // Clear the bit for core 0 first
KeInsertQueueDpc(&DpcArray[0], pRoutine, pContext); // Queue DPC for core 0
}
KeLowerIrql(Irql);
}
else
{
KIRQL DummyIrql;
KeRaiseIrql(HIGH_LEVEL, &DummyIrql);
pRoutine(pContext);
KeLowerIrql(DummyIrql);
}
KeFlushQueuedDpcs();
KeLeaveCriticalRegion();
}