SuperTinyKernel™ RTOS 1.06.0
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
 The actual task that executes timer callback. More...
struct  TimerCommand

Public Types

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

Public Member Functions

 TimerHost ()
 ~TimerHost ()
 Destructor.
void Initialize (IKernel *kernel, EAccessMode mode)
 Initialize timer host instance.
bool Start (Timer &timer, uint32_t delay, uint32_t period=0)
 Start timer.
bool Stop (Timer &timer)
 Stop running timer.
bool Reset (Timer &timer)
 Reset periodic timer's deadline.
bool Restart (Timer &timer, uint32_t delay, uint32_t period=0)
 Atomically stop and re-start timer.
bool StartOrReset (Timer &timer, uint32_t delay, uint32_t period=0)
 Start timer if inactive, or reset its deadline if already active and periodic.
bool SetPeriod (Timer &timer, 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
typedef StackMemoryDef< TASK_HANDLER_STACK_SIZE >::Type TimerHostMemory
typedef sync::Pipe< Timer *, 32 > ReadyQueue
typedef sync::Pipe< TimerCommand, 32 > CommandQueue

Private Member Functions

 STK_NONCOPYABLE_CLASS (TimerHost)
void UpdateTime ()
void ProcessTimers ()
bool ProcessCommands (Timeout next_sleep)
bool PushCommand (TimerCommand cmd)

Private Attributes

TaskTickMemory m_task_tick_memory
 tick task memory
TimerHostMemory m_task_handler_memory [1]
 handler task memory
TimerWorkerTask m_task_tick
 timer task
TimerWorkerTask m_task_process [1]
 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:32
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 &timer, uint32_t delay, uint32_t period=0)
Start timer.
Abstract base class for a timer managed by TimerHost.
virtual void OnExpired(TimerHost *host)=0
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

Definition at line 355 of file stk_time_timer.h.

◆ ReadyQueue

Definition at line 354 of file stk_time_timer.h.

◆ TaskTickMemory

◆ TimerFuncType

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

Timer task function prototype.

Definition at line 279 of file stk_time_timer.h.

◆ TimerHostMemory

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:454
#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:541
@ 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

Definition at line 176 of file stk_time_timer.h.

178 {}
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
TimerWorkerTask m_task_process[1]
handler tasks
TaskTickMemory m_task_tick_memory
tick task memory
TimerHostMemory m_task_handler_memory[1]
handler 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 ( )
inline

Destructor.

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

Definition at line 183 of file stk_time_timer.h.

184 {}

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 261 of file stk_time_timer.h.

261{ 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 271 of file stk_time_timer.h.

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

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 387 of file stk_time_timer.h.

388{
389 for (int32_t i = 0; i < STK_TIMER_THREADS_COUNT; ++i)
390 {
391 m_task_process[i].Initialize(this, m_task_handler_memory[i], TASK_HANDLER_STACK_SIZE, mode, [](TimerHost *host) {
392 host->ProcessTimers();
393 });
394 kernel->AddTask(&m_task_process[i]);
395 }
396
398 host->UpdateTime();
399 });
400 kernel->AddTask(&m_task_tick);
401}

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_timerhost_init().

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 255 of file stk_time_timer.h.

