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::SwitchStrategyRoundRobin Class Referencefinal

Round-Robin task-switching strategy: each runnable task receives one time slice (one tick interval) in turn before the kernel moves to the next task. More...

#include <stk_strategy_rrobin.h>

Inheritance diagram for stk::SwitchStrategyRoundRobin:
Collaboration diagram for stk::SwitchStrategyRoundRobin:

Public Types

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

Public Member Functions

 SwitchStrategyRoundRobin ()
 Construct an empty strategy with no tasks and a null cursor.
STK_VIRT_DTOR ~SwitchStrategyRoundRobin ()=default
 Destructor.
void AddTask (IKernelTask *task) override
 Add task to the runnable set.
void RemoveTask (IKernelTask *task) override
 Remove task from whichever list it currently occupies.
IKernelTaskGetNext () override
 Advance cursor and return the next runnable task.
IKernelTaskGetFirst () override
 Get first task in the managed set (used by the kernel for initial scheduling).
size_t GetSize () const override
 Get total number of tasks managed by this strategy.
void OnTaskSleep (IKernelTask *task) override
 Notification that a task has entered the sleeping state.
void OnTaskWake (IKernelTask *task) override
 Notification that a task has become runnable again.
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.

Protected Member Functions

 STK_NONCOPYABLE_CLASS (SwitchStrategyRoundRobin)
void AddActive (IKernelTask *task)
 Append a task to m_tasks and restore the cursor if necessary.
void RemoveActive (IKernelTask *task)
 Remove a task from m_tasks and update the cursor.

Protected Attributes

IKernelTask::ListHeadType m_tasks
 Runnable tasks eligible for scheduling.
IKernelTask::ListHeadType m_sleep
 Sleeping (blocked) tasks not eligible for scheduling.
IKernelTaskm_prev
 Iterator cursor: the most recently scheduled task, or nullptr when no runnable tasks exist. GetNext() advances from this position.

Detailed Description

Round-Robin task-switching strategy: each runnable task receives one time slice (one tick interval) in turn before the kernel moves to the next task.

Internally maintains two intrusive lists:

  • m_tasks — tasks currently eligible for scheduling (runnable).
  • m_sleep — tasks that called Sleep() or are otherwise blocked.

The iterator cursor (m_prev) points to the most recently scheduled task. On each call to GetNext() the cursor advances by one position in m_tasks, wrapping around at the end (closed-loop list). When m_tasks is empty, GetNext() returns nullptr and the kernel transitions to the sleep trap.

Note
All runnable tasks receive equal CPU time regardless of creation order or any other factor. There is no priority or weight mechanism in this strategy (WEIGHT_API = 0).
Requires the kernel Sleep API (SLEEP_EVENT_API = 1): the kernel must call OnTaskSleep() and OnTaskWake() when a task's sleep state changes.
See also
SwitchStrategyRR, ITaskSwitchStrategy

Definition at line 41 of file stk_strategy_rrobin.h.

Member Enumeration Documentation

◆ EConfig

Compile-time capability flags reported to the kernel.

Enumerator
WEIGHT_API 

This strategy does not use per-task weights; all tasks are treated equally.

SLEEP_EVENT_API 

This strategy requires OnTaskSleep() / OnTaskWake() events to maintain the active/sleep list split.

DEADLINE_MISSED_API 

This strategy does not use OnTaskDeadlineMissed() events.

PRIORITY_INHERITANCE_API 

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

Definition at line 47 of file stk_strategy_rrobin.h.

48 {
49 WEIGHT_API = 0,
50 SLEEP_EVENT_API = 1,
53 };
@ SLEEP_EVENT_API
This strategy requires OnTaskSleep() / OnTaskWake() events to maintain the active/sleep list split.
@ PRIORITY_INHERITANCE_API
This strategy does not require Priority Inheritance and OnTaskPriorityChange() events.
@ DEADLINE_MISSED_API
This strategy does not use OnTaskDeadlineMissed() events.
@ WEIGHT_API
This strategy does not use per-task weights; all tasks are treated equally.

Constructor & Destructor Documentation

◆ SwitchStrategyRoundRobin()

