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:
60
65
70
78 void AddTask(IKernelTask *task) override
79 {
80 STK_ASSERT(task != nullptr);
81 STK_ASSERT(task->GetHead() == nullptr);
82
83 const bool tail = (m_prev == m_tasks.GetLast());
84
85 m_tasks.LinkBack(task);
86
87 // if pointer was pointing to the tail, become a tail
88 if (tail)
89 {
90 m_prev = task;
91 }
92 }
93
100 void RemoveTask(IKernelTask *task) override
101 {
102 STK_ASSERT(task != nullptr);
103 STK_ASSERT(GetSize() != 0);
104 STK_ASSERT((task->GetHead() == &m_tasks) || (task->GetHead() == &m_sleep));
105
106 if (task->GetHead() == &m_tasks)
107 {
108 RemoveActive(task);
109 }
110 else
111 {
112 m_sleep.Unlink(task);
113 }
114 }
115
126 {
127 IKernelTask *next = m_prev;
128
129 if (next != nullptr)
130 {
131 next = (*next->GetNext());
132 m_prev = next;
133 }
134
135 return next;
136 }
137
145 {
146 STK_ASSERT(GetSize() != 0U);
147
148 return (*(!m_tasks.IsEmpty() ? m_tasks.GetFirst() : m_sleep.GetFirst()));
149 }
150
154 size_t GetSize() const override
155 {
156 return m_tasks.GetSize() + m_sleep.GetSize();
157 }
158
164 void OnTaskSleep(IKernelTask *task) override
165 {
166 STK_ASSERT(task != nullptr);
167 STK_ASSERT(task->IsSleeping());
168 STK_ASSERT(task->GetHead() == &m_tasks);
169
170 RemoveActive(task);
171 m_sleep.LinkBack(task);
172 }
173
180 void OnTaskWake(IKernelTask *task) override
181 {
182 STK_ASSERT(task != nullptr);
183 STK_ASSERT(!task->IsSleeping());
184 STK_ASSERT(task->GetHead() == &m_sleep);
185
186 m_sleep.Unlink(task);
187 AddActive(task);
188 }
189
197 bool OnTaskYield(IKernelTask *task) override
198 {
199 if __stk_constexpr_cpp17 (NoSleepYield)
200 {
201 STK_ASSERT(task != nullptr);
202
203 bool handled = false;
204
205 if (task->GetHead() == &m_tasks)
206 {
207 m_prev = task; // GetNext() will return task's successor (or task itself if alone)
208 handled = true;
209 }
210
211 return handled;
212 }
213 else
214 {
215 STK_UNUSED(task);
216 return false;
217 }
218 }
219
220protected:
222
230 {
231 m_tasks.LinkBack(task);
232
233 // update pointer: if all tasks were sleeping, this task will change state
234 // of the kernel to active
235 if (m_prev == nullptr)
236 {
237 m_prev = task;
238 }
239 }
240
258 {
259 IKernelTask *const next = (*task->GetNext());
260
261 m_tasks.Unlink(task);
262
263 // update pointer: if there are no tasks left GetNext() will return nullptr causing a sleep
264 // state for the kernel
265 if (next == task)
266 {
267 m_prev = nullptr;
268 }
269 else if (m_prev == task)
270 {
271 // cursor was on the removed task: step back so that GetNext() returns its successor
272 m_prev = (*next->GetPrev());
273 }
274 else
275 {
276 // cursor is on another task: leave the rotation untouched
277 }
278 }
279
283};
284
290
296
302
308
309} // namespace stk
310
311#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:902
DLHeadType ListHeadType
List head type for IKernelTask elements.
Definition stk_common.h:907
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.