255{ 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

Definition at line 653 of file stk_time_timer.h.

654{
655 // if nothing is active, sleep indefinitely until a command arrives
656 next_sleep = (m_active.IsEmpty() ? WAIT_INFINITE : next_sleep);
657
658 TimerCommand cmd;
659 while (m_commands.Read(cmd, next_sleep))
660 {
661 switch (cmd.cmd)
662 {
664 Timer *timer = cmd.timer;
665 STK_ASSERT(timer != nullptr);
666
667 // reject if already active or linked (double-start)
668 if (timer->m_active)
669 continue;
670
671 STK_ASSERT(!timer->IsLinked());
672
673 timer->m_deadline = cmd.timestamp + cmd.delay;
674 timer->m_period = cmd.period;
675 timer->m_active = true;
676 timer->m_pending = false;
677
678 m_active.LinkBack(timer);
679 next_sleep = NO_WAIT;
680 break; }
681
683 Timer *timer = cmd.timer;
684 STK_ASSERT(timer != nullptr);
685
686 timer->m_active = false;
687 timer->m_pending = false;
688
689 // allow possibly duplicate CMD_STOP as it is harmless for the logic
690 if (timer->IsLinked())
691 m_active.Unlink(timer);
692 break; }
693
695 Timer *timer = cmd.timer;
696 STK_ASSERT(timer != nullptr);
697
698 // only reset if still active and periodic
699 if (!timer->m_active || (timer->m_period == 0))
700 continue;
701
702 STK_ASSERT(timer->GetHead() == &m_active);
703
704 timer->m_deadline = cmd.timestamp + timer->m_period;
705 timer->m_pending = false;
706
707 next_sleep = NO_WAIT;
708 break; }
709
711 // atomic stop + re-start: no precondition on current timer state
712 Timer *timer = cmd.timer;
713 STK_ASSERT(timer != nullptr);
714
715 // unlink if currently in the active list
716 if (timer->IsLinked())
717 m_active.Unlink(timer);
718
719 // re-arm with fresh parameters
720 timer->m_deadline = cmd.timestamp + cmd.delay;
721 timer->m_period = cmd.period;
722 timer->m_active = true;
723 timer->m_pending = false;
724
725 // re-link to the back of the list
726 m_active.LinkBack(timer);
727 next_sleep = NO_WAIT;
728 break; }
729
731 Timer *timer = cmd.timer;
732 STK_ASSERT(timer != nullptr);
733
734 // not currently active: start with supplied parameters
735 if (!timer->m_active)
736 {
737 STK_ASSERT(!timer->IsLinked());
738
739 timer->m_deadline = cmd.timestamp + cmd.delay;
740 timer->m_period = cmd.period;
741 timer->m_active = true;
742 timer->m_pending = false;
743
744 m_active.LinkBack(timer);
745 }
746 else
747 // active and periodic: reset deadline anchored to call-site timestamp
748 if (timer->m_period != 0)
749 {
750 STK_ASSERT(timer->GetHead() == &m_active);
751
752 timer->m_deadline = cmd.timestamp + timer->m_period;
753 timer->m_pending = false;
754 }
755
756 // active one-shot: no action — cannot reset a one-shot mid-flight,
757 // caller should use Restart() if unconditional re-arm is needed.
758
759 next_sleep = NO_WAIT;
760 break; }
761
763 Timer *timer = cmd.timer;
764 STK_ASSERT(timer != nullptr);
765 STK_ASSERT(cmd.period != 0U);
766
767 // guard: only apply if still active and periodic
768 if (!timer->m_active || (timer->m_period == 0U))
769 continue;
770
771 STK_ASSERT(timer->GetHead() == &m_active);
772
773 // new period takes effect on the next reload, current deadline is
774 // intentionally left unchanged so the in-flight interval is not
775 // truncated or extended, caller can follow up with Reset() if
776 // immediate application is required
777 timer->m_period = cmd.period;
778 break; }
779
781 // wake all handler tasks with shutdown sentinels
782 for (int32_t i = 0; i < STK_TIMER_THREADS_COUNT; ++i)
783 m_queue.Write(nullptr, NO_WAIT);
784
785 // signal UpdateTime() to exit its loop
786 return false; }
787
788 default: {
789 STK_ASSERT(false);
790 break; }
791 }
792 }
793
794 return true;
795}
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:330
static constexpr Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
Definition stk_common.h:177
static constexpr Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
Definition stk_common.h:171
ReadyQueue m_queue
queue of timers ready for handling
CommandQueue m_commands
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, _ClosedLoop >::GetHead(), stk::util::DListEntry< T, _ClosedLoop >::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::NO_WAIT, stk::time::TimerHost::TimerCommand::period, STK_ASSERT, STK_TIMER_THREADS_COUNT, 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