stk::SwitchStrategyRoundRobin::SwitchStrategyRoundRobin ( )
inline

Construct an empty strategy with no tasks and a null cursor.

Definition at line 57 of file stk_strategy_rrobin.h.

57 : m_tasks(), m_sleep(), m_prev(nullptr)
58 {}
IKernelTask::ListHeadType m_tasks
Runnable tasks eligible for scheduling.
IKernelTask::ListHeadType m_sleep
Sleeping (blocked) tasks not eligible for scheduling.
IKernelTask * m_prev
Iterator cursor: the most recently scheduled task, or nullptr when no runnable tasks exist....

References m_prev, m_sleep, and m_tasks.

Referenced by STK_NONCOPYABLE_CLASS().

Here is the caller graph for this function:

◆ ~SwitchStrategyRoundRobin()

STK_VIRT_DTOR stk::SwitchStrategyRoundRobin::~SwitchStrategyRoundRobin ( )
default

Destructor.

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

References STK_VIRT_DTOR.

Member Function Documentation

◆ AddActive()

void stk::SwitchStrategyRoundRobin::AddActive ( IKernelTask * task)
inlineprotected

Append a task to m_tasks and restore the cursor if necessary.

Parameters
[in]taskTask to make runnable.
Note
Cursor invariant: if m_prev is nullptr (all tasks were previously sleeping), it is set to the newly added task so GetNext() immediately returns a valid task on the next call rather than returning nullptr and causing a spurious sleep cycle.

Definition at line 193 of file stk_strategy_rrobin.h.

194 {
195 m_tasks.LinkBack(task);
196
197 // update pointer: if all tasks were sleeping, this task will change state
198 // of the kernel to active
199 if (m_prev == nullptr)
200 {
201 m_prev = task;
202 }
203 }

References m_prev, and m_tasks.

Referenced by OnTaskWake().

Here is the caller graph for this function:

◆ AddTask()

void stk::SwitchStrategyRoundRobin::AddTask ( IKernelTask * task)
inlineoverridevirtual

Add task to the runnable set.

Parameters
[in]taskTask to add. Must not be nullptr and must not already be in any list.
Note
The task is appended to the back of m_tasks.
Cursor invariant: if m_prev was already pointing at the tail before insertion, it is advanced to the new tail so that GetNext() will return the new task on its next iteration rather than skipping it.

Implements stk::ITaskSwitchStrategy.

Definition at line 72 of file stk_strategy_rrobin.h.

73 {
74 STK_ASSERT(task != nullptr);
75 STK_ASSERT(task->GetHead() == nullptr);
76
77 const bool tail = (m_prev == m_tasks.GetLast());
78
79 m_tasks.LinkBack(task);
80
81 // if pointer was pointing to the tail, become a tail
82 if (tail)
83 {
84 m_prev = task;
85 }
86 }
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:516

References stk::util::DListEntry< T, TClosedLoop >::GetHead(), m_prev, m_tasks, and STK_ASSERT.

Here is the call graph for this function:

◆ GetFirst()

IKernelTask * stk::SwitchStrategyRoundRobin::GetFirst ( )
inlineoverridevirtual

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

Returns
The first task in m_tasks if any task is runnable; otherwise the first task in m_sleep. Asserts if the combined set is empty (GetSize() == 0).
Note
Preference is given to runnable tasks. The sleep fallback allows the kernel to identify any task even when all are currently sleeping.

Implements stk::ITaskSwitchStrategy.

Definition at line 138 of file stk_strategy_rrobin.h.

139 {
140 STK_ASSERT(GetSize() != 0U);
141
142 return (*(!m_tasks.IsEmpty() ? m_tasks.GetFirst() : m_sleep.GetFirst()));
143 }
size_t GetSize() const override
Get total number of tasks managed by this strategy.

References GetSize(), m_sleep, m_tasks, and STK_ASSERT.

Here is the call graph for this function:

◆ GetNext()

IKernelTask * stk::SwitchStrategyRoundRobin::GetNext ( )
inlineoverridevirtual

Advance cursor and return the next runnable task.

