SuperTinyKernel™ RTOS 1.06.x
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk::time::TimerHost Class Reference

Software timer multiplexer that manages multiple Timer instances on top of a small fixed set of kernel tasks. More...

#include <stk_time_timer.h>

Collaboration diagram for stk::time::TimerHost:

Classes

class  Timer
 Abstract base class for a timer managed by TimerHost. More...
class  TimerWorkerTask
 Internal kernel task used by TimerHost for both the tick task and handler tasks. More...
struct  TimerCommand
 POD command record passed from the public API methods to the tick task via the command queue. More...

Public Types

enum  EConsts : size_t {
  TASK_COUNT = (1U + 1U ) ,
  TASK_TICK_MEMORY_SIZE = Max<size_t>(256U, STK_STACK_SIZE_MIN) ,
  TASK_HANDLER_STACK_SIZE = Max<size_t>( 256U , STK_STACK_SIZE_MIN)
}

Public Member Functions

 TimerHost ()
 Default constructor. Zero-initializes all internal state.
 ~TimerHost ()=default
 Destructor.
void Initialize (IKernel *kernel, EAccessMode mode)
 Initialize timer host instance.
bool Start (Timer &tmr, uint32_t delay, uint32_t period=0)
 Start timer.
bool Stop (Timer &tmr)
 Stop running timer.
bool Reset (Timer &tmr)
 Reset periodic timer's deadline.
bool Restart (Timer &tmr, uint32_t delay, uint32_t period=0)
 Atomically stop and re-start timer.
bool StartOrReset (Timer &tmr, uint32_t delay, uint32_t period=0)
 Start timer if inactive, or reset its deadline if already active and periodic.
bool SetPeriod (Timer &tmr, uint32_t period)
 Change the period of a running periodic timer without affecting its current deadline.
bool IsEmpty () const
 Return true if no timers are currently active.
size_t GetSize () const
 Return number of currently active timers.
bool Shutdown ()
 Shutdown host instance. All timers are stopped and removed from the host.
Ticks GetTimeNow () const
 Get current time.

Private Types

typedef void(* TimerFuncType) (TimerHost *host)
 Timer task function prototype.
typedef StackMemoryDef< TASK_TICK_MEMORY_SIZE >::Type TaskTickMemory
 Stack memory type for the single tick task.
typedef StackMemoryDef< TASK_HANDLER_STACK_SIZE >::Type TimerHostMemory
 Stack memory type for each handler task.
typedef sync::PipeT< Timer *, 32U > ReadyQueue
 Lock-free pipe used to transfer expired timer pointers from the tick task to handler tasks.
typedef sync::PipeT< TimerCommand, 32U > CommandQueue
 Lock-free pipe used to send TimerCommand records from API callers to the tick task.

Private Member Functions

 STK_NONCOPYABLE_CLASS (TimerHost)
void UpdateTime ()
 Tick task body: drives the timer list and dispatches expired timers.
void ProcessTimers ()
 Handler task body: dequeues expired timers and invokes their OnExpired() callbacks.
bool ProcessCommands (Timeout next_sleep)
 Drain the command queue and execute each pending command.
bool PushCommand (TimerCommand cmd)
 Enqueue a command for the tick task.

Private Attributes

TaskTickMemory m_task_tick_memory
 tick task memory
TimerHostMemory m_task_handler_memory [1U]
 handler task memory
TimerWorkerTask m_task_tick
 timer task
TimerWorkerTask m_task_process [1U]
 handler tasks
util::DListHead< Timer, false > m_active
 active timers (tick task only)
ReadyQueue m_queue
 queue of timers ready for handling
CommandQueue m_commands
 command queue
Ticks m_now
 last known current time (ticks)

Detailed Description

Software timer multiplexer that manages multiple Timer instances on top of a small fixed set of kernel tasks.

TimerHost internally runs two categories of tasks:

  • One tick task that maintains the active timer list, evaluates deadlines every wake cycle, and queues expired timers for dispatch.
  • One or more handler tasks (see STK_TIMER_THREADS_COUNT) that dequeue expired timers and invoke their OnExpired() callbacks.

All timers share the same tick and handler tasks, so the total kernel task overhead is constant regardless of how many timers are active.

Two timer modes are supported:

  • One-shot: fires once after delay ticks and becomes inactive automatically.
  • Periodic: fires every period ticks until explicitly stopped.
