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_strategy_rrobin.h
Go to the documentation of this file.
1/*
2 * SuperTinyKernel™ (STK): Lightweight High-Performance Deterministic C++ RTOS for Embedded Systems.
3 *
4 * Source: https://github.com/SuperTinyKernel-RTOS
5 *
6 * Copyright (c) 2022-2026 Neutron Code Limited <stk@neutroncode.com>. All Rights Reserved.
7 * License: MIT License, see LICENSE for a full text.
8 */
9
10#ifndef STK_STRATEGY_RROBIN_H_
11#define STK_STRATEGY_RROBIN_H_
12
17
18#include "stk_common.h"
19
20namespace stk {
21
46template <bool NoSleepYield> class SwitchStrategyRoundRobinT final : public ITaskSwitchStrategy
47{
48public:
61
66
71
79 void AddTask(IKernelTask *task) override
80 {
81 STK_ASSERT(task != nullptr);
82 STK_ASSERT(task->GetHead() == nullptr);
83
84 const bool tail = (m_prev == m_tasks.GetLast());
85
86 m_tasks.LinkBack(task);
87
88 // if pointer was pointing to the tail, become a tail
89 if (tail)
90 {
91 m_prev = task;
92 }
93 }
94
101 void RemoveTask(IKernelTask *task) override
102 {
103 STK_ASSERT(task != nullptr);
104 STK_ASSERT(GetSize() != 0);
105 STK_ASSERT((task->GetHead() == &m_tasks) || (task->GetHead() == &m_sleep));
106
107 if (task->GetHead() == &m_tasks)
108 {
109 RemoveActive(task);
110 }
111 else
112 {
113 m_sleep.Unlink(task);
114 }
115 }
116
127 {
128 IKernelTask *next = m_prev;
129
130 if (next != nullptr)
131 {
132 next = (*next->GetNext());
133 m_prev = next;
134 }
135
136 return next;
137 }
138
146 {
147 STK_ASSERT(GetSize() != 0U);
148
149 return (*(!m_tasks.IsEmpty() ? m_tasks.GetFirst() : m_sleep.GetFirst()));
150 }
151
155 size_t GetSize() const override
156 {
157 return m_tasks.GetSize() + m_sleep.GetSize();
158 }
159
165 void OnTaskSleep(IKernelTask *task) override
166 {
167 STK_ASSERT(task != nullptr);
168 STK_ASSERT(task->IsSleeping());
169 STK_ASSERT(task->GetHead() == &m_tasks);
170
171 RemoveActive(task);
172 m_sleep.LinkBack(task);
173 }
174
181 void OnTaskWake(IKernelTask *task) override
182 {
183 STK_ASSERT(task != nullptr);
184 STK_ASSERT(!task->IsSleeping());
185 STK_ASSERT(task->GetHead() == &m_sleep);
186
187 m_sleep.Unlink(task);
188 AddActive(task);
189 }
190
198 bool OnTaskYield(IKernelTask *task) override
199 {
200 if __stk_constexpr_cpp17 (NoSleepYield)
201 {
202 STK_ASSERT(task != nullptr);
203
204 bool handled = false;
205
206 if (task->GetHead() == &m_tasks)
207 {
208 m_prev = task; // GetNext() will return task's successor (or task itself if alone)
209 handled = true;
210 }
211
212 return handled;
213 }
214 else
215 {
216 STK_UNUSED(task);
217 return false;
218 }
219 }
220
221protected:
223
231 {
232 m_tasks.LinkBack(task);
233
234 // update pointer: if all tasks were sleeping, this task will change state
235 // of the kernel to active
236 if (m_prev == nullptr)
237 {
238 m_prev = task;
239 }
240 }
241
259 {
260 IKernelTask *const next = (*task->GetNext());
261
262 m_tasks.Unlink(task);
263
264 // update pointer: if there are no tasks left GetNext() will return nullptr causing a sleep
265 // state for the kernel
266 if (next == task)
267 {
268 m_prev = nullptr;
269 }
270 else if (m_prev == task)
271 {
272 // cursor was on the removed task: step back so that GetNext() returns its successor
273 m_prev = (*next->GetPrev());
274 }
275 else
276 {
277 // cursor is on another task: leave the rotation untouched
278 }
279 }
280
284};
285
291
297
303
309
310} // namespace stk
311
312#endif /* STK_STRATEGY_RROBIN_H_ */
Contains interface definitions of the library.
#define STK_UNUSED(X)
Explicitly marks a variable as unused to suppress compiler warnings.
Definition stk_defs.h:715
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:516
#define __stk_constexpr_cpp17
constexpr definition for C++17 and above.
Definition stk_defs.h:489
#define STK_VIRT_DTOR
Makes destructors virtual and compliant to strict rules if STK_STRICT_COMPLIANCY=0.
Definition stk_defs.h:261
Namespace of STK package.
SwitchStrategyRoundRobinT< true > SwitchStrategyRR_NSY
Shorthand for SwitchStrategyRoundRobinNoSleepYield.
SwitchStrategyRoundRobinT< false > SwitchStrategyRoundRobin
Shorthand alias for SwitchStrategyRoundRobinT<>.
SwitchStrategyRoundRobinT< true > SwitchStrategyRoundRobinNoSleepYield
Round-Robin strategy where Yield() keeps the task runnable (NOSLEEP_YIELD_API = 1).
SwitchStrategyRoundRobinT< false > SwitchStrategyRR
Shorthand alias for SwitchStrategyRoundRobin.
Scheduling-strategy-facing interface for a kernel task slot.
Definition stk_common.h:963
DLHeadType ListHeadType
List head type for IKernelTask elements.
Definition stk_common.h:968
virtual bool IsSleeping() const =0
Check whether the task is currently sleeping.
Interface for a task switching strategy implementation.
DLEntryType * GetNext()
Get the next entry in the list.
DLHeadType * GetHead()
Get the list head this entry currently belongs to.
DLEntryType * GetPrev()
Get the previous entry in the list.
void AddTask(IKernelTask *task) override
Add task to the runnable set.
void OnTaskWake(IKernelTask *task) override
Notification that a task has become runnable again.
SwitchStrategyRoundRobinT()
Construct an empty strategy with no tasks and a null cursor.
STK_NONCOPYABLE_CLASS(SwitchStrategyRoundRobinT)
IKernelTask * GetNext() override
Advance cursor and return the next runnable task.
void RemoveTask(IKernelTask *task) override
Remove task from whichever list it currently occupies.
void AddActive(IKernelTask *task)
Append a task to m_tasks and restore the cursor if necessary.
void OnTaskSleep(IKernelTask *task) override
Notification that a task has entered the sleeping state.
IKernelTask * GetFirst() override
Get first task in the managed set (used by the kernel for initial scheduling).
STK_VIRT_DTOR ~SwitchStrategyRoundRobinT()=default
Destructor.
void RemoveActive(IKernelTask *task)
Remove a task from m_tasks and update the cursor.
size_t GetSize() const override
Get total number of tasks managed by this strategy.
bool OnTaskYield(IKernelTask *task) override
Notification that the running task called Yield() (non-HRT kernel modes only).
EConfig
Compile-time capability flags reported to the kernel.