forked from xt-sys/exectos
Implement idle thread loop
This commit is contained in:
@@ -18,6 +18,7 @@ namespace KE
|
|||||||
class Dispatcher
|
class Dispatcher
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
STATIC XTAPI VOID EnterIdleLoop(VOID);
|
||||||
STATIC XTFASTCALL VOID ExitDispatcher(IN KRUNLEVEL OldRunLevel);
|
STATIC XTFASTCALL VOID ExitDispatcher(IN KRUNLEVEL OldRunLevel);
|
||||||
STATIC XTCDECL VOID HandleDispatchInterrupt(IN PKTRAP_FRAME TrapFrame);
|
STATIC XTCDECL VOID HandleDispatchInterrupt(IN PKTRAP_FRAME TrapFrame);
|
||||||
STATIC XTFASTCALL BOOLEAN SwitchContext(IN PKTHREAD CurrentThread,
|
STATIC XTFASTCALL BOOLEAN SwitchContext(IN PKTHREAD CurrentThread,
|
||||||
|
|||||||
@@ -10,6 +10,76 @@
|
|||||||
#include <xtos.hh>
|
#include <xtos.hh>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enters the system idle thread loop for the current processor, running continuously when no other
|
||||||
|
* threads are scheduled for execution.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
VOID
|
||||||
|
KE::Dispatcher::EnterIdleLoop(VOID)
|
||||||
|
{
|
||||||
|
PKTHREAD CurrentThread, NextThread;
|
||||||
|
PKPROCESSOR_CONTROL_BLOCK Prcb;
|
||||||
|
|
||||||
|
/* Retrieve the processor control block */
|
||||||
|
Prcb = KE::Processor::GetCurrentProcessorControlBlock();
|
||||||
|
|
||||||
|
/* Enter the infinite idle loop */
|
||||||
|
while(TRUE)
|
||||||
|
{
|
||||||
|
/* Temporarily enable interrupts and yield the processor to handle pending hardware events */
|
||||||
|
AR::CpuFunctions::SetInterruptFlag();
|
||||||
|
AR::CpuFunctions::YieldProcessor();
|
||||||
|
AR::CpuFunctions::YieldProcessor();
|
||||||
|
AR::CpuFunctions::ClearInterruptFlag();
|
||||||
|
|
||||||
|
/* Check for pending deferred ready threads, DPCs, or timer requests */
|
||||||
|
if(Prcb->DeferredReadyListHead.Next ||
|
||||||
|
Prcb->DpcData[0].DpcQueueDepth ||
|
||||||
|
Prcb->TimerRequest)
|
||||||
|
{
|
||||||
|
/* Unimplemented path */
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if a new thread has been scheduled for execution */
|
||||||
|
if(Prcb->NextThread)
|
||||||
|
{
|
||||||
|
/* Enable interrupts to allow hardware events during context switch preparation */
|
||||||
|
AR::CpuFunctions::SetInterruptFlag();
|
||||||
|
|
||||||
|
/* Capture the current and next thread pointers */
|
||||||
|
CurrentThread = Prcb->CurrentThread;
|
||||||
|
NextThread = Prcb->NextThread;
|
||||||
|
|
||||||
|
/* Update the processor control block with the incoming thread */
|
||||||
|
Prcb->NextThread = NULLPTR;
|
||||||
|
Prcb->CurrentThread = NextThread;
|
||||||
|
|
||||||
|
/* Transition the incoming thread to the running state */
|
||||||
|
NextThread->State = Running;
|
||||||
|
|
||||||
|
/* Start a guarded code block */
|
||||||
|
{
|
||||||
|
/* Raise runlevel to SYNC level */
|
||||||
|
KE::RaiseRunLevel RunLevel(SYNC_LEVEL);
|
||||||
|
|
||||||
|
/* Perform the context switch away from the idle thread */
|
||||||
|
KE::Dispatcher::SwitchContext(CurrentThread, APC_LEVEL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No threads scheduled, enter a low-power processor state and wait for interrupts */
|
||||||
|
Prcb->PowerState.IdleFunction(&Prcb->PowerState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exits the dispatcher, switches context to a new thread and lowers runlevel to its original state.
|
* Exits the dispatcher, switches context to a new thread and lowers runlevel to its original state.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user