Note
TimerHost must be initialized before use by calling Initialize(). The maximum number of concurrently active timers is STK_TIMER_COUNT_MAX (default: 32). The maximum timer period is bounded by uint32_t (~49 days at 1 ms resolution).
// define a concrete timer by overriding OnExpired
class HeartbeatTimer : public stk::time::TimerHost::Timer
{
public:
{
// called every 500 ms
ToggleLed();
}
};
// declare host and timer instances (static storage, no heap)
HeartbeatTimer g_Heartbeat;
// one-shot example: send a delayed notification
class NotifyTimer : public stk::time::TimerHost::Timer
{
public:
{
g_Event.Signal();
}
};
NotifyTimer g_Notify;
void SetupTimers(stk::IKernel *kernel)
{
// initialize the host, must be called before Start()
// start 500 ms periodic heartbeat
uint32_t period = stk::GetTicksFromMsec(500);
g_TimerHost.Start(g_Heartbeat, period, period);
// start a one-shot notification after 1 second
uint32_t delay = stk::GetTicksFromMsec(1000);
g_TimerHost.Start(g_Notify, delay);
}
static stk::time::TimerHost * g_TimerHost
@ ACCESS_USER
Unprivileged access mode (access to some hardware is restricted, see CPU manual for details).
Definition stk_common.h:33
Software timer multiplexer that manages multiple Timer instances on top of a small fixed set of kerne...
void Initialize(IKernel *kernel, EAccessMode mode)
Initialize timer host instance.
bool Start(Timer &tmr, uint32_t delay, uint32_t period=0)
Start timer.
Abstract base class for a timer managed by TimerHost.
virtual void OnExpired(TimerHost *host)=0
Callback invoked by the handler task when this timer expires.
See also
TimerHost::Timer, STK_TIMER_THREADS_COUNT, STK_TIMER_HANDLER_STACK_SIZE, STK_TIMER_COUNT_MAX

Definition at line 111 of file stk_time_timer.h.

Member Typedef Documentation

◆ CommandQueue

Lock-free pipe used to send TimerCommand records from API callers to the tick task.

Definition at line 462 of file stk_time_timer.h.

◆ ReadyQueue

Lock-free pipe used to transfer expired timer pointers from the tick task to handler tasks.

Definition at line 457 of file stk_time_timer.h.

◆ TaskTickMemory

Stack memory type for the single tick task.

Definition at line 447 of file stk_time_timer.h.

◆ TimerFuncType

typedef void(* stk::time::TimerHost::TimerFuncType) (TimerHost *host)
private

Timer task function prototype.

Definition at line 318 of file stk_time_timer.h.

◆ TimerHostMemory

Stack memory type for each handler task.

Definition at line 452 of file stk_time_timer.h.

Member Enumeration Documentation

◆ EConsts

Enumerator
TASK_COUNT 

total number of tasks serving this instance

stack memory size of the tick task

TASK_TICK_MEMORY_SIZE 

stack memory size of the timer handler task

TASK_HANDLER_STACK_SIZE 

Definition at line 114 of file stk_time_timer.h.

115 {
118
121
124 };
#define STK_STACK_SIZE_MIN
Minimum stack size in elements of Word, shared by all stack allocation lower-bound checks.
Definition stk_defs.h:533
#define STK_TIMER_THREADS_COUNT
Number of threads handling timers in TimerHost (default: 1).
#define STK_TIMER_HANDLER_STACK_SIZE
Stack size of the timer handler, increase if your timers consume more (default: 256).
static constexpr T Max(T a, T b)
Compile-time maximum of two values.
Definition stk_defs.h:625
@ TASK_TICK_MEMORY_SIZE
stack memory size of the timer handler task
@ TASK_COUNT
total number of tasks serving this instance

Constructor & Destructor Documentation

◆ TimerHost()

stk::time::TimerHost::TimerHost ( )
inlineexplicit

Default constructor. Zero-initializes all internal state.

Note
Call Initialize() before using any other member function.

Definition at line 215 of file stk_time_timer.h.

217 m_active(), m_now(0)
218 {}
TimerWorkerTask m_task_process[1U]
handler tasks
TimerHostMemory m_task_handler_memory[1U]
handler task memory
Ticks m_now
last known current time (ticks)
util::DListHead< Timer, false > m_active
active timers (tick task only)
TimerWorkerTask m_task_tick
timer task
TaskTickMemory m_task_tick_memory
tick task memory

References m_active, m_now, m_task_handler_memory, m_task_process, m_task_tick, and m_task_tick_memory.

Referenced by Initialize(), stk::time::TimerHost::TimerWorkerTask::Initialize(), and STK_NONCOPYABLE_CLASS().

Here is the caller graph for this function:

◆ ~TimerHost()

stk::time::TimerHost::~TimerHost ( )
default

