SuperTinyKernel™ RTOS 1.08.x
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk::SwitchStrategyMonotonic< TStrategyType > Class Template Referencefinal

Monotonic scheduling strategy: Rate-Monotonic (RM) or Deadline-Monotonic (DM), selected at compile time by the TStrategyType template parameter. More...

#include <stk_strategy_monotonic.h>

Inheritance diagram for stk::SwitchStrategyMonotonic< TStrategyType >:
Collaboration diagram for stk::SwitchStrategyMonotonic< TStrategyType >:

Public Types

enum  EConfig {
  WEIGHT_API = 0 ,
  SLEEP_EVENT_API = 0 ,
  DEADLINE_MISSED_API = 0 ,
  PRIORITY_INHERITANCE_API = 0 ,
  NOSLEEP_YIELD_API = 0 ,
  TIMESLICE_API = 0
}
 Compile-time capability flags reported to the kernel. More...

Public Member Functions

 SwitchStrategyMonotonic ()
 Construct an empty strategy with no tasks.
STK_VIRT_DTOR ~SwitchStrategyMonotonic ()=default
 Destructor.
void AddTask (IKernelTask *task) override
 Add a task to the priority-sorted runnable list.
void RemoveTask (IKernelTask *task) override
 Remove a task from the list.
IKernelTask * GetNext () override
 Select and return the highest-priority non-sleeping task.
IKernelTask * GetFirst () override
 Get the first task in the managed set (used by the kernel for initial scheduling).
size_t GetSize () const override
 Get the total number of tasks managed by this strategy.
void OnTaskSleep (IKernelTask *) override
 Not supported, asserts unconditionally.
void OnTaskWake (IKernelTask *) override
 Not supported, asserts unconditionally.
virtual bool OnTaskYield (IKernelTask *task)
 Notification that the running task called Yield() (non-HRT kernel modes only).
virtual bool OnTaskTimeSlice (IKernelTask *task)
 Notification that the running task's time slice expired (KERNEL_TIMESLICE only).
virtual bool OnTaskDeadlineMissed (IKernelTask *task)
 Notification that a task has exceeded its HRT deadline; returns whether the strategy can recover without a hard fault.
virtual void OnTaskWeightChange (IKernelTask *task, Weight old_weight)
 Notification that a runnable task's scheduling weight has changed.

Private Member Functions

 STK_NONCOPYABLE_CLASS (SwitchStrategyMonotonic)

Private Attributes

IKernelTask::ListHeadType m_tasks
 All tasks (runnable and sleeping) in priority order. GetNext() skips sleeping tasks via IsSleeping(). AddTask() maintains sort order.

Detailed Description

template<EMonotonicSwitchStrategyType TStrategyType>
class stk::SwitchStrategyMonotonic< TStrategyType >

Monotonic scheduling strategy: Rate-Monotonic (RM) or Deadline-Monotonic (DM), selected at compile time by the TStrategyType template parameter.

Template Parameters
TStrategyTypePolicy selector (EMonotonicSwitchStrategyType):
  • MSS_TYPE_RATE - Rate-Monotonic: tasks with a shorter scheduling period receive higher priority. The most frequently activating task always runs first.
  • MSS_TYPE_DEADLINE - Deadline-Monotonic: tasks with a shorter execution deadline receive higher priority.
Sorted-list design
m_tasks is maintained as a priority-sorted intrusive list. AddTask() inserts each new task at the correct sorted position (O(n) insertion sort) so that GetNext() need only scan from the front: the first non-sleeping task it encounters is always the highest-priority runnable task. No re-sorting occurs at runtime after a task is added.
Sleep handling - no separate sleep list
Unlike RR, SWRR, EDF, and FP strategies, this strategy does not maintain a separate sleep list (SLEEP_EVENT_API = 0). Sleeping tasks remain in m_tasks in their sorted position and are skipped by GetNext() via IKernelTask::IsSleeping(). OnTaskSleep() and OnTaskWake() assert unconditionally, the kernel must not be configured to deliver these events to this strategy.
HRT mode requirement
This strategy reads GetHrtPeriodicity() and GetHrtDeadline() from each task during AddTask() to determine its priority. These values are only populated in KERNEL_HRT mode; outside KERNEL_HRT the accessors assert (debug builds) and return 0, so every sort key ties: the list stays in registration order and the first non-sleeping task always wins, the other tasks do not run.
Note
Does not use per-task weights (WEIGHT_API = 0). Priority is derived entirely from HRT timing parameters set via IKernel::AddTask(periodicity_tc, deadline_tc, ...).
For schedulability analysis of the configured task set use SchedulabilityCheck::IsSchedulableWCRT().
See also
SwitchStrategyRM, SwitchStrategyDM, SchedulabilityCheck, ITaskSwitchStrategy