Definition at line 632 of file stk_time_timer.h.

633{
634 Timer *timer;
635 while (m_queue.Read(timer))
636 {
637 // nullptr is the shutdown sentinel pushed by CMD_SHUTDOWN
638 if (timer == nullptr)
639 break;
640
641 if (timer->m_pending)
642 {
643 timer->m_pending = false;
644 timer->OnExpired(this);
645 }
646 }
647}

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

Definition at line 801 of file stk_time_timer.h.

802{
803 if (!m_commands.Write(cmd, NO_WAIT))
804 {
805 // queue full: this indicates a usage error — more commands are being
806 // issued than the tick task can drain. Loud in debug, recoverable in
807 // release (caller receives false and can retry or escalate).
808 STK_ASSERT(false);
809 return false;
810 }
811
812 return true;
813}

References m_commands, stk::NO_WAIT, and STK_ASSERT.

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 & timer)
inline

Reset periodic timer's deadline.

Parameters
[in]timerTimer 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 448 of file stk_time_timer.h.

449{
450 // timer must be active and periodic
451 if (!timer.m_active || (timer.m_period == 0))
452 return false;
453
454 return PushCommand({
456 .timer = &timer,
457 .timestamp = GetTicks(),
458 .delay = 0U,
459 .period = 0U
460 });
461}
Ticks GetTicks()
Get number of ticks elapsed since kernel start.
Definition stk_helper.h:258
bool PushCommand(TimerCommand cmd)

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 & timer,
uint32_t delay,
uint32_t period = 0 )
inline

Atomically stop and re-start timer.

Parameters
[in]timerTimer 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 467 of file stk_time_timer.h.

468{
469 STK_ASSERT(delay <= static_cast<uint32_t>(WAIT_INFINITE));
470 STK_ASSERT((period == 0U) || (period <= static_cast<uint32_t>(WAIT_INFINITE)));
471
472 return PushCommand({
474 .timer = &timer,
475 .timestamp = GetTicks(),
476 .delay = delay,
477 .period = period
478 });
479}

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 & timer,
uint32_t period )
inline

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

Parameters
[in]timerTimer 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 503 of file stk_time_timer.h.

504{
505 // period == 0 is rejected: it would silently convert a periodic timer
506 // to one-shot semantics, which is better expressed via Stop() + Start()
507 if (!timer.m_active || (timer.m_period == 0U) || (period == 0U) ||
508 (period > static_cast<uint32_t>(WAIT_INFINITE)))
509 {
510 return false;
511 }
512
513 return PushCommand({
515 .timer = &timer,
516 .timestamp = 0,
517 .delay = 0U,
518 .period = period
519 });
520}

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 526 of file stk_time_timer.h.

527{
528 return PushCommand({
530 .timer = nullptr,
531 .timestamp = 0,
532 .delay = 0U,
533 .period = 0U
534 });
535}

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 & timer,
uint32_t delay,
uint32_t period = 0 )
inline

Start timer.

Parameters
[in]timerTimer 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 407 of file stk_time_timer.h.

408{
409 STK_ASSERT(delay <= static_cast<uint32_t>(WAIT_INFINITE));
410 STK_ASSERT((period == 0U) || (period <= static_cast<uint32_t>(WAIT_INFINITE)));
411
412 // timer must not already be active
413 if (timer.m_active)
414 return false;
415
416 return PushCommand({
418 .timer = &timer,
419 .timestamp = GetTicks(),
420 .delay = delay,
421 .period = period
422 });
423}

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 & timer,
uint32_t delay,
uint32_t period = 0 )
inline

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

Parameters
[in]timerTimer 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 485 of file stk_time_timer.h.

