SuperTinyKernel™ RTOS 1.06.x
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk_strategy_fpriority.h
Go to the documentation of this file.
1/*
2 * SuperTinyKernel(TM) RTOS: 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_FPRIORITY_H_
11#define STK_STRATEGY_FPRIORITY_H_
12
17
18#include "stk_common.h"
19
20namespace stk {
21
57template <uint8_t MAX_PRIORITIES>
59{
60public:
71
80 {
81 PRIORITY_HIGHEST = (MAX_PRIORITIES - 1),
82 PRIORITY_HIGH = ((MAX_PRIORITIES / 2) + (MAX_PRIORITIES - 1)) / 2,
83 PRIORITY_ABOVE_NORMAL = (MAX_PRIORITIES / 2) + 1,
84 PRIORITY_NORMAL = (MAX_PRIORITIES / 2),
85 PRIORITY_BELOW_NORMAL = (MAX_PRIORITIES / 2) - 1,
86 PRIORITY_LOWER = (MAX_PRIORITIES / 4),
89 };
90
96 {
97 STK_STATIC_ASSERT_DESC(MAX_PRIORITIES <= 32U, "MAX_PRIORITIES exceeds 32-bit bitmap width");
98 }
99
104
117 void AddTask(IKernelTask *task) override
118 {
119 STK_ASSERT(task != nullptr);
120 STK_ASSERT(task->GetHead() == nullptr);
121 STK_ASSERT(GetTaskPriority(task) < MAX_PRIORITIES);
122
123 const Priority prio = GetTaskPriority(task);
124 const bool is_tail = (m_prev[prio] == m_tasks[prio].GetLast());
125
126 AddActive(task);
127
128 // if pointer was pointing to the tail, become a tail
129 if (is_tail)
130 {
131 m_prev[prio] = task;
132 }
133 }
134
143 void RemoveTask(IKernelTask *task) override
144 {
145 STK_ASSERT(task != nullptr);
146 STK_ASSERT(GetSize() != 0U);
147 STK_ASSERT((task->GetHead() == &m_tasks[GetTaskPriority(task)]) || (task->GetHead() == &m_sleep));
148
149 if (task->GetHead() == &m_sleep)
150 {
151 m_sleep.Unlink(task);
152 }
153 else
154 {
155 RemoveActive(task, GetTaskPriority(task));
156 }
157 }
158
169 {
170 IKernelTask *next = nullptr;
171
172 if (m_ready_bitmap != 0U)
173 {
175
176 next = (*m_prev[prio]->GetNext());
177 m_prev[prio] = next;
178 }
179
180 return next;
181 }
182
192 {
193 STK_ASSERT(GetSize() != 0U);
194
195 IKernelTask *first_task = nullptr;
196
197 if (m_ready_bitmap == 0U)
198 {
199 first_task = (*m_sleep.GetFirst());
200 }
201 else
202 {
204 first_task = (*m_tasks[prio].GetFirst());
205 }
206
207 return first_task;
208 }
209
215 size_t GetSize() const override
216 {
217 size_t total = m_sleep.GetSize();
218 for (Priority i = 0U; i < MAX_PRIORITIES; ++i)
219 {
220 total += m_tasks[i].GetSize();
221 }
222
223 return total;
224 }
225
232 void OnTaskSleep(IKernelTask *task) override
233 {
234 STK_ASSERT(task != nullptr);
235 STK_ASSERT(task->IsSleeping());
236 STK_ASSERT(task->GetHead() == &m_tasks[GetTaskPriority(task)]);
237
238 RemoveActive(task, GetTaskPriority(task));
239 m_sleep.LinkBack(task);
240 }
241
251 void OnTaskWake(IKernelTask *task) override
252 {
253 STK_ASSERT(task != nullptr);
254 STK_ASSERT(!task->IsSleeping());
255 STK_ASSERT(task->GetHead() == &m_sleep);
256
257 m_sleep.Unlink(task);
258 AddActive(task);
259 }
260
270 void OnTaskWeightChange(IKernelTask *task, Weight old_weight) override
271 {
272 const Priority old_prio = GetTaskPriorityFromWeight(old_weight);
273
274 STK_ASSERT(GetTaskPriority(task) < MAX_PRIORITIES);
275 STK_ASSERT(old_prio < MAX_PRIORITIES);
276
277 if (task->GetHead() != &m_sleep)
278 {
279 STK_ASSERT(task->GetHead() == &m_tasks[old_prio]);
280
281 // remove from the old priority list
282 RemoveActive(task, old_prio);
283
284 // re-add to the current priority list
285 AddActive(task);
286 }
287 }
288
289protected:
291 typedef uint8_t Priority;
292
303 {
304 const Priority prio = GetTaskPriority(task);
305
306 m_tasks[prio].LinkBack(task);
307
308 // init pointer
309 if (m_tasks[prio].GetSize() == 1U)
310 {
311 m_prev[prio] = task;
312
313 m_ready_bitmap |= (1U << prio);
314 }
315 }
316
330 void RemoveActive(IKernelTask *task, const Priority prio)
331 {
332 IKernelTask *next = (*task->GetNext());
333
334 m_tasks[prio].Unlink(task);
335
336 // update pointer
337 if (next != task)
338 {
339 m_prev[prio] = (*next->GetPrev());
340 }
341 else
342 {
343 m_prev[prio] = nullptr;
344
345 // this will cause a switch to a lower priority task list
346 m_ready_bitmap &= ~(1U << prio);
347 }
348 }
349
355 {
356 return static_cast<Priority>(weight);
357 }
358
367
378 {
379 #if defined(__GNUC__)
380 return GetTaskPriorityFromWeight(31U - __builtin_clz(bitmap));
381 #else
382 for (int8_t i = 31; i >= 0; --i)
383 {
384 if (bitmap & (1U << i))
385 {
387 }
388 }
389 return 0;
390 #endif
391 }
392
393private:
395
398 uint32_t m_ready_bitmap;
399 IKernelTask *m_prev[MAX_PRIORITIES];
400};
401
408
409} // namespace stk
410
411#endif /* STK_STRATEGY_FPRIORITY_H_ */
Contains interface definitions of the library.
#define __stk_forceinline
Forces compiler to always inline the decorated function, regardless of optimisation level.
Definition stk_defs.h:175
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:409
#define STK_STATIC_ASSERT_DESC(X, DESC)
Compile-time assertion with a custom error description. Produces a compilation error if X is false.
Definition stk_defs.h:429
#define STK_VIRT_DTOR
Makes destructors virtual and compliant to strict rules if STK_STRICT_COMPLIANCY=0.
Definition stk_defs.h:159
Namespace of STK package.
SwitchStrategyFixedPriority< 32 > SwitchStrategyFP32
Shorthand alias for SwitchStrategyFixedPriority<32>: 32 priority levels (0..31), using a single 32-bi...
int32_t Weight
Weight value (aka priority).
Definition stk_common.h:145
Scheduling-strategy-facing interface for a kernel task slot.
Definition stk_common.h:671
virtual Weight GetWeight() const =0
Get static base weight assigned to the task.
DLHeadType ListHeadType
List head type for IKernelTask elements.
Definition stk_common.h:676
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.
Fixed-priority preemptive scheduling strategy with round-robin arbitration within each priority level...
static __stk_forceinline Priority GetTaskPriorityFromWeight(int32_t weight)
Get priority from the task.
SwitchStrategyFixedPriority()
Construct an empty strategy with all priority levels empty, a clear bitmap, and null cursors.
void AddActive(IKernelTask *task)
Append a task to its priority level's runnable list and update the bitmap.
STK_VIRT_DTOR ~SwitchStrategyFixedPriority()=default
Destructor.
IKernelTask * GetFirst() override
Get the first task in the managed set (used by the kernel for initial scheduling).
void OnTaskSleep(IKernelTask *task) override
Notification that a task has entered the sleeping state.
static __stk_forceinline Priority GetTaskPriority(IKernelTask *task)
Get priority from the task.
IKernelTask * GetNext() override
Select and return the next task to run.
STK_NONCOPYABLE_CLASS(SwitchStrategyFixedPriority)
void AddTask(IKernelTask *task) override
Add task to the runnable set at its fixed priority level.
void RemoveTask(IKernelTask *task) override
Remove task from whichever list it currently occupies.
EPriority
Symbolic priority level constants for common use cases.
void OnTaskWeightChange(IKernelTask *task, Weight old_weight) override
Move a runnable task to a new priority level after its weight changed.
void RemoveActive(IKernelTask *task, const Priority prio)
Remove a task from its priority level's runnable list and update the bitmap/cursor.
static __stk_forceinline Priority GetHighestReadyPriority(uint32_t bitmap)
Find the index of the highest set bit in bitmap.
void OnTaskWake(IKernelTask *task) override
Notification that a task has become runnable again.
EConfig
Compile-time capability flags reported to the kernel.
IKernelTask::ListHeadType m_tasks[MAX_PRIORITIES]
size_t GetSize() const override
Get the total number of tasks managed by this strategy.