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:
|
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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user