486{
487 STK_ASSERT(delay <= static_cast<uint32_t>(WAIT_INFINITE));
488 STK_ASSERT((period == 0U) || (period <= static_cast<uint32_t>(WAIT_INFINITE)));
489
490 return PushCommand({
492 .timer = &timer,
493 .timestamp = GetTicks(),
494 .delay = delay,
495 .period = period
496 });
497}

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 & timer)
inline

Stop running timer.

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

Definition at line 429 of file stk_time_timer.h.

430{
431 // timer must be active
432 if (!timer.m_active)
433 return false;
434
435 return PushCommand({
437 .timer = &timer,
438 .timestamp = 0,
439 .delay = 0U,
440 .period = 0U
441 });
442}

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

Referenced by 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

Definition at line 541 of file stk_time_timer.h.

542{
543 Timeout next_sleep = NO_WAIT;
544
545 while (ProcessCommands(next_sleep))
546 {
547 next_sleep = WAIT_INFINITE;
548
549 Ticks now = GetTicks();
550
551 // using WriteVolatile64() to guarantee correct lockless reading order by ReadVolatile64
553
554 Timer *timer = static_cast<Timer *>(m_active.GetFirst());
555 while (timer != nullptr)
556 {
557 Timer *next = static_cast<Timer *>(timer->GetNext());
558
559 if (timer->m_active)
560 {
561 // check if still pending to be handled
562 if (timer->m_pending)
563 {
564 timer = next;
565 continue;
566 }
567
568 bool one_shot = false;
569 Ticks diff = now - timer->m_deadline;
570
571 if (diff >= 0)
572 {
573 // set timestamp at which timer expired
574 timer->m_timestamp = now;
575
576 // avoid updating timer again before it was handled
577 timer->m_pending = true;
578
579 // periodic
580 if (timer->m_period != 0)
581 {
582 // reload (use now to avoid drift accumulation)
583 timer->m_deadline = now + static_cast<Ticks>(timer->m_period) - diff;
584 }
585 // one-shot
586 else
587 {
588 one_shot = true;
589
590 // remove from active timers
591 m_active.Unlink(timer);
592
593 // mark as inactive (must follow Unlink)
594 timer->m_active = false;
595 }
596
597 __stk_full_memfence();
598
599 // push to the handling queue
600 m_queue.Write(timer);
601 }
602
603 // one-shot timer does not affect next_sleep
604 if (!one_shot)
605 {
606 Timeout next_deadline = static_cast<Timeout>(timer->m_deadline - now);
607 STK_ASSERT(next_deadline > 0);
608
609 if ((next_deadline > 0) && (next_deadline < next_sleep))
610 next_sleep = next_deadline;
611 }
612 }
613 else
614 {
615 // could be stopped externally, remove from active timers
616 m_active.Unlink(timer);
617 }
618
619 timer = next;
620 }
621 }
622
623 // unlink all timers on shutdown
624 while (Timer::DLEntryType *timer = m_active.GetFirst())
625 m_active.Unlink(timer);
626}
int64_t Ticks
Ticks value.
Definition stk_common.h:128
int32_t Timeout
Timeout time (ticks).
Definition stk_common.h:123
__stk_forceinline void WriteVolatile64(volatile T *addr, T value)
Atomically write a 64-bit volatile value.
Definition stk_arch.h:411
DListEntry< Timer, _ClosedLoop > DLEntryType
bool ProcessCommands(Timeout next_sleep)

References stk::util::DListEntry< T, _ClosedLoop >::GetNext(), stk::GetTicks(), 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::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 361 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 363 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 364 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 362 of file stk_time_timer.h.

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

◆ m_task_handler_memory

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

handler task memory

Definition at line 358 of file stk_time_timer.h.

Referenced by Initialize(), and TimerHost().

◆ m_task_process

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

handler tasks

Definition at line 360 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 359 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 357 of file stk_time_timer.h.

Referenced by Initialize(), and TimerHost().


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