Destructor.

Note
MISRA deviation: [STK-DEV-005] Rule 10-3-2.

Member Function Documentation

◆ GetSize()

size_t stk::time::TimerHost::GetSize ( ) const
inline

Return number of currently active timers.

Returns
Active timer count.
Note
The value is advisory and may change immediately after the call.

Definition at line 300 of file stk_time_timer.h.

300{ return m_active.GetSize(); }

References m_active.

Referenced by stk_timerhost_get_size().

Here is the caller graph for this function:

◆ GetTimeNow()

Ticks stk::time::TimerHost::GetTimeNow ( ) const
inline

Get current time.

Returns
Current time (ticks).

Definition at line 310 of file stk_time_timer.h.

310{ return hw::ReadVolatile64(&m_now); }
static __stk_forceinline T ReadVolatile64(volatile const T *addr)
Atomically read a 64-bit volatile value.
Definition stk_arch.h:379

References m_now, and stk::hw::ReadVolatile64().

Referenced by stk_timerhost_get_time_now().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Initialize()

void stk::time::TimerHost::Initialize ( IKernel * kernel,
EAccessMode mode )
inline

Initialize timer host instance.

Parameters
[in]kernelKernel to which instance will be bound.
[in]modeAccess mode for the timer handling tasks which call expired timers.

Definition at line 502 of file stk_time_timer.h.

503{
504 for (size_t i = 0U; i < STK_TIMER_THREADS_COUNT; ++i)
505 {
506 m_task_process[i].Initialize(this, m_task_handler_memory[i], TASK_HANDLER_STACK_SIZE, mode, [](TimerHost *host)
507 {
508 host->ProcessTimers();
509 });
510 kernel->AddTask(&m_task_process[i]);
511 }
512
514 {
515 host->UpdateTime();
516 });
517 kernel->AddTask(&m_task_tick);
518}
TimerHost()
Default constructor. Zero-initializes all internal state.

References stk::ACCESS_USER, stk::IKernel::AddTask(), m_task_handler_memory, m_task_process, m_task_tick, m_task_tick_memory, ProcessTimers(), STK_TIMER_THREADS_COUNT, TASK_HANDLER_STACK_SIZE, TASK_TICK_MEMORY_SIZE, TimerHost(), and UpdateTime().

Referenced by stk::interop_c_helper::InitializeTimerHost().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsEmpty()

bool stk::time::TimerHost::IsEmpty ( ) const
inline

Return true if no timers are currently active.

Returns
True if active timer count is zero.
Note
The value is advisory and may change immediately after the call.

Definition at line 294 of file stk_time_timer.h.

294{ return m_active.IsEmpty(); }

References m_active.

Referenced by stk_timerhost_is_empty().

Here is the caller graph for this function:

◆ ProcessCommands()

bool stk::time::TimerHost::ProcessCommands ( Timeout next_sleep)
inlineprivate

Drain the command queue and execute each pending command.

Parameters
[in]next_sleepMaximum ticks to block waiting for the first command when the active list is non-empty. Overridden to WAIT_INFINITE when empty.
Returns
True to continue the tick loop; false when CMD_SHUTDOWN is processed.
Note
Called exclusively from the tick task (UpdateTime()).

Definition at line 814 of file stk_time_timer.h.

