From 7d8b33390a1e94d6cfb33b404279056c5ad8f6ef Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 30 May 2026 23:53:47 +0200 Subject: [PATCH] Add runtime accounting and DPC throttling --- sdk/xtdk/amd64/ketypes.h | 14 ++++++ sdk/xtdk/i686/ketypes.h | 14 ++++++ xtoskrnl/ke/dispatch.cc | 98 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+) diff --git a/sdk/xtdk/amd64/ketypes.h b/sdk/xtdk/amd64/ketypes.h index 1c9b2b5..d6e0b9d 100644 --- a/sdk/xtdk/amd64/ketypes.h +++ b/sdk/xtdk/amd64/ketypes.h @@ -133,6 +133,15 @@ #define CONTEXT_FLOATING_POINT (CONTEXT_ARCHITECTURE | 0x08) #define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARCHITECTURE | 0x10) +/* Clock control flags */ +#define CLOCK_QUANTUM_DECREMENT 3 + +/* DPC definitions */ +#define DPC_ADJUST_THRESHOLD 20 +#define DPC_IDEAL_RATE 20 +#define DPC_MAXIMUM_QUEUE_DEPTH 4 +#define DPC_MINIMUM_RATE 3 + /* Interrupt request levels definitions */ #define PASSIVE_LEVEL 0 #define LOW_LEVEL 0 @@ -564,7 +573,11 @@ typedef struct _KPROCESSOR_CONTROL_BLOCK KSPIN_LOCK_QUEUE LockQueue[MaximumLock]; KDPC_DATA DpcData[2]; PVOID DpcStack; + LONG MaximumDpcQueueDepth; + ULONG DpcRequestRate; + BOOLEAN DpcInterruptRequested; VOLATILE BOOLEAN DpcRoutineActive; + ULONG DpcLastCount; VOLATILE ULONG_PTR TimerHand; VOLATILE ULONG_PTR TimerRequest; ULONG_PTR MultiThreadProcessorSet; @@ -574,6 +587,7 @@ typedef struct _KPROCESSOR_CONTROL_BLOCK ULONG UserTime; ULONG DpcTime; ULONG InterruptTime; + ULONG AdjustDpcThreshold; PROCESSOR_POWER_STATE PowerState; ULONG ProfilingCountdown; } KPROCESSOR_CONTROL_BLOCK, *PKPROCESSOR_CONTROL_BLOCK; diff --git a/sdk/xtdk/i686/ketypes.h b/sdk/xtdk/i686/ketypes.h index 8da6b5a..1fc3a85 100644 --- a/sdk/xtdk/i686/ketypes.h +++ b/sdk/xtdk/i686/ketypes.h @@ -155,6 +155,15 @@ #define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARCHITECTURE | 0x10) #define CONTEXT_EXTENDED_REGISTERS (CONTEXT_ARCHITECTURE | 0x20) +/* Clock control flags */ +#define CLOCK_QUANTUM_DECREMENT 3 + +/* DPC definitions */ +#define DPC_ADJUST_THRESHOLD 20 +#define DPC_IDEAL_RATE 20 +#define DPC_MAXIMUM_QUEUE_DEPTH 4 +#define DPC_MINIMUM_RATE 3 + /* Interrupt request levels definitions */ #define PASSIVE_LEVEL 0 #define LOW_LEVEL 0 @@ -524,7 +533,11 @@ typedef struct _KPROCESSOR_CONTROL_BLOCK ULONG_PTR MultiThreadProcessorSet; KDPC_DATA DpcData[2]; PVOID DpcStack; + LONG MaximumDpcQueueDepth; + ULONG DpcRequestRate; + BOOLEAN DpcInterruptRequested; VOLATILE BOOLEAN DpcRoutineActive; + ULONG DpcLastCount; VOLATILE ULONG_PTR TimerHand; VOLATILE ULONG_PTR TimerRequest; SINGLE_LIST_ENTRY DeferredReadyListHead; @@ -533,6 +546,7 @@ typedef struct _KPROCESSOR_CONTROL_BLOCK ULONG UserTime; ULONG DpcTime; ULONG InterruptTime; + ULONG AdjustDpcThreshold; PROCESSOR_POWER_STATE PowerState; ULONG ProfilingCountdown; } KPROCESSOR_CONTROL_BLOCK, *PKPROCESSOR_CONTROL_BLOCK; diff --git a/xtoskrnl/ke/dispatch.cc b/xtoskrnl/ke/dispatch.cc index 2682d4d..5654a46 100644 --- a/xtoskrnl/ke/dispatch.cc +++ b/xtoskrnl/ke/dispatch.cc @@ -4,6 +4,7 @@ * FILE: xtoskrnl/ke/dispatch.cc * DESCRIPTION: Kernel Thread Dispatcher * DEVELOPERS: Rafal Kupiec + * Aiken Harris */ #include @@ -66,4 +67,101 @@ VOID KE::Dispatcher::UpdateRunTime(IN PKTRAP_FRAME TrapFrame, IN KRUNLEVEL RunLevel) { + PKPROCESSOR_CONTROL_BLOCK ControlBlock; + PKTHREAD Thread; + + /* Retrieve current processor control block and current thread */ + ControlBlock = KE::Processor::GetCurrentProcessorControlBlock(); + Thread = KE::Processor::GetCurrentThread(); + + /* Increment interrupt count */ + ControlBlock->InterruptCount++; + + /* Check if the thread ran in user mode */ + if(TrapFrame->PreviousMode == UserMode) + { + /* Atomically increment the process-wide user time */ + RTL::Atomic::Increment32((PLONG)&Thread->ApcState.Process->UserTime); + + /* Increment thread and total time this processor has spent executing in user time */ + ControlBlock->UserTime++; + Thread->UserTime++; + } + else + { + /* Increment the total time this processor has spent executing in kernel mode */ + ControlBlock->KernelTime++; + + /* Check if normal kernel thread execution was interrupted */ + if((RunLevel < DISPATCH_LEVEL) || !(ControlBlock->DpcRoutineActive)) + { + /* Atomically increment the process-wide kernel time */ + RTL::Atomic::Increment32((PLONG)&Thread->ApcState.Process->KernelTime); + + /* Increment the kernel execution time for the current thread */ + Thread->KernelTime++; + } + else if(RunLevel > DISPATCH_LEVEL) + { + /* Increment the time spent servicing hardware interrupts */ + ControlBlock->InterruptTime++; + } + else + { + /* Increment the time spent servicing DPCs */ + ControlBlock->DpcTime++; + } + } + + /* Calculate the new DPC request rate as a moving average of the current and previous rates */ + ControlBlock->DpcRequestRate = ((ControlBlock->DpcData[0].DpcCount - ControlBlock->DpcLastCount) + + ControlBlock->DpcRequestRate) >> 1; + + /* Snapshot the current DPC count */ + ControlBlock->DpcLastCount = ControlBlock->DpcData[0].DpcCount; + + /* Check if there are pending DPCs, no DPC routine is currently executing, and DPC interrupt is not pending */ + if((ControlBlock->DpcData[0].DpcQueueDepth) && + !(ControlBlock->DpcRoutineActive) && + !(ControlBlock->DpcInterruptRequested)) + { + /* Reset the adjustment threshold counter */ + ControlBlock->AdjustDpcThreshold = DPC_ADJUST_THRESHOLD; + + /* Request a DISPATCH_LEVEL software interrupt to process the pending DPCs */ + HL::Irq::SendSoftwareInterrupt(DISPATCH_LEVEL); + + /* Evaluate if the DPC request rate is below the ideal threshold */ + if((ControlBlock->DpcRequestRate < DPC_IDEAL_RATE) && (ControlBlock->MaximumDpcQueueDepth > 1)) + { + /* Decrease the maximum queue depth */ + ControlBlock->MaximumDpcQueueDepth--; + } + } + else + { + /* Decrement the tuning threshold counter and verify if an adjustment cycle is required */ + if(!(--ControlBlock->AdjustDpcThreshold)) + { + /* Reset the counter for the next tuning cycle */ + ControlBlock->AdjustDpcThreshold = DPC_ADJUST_THRESHOLD; + + /* Check if the current queue depth limit is below the system-wide absolute maximum */ + if(ControlBlock->MaximumDpcQueueDepth != DPC_MAXIMUM_QUEUE_DEPTH) + { + /* Increase the maximum queue depth to batch more DPCs */ + ControlBlock->MaximumDpcQueueDepth++; + } + } + } + + /* Decrement the execution time slice */ + Thread->Quantum -= CLOCK_QUANTUM_DECREMENT; + + /* Check if the thread has exhausted its quantum, ignoring the idle thread */ + if((Thread->Quantum <= 0) && (Thread != ControlBlock->IdleThread)) + { + /* Request a DISPATCH_LEVEL software interrupt to preempt the thread */ + HL::Irq::SendSoftwareInterrupt(DISPATCH_LEVEL); + } }