From bae43034a6ee8414d05f77e7e30b8ea09d105632 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 18 Jun 2026 11:18:36 +0200 Subject: [PATCH] Implement thread preemption and context switching in dispatch interrupt handler --- xtoskrnl/includes/ke/schedule.hh | 3 ++ xtoskrnl/ke/dispatch.cc | 60 ++++++++++++++++++++++++++++++-- xtoskrnl/ke/schedule.cc | 35 +++++++++++++++++++ 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/xtoskrnl/includes/ke/schedule.hh b/xtoskrnl/includes/ke/schedule.hh index f71f63f..fbbdf8d 100644 --- a/xtoskrnl/includes/ke/schedule.hh +++ b/xtoskrnl/includes/ke/schedule.hh @@ -19,7 +19,10 @@ namespace KE { public: STATIC XTFASTCALL VOID InsertDeferredReadyList(IN PKTHREAD Thread); + STATIC XTAPI VOID ProcessQuantumEnd(VOID); STATIC XTAPI VOID ProcessReadyThread(IN PKTHREAD Thread); + STATIC XTFASTCALL VOID QueueReadyThread(IN PKTHREAD Thread, + IN PKPROCESSOR_CONTROL_BLOCK Prcb); STATIC XTAPI VOID ReadyThread(IN PKTHREAD Thread); }; } diff --git a/xtoskrnl/ke/dispatch.cc b/xtoskrnl/ke/dispatch.cc index 33ec4d2..b051b62 100644 --- a/xtoskrnl/ke/dispatch.cc +++ b/xtoskrnl/ke/dispatch.cc @@ -115,8 +115,64 @@ XTCDECL VOID KE::Dispatcher::HandleDispatchInterrupt(IN PKTRAP_FRAME TrapFrame) { + PKTHREAD CurrentThread, NextThread; + PKPROCESSOR_CONTROL_BLOCK Prcb; + + /* Receive the Processor Control Block*/ + Prcb = KE::Processor::GetCurrentProcessorControlBlock(); + + /* Raise runlevel to DISPATCH level */ + KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); + /* End the interrupt */ HL::Pic::SendEoi(); + + /* Check if there is pending deferred work */ + if(Prcb->DeferredReadyListHead.Next || + Prcb->DpcData[0].DpcQueueDepth || + Prcb->TimerRequest) + { + UNIMPLEMENTED; + } + + /* Re-enable hardware interrupts */ + AR::CpuFunctions::SetInterruptFlag(); + + /* Check if the current thread has exhausted its execution quantum */ + if((Prcb->CurrentThread->Quantum <= 0) && (Prcb->CurrentThread != Prcb->IdleThread)) + { + /* Trigger the scheduler to recalculate thread parameters */ + KE::Scheduler::ProcessQuantumEnd(); + } + else if(Prcb->NextThread) + { + /* Start a guarded code block */ + { + /* Lock the processor control block */ + KE::SpinLockGuard ControlBlockGuard(&Prcb->PrcbLock); + + /* Capture the outgoing (preempted) and incoming threads */ + CurrentThread = Prcb->CurrentThread; + NextThread = Prcb->NextThread; + + /* Acknowledge the pending thread and swap the pointers */ + Prcb->NextThread = NULLPTR; + Prcb->CurrentThread = NextThread; + + /* Update scheduling states */ + NextThread->State = Running; + CurrentThread->WaitReason = WrDispatchInt; + + /* Re-queue the preempted thread back into the local run queue or defer it */ + KE::Scheduler::QueueReadyThread(CurrentThread, Prcb); + } + + /* Perform the context switch */ + SwitchContext(CurrentThread, APC_LEVEL); + } + + /* Disable hardware interrupts before returning from the handler */ + AR::CpuFunctions::ClearInterruptFlag(); } /** @@ -198,7 +254,7 @@ KE::Dispatcher::UpdateRunTime(IN PKTRAP_FRAME TrapFrame, /* Reset the adjustment threshold counter */ ControlBlock->AdjustDpcThreshold = DPC_ADJUST_THRESHOLD; - /* Request a DISPATCH_LEVEL software interrupt to process the pending DPCs */ + /* 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 */ @@ -231,7 +287,7 @@ KE::Dispatcher::UpdateRunTime(IN PKTRAP_FRAME TrapFrame, /* 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 */ + /* Request a DISPATCH level software interrupt to preempt the thread */ HL::Irq::SendSoftwareInterrupt(DISPATCH_LEVEL); } } diff --git a/xtoskrnl/ke/schedule.cc b/xtoskrnl/ke/schedule.cc index c9b5ae1..320acad 100644 --- a/xtoskrnl/ke/schedule.cc +++ b/xtoskrnl/ke/schedule.cc @@ -36,6 +36,20 @@ KE::Scheduler::InsertDeferredReadyList(IN PKTHREAD Thread) RTL::LifoQueue::PushEntryList(&Prcb->DeferredReadyListHead, &Thread->SwapListEntry); } +/** + * Handles the expiration of the currently executing thread's time quantum. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +KE::Scheduler::ProcessQuantumEnd(VOID) +{ + UNIMPLEMENTED; +} + /** * Transitions a thread to the ready state and queues it for execution within the dispatcher database. * @@ -74,6 +88,27 @@ KE::Scheduler::ProcessReadyThread(IN PKTHREAD Thread) } } +/** + * Enqueues a thread into the target processor's execution queue. + * + * @param Thread + * Supplies a pointer to the thread that is ready for execution. + * + * @param Prcb + * Supplies a pointer to the Processor Control Block of the target core. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTFASTCALL +VOID +KE::Scheduler::QueueReadyThread(IN PKTHREAD Thread, + IN PKPROCESSOR_CONTROL_BLOCK Prcb) +{ + UNIMPLEMENTED; +} + /** * Prepares a thread for execution by safely acquiring the dispatcher database lock. *