forked from xt-sys/exectos
Implement thread preemption and context switching in dispatch interrupt handler
This commit is contained in:
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user