Implement thread preemption and context switching in dispatch interrupt handler
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 34s
Builds / ExectOS (i686, debug) (push) Successful in 33s
Builds / ExectOS (i686, release) (push) Successful in 46s
Builds / ExectOS (amd64, release) (push) Successful in 48s

This commit is contained in:
2026-06-18 11:18:36 +02:00
parent 156ae3efab
commit bae43034a6
3 changed files with 96 additions and 2 deletions

View File

@@ -19,7 +19,10 @@ namespace KE
{ {
public: public:
STATIC XTFASTCALL VOID InsertDeferredReadyList(IN PKTHREAD Thread); STATIC XTFASTCALL VOID InsertDeferredReadyList(IN PKTHREAD Thread);
STATIC XTAPI VOID ProcessQuantumEnd(VOID);
STATIC XTAPI VOID ProcessReadyThread(IN PKTHREAD Thread); 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); STATIC XTAPI VOID ReadyThread(IN PKTHREAD Thread);
}; };
} }

View File

@@ -115,8 +115,64 @@ XTCDECL
VOID VOID
KE::Dispatcher::HandleDispatchInterrupt(IN PKTRAP_FRAME TrapFrame) 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 */ /* End the interrupt */
HL::Pic::SendEoi(); 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 */ /* Reset the adjustment threshold counter */
ControlBlock->AdjustDpcThreshold = DPC_ADJUST_THRESHOLD; 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); HL::Irq::SendSoftwareInterrupt(DISPATCH_LEVEL);
/* Evaluate if the DPC request rate is below the ideal threshold */ /* 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 */ /* Check if the thread has exhausted its quantum, ignoring the idle thread */
if((Thread->Quantum <= 0) && (Thread != ControlBlock->IdleThread)) 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); HL::Irq::SendSoftwareInterrupt(DISPATCH_LEVEL);
} }
} }

View File

@@ -36,6 +36,20 @@ KE::Scheduler::InsertDeferredReadyList(IN PKTHREAD Thread)
RTL::LifoQueue::PushEntryList(&Prcb->DeferredReadyListHead, &Thread->SwapListEntry); 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. * 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. * Prepares a thread for execution by safely acquiring the dispatcher database lock.
* *