815{
816 TimerCommand cmd = {};
817 bool working = true;
818
819 // if nothing is active, sleep indefinitely until a command arrives
820 if (m_active.IsEmpty())
821 {
822 next_sleep = WAIT_INFINITE;
823 }
824
825 while (working)
826 {
827 if (!m_commands.Read(cmd, next_sleep))
828 {
829 break;
830 }
831
832 switch (cmd.cmd)
833 {
835 {
836 Timer *const tmr = cmd.timer;
837 STK_ASSERT(tmr != nullptr);
838
839 // reject if already active or linked (double-start)
840 if (!tmr->m_active)
841 {
842 STK_ASSERT(!tmr->IsLinked());
843
844 tmr->m_deadline = cmd.timestamp + static_cast<Ticks>(cmd.delay);
845 tmr->m_period = cmd.period;
846 tmr->m_active = true;
847 tmr->m_pending = false;
848
849 m_active.LinkBack(tmr);
850 next_sleep = NO_WAIT;
851 }
852
853 break; }
854
856 {
857 Timer *const tmr = cmd.timer;
858 STK_ASSERT(tmr != nullptr);
859
860 tmr->m_active = false;
861 tmr->m_pending = false;
862
863 // allow possibly duplicate CMD_STOP as it is harmless for the logic
864 if (tmr->IsLinked())
865 {
866 m_active.Unlink(tmr);
867 }
868
869 break; }
870
872 {
873 Timer *const tmr = cmd.timer;
874 STK_ASSERT(tmr != nullptr);
875
876 // only reset if still active and periodic
877 if (tmr->m_active && (tmr->m_period != 0U))
878 {
879 STK_ASSERT(tmr->GetHead() == &m_active);
880
881 tmr->m_deadline = cmd.timestamp + static_cast<Ticks>(tmr->m_period);
882 tmr->m_pending = false;
883
884 next_sleep = NO_WAIT;
885 }
886
887 break; }
888
890 {
891 // atomic stop + re-start: no precondition on current timer state
892 Timer *const tmr = cmd.timer;
893 STK_ASSERT(tmr != nullptr);
894
895 // unlink if currently in the active list
896 if (tmr->IsLinked())
897 {
898 m_active.Unlink(tmr);
899 }
900
901 // re-arm with fresh parameters
902 tmr->m_deadline = cmd.timestamp + static_cast<Ticks>(cmd.delay);
903 tmr->m_period = cmd.period;
904 tmr->m_active = true;
905 tmr->m_pending = false;
906 tmr->m_rearming = false;
907
908 // re-link to the back of the list
909 m_active.LinkBack(tmr);
910 next_sleep = NO_WAIT;
911
912 break; }
913
915 {
916 Timer *const tmr = cmd.timer;
917 STK_ASSERT(tmr != nullptr);
918
919 // not currently active: start with supplied parameters
920 if (!tmr->m_active)
921 {
922 STK_ASSERT(!tmr->IsLinked());
923
924 tmr->m_deadline = cmd.timestamp + static_cast<Ticks>(cmd.delay);
925 tmr->m_period = cmd.period;
926 tmr->m_active = true;
927 tmr->m_pending = false;
928 tmr->m_rearming = false;
929
930 m_active.LinkBack(tmr);
931 }
932 // active and periodic: reset deadline anchored to call-site timestamp
933 else if (tmr->m_period != 0U)
934 {
935 STK_ASSERT(tmr->GetHead() == &m_active);
936
937 tmr->m_deadline = cmd.timestamp + static_cast<Ticks>(tmr->m_period);
938 tmr->m_pending = false;
939 }
940 else
941 {
942 // noop
943 }
944
945 // active one-shot: no action - cannot reset a one-shot mid-flight,
946 // caller should use Restart() if unconditional re-arm is needed
947
948 next_sleep = NO_WAIT;
949
950 break; }
951
953 {
954 Timer *const tmr = cmd.timer;
955 STK_ASSERT(tmr != nullptr);
956 STK_ASSERT(cmd.period != 0U);
957
958 // guard: only apply if still active and periodic
959 if (tmr->m_active && (tmr->m_period != 0U))
960 {
961 STK_ASSERT(tmr->GetHead() == &m_active);
962
963 // new period takes effect on the next reload, current deadline is
964 // intentionally left unchanged so the in-flight interval is not
965 // truncated or extended, caller can follow up with Reset() if
966 // immediate application is required
967 tmr->m_period = cmd.period;
968 }
969
970 break; }
971
973 {
974 // wake all handler tasks with shutdown sentinels
975 for (size_t i = 0U; i < STK_TIMER_THREADS_COUNT; ++i)
976 {
977 STK_UNUSED(m_queue.Write(nullptr, NO_WAIT));
978 }
979
980 // signal UpdateTime() to exit its loop
981 working = false;
982
983 break; }
984
985 default:
986 {
987 STK_ASSERT(false);
988
989 break; }
990 }
991 }
992
993 return working;
994}
#define STK_UNUSED(X)
Explicitly marks a variable as unused to suppress compiler warnings.
Definition stk_defs.h:608
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:409
constexpr Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
Definition stk_common.h:189
int64_t Ticks
Ticks value.
Definition stk_common.h:130
constexpr Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
Definition stk_common.h:183
ReadyQueue m_queue
queue of timers ready for handling
CommandQueue m_commands
command queue
POD command record passed from the public API methods to the tick task via the command queue.
@ CMD_SET_PERIOD
change period of a running periodic timer
@ CMD_START_OR_RESET
start if inactive, reset deadline if active and periodic
@ CMD_RESTART
atomic stop + re-start