Returns
Pointer to the next task in m_tasks after the cursor position, or nullptr if m_tasks is empty (no runnable tasks — kernel will sleep).
Note
The cursor (m_prev) is updated to the returned task on each call. Because m_tasks is a closed-loop list the cursor wraps automatically from the last task back to the first, producing continuous round-robin rotation.
If the cursor itself is nullptr (all tasks were sleeping and none have woken), the method returns nullptr immediately without touching m_prev.

Implements stk::ITaskSwitchStrategy.

Definition at line 119 of file stk_strategy_rrobin.h.

120 {
121 IKernelTask *next = m_prev;
122
123 if (next != nullptr)
124 {
125 next = (*next->GetNext());
126 m_prev = next;
127 }
128
129 return next;
130 }

References stk::util::DListEntry< T, TClosedLoop >::GetNext(), and m_prev.

Here is the call graph for this function:

◆ GetSize()

size_t stk::SwitchStrategyRoundRobin::GetSize ( ) const
inlineoverridevirtual

Get total number of tasks managed by this strategy.

Returns
Sum of tasks in m_tasks (runnable) and m_sleep (sleeping).

Implements stk::ITaskSwitchStrategy.

Definition at line 148 of file stk_strategy_rrobin.h.

149 {
150 return m_tasks.GetSize() + m_sleep.GetSize();
151 }

References m_sleep, and m_tasks.

Referenced by GetFirst(), and 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 1371 of file stk_common.h.

1372 {
1373 STK_UNUSED(task);
1374 return false;
1375 }
#define STK_UNUSED(X)
Explicitly marks a variable as unused to suppress compiler warnings.
Definition stk_defs.h:715

References STK_UNUSED.

◆ OnTaskSleep()

void stk::SwitchStrategyRoundRobin::OnTaskSleep ( IKernelTask * task)
inlineoverridevirtual

Notification that a task has entered the sleeping state.

Parameters
[in]taskThe task that is now sleeping. Must be in m_tasks (asserted).
Note
Moves the task from m_tasks to m_sleep via RemoveActive(), which also updates the cursor so GetNext() continues correctly.

Implements stk::ITaskSwitchStrategy.

Definition at line 158 of file stk_strategy_rrobin.h.

159 {
160 STK_ASSERT(task != nullptr);
161 STK_ASSERT(task->IsSleeping());
162 STK_ASSERT(task->GetHead() == &m_tasks);
163
164 RemoveActive(task);
165 m_sleep.LinkBack(task);
166 }
void RemoveActive(IKernelTask *task)
Remove a task from m_tasks and update the cursor.

References stk::util::DListEntry< T, TClosedLoop >::GetHead(), stk::IKernelTask::IsSleeping(), m_sleep, m_tasks, RemoveActive(), and STK_ASSERT.

Here is the call graph for this function:

◆ OnTaskWake()

void stk::SwitchStrategyRoundRobin::OnTaskWake ( IKernelTask * task)
inlineoverridevirtual

Notification that a task has become runnable again.

Parameters
[in]taskThe task that woke up. Must be in m_sleep (asserted).
Note
Moves the task from m_sleep to m_tasks via AddActive(), which also restores the cursor if it was null (i.e. this is the first runnable task after a period where all tasks were sleeping).

Implements stk::ITaskSwitchStrategy.

Definition at line 174 of file stk_strategy_rrobin.h.

175 {
176 STK_ASSERT(task != nullptr);
177 STK_ASSERT(!task->IsSleeping());
178 STK_ASSERT(task->GetHead() == &m_sleep);
179
180 m_sleep.Unlink(task);
181 AddActive(task);
182 }
void AddActive(IKernelTask *task)
Append a task to m_tasks and restore the cursor if necessary.

References AddActive(), stk::util::DListEntry< T, TClosedLoop >::GetHead(), stk::IKernelTask::IsSleeping(), m_sleep, and STK_ASSERT.

Here is the call graph for this function:

◆ 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 >, and stk::SwitchStrategyFixedPriority< 32 >.

Definition at line 1389 of file stk_common.h.

1390 {
1391 STK_UNUSED(task);
1392 STK_UNUSED(old_weight);
1393 }

References STK_UNUSED.

◆ RemoveActive()

