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

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
}
 Compile-time capability flags reported to the kernel. More...

Public Member Functions

 SwitchStrategyRoundRobin ()
 Construct an empty strategy with no tasks and a null cursor.
 ~SwitchStrategyRoundRobin ()
 Destructor.
void AddTask (IKernelTask *task)
 Add task to the runnable set.
void RemoveTask (IKernelTask *task)
 Remove task from whichever list it currently occupies.
IKernelTaskGetNext ()
 Advance cursor and return the next runnable task.
IKernelTaskGetFirst () const
 Get first task in the managed set (used by the kernel for initial scheduling).
size_t GetSize () const
 Get total number of tasks managed by this strategy.
void OnTaskSleep (IKernelTask *task)
 Notification that a task has entered the sleeping state.
void OnTaskWake (IKernelTask *task)
 Notification that a task has become runnable again.
bool OnTaskDeadlineMissed (IKernelTask *)
 Not supported, asserts unconditionally.

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.

Definition at line 47 of file stk_strategy_rrobin.h.

48 {
49 WEIGHT_API = 0,
50 SLEEP_EVENT_API = 1,
52 };
@ 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.
@ 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 56 of file stk_strategy_rrobin.h.

56 : m_tasks(), m_sleep(), m_prev(nullptr)
57 {}
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::SwitchStrategyRoundRobin::~SwitchStrategyRoundRobin ( )
inline

Destructor.

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

Definition at line 62 of file stk_strategy_rrobin.h.

63 {}

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 200 of file stk_strategy_rrobin.h.

201 {
202 m_tasks.LinkBack(task);
203
204 // update pointer: if all tasks were sleeping, this task will change state
205 // of the kernel to active
206 if (m_prev == nullptr)
207 m_prev = task;
208 }

References m_prev, and m_tasks.

Referenced by OnTaskWake().

Here is the caller graph for this function:

◆ AddTask()

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

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 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 m_prev = task;
84 }
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:330

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

Here is the call graph for this function:

◆ GetFirst()

IKernelTask * stk::SwitchStrategyRoundRobin::GetFirst ( ) const
inlinevirtual

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 132 of file stk_strategy_rrobin.h.

133 {
134 STK_ASSERT(GetSize() != 0U);
135
136 if (!m_tasks.IsEmpty())
137 return (*m_tasks.GetFirst());
138 else
139 return (*m_sleep.GetFirst());
140 }
size_t GetSize() const
Get total number of tasks managed by this strategy.

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

Referenced by stk::test::TEST().

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

◆ GetNext()

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

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 113 of file stk_strategy_rrobin.h.

114 {
115 IKernelTask *ret = m_prev;
116
117 if (ret != nullptr)
118 {
119 ret = (*ret->GetNext());
120 m_prev = ret;
121 }
122
123 return ret;
124 }

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

Here is the call graph for this function:

◆ GetSize()

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

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 145 of file stk_strategy_rrobin.h.

146 {
147 return m_tasks.GetSize() + m_sleep.GetSize();
148 }

References m_sleep, and m_tasks.

Referenced by GetFirst(), and RemoveTask().

Here is the caller graph for this function:

◆ OnTaskDeadlineMissed()

bool stk::SwitchStrategyRoundRobin::OnTaskDeadlineMissed ( IKernelTask * )
inlinevirtual

Not supported, asserts unconditionally.

Note
This strategy uses DEADLINE_MISSED_API = 0. See OnTaskDeadlineMissed() for rationale.

Implements stk::ITaskSwitchStrategy.

Definition at line 184 of file stk_strategy_rrobin.h.

185 {
186 // Budget Overrun API unsupported
187 STK_ASSERT(false);
188 return false;
189 }

References STK_ASSERT.

◆ OnTaskSleep()

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

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 155 of file stk_strategy_rrobin.h.

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

References stk::util::DListEntry< T, _ClosedLoop >::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)
inlinevirtual

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 171 of file stk_strategy_rrobin.h.

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

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

Here is the call graph for this function:

◆ 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 222 of file stk_strategy_rrobin.h.

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

References stk::util::DListEntry< T, _ClosedLoop >::GetNext(), stk::util::DListEntry< T, _ClosedLoop >::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)
inlinevirtual

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 92 of file stk_strategy_rrobin.h.

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

References stk::util::DListEntry< T, _ClosedLoop >::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 239 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 238 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 237 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: