Files
exectos/xtoskrnl/ke/timer.cc
Aiken Harris f562aa0874
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 38s
Builds / ExectOS (i686, release) (push) Successful in 36s
Builds / ExectOS (amd64, debug) (push) Successful in 47s
Builds / ExectOS (i686, debug) (push) Successful in 46s
Implement timer table list and check for expired timers
2026-05-28 00:36:25 +02:00

261 lines
6.4 KiB
C++

/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/ke/timer.cc
* DESCRIPTION: Kernel timer object support
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
* Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Cancels the timer.
*
* @param Timer
* Supplies a pointer to a timer object.
*
* @return This routine returns TRUE if the cancelled timer was set, or FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
KE::Timer::CancelTimer(IN PKTIMER Timer)
{
BOOLEAN Result;
KRUNLEVEL RunLevel;
/* Set default result value */
Result = FALSE;
/* Raise run level and acquire dispatcher lock */
RunLevel = KE::RunLevel::RaiseRunLevel(SYNC_LEVEL);
KE::SpinLock::AcquireQueuedSpinLock(DispatcherLock);
/* Check timer status */
if(Timer->Header.Inserted)
{
/* Remove the timer from the list */
RemoveTimer(Timer);
Result = TRUE;
}
/* Release dispatcher lock and process the deferred ready list */
KE::SpinLock::ReleaseQueuedSpinLock(DispatcherLock);
KE::Dispatcher::ExitDispatcher(RunLevel);
/* Return result */
return Result;
}
/**
* Clears the signal state of the timer.
*
* @param Timer
* Supplies a pointer to a timer object.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Timer::ClearTimer(IN PKTIMER Timer)
{
/* Clear signal state */
Timer->Header.SignalState = 0;
}
/**
* Reads the current signal state of the given timer.
*
* @param Timer
* Supplies a pointer to a timer object.
*
* @return This routine returns TRUE if the timer is set, or FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
KE::Timer::GetState(IN PKTIMER Timer)
{
/* Return timer state */
return (BOOLEAN)Timer->Header.SignalState;
}
/**
* Initializes an extended kernel timer.
*
* @param Timer
* Supplies a pointer to a timer object.
*
* @param Type
* Supplies the type of the timer.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Timer::InitializeTimer(OUT PKTIMER Timer,
IN KTIMER_TYPE Type)
{
/* Initialize the header */
Timer->Header.Type = TimerNotificationObject + (UCHAR)Type;
Timer->Header.Inserted = 0;
Timer->Header.SignalState = 0;
/* Initialize the timer data */
Timer->DueTime.QuadPart = 0;
Timer->Period = 0;
/* Initialize linked lists */
RTL::LinkedList::InitializeListHead(&Timer->Header.WaitListHead);
RTL::LinkedList::InitializeListHead(&Timer->TimerListEntry);
}
/**
* Queries the timer's interrupt due time.
*
* @param Timer
* Supplies a pointer to a timer object.
*
* @return This routine returns the time remaining on the timer, or 0 if the timer is not set.
*
* @since XT 1.0
*/
XTAPI
ULONGLONG
KE::Timer::QueryTimer(IN PKTIMER Timer)
{
KRUNLEVEL RunLevel;
ULONGLONG DueTime;
/* Set initial due time */
DueTime = 0;
/* Raise run level and acquire dispatcher lock */
RunLevel = KE::RunLevel::RaiseRunLevel(SYNC_LEVEL);
KE::SpinLock::AcquireQueuedSpinLock(DispatcherLock);
/* Check timer status */
if(Timer->Header.Inserted)
{
/* Get timer's due time */
DueTime = Timer->DueTime.QuadPart;
}
/* Release dispatcher lock and process the deferred ready list */
KE::SpinLock::ReleaseQueuedSpinLock(DispatcherLock);
KE::Dispatcher::ExitDispatcher(RunLevel);
/* Return timer's due time */
return DueTime;
}
/**
* Removes a specified timer from the timer list.
*
* @param Timer
* Supplies a pointer to a timer object.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Timer::RemoveTimer(IN OUT PKTIMER Timer)
{
/* Remove the timer from the list */
Timer->Header.Inserted = FALSE;
RTL::LinkedList::RemoveEntryList(&Timer->TimerListEntry);
}
/**
* Sets the supplied timer to expire at the specified time.
*
* @param Timer
* Supplies a pointer to a timer object.
*
* @param DueTime
* Supplies the time at which the timer should expire (both absolute and relative times are supported).
*
* @param Period
* Supplies the timer period.
*
* @param Dpc
* Supplies a pointer to a Deferred Procedure Call (DPC) object.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Timer::SetTimer(IN PKTIMER Timer,
IN LARGE_INTEGER DueTime,
IN LONG Period,
IN PKDPC Dpc)
{
UNIMPLEMENTED;
}
/**
* Verifies if any system timers have expired for the current tick and requests a software
* DISPATCH interrupt to process them if necessary.
*
* @param Prcb
* Supplies a pointer to the current Processor Control Block.
*
* @param TrapFrame
* Supplies a pointer to the trap frame representing the interrupted context.
*
* @param Time
* Supplies the current absolute interrupt time.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Timer::VerifySystemTimerExpiration(IN PKPROCESSOR_CONTROL_BLOCK Prcb,
IN PKTRAP_FRAME TrapFrame,
IN LARGE_INTEGER Time)
{
LARGE_INTEGER TickCount;
ULONG TimerHand;
PKTIMER Timer;
/* Retrieve the current system tick count and calculate the index into the timer table */
TickCount = KE::SharedData::GetTickCount();
TimerHand = TickCount.LowPart & (KTIMER_TABLE_SIZE - 1);
/* Check if there are any active timers scheduled */
if(!RTL::LinkedList::ListEmpty(&TimerTableListHead[TimerHand]))
{
/* Retrieve the first timer object from the list */
Timer = CONTAIN_RECORD((&TimerTableListHead[TimerHand])->Flink, KTIMER, TimerListEntry);
/* Check if the timer due time has been reached */
if(Timer->DueTime.QuadPart <= Time.QuadPart)
{
/* Ensure there is no pending timer expiration request */
if(!Prcb->TimerRequest)
{
/* Register the timer expiration request and record a timer slot */
Prcb->TimerRequest = (ULONG_PTR)TrapFrame;
Prcb->TimerHand = TimerHand;
/* Request a DPC to safely retire the timer */
HL::Irq::SendSoftwareInterrupt(DISPATCH_LEVEL);
}
}
}
}