References stk::time::TimerHost::TimerCommand::cmd, stk::time::TimerHost::TimerCommand::CMD_RESET, stk::time::TimerHost::TimerCommand::CMD_RESTART, stk::time::TimerHost::TimerCommand::CMD_SET_PERIOD, stk::time::TimerHost::TimerCommand::CMD_SHUTDOWN, stk::time::TimerHost::TimerCommand::CMD_START, stk::time::TimerHost::TimerCommand::CMD_START_OR_RESET, stk::time::TimerHost::TimerCommand::CMD_STOP, stk::time::TimerHost::TimerCommand::delay, stk::util::DListEntry< T, TClosedLoop >::GetHead(), stk::util::DListEntry< T, TClosedLoop >::IsLinked(), m_active, stk::time::TimerHost::Timer::m_active, m_commands, stk::time::TimerHost::Timer::m_deadline, stk::time::TimerHost::Timer::m_pending, stk::time::TimerHost::Timer::m_period, m_queue, stk::time::TimerHost::Timer::m_rearming, stk::NO_WAIT, stk::time::TimerHost::TimerCommand::period, STK_ASSERT, STK_TIMER_THREADS_COUNT, STK_UNUSED, stk::time::TimerHost::TimerCommand::timer, stk::time::TimerHost::TimerCommand::timestamp, and stk::WAIT_INFINITE.

Referenced by UpdateTime().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ProcessTimers()

void stk::time::TimerHost::ProcessTimers ( )
inlineprivate

Handler task body: dequeues expired timers and invokes their OnExpired() callbacks.

Note
Runs in each handler task context. Loops until a nullptr sentinel is dequeued.

Definition at line 781 of file stk_time_timer.h.

782{
783 Timer *tmr = nullptr;
784 bool keep_running = true;
785
786 while (keep_running)
787 {
788 if (!m_queue.Read(tmr))
789 {
790 break; // no pending timers available
791 }
792
793 // nullptr is the shutdown sentinel pushed by CMD_SHUTDOWN
794 if (tmr == nullptr)
795 {
796 keep_running = false;
797 }
798 else if (tmr->m_pending)
799 {
800 tmr->m_pending = false;
801 tmr->OnExpired(this);
802 }
803 else
804 {
805 // noop
806 }
807 }
808}

References stk::time::TimerHost::Timer::m_pending, m_queue, and stk::time::TimerHost::Timer::OnExpired().

Referenced by Initialize().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ PushCommand()

bool stk::time::TimerHost::PushCommand ( TimerCommand cmd)
inlineprivate

Enqueue a command for the tick task.

Parameters
[in]cmdFully initialized TimerCommand to push.
Returns
True on success, false if the command queue is full.
Note
May be called from any task context. On queue-full the assertion fires in debug builds; in release the caller receives false and may retry or escalate.

Definition at line 1000 of file stk_time_timer.h.

1001{
1002 bool success = true;
1003 bool proceed_to_write = true;
1004
1005 const bool is_rearm = (cmd.cmd == TimerCommand::CMD_RESTART) ||
1007
1008 // rearm coalescing (CMD_RESTART and CMD_START_OR_RESET only)
1009 if (is_rearm && (cmd.timer != nullptr))
1010 {
1011 if (cmd.timer->m_rearming)
1012 {
1013 // already rearming - successfully coalesced, no need to write to queue
1014 proceed_to_write = false;
1015 }
1016 else
1017 {
1018 cmd.timer->m_rearming = true;
1019
1020 // prevent compiler from sinking the flag write past Write()
1021 __stk_full_memfence();
1022 }
1023 }
1024
1025 // write to command queue
1026 if (proceed_to_write)
1027 {
1028 if (!m_commands.Write(cmd, NO_WAIT))
1029 {
1030 // revert the flag if this was a failed rearm attempt
1031 if (is_rearm && (cmd.timer != nullptr))
1032 {
1033 cmd.timer->m_rearming = false;
1034 }
1035
1036 // queue full: this indicates a usage error - more commands are being
1037 // issued than the tick task can drain (recoverable in
1038 // release, caller receives false and can retry or escalate)
1039 STK_ASSERT(false);
1040 success = false;
1041 }
1042 }
1043
1044 return success;
1045}

References stk::time::TimerHost::TimerCommand::cmd, stk::time::TimerHost::TimerCommand::CMD_RESTART, stk::time::TimerHost::TimerCommand::CMD_START_OR_RESET, m_commands, stk::time::TimerHost::Timer::m_rearming, stk::NO_WAIT, STK_ASSERT, and stk::time::TimerHost::TimerCommand::timer.

Referenced by Reset(), Restart(), SetPeriod(), Shutdown(), Start(), StartOrReset(), and Stop().

Here is the caller graph for this function:

◆ Reset()

bool stk::time::TimerHost::Reset ( Timer & tmr)
inline

Reset periodic timer's deadline.