void stk::SwitchStrategyRoundRobin::RemoveActive ( IKernelTask * task)
inlineprotected

Remove a task from m_tasks and update the cursor.

Parameters
[in]taskRunnable task to remove.
Note
Cursor update algorithm: the cursor must be repositioned so that the next call to GetNext() returns the task that would have followed the removed one.
  • Capture next = task->GetNext() (the successor in the closed-loop list) before unlinking, while the list links are still valid.
  • After unlinking, if next != task (i.e. other tasks remain), set m_prev = next->GetPrev(). GetNext() will then advance from m_prev to next, preserving the round-robin sequence without skipping a task.
  • If next == task the removed task was the only element; set m_prev to nullptr so GetNext() returns nullptr and the kernel sleeps.

Definition at line 217 of file stk_strategy_rrobin.h.

218 {
219 IKernelTask *const next = (*task->GetNext());
220
221 m_tasks.Unlink(task);
222
223 // update pointer: set to previous task so that GetNext() could return next,
224 // if there are no tasks left GetNext() will return nullptr causing a sleep
225 // state for the kernel
226 if (next != task)
227 {
228 m_prev = (*next->GetPrev());
229 }
230 else
231 {
232 m_prev = nullptr;
233 }
234 }

References stk::util::DListEntry< T, TClosedLoop >::GetNext(), stk::util::DListEntry< T, TClosedLoop >::GetPrev(), m_prev, and m_tasks.

Referenced by OnTaskSleep(), and RemoveTask().

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

◆ RemoveTask()

void stk::SwitchStrategyRoundRobin::RemoveTask ( IKernelTask * task)
inlineoverridevirtual

Remove task from whichever list it currently occupies.

Parameters
[in]taskTask to remove. Must not be nullptr and must belong to either m_tasks or m_sleep (asserted).
Note
If the task is in m_tasks, delegates to RemoveActive() which also updates the cursor. If the task is in m_sleep, simply unlinks it.

Implements stk::ITaskSwitchStrategy.

Definition at line 94 of file stk_strategy_rrobin.h.

95 {
96 STK_ASSERT(task != nullptr);
97 STK_ASSERT(GetSize() != 0);
98 STK_ASSERT((task->GetHead() == &m_tasks) || (task->GetHead() == &m_sleep));
99
100 if (task->GetHead() == &m_tasks)
101 {
102 RemoveActive(task);
103 }
104 else
105 {
106 m_sleep.Unlink(task);
107 }
108 }

References stk::util::DListEntry< T, TClosedLoop >::GetHead(), GetSize(), m_sleep, m_tasks, RemoveActive(), and STK_ASSERT.

Here is the call graph for this function:

◆ STK_NONCOPYABLE_CLASS()

stk::SwitchStrategyRoundRobin::STK_NONCOPYABLE_CLASS ( SwitchStrategyRoundRobin )
protected

References SwitchStrategyRoundRobin().

Here is the call graph for this function:

Member Data Documentation

◆ m_prev

IKernelTask* stk::SwitchStrategyRoundRobin::m_prev
protected

Iterator cursor: the most recently scheduled task, or nullptr when no runnable tasks exist. GetNext() advances from this position.

Definition at line 238 of file stk_strategy_rrobin.h.

Referenced by AddActive(), AddTask(), GetNext(), RemoveActive(), and SwitchStrategyRoundRobin().

◆ m_sleep

IKernelTask::ListHeadType stk::SwitchStrategyRoundRobin::m_sleep
protected

Sleeping (blocked) tasks not eligible for scheduling.

Definition at line 237 of file stk_strategy_rrobin.h.

Referenced by GetFirst(), GetSize(), OnTaskSleep(), OnTaskWake(), RemoveTask(), and SwitchStrategyRoundRobin().

◆ m_tasks

IKernelTask::ListHeadType stk::SwitchStrategyRoundRobin::m_tasks
protected

Runnable tasks eligible for scheduling.

Definition at line 236 of file stk_strategy_rrobin.h.

Referenced by AddActive(), AddTask(), GetFirst(), GetSize(), OnTaskSleep(), RemoveActive(), RemoveTask(), and SwitchStrategyRoundRobin().


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