Definition at line 70 of file stk_strategy_monotonic.h.

Member Enumeration Documentation

◆ EConfig

Compile-time capability flags reported to the kernel.

Enumerator
WEIGHT_API 

This strategy does not use per-task weights. Priority is derived from HRT timing parameters (GetHrtPeriodicity() for RM, GetHrtDeadline() for DM) at AddTask() time.

SLEEP_EVENT_API 

This strategy does not use OnTaskSleep() / OnTaskWake() events. Sleeping tasks remain in m_tasks and are skipped by GetNext() via IKernelTask::IsSleeping(). Delivering these events will trigger an assertion.

DEADLINE_MISSED_API 

This strategy does not use OnTaskDeadlineMissed() events.

PRIORITY_INHERITANCE_API 

This strategy does not require Priority Inheritance and OnTaskPriorityChange() events.

NOSLEEP_YIELD_API 

This strategy does not handle Yield() itself (OnTaskYield() is not used); the kernel puts the yielding task to sleep for a tick.

TIMESLICE_API 

This strategy does not support KERNEL_TIMESLICE mode.

Definition at line 76 of file stk_strategy_monotonic.h.

77 {
78 WEIGHT_API = 0,
79 SLEEP_EVENT_API = 0,
83 TIMESLICE_API = 0
84 };
@ DEADLINE_MISSED_API
This strategy does not use OnTaskDeadlineMissed() events.
@ NOSLEEP_YIELD_API
This strategy does not handle Yield() itself (OnTaskYield() is not used); the kernel puts the yieldin...
@ WEIGHT_API
This strategy does not use per-task weights. Priority is derived from HRT timing parameters (GetHrtPe...
@ TIMESLICE_API
This strategy does not support KERNEL_TIMESLICE mode.
@ PRIORITY_INHERITANCE_API
This strategy does not require Priority Inheritance and OnTaskPriorityChange() events.
@ SLEEP_EVENT_API
This strategy does not use OnTaskSleep() / OnTaskWake() events. Sleeping tasks remain in m_tasks and ...

Constructor & Destructor Documentation

◆ SwitchStrategyMonotonic()

template<EMonotonicSwitchStrategyType TStrategyType>
stk::SwitchStrategyMonotonic< TStrategyType >::SwitchStrategyMonotonic ( )
inlineexplicit

Construct an empty strategy with no tasks.

Definition at line 88 of file stk_strategy_monotonic.h.

88 : m_tasks()
89 {}
IKernelTask::ListHeadType m_tasks
All tasks (runnable and sleeping) in priority order. GetNext() skips sleeping tasks via IsSleeping()....

◆ ~SwitchStrategyMonotonic()

Destructor.

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

Member Function Documentation

◆ AddTask()

template<EMonotonicSwitchStrategyType TStrategyType>
void stk::SwitchStrategyMonotonic< TStrategyType >::AddTask ( IKernelTask * task)
inlineoverridevirtual

Add a task to the priority-sorted runnable list.

Parameters
[in]taskTask to add. Must not be NULL and must not already be in any list.
Note
Performs an O(n) insertion sort into m_tasks so that higher-priority tasks appear closer to the head. The sort key depends on TStrategyType:
  • MSS_TYPE_RATE: key = GetHrtPeriodicity() (smaller -> nearer to head).
  • MSS_TYPE_DEADLINE: key = GetHrtDeadline() (smaller -> nearer to head).
Three insertion cases handled:
  1. Empty list: insert at front (LinkFront).
  2. New task has a strictly smaller key than the current head: insert at front (LinkFront), becoming the new highest-priority task.
  3. Otherwise: scan forward until a task with a strictly larger key is found, then insert immediately before it (Link), or append at back (LinkBack) if the scan reaches the end of the list.
Tasks with equal keys are ordered by registration time: later-added tasks go behind earlier-added tasks with the same key.

Implements stk::ITaskSwitchStrategy.

Definition at line 112 of file stk_strategy_monotonic.h.

113 {
114 STK_ASSERT(task != nullptr);
115 STK_ASSERT(task->GetHead() == nullptr);
116
117 if (m_tasks.IsEmpty())
118 {
119 m_tasks.LinkFront(task);
120 }
121 else
122 {
123 IKernelTask *itr = (*m_tasks.GetFirst()), *const start = itr;
124
125 for (;;)
126 {
127 bool higher_priority = false;
128 switch (TStrategyType)
129 {
130 case MSS_TYPE_RATE:
131 higher_priority = (task->GetHrtPeriodicity() < itr->GetHrtPeriodicity());
132 break;
134 higher_priority = (task->GetHrtDeadline() < itr->GetHrtDeadline());
135 break;
136 default:
137 STK_ASSERT(false);
138 break;
139 }
140
141 if (higher_priority)
142 {
143 if (itr == start)
144 {
145 m_tasks.LinkFront(task);
146 break;
147 }
148
149 m_tasks.Link(task, itr, itr->GetPrev());
150 break;
151 }
152
153 // end of the list
154 itr = (*itr->GetNext());
155 if (itr == start)
156 {
157 m_tasks.LinkBack(task);
158 break;
159 }
160 }
161 }
162 }
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:516
Monotonic scheduling strategy: Rate-Monotonic (RM) or Deadline-Monotonic (DM), selected at compile ti...
IKernelTask * GetNext() override
Select and return the highest-priority non-sleeping task.

◆ GetFirst()

template<EMonotonicSwitchStrategyType TStrategyType>
IKernelTask * stk::SwitchStrategyMonotonic< TStrategyType >::GetFirst ( )
inlineoverridevirtual

Get the first task in the managed set (used by the kernel for initial scheduling).

Returns
The first task in m_tasks (highest priority due to sort order). Asserts if m_tasks is empty.
Note
Because all tasks (runnable and sleeping) reside in m_tasks there is no sleep-list fallback path, unlike RR, SWRR, EDF, and FP strategies. The returned task may be sleeping; the kernel uses it only to seed the initial context before the first GetNext() call.

Implements stk::ITaskSwitchStrategy.

Definition at line 223 of file stk_strategy_monotonic.h.

224 {
225 STK_ASSERT(m_tasks.GetSize() != 0U);
226
227 return (*m_tasks.GetFirst());
228 }

◆ GetNext()

template<EMonotonicSwitchStrategyType TStrategyType>
IKernelTask * stk::SwitchStrategyMonotonic< TStrategyType >::GetNext ( )
inlineoverridevirtual

Select and return the highest-priority non-sleeping task.

Returns
The first non-sleeping task in m_tasks, or NULL if every task in the list is currently sleeping (kernel will sleep until the next activation).
Note
Because m_tasks is sorted in descending priority order by AddTask(), a linear scan from the head is sufficient: the first task for which IsSleeping() returns false is always the highest-priority runnable task. Complexity is O(k) where k is the number of sleeping tasks at the front of the list (i.e. higher-priority tasks currently between activations).

Implements stk::ITaskSwitchStrategy.

Definition at line 188 of file stk_strategy_monotonic.h.

189 {
190 IKernelTask *next = nullptr;
191
192 if (!m_tasks.IsEmpty())
193 {
194 IKernelTask *itr = (*m_tasks.GetFirst()), *const start = itr;
195
196 // scan from head (highest priority); skip tasks that are sleeping between
197 // periodic activations; return the first task ready to run
198 do
199 {
200 if (!itr->IsSleeping())
201 {
202 next = itr;
203 break; // list is sorted by priority; no need to continue
204 }
205
206 itr = (*itr->GetNext());
207 }
208 while (itr != start);
209 }
210
211 // nullptr means all tasks are sleeping, return idle signal to kernel
212 return next;
213 }

◆ GetSize()

template<EMonotonicSwitchStrategyType TStrategyType>
size_t stk::SwitchStrategyMonotonic< TStrategyType >::GetSize ( ) const
inlineoverridevirtual

Get the total number of tasks managed by this strategy.

Returns
Number of tasks in m_tasks. Includes both runnable and sleeping tasks since this strategy does not maintain a separate sleep list.

Implements stk::ITaskSwitchStrategy.

Definition at line 234 of file stk_strategy_monotonic.h.

235 {
236 return m_tasks.GetSize();
237 }

Referenced by stk::SwitchStrategyMonotonic< MSS_TYPE_RATE >::RemoveTask().

Here is the caller graph for this function:

◆ OnTaskDeadlineMissed()

virtual bool stk::ITaskSwitchStrategy::OnTaskDeadlineMissed ( IKernelTask * task)
inlinevirtualinherited

Notification that a task has exceeded its HRT deadline; returns whether the strategy can recover without a hard fault.

Parameters
[in]taskThe task whose deadline was missed. Must not be nullptr.
Returns
true — the strategy has absorbed the overrun (e.g. by escalating its scheduling mode): the kernel must not call HrtHardFailDeadline() for this tick. false — the strategy cannot recover: the kernel must call HrtHardFailDeadline() as normal.
Note
Budget Overrun API. Called by the kernel from UpdateTaskState() within a tick, after GetNext() has already been called for that tick. Only invoked when DEADLINE_MISSED_API == 1 in the concrete strategy's EConfig. Strategies that set DEADLINE_MISSED_API = 0 do not need to implement this method; the kernel will not call it and will proceed directly to HrtHardFailDeadline().
Returning true carries no implicit side-effects on task sleep state or duration counters — normal tick-driven scheduling remains responsible for those. This call only communicates "do not hard-fault this tick."
The base implementation returns false (unrecoverable), which is the correct default for strategies that do not implement overrun recovery.

Definition at line 1487 of file stk_common.h.

1488 {
1489 STK_UNUSED(task);
1490 return false;
1491 }
#define STK_UNUSED(X)
Explicitly marks a variable as unused to suppress compiler warnings.
Definition stk_defs.h:715

References STK_UNUSED.

◆ OnTaskSleep()

template<EMonotonicSwitchStrategyType TStrategyType>
void stk::SwitchStrategyMonotonic< TStrategyType >::OnTaskSleep ( IKernelTask * )
inlineoverridevirtual

Not supported, asserts unconditionally.

Note
This strategy uses SLEEP_EVENT_API = 0. Sleeping tasks remain in m_tasks in their sorted position and are detected by IsSleeping() in GetNext(). Calling this method indicates a kernel/strategy configuration mismatch.

Implements stk::ITaskSwitchStrategy.

Definition at line 244 of file stk_strategy_monotonic.h.

245 {
246 // Sleep API unsupported: RM/DM keeps a single sorted non-volatile list.
247 STK_ASSERT(false);
248 }

◆ OnTaskTimeSlice()

virtual bool stk::ITaskSwitchStrategy::OnTaskTimeSlice ( IKernelTask * task)
inlinevirtualinherited

Notification that the running task's time slice expired (KERNEL_TIMESLICE only).

Parameters
[in]taskPointer to the running task, currently in the runnable set.
Returns
true if the strategy rotated to a same-priority peer (the following GetNext() returns it); false to keep running the task (no peer, or the task is not eligible for time-slicing).
Note
Unlike OnTaskYield() this must not release preemption-threshold style holds.
Called from the tick handler. Only invoked when TIMESLICE_API == 1.
See also
SwitchStrategyPreemptionThreshold::OnTaskTimeSlice

Reimplemented in stk::SwitchStrategyPreemptionThreshold< MAX_PRIORITIES, TIMESLICE >, stk::SwitchStrategyPreemptionThreshold< 32 >, and stk::SwitchStrategyPreemptionThreshold< 32, true >.

Definition at line 1461 of file stk_common.h.

1462 {
1463 STK_UNUSED(task);
1464 return false;
1465 }

References STK_UNUSED.

◆ OnTaskWake()

template<EMonotonicSwitchStrategyType TStrategyType>
void stk::SwitchStrategyMonotonic< TStrategyType >::OnTaskWake ( IKernelTask * )
inlineoverridevirtual

Not supported, asserts unconditionally.

Note
This strategy uses SLEEP_EVENT_API = 0. See OnTaskSleep() for rationale.

Implements stk::ITaskSwitchStrategy.

Definition at line 253 of file stk_strategy_monotonic.h.

254 {
255 // Sleep API unsupported: RM/DM keeps a single sorted non-volatile list.
256 STK_ASSERT(false);
257 }

◆ OnTaskWeightChange()

virtual void stk::ITaskSwitchStrategy::OnTaskWeightChange ( IKernelTask * task,
Weight old_weight )
inlinevirtualinherited

Notification that a runnable task's scheduling weight has changed.

Parameters
[in]taskThe task whose weight was just updated via SetWeight().
[in]old_weightThe previous weight of this task (required to remove it from the priority list belonging to that weight).
Note
Called only for tasks that are currently in the runnable set (not sleeping). The strategy must relink the task to reflect its new weight. For strategies with WEIGHT_API = 0 this is a no-op. For SwitchStrategyFixedPriority it moves the task from its old priority-level list to the new one and updates m_ready_bitmap.
Called from within a ScopedCriticalSection.

Reimplemented in stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >, stk::SwitchStrategyFixedPriority< 32 >, stk::SwitchStrategyFixedPriority< 32, true >, stk::SwitchStrategyPreemptionThreshold< MAX_PRIORITIES, TIMESLICE >, stk::SwitchStrategyPreemptionThreshold< 32 >, and stk::SwitchStrategyPreemptionThreshold< 32, true >.

Definition at line 1505 of file stk_common.h.

1506 {
1507 STK_UNUSED(task);
1508 STK_UNUSED(old_weight);
1509 }

References STK_UNUSED.

◆ OnTaskYield()

virtual bool stk::ITaskSwitchStrategy::OnTaskYield ( IKernelTask * task)
inlinevirtualinherited

Notification that the running task called Yield() (non-HRT kernel modes only).

Parameters
[in]taskPointer to the yielding task, currently in the runnable set.
Returns
true if the strategy handled the yield itself: the task stays runnable (it is NOT put to sleep) and the strategy must arrange for the following GetNext() to return another task according to its own policy; false (default) if the kernel shall perform the legacy yield, i.e. sleep the task for YIELD_TICKS.
Note
Called from within a critical section, in the context of the yielding task.
Never called in KERNEL_HRT mode, where Yield() signals job completion.
See also
SwitchStrategyPreemptionThreshold::OnTaskYield

Reimplemented in stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >, stk::SwitchStrategyFixedPriority< 32 >, stk::SwitchStrategyFixedPriority< 32, true >, stk::SwitchStrategyPreemptionThreshold< MAX_PRIORITIES, TIMESLICE >, stk::SwitchStrategyPreemptionThreshold< 32 >, stk::SwitchStrategyPreemptionThreshold< 32, true >, stk::SwitchStrategyRoundRobinT< NoSleepYield >, stk::SwitchStrategyRoundRobinT< false >, stk::SwitchStrategyRoundRobinT< true >, stk::SwitchStrategySmoothWeightedRoundRobinT< NoSleepYield >, stk::SwitchStrategySmoothWeightedRoundRobinT< false >, and stk::SwitchStrategySmoothWeightedRoundRobinT< true >.

Definition at line 1446 of file stk_common.h.

1447 {
1448 STK_UNUSED(task);
1449 return false;
1450 }

References STK_UNUSED.

◆ RemoveTask()

template<EMonotonicSwitchStrategyType TStrategyType>
void stk::SwitchStrategyMonotonic< TStrategyType >::RemoveTask ( IKernelTask * task)
inlineoverridevirtual

Remove a task from the list.

Parameters
[in]taskTask to remove. Must not be NULL. Must be in m_tasks (asserted).
Note
Unlike RR, SWRR, EDF, and FP strategies there is no separate sleep list: all tasks, runnable and sleeping, reside in m_tasks, so this method simply unlinks the task unconditionally without a list-membership check.

Implements stk::ITaskSwitchStrategy.

Definition at line 170 of file stk_strategy_monotonic.h.

171 {
172 STK_ASSERT(task != nullptr);
173 STK_ASSERT(GetSize() != 0U);
174 STK_ASSERT(task->GetHead() == &m_tasks);
175
176 m_tasks.Unlink(task);
177 }
size_t GetSize() const override
Get the total number of tasks managed by this strategy.

◆ STK_NONCOPYABLE_CLASS()

template<EMonotonicSwitchStrategyType TStrategyType>
stk::SwitchStrategyMonotonic< TStrategyType >::STK_NONCOPYABLE_CLASS ( SwitchStrategyMonotonic< TStrategyType > )
private

Member Data Documentation

◆ m_tasks

template<EMonotonicSwitchStrategyType TStrategyType>
IKernelTask::ListHeadType stk::SwitchStrategyMonotonic< TStrategyType >::m_tasks
private

All tasks (runnable and sleeping) in priority order. GetNext() skips sleeping tasks via IsSleeping(). AddTask() maintains sort order.

Definition at line 262 of file stk_strategy_monotonic.h.


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