Parameters
[in]tmrTimer instance. Must be active and periodic.
Returns
True on success, false if timer is not active, not periodic, or command queue is full.

Definition at line 583 of file stk_time_timer.h.

584{
585 bool success;
586
587 // timer must be active and periodic
588 if (tmr.m_active && (tmr.m_period != 0U))
589 {
590 success = PushCommand({
592 .timer = &tmr,
593 .timestamp = GetTicks(),
594 .delay = 0U,
595 .period = 0U
596 });
597 }
598 else
599 {
600 success = false;
601 }
602
603 return success;
604}
static Ticks GetTicks()
Get number of ticks elapsed since kernel start.
Definition stk_helper.h:319
bool PushCommand(TimerCommand cmd)
Enqueue a command for the tick task.

References stk::time::TimerHost::TimerCommand::CMD_RESET, stk::GetTicks(), stk::time::TimerHost::Timer::m_active, stk::time::TimerHost::Timer::m_period, and PushCommand().

Referenced by stk_timer_reset().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Restart()

bool stk::time::TimerHost::Restart ( Timer & tmr,
uint32_t delay,
uint32_t period = 0 )
inline

Atomically stop and re-start timer.

Parameters
[in]tmrTimer instance (active or inactive).
[in]delayInitial delay in ticks before first expiration.
[in]periodReload period in ticks (0 is one-shot timer).
Returns
True on success, false if command queue is full.
Note
Unlike calling Stop() followed by Start(), this operation is atomic with respect to the tick task: the timer cannot fire between the implicit stop and re-start, and only one command queue slot is consumed. Useful for watchdog refresh and debounce reset patterns. Safe to call regardless of whether the timer is currently active.

Definition at line 610 of file stk_time_timer.h.

611{
612 STK_ASSERT(delay <= static_cast<uint32_t>(WAIT_INFINITE));
613 STK_ASSERT((period == 0U) || (period <= static_cast<uint32_t>(WAIT_INFINITE)));
614
615 return PushCommand({
617 .timer = &tmr,
618 .timestamp = GetTicks(),
619 .delay = delay,
620 .period = period
621 });
622}

References stk::time::TimerHost::TimerCommand::CMD_RESTART, stk::GetTicks(), PushCommand(), STK_ASSERT, and stk::WAIT_INFINITE.

Referenced by stk_timer_restart().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetPeriod()

bool stk::time::TimerHost::SetPeriod ( Timer & tmr,
uint32_t period )
inline

Change the period of a running periodic timer without affecting its current deadline.

Parameters
[in]tmrTimer instance. Must be active and periodic.
[in]periodNew reload period in ticks. Must be non-zero.
Returns
True on success, false if timer is not active, not periodic, period is zero, or command queue is full.
Note
The new period takes effect on the next reload after the current deadline fires. To apply the new period immediately (restart from now), call Reset() after SetPeriod().

Definition at line 646 of file stk_time_timer.h.

647{
648 bool success;
649
650 // period == 0 is rejected: it would silently convert a periodic timer
651 // to one-shot semantics, which is better expressed via Stop() + Start()
652 if (tmr.m_active && (tmr.m_period != 0U) && (period != 0U) &&
653 (period <= static_cast<uint32_t>(WAIT_INFINITE)))
654 {
655 success = PushCommand({
657 .timer = &tmr,
658 .timestamp = 0,
659 .delay = 0U,
660 .period = period
661 });
662 }
663 else
664 {
665 success = false;
666 }
667
668 return success;
669}

References stk::time::TimerHost::TimerCommand::CMD_SET_PERIOD, stk::time::TimerHost::Timer::m_active, stk::time::TimerHost::Timer::m_period, PushCommand(), and stk::WAIT_INFINITE.

Referenced by stk_timer_set_period().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Shutdown()

bool stk::time::TimerHost::Shutdown ( )
inline

Shutdown host instance. All timers are stopped and removed from the host.

Returns
True on success, false if command queue is full.

Definition at line 675 of file stk_time_timer.h.

676{
677 return PushCommand({
679 .timer = nullptr,
680 .timestamp = 0,
681 .delay = 0U,
682 .period = 0U
683 });
684}

References stk::time::TimerHost::TimerCommand::CMD_SHUTDOWN, and PushCommand().

Referenced by stk_timerhost_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Start()

bool stk::time::TimerHost::Start ( Timer & tmr,
uint32_t delay,
uint32_t period = 0 )
inline

Start timer.

Parameters
[in]tmrTimer instance. Must not already be active.
[in]delayInitial delay in ticks before first expiration.
[in]periodReload period in ticks (0 is one-shot timer).
Returns
True on success, false if timer is already active or command queue is full.

Definition at line 524 of file stk_time_timer.h.

525{
526 STK_ASSERT(delay <= static_cast<uint32_t>(WAIT_INFINITE));
527 STK_ASSERT((period == 0U) || (period <= static_cast<uint32_t>(WAIT_INFINITE)));
528
529 bool success;
530
531 // timer must not already be active
532 if (!tmr.m_active)
533 {
534 success = PushCommand({
536 .timer = &tmr,
537 .timestamp = GetTicks(),
538 .delay = delay,
539 .period = period
540 });
541 }
542 else
543 {
544 // duplicate attempt to start already started timer is not an error (ignore)
545 success = true;
546 }
547
548 return success;
549}

References stk::time::TimerHost::TimerCommand::CMD_START, stk::GetTicks(), stk::time::TimerHost::Timer::m_active, PushCommand(), STK_ASSERT, and stk::WAIT_INFINITE.

Referenced by stk_timer_start().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ StartOrReset()

bool stk::time::TimerHost::StartOrReset ( Timer & tmr,
uint32_t delay,
uint32_t period = 0 )
inline

Start timer if inactive, or reset its deadline if already active and periodic.

Parameters
[in]tmrTimer instance (active or inactive).
[in]delayInitial delay in ticks (used only when starting).
[in]periodReload period in ticks (used only when starting, 0 is one-shot).
Returns
True on success, false if command queue is full.
Note
Collapses the common pattern: if (timer.IsActive()) host.Reset(timer); else host.Start(timer, delay, period); into a single atomic operation, eliminating the TOCTOU race between the IsActive() check and the subsequent call. If the timer is active but one-shot, no action is taken (a one-shot timer mid-flight cannot be reset; use Restart() instead).

Definition at line 628 of file stk_time_timer.h.

629{
630 STK_ASSERT(delay <= static_cast<uint32_t>(WAIT_INFINITE));
631 STK_ASSERT((period == 0U) || (period <= static_cast<uint32_t>(WAIT_INFINITE)));
632
633 return PushCommand({
635 .timer = &tmr,
636 .timestamp = GetTicks(),
637 .delay = delay,
638 .period = period
639 });
640}

References stk::time::TimerHost::TimerCommand::CMD_START_OR_RESET, stk::GetTicks(), PushCommand(), STK_ASSERT, and stk::WAIT_INFINITE.

Referenced by stk_timer_start_or_reset().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ STK_NONCOPYABLE_CLASS()

stk::time::TimerHost::STK_NONCOPYABLE_CLASS ( TimerHost )
private

References TimerHost().

Here is the call graph for this function:

◆ Stop()

bool stk::time::TimerHost::Stop ( Timer & tmr)
inline

Stop running timer.

Parameters
[in]tmrTimer instance. Must be active.
Returns
True on success, false if timer is not active or command queue is full.

Definition at line 555 of file stk_time_timer.h.

556{
557 bool success;
558
559 // timer must be active
560 if (tmr.m_active)
561 {
562 success = PushCommand({
564 .timer = &tmr,
565 .timestamp = 0,
566 .delay = 0U,
567 .period = 0U
568 });
569 }
570 else
571 {
572 // duplicate attempt to stop already stopped timer is not an error (ignore)
573 success = true;
574 }
575
576 return success;
577}

References stk::time::TimerHost::TimerCommand::CMD_STOP, stk::time::TimerHost::Timer::m_active, and PushCommand().

Referenced by FrtosPendDrainer::OnExpired(), and stk_timer_stop().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateTime()

void stk::time::TimerHost::UpdateTime ( )
inlineprivate

Tick task body: drives the timer list and dispatches expired timers.

Note
Runs exclusively in the tick task context. Loops until CMD_SHUTDOWN is received.

Definition at line 690 of file stk_time_timer.h.

691{
692 Timeout next_sleep = NO_WAIT;
693
694 while (ProcessCommands(next_sleep))
695 {
696 next_sleep = WAIT_INFINITE;
697 const Ticks now = GetTicks();
698
699 // using WriteVolatile64() to guarantee correct lockless reading order by ReadVolatile64
701
703 while (tmr != nullptr)
704 {
705 Timer *const next = util::DListCast::ListEntryToParent<Timer>(tmr->GetNext());
706
707 if (tmr->m_active)
708 {
709 // check if still pending to be handled
710 if (!tmr->m_pending)
711 {
712 bool one_shot = false;
713 const Ticks diff = now - tmr->m_deadline;
714
715 if (diff >= 0)
716 {
717 // set timestamp at which timer expired
718 tmr->m_timestamp = now;
719
720 // avoid updating timer again before it was handled
721 tmr->m_pending = true;
722
723 // periodic
724 if (tmr->m_period != 0U)
725 {
726 // reload (use now to avoid drift accumulation)
727 tmr->m_deadline = now + static_cast<Ticks>(tmr->m_period) - diff;
728 }
729 // one-shot
730 else
731 {
732 one_shot = true;
733
734 // remove from active timers
735 m_active.Unlink(tmr);
736
737 // mark as inactive (must follow Unlink)
738 tmr->m_active = false;
739 }
740
741 __stk_full_memfence();
742
743 // push to the handling queue
744 STK_UNUSED(m_queue.Write(tmr));
745 }
746
747 // one-shot timer does not affect next_sleep
748 if (!one_shot)
749 {
750 const Timeout next_deadline = static_cast<Timeout>(tmr->m_deadline - now);
751 STK_ASSERT(next_deadline > 0);
752
753 if ((next_deadline > 0) && (next_deadline < next_sleep))
754 {
755 next_sleep = next_deadline;
756 }
757 }
758 }
759 }
760 else
761 {
762 // could be stopped externally, remove from active timers
763 m_active.Unlink(tmr);
764 }
765
766 tmr = next;
767 }
768 }
769
770 // unlink all timers on shutdown
771 while (Timer::DLEntryType *const tmr = m_active.GetFirst())
772 {
773 m_active.Unlink(tmr);
774 }
775}
int32_t Timeout
Timeout time (ticks).
Definition stk_common.h:125
static __stk_forceinline void WriteVolatile64(volatile T *addr, T value)
Atomically write a 64-bit volatile value.
Definition stk_arch.h:444
DListEntry< Timer, TClosedLoop > DLEntryType
static __stk_forceinline TTargetType * ListEntryToParent(TSourceType *const lentry)
Safely casts an intrusive list entry to its concrete parent container object type.
bool ProcessCommands(Timeout next_sleep)
Drain the command queue and execute each pending command.

References stk::util::DListEntry< T, TClosedLoop >::GetNext(), stk::GetTicks(), stk::util::DListCast::ListEntryToParent(), m_active, stk::time::TimerHost::Timer::m_active, stk::time::TimerHost::Timer::m_deadline, m_now, stk::time::TimerHost::Timer::m_pending, stk::time::TimerHost::Timer::m_period, m_queue, stk::time::TimerHost::Timer::m_timestamp, stk::NO_WAIT, ProcessCommands(), STK_ASSERT, STK_UNUSED, stk::WAIT_INFINITE, and stk::hw::WriteVolatile64().

Referenced by Initialize().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_active

util::DListHead<Timer, false> stk::time::TimerHost::m_active
private

active timers (tick task only)

Definition at line 468 of file stk_time_timer.h.

Referenced by GetSize(), IsEmpty(), ProcessCommands(), TimerHost(), and UpdateTime().

◆ m_commands

CommandQueue stk::time::TimerHost::m_commands
private

command queue

Definition at line 470 of file stk_time_timer.h.

Referenced by ProcessCommands(), and PushCommand().

◆ m_now

Ticks stk::time::TimerHost::m_now
private

last known current time (ticks)

Definition at line 471 of file stk_time_timer.h.

Referenced by GetTimeNow(), TimerHost(), and UpdateTime().

◆ m_queue

ReadyQueue stk::time::TimerHost::m_queue
private

queue of timers ready for handling

Definition at line 469 of file stk_time_timer.h.

Referenced by ProcessCommands(), ProcessTimers(), and UpdateTime().

◆ m_task_handler_memory

TimerHostMemory stk::time::TimerHost::m_task_handler_memory[1U]
private

handler task memory

Definition at line 465 of file stk_time_timer.h.

Referenced by Initialize(), and TimerHost().

◆ m_task_process

TimerWorkerTask stk::time::TimerHost::m_task_process[1U]
private

handler tasks

Definition at line 467 of file stk_time_timer.h.

Referenced by Initialize(), and TimerHost().

◆ m_task_tick

TimerWorkerTask stk::time::TimerHost::m_task_tick
private

timer task

Definition at line 466 of file stk_time_timer.h.

Referenced by Initialize(), and TimerHost().

◆ m_task_tick_memory

TaskTickMemory stk::time::TimerHost::m_task_tick_memory
private

tick task memory

Definition at line 464 of file stk_time_timer.h.

Referenced by Initialize(), and TimerHost().


The documentation for this class was generated from the following file: