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::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield > Class Template Referencefinal

Fixed-priority preemptive scheduling strategy with round-robin arbitration within each priority level. More...

#include <stk_strategy_fpriority.h>

Inheritance diagram for stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >:
Collaboration diagram for stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >:

Public Types

enum  EConfig {
  WEIGHT_API = 1 ,
  SLEEP_EVENT_API = 1 ,
  DEADLINE_MISSED_API = 0 ,
  PRIORITY_INHERITANCE_API = 1 ,
  NOSLEEP_YIELD_API = NoSleepYield ,
  TIMESLICE_API = 0
}
 Compile-time capability flags reported to the kernel. More...
enum  EPriority {
  PRIORITY_HIGHEST = (MAX_PRIORITIES - 1) ,
  PRIORITY_HIGH = ((MAX_PRIORITIES / 2) + (MAX_PRIORITIES - 1)) / 2 ,
  PRIORITY_ABOVE_NORMAL = (MAX_PRIORITIES / 2) + 1 ,
  PRIORITY_NORMAL = (MAX_PRIORITIES / 2) ,
  PRIORITY_BELOW_NORMAL = (MAX_PRIORITIES / 2) - 1 ,
  PRIORITY_LOWER = (MAX_PRIORITIES / 4) ,
  PRIORITY_ABOVE_LOWEST = (0 + 1) ,
  PRIORITY_LOWEST = 0
}
 Symbolic priority level constants for common use cases. More...

Public Member Functions

 SwitchStrategyFixedPriority ()
 Construct an empty strategy with all priority levels empty, a clear bitmap, and null cursors.
STK_VIRT_DTOR ~SwitchStrategyFixedPriority ()=default
 Destructor.
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.
IKernelTask * GetNext () override
 Select and return the next task to run.
IKernelTask * GetFirst () override
 Get the first task in the managed set (used by the kernel for initial scheduling).
size_t GetSize () const override
 Get the 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.
void OnTaskWeightChange (IKernelTask *task, Weight old_weight) override
 Move a runnable task to a new priority level after its weight changed.
bool OnTaskYield (IKernelTask *task) override
 Notification that the running task called Yield() (non-HRT kernel modes only).
virtual bool OnTaskTimeSlice (IKernelTask *task)
 Notification that the running task's time slice expired (KERNEL_TIMESLICE only).
virtual bool OnTaskDeadlineMissed (IKernelTask *task)
 Notification that a task has exceeded its HRT deadline; returns whether the strategy can recover without a hard fault.

Protected Types

typedef uint8_t Priority
 Priority type.

Protected Member Functions

void AddActive (IKernelTask *task)
 Append a task to its priority level's runnable list and update the bitmap.
void RemoveActive (IKernelTask *task, const Priority prio)
 Remove a task from its priority level's runnable list and update the bitmap/cursor.

Static Protected Member Functions

static __stk_forceinline Priority GetTaskPriorityFromWeight (int32_t weight)
 Get priority from the task.
static __stk_forceinline Priority GetTaskPriority (IKernelTask *task)
 Get priority from the task.
static __stk_forceinline Priority GetHighestReadyPriority (uint32_t bitmap)
 Find the index of the highest set bit in bitmap.

Private Member Functions

 STK_NONCOPYABLE_CLASS (SwitchStrategyFixedPriority)

Private Attributes

IKernelTask::ListHeadType m_tasks [MAX_PRIORITIES]
 Per-priority runnable task lists. m_tasks[i] holds all runnable tasks at priority level i.
IKernelTask::ListHeadType m_sleep
 Sleeping (blocked) tasks. Priority is retained in GetWeight() and restored on OnTaskWake().
uint32_t m_ready_bitmap
 Bitmask of non-empty priority levels: bit i is set when m_tasks[i] has at least one runnable task. Updated by AddActive() (bit set) and RemoveActive() (bit cleared on last removal).
IKernelTask * m_prev [MAX_PRIORITIES]
 Per-priority round-robin cursor. m_prev[i] is the most recently scheduled task at level i, or nullptr when level i is empty. GetNext() advances from this position.

Detailed Description

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
class stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >

Fixed-priority preemptive scheduling strategy with round-robin arbitration within each priority level.

Template Parameters
MAX_PRIORITIESNumber of distinct priority levels. Must be in the range [1, 32] (enforced by a compile-time assertion). Bit i of the 32-bit m_ready_bitmap represents priority level i. The concrete alias SwitchStrategyFP32 uses MAX_PRIORITIES = 32.
NoSleepYieldIf true, Yield() keeps the task in the runnable set and hands the CPU to the next task at the same priority level (see OnTaskYield). If false (default), the kernel performs the legacy yield: the task sleeps for YIELD_TICKS, which also lets lower-priority tasks run during that tick.
Priority assignment
Each task's priority is read from ITask::GetWeight(), cast to uint8_t, and must be in the range [0, MAX_PRIORITIES - 1]. Tasks do not use the dynamic current-weight mechanism, the static weight value is the priority. Configure a task's priority by overriding ITask::GetWeight() to return the desired level.
Scheduling rules
  • The highest runnable priority level is always selected. A task at priority N will never run while any task at priority > N is runnable.
  • Tasks at the same priority level are scheduled in round-robin order (one tick slice each), using a per-level cursor (m_prev[prio]).
  • Higher numeric value = higher priority. 0 is the lowest, MAX_PRIORITIES - 1 is highest.
No-sleep yield
When NoSleepYield is true, OnTaskYield() moves the yielding task's per-level cursor onto the task itself, so the following GetNext() returns its successor at the same priority level. If the task is alone at its level, it is selected again (no context switch): a yield never hands the CPU to a lower priority level, unlike the legacy sleep-based yield.
Priority detection — O(1) bitmap
m_ready_bitmap is a 32-bit bitmask where bit i is set whenever priority level i has at least one runnable task. GetNext() and GetFirst() locate the highest set bit in O(1) via __builtin_clz (GCC/Clang) or a portable 32->0 scan fallback. The bitmap is kept consistent by AddActive() (bit set) and RemoveActive() (bit cleared on last removal).
Note
Uses the Weight API (WEIGHT_API = 1): GetWeight() is interpreted as the task's fixed priority level. The dynamic weight functions (SetCurrentWeight / GetCurrentWeight) are not used by this strategy.
Requires the kernel Sleep API (SLEEP_EVENT_API = 1): OnTaskSleep() and OnTaskWake() maintain the per-priority runnable lists and keep m_ready_bitmap accurate.
See also
SwitchStrategyFP32, SwitchStrategyFP32_NSY, ITaskSwitchStrategy, ITask::GetWeight

Definition at line 69 of file stk_strategy_fpriority.h.

Member Typedef Documentation

◆ Priority

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
typedef uint8_t stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::Priority
protected

Priority type.

Definition at line 339 of file stk_strategy_fpriority.h.

Member Enumeration Documentation

◆ EConfig

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
enum stk::SwitchStrategyFixedPriority::EConfig

Compile-time capability flags reported to the kernel.

Enumerator
WEIGHT_API 

This strategy interprets GetWeight() as the task's fixed priority level (0 .. MAX_PRIORITIES - 1). Dynamic weight functions are not used.

SLEEP_EVENT_API 

This strategy requires OnTaskSleep() / OnTaskWake() events to maintain per-priority runnable lists and keep m_ready_bitmap accurate.

DEADLINE_MISSED_API 

This strategy does not use OnTaskDeadlineMissed() events.

PRIORITY_INHERITANCE_API 

This strategy expects OnTaskPriorityChange() events to support priority inheritance requests.

NOSLEEP_YIELD_API 

(1) enables OnTaskYield(): yielding task stays runnable and hands the CPU to same-priority peers.

TIMESLICE_API 

This strategy does not support KERNEL_TIMESLICE mode.

Definition at line 75 of file stk_strategy_fpriority.h.

76 {
77 WEIGHT_API = 1,
78 SLEEP_EVENT_API = 1,
82 TIMESLICE_API = 0
83 };
Fixed-priority preemptive scheduling strategy with round-robin arbitration within each priority level...
@ DEADLINE_MISSED_API
This strategy does not use OnTaskDeadlineMissed() events.
@ SLEEP_EVENT_API
This strategy requires OnTaskSleep() / OnTaskWake() events to maintain per-priority runnable lists an...
@ WEIGHT_API
This strategy interprets GetWeight() as the task's fixed priority level (0 .. MAX_PRIORITIES - 1)....
@ NOSLEEP_YIELD_API
(1) enables OnTaskYield(): yielding task stays runnable and hands the CPU to same-priority peers.
@ PRIORITY_INHERITANCE_API
This strategy expects OnTaskPriorityChange() events to support priority inheritance requests.
@ TIMESLICE_API
This strategy does not support KERNEL_TIMESLICE mode.

◆ EPriority

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
enum stk::SwitchStrategyFixedPriority::EPriority

Symbolic priority level constants for common use cases.

Note
Concrete values depend on MAX_PRIORITIES. For SwitchStrategyFP32 (MAX_PRIORITIES = 32): PRIORITY_HIGHEST = 31, PRIORITY_HIGH = 23, PRIORITY_ABOVE_NORMAL = 17, PRIORITY_NORMAL = 16, PRIORITY_BELOW_NORMAL = 15, PRIORITY_LOWER = 8, PRIORITY_ABOVE_LOWEST = 1, PRIORITY_LOWEST = 0.
Enumerator
PRIORITY_HIGHEST 

Highest available priority level.

PRIORITY_HIGH 

High priority; mid-point between NORMAL and HIGHEST.

PRIORITY_ABOVE_NORMAL 

Slightly elevated priority; one step above NORMAL.

PRIORITY_NORMAL 

Mid-range priority level (MAX_PRIORITIES / 2).

PRIORITY_BELOW_NORMAL 

Slightly reduced priority; one step below NORMAL.

PRIORITY_LOWER 

Lower priority; mid-point between LOWEST and NORMAL.

PRIORITY_ABOVE_LOWEST 

Slightly elevated low priority; one step above LOWEST.

PRIORITY_LOWEST 

Lowest priority level; tasks only run when idle.

Definition at line 92 of file stk_strategy_fpriority.h.

93 {
95 PRIORITY_HIGH = ((MAX_PRIORITIES / 2) + (MAX_PRIORITIES - 1)) / 2,
100 PRIORITY_ABOVE_LOWEST = (0 + 1),
101 PRIORITY_LOWEST = 0
102 };
@ PRIORITY_HIGH
High priority; mid-point between NORMAL and HIGHEST.
@ PRIORITY_ABOVE_LOWEST
Slightly elevated low priority; one step above LOWEST.
@ PRIORITY_HIGHEST
Highest available priority level.
@ PRIORITY_NORMAL
Mid-range priority level (MAX_PRIORITIES / 2).
@ PRIORITY_LOWER
Lower priority; mid-point between LOWEST and NORMAL.
@ PRIORITY_ABOVE_NORMAL
Slightly elevated priority; one step above NORMAL.
@ PRIORITY_LOWEST
Lowest priority level; tasks only run when idle.
@ PRIORITY_BELOW_NORMAL
Slightly reduced priority; one step below NORMAL.

Constructor & Destructor Documentation

◆ SwitchStrategyFixedPriority()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::SwitchStrategyFixedPriority ( )
inlineexplicit

Construct an empty strategy with all priority levels empty, a clear bitmap, and null cursors.

Note
A compile-time assertion enforces MAX_PRIORITIES <= 32, matching the width of the 32-bit m_ready_bitmap. Instantiating with MAX_PRIORITIES > 32 is a compile error.

Definition at line 108 of file stk_strategy_fpriority.h.

109 {
110 STK_STATIC_ASSERT_DESC(MAX_PRIORITIES <= 32U, "MAX_PRIORITIES exceeds 32-bit bitmap width");
111 }
#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:536
IKernelTask::ListHeadType m_sleep
Sleeping (blocked) tasks. Priority is retained in GetWeight() and restored on OnTaskWake().
IKernelTask * m_prev[MAX_PRIORITIES]
Per-priority round-robin cursor. m_prev[i] is the most recently scheduled task at level i,...
uint32_t m_ready_bitmap
Bitmask of non-empty priority levels: bit i is set when m_tasks[i] has at least one runnable task....
IKernelTask::ListHeadType m_tasks[MAX_PRIORITIES]
Per-priority runnable task lists. m_tasks[i] holds all runnable tasks at priority level i.

◆ ~SwitchStrategyFixedPriority()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
STK_VIRT_DTOR stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::~SwitchStrategyFixedPriority ( )
default

Destructor.

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

Member Function Documentation

◆ AddActive()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
void stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::AddActive ( IKernelTask * task)
inlineprotected

Append a task to its priority level's runnable list and update the bitmap.

Parameters
[in]taskTask to make runnable.
Note
Appends to the back of m_tasks[prio].
Bitmap and cursor are only updated when the level was previously empty (GetSize() == 1 after LinkBack): m_ready_bitmap bit prio is set and m_prev[prio] is initialized to task. Subsequent additions at the same level leave the cursor untouched (the tail-adjustment in AddTask() handles the cursor for non-first additions).

Definition at line 350 of file stk_strategy_fpriority.h.

351 {
353
354 m_tasks[prio].LinkBack(task);
355
356 // init pointer
357 if (m_tasks[prio].GetSize() == 1U)
358 {
359 m_prev[prio] = task;
360
361 m_ready_bitmap |= (1U << prio);
362 }
363 }
static __stk_forceinline Priority GetTaskPriority(IKernelTask *task)
Get priority from the task.
size_t GetSize() const override
Get the total number of tasks managed by this strategy.

Referenced by stk::SwitchStrategyFixedPriority< 32 >::AddTask(), stk::SwitchStrategyFixedPriority< 32 >::OnTaskWake(), and stk::SwitchStrategyFixedPriority< 32 >::OnTaskWeightChange().

Here is the caller graph for this function:

◆ AddTask()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
void stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::AddTask ( IKernelTask * task)
inlineoverridevirtual

Add task to the runnable set at its fixed priority level.

Parameters
[in]taskTask to add. Must not be NULL and must not already be in any list.
Note
Priority is extracted by casting GetWeight() to uint8_t. The result must be less than MAX_PRIORITIES (asserted); passing a task whose GetWeight() is out of range is a programming error.
Delegates to AddActive() which appends the task to m_tasks[prio], sets m_ready_bitmap bit prio if this is the first task at that level, and initializes m_prev[prio].
Tail-cursor invariant (same as RR): if m_prev[prio] was already pointing at the tail before insertion, it is advanced to the new tail so GetNext() will include the new task in the very next rotation at this priority level.

Implements stk::ITaskSwitchStrategy.

Definition at line 130 of file stk_strategy_fpriority.h.

131 {
132 STK_ASSERT(task != nullptr);
133 STK_ASSERT(task->GetHead() == nullptr);
135
137 const bool is_tail = (m_prev[prio] == m_tasks[prio].GetLast());
138
140
141 // if pointer was pointing to the tail, become a tail
142 if (is_tail)
143 {
144 m_prev[prio] = task;
145 }
146 }
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:516
void AddActive(IKernelTask *task)
Append a task to its priority level's runnable list and update the bitmap.

◆ GetFirst()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
IKernelTask * stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::GetFirst ( )
inlineoverridevirtual

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

Returns
The first task in the highest runnable priority level if any task is runnable (bitmap non-zero); otherwise the first task in m_sleep. Asserts if the combined set is empty (GetSize() == 0).
Note
Uses m_ready_bitmap to determine whether any runnable task exists, consistent with GetNext(). The sleep fallback allows the kernel to identify any task even when all are currently sleeping.

Implements stk::ITaskSwitchStrategy.

Definition at line 204 of file stk_strategy_fpriority.h.

205 {
206 STK_ASSERT(GetSize() != 0U);
207
208 IKernelTask *first_task = nullptr;
209
210 if (m_ready_bitmap == 0U)
211 {
212 first_task = (*m_sleep.GetFirst());
213 }
214 else
215 {
217 first_task = (*m_tasks[prio].GetFirst());
218 }
219
220 return first_task;
221 }
static __stk_forceinline Priority GetHighestReadyPriority(uint32_t bitmap)
Find the index of the highest set bit in bitmap.

◆ GetHighestReadyPriority()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
__stk_forceinline Priority stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::GetHighestReadyPriority ( uint32_t bitmap)
inlinestaticprotected

Find the index of the highest set bit in bitmap.

Parameters
[in]bitmapBitmask of ready priority levels. Must not be 0 (behaviour is undefined for __builtin_clz(0); callers must check before calling).
Returns
Index of the most-significant set bit (0-based), which is the highest runnable priority level.
Note
On GCC/Clang: uses __builtin_clz for an O(1) hardware instruction (BSR on x86, CLZ on ARM). On other compilers: falls back to a portable O(32) linear scan from bit 31 down to 0.

Definition at line 432 of file stk_strategy_fpriority.h.

433 {
435 }
static uint32_t CountLeadingZeros(const uint32_t value) noexcept
Count leading zeros.
Definition stk_defs.h:783
static __stk_forceinline Priority GetTaskPriorityFromWeight(int32_t weight)
Get priority from the task.

Referenced by stk::SwitchStrategyFixedPriority< 32 >::GetFirst(), and stk::SwitchStrategyFixedPriority< 32 >::GetNext().

Here is the caller graph for this function:

◆ GetNext()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
IKernelTask * stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::GetNext ( )
inlineoverridevirtual

Select and return the next task to run.

Returns
The next task in the highest runnable priority level's round-robin rotation, or nullptr if no runnable tasks exist (m_ready_bitmap == 0, kernel sleeps).
Note
Priority selection is O(1) via GetHighestReadyPriority() on m_ready_bitmap. Within the selected level the cursor (m_prev[prio]) is advanced by one position in the closed-loop list, implementing round-robin within the level.
Tasks at a lower priority are never returned while any higher-priority task has its bitmap bit set — preemption is enforced entirely by the bitmap lookup.

Implements stk::ITaskSwitchStrategy.

Definition at line 181 of file stk_strategy_fpriority.h.

182 {
183 IKernelTask *next = nullptr;
184
185 if (m_ready_bitmap != 0U)
186 {
188
189 next = (*m_prev[prio]->GetNext());
190 m_prev[prio] = next;
191 }
192
193 return next;
194 }

◆ GetSize()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
size_t stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::GetSize ( ) const
inlineoverridevirtual

Get the total number of tasks managed by this strategy.

Returns
Sum of tasks across all priority levels in m_tasks plus tasks in m_sleep.
Note
O(MAX_PRIORITIES): iterates all priority levels to accumulate the count. Unlike the RR and SWRR strategies this is not O(1).

Implements stk::ITaskSwitchStrategy.

Definition at line 228 of file stk_strategy_fpriority.h.

229 {
230 size_t total = m_sleep.GetSize();
231 for (Priority i = 0U; i < MAX_PRIORITIES; ++i)
232 {
233 total += m_tasks[i].GetSize();
234 }
235
236 return total;
237 }

Referenced by stk::SwitchStrategyFixedPriority< 32 >::AddActive(), stk::SwitchStrategyFixedPriority< 32 >::GetFirst(), and stk::SwitchStrategyFixedPriority< 32 >::RemoveTask().

Here is the caller graph for this function:

◆ GetTaskPriority()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
__stk_forceinline Priority stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::GetTaskPriority ( IKernelTask * task)
inlinestaticprotected

◆ GetTaskPriorityFromWeight()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
__stk_forceinline Priority stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::GetTaskPriorityFromWeight ( int32_t weight)
inlinestaticprotected

Get priority from the task.

Parameters
[in]weightWeight of the task read from GetWeight().
Returns
Weight value.

Definition at line 409 of file stk_strategy_fpriority.h.

410 {
411 return static_cast<Priority>(weight);
412 }

Referenced by stk::SwitchStrategyFixedPriority< 32 >::GetHighestReadyPriority(), stk::SwitchStrategyFixedPriority< 32 >::GetTaskPriority(), and stk::SwitchStrategyFixedPriority< 32 >::OnTaskWeightChange().

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 1487 of file stk_common.h.

1488 {
1489 STK_UNUSED(task);
1490 return false;
1491 }
#define STK_UNUSED(X)
Explicitly marks a variable as unused to suppress compiler warnings.
Definition stk_defs.h:715

References STK_UNUSED.

◆ OnTaskSleep()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
void stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::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[priority] (asserted).
Note
Delegates to RemoveActive() which unlinks the task from its priority level list, updates the per-level cursor, and clears bit prio in m_ready_bitmap if this was the last runnable task at that level. Then appends the task to m_sleep.

Implements stk::ITaskSwitchStrategy.

Definition at line 245 of file stk_strategy_fpriority.h.

246 {
247 STK_ASSERT(task != nullptr);
248 STK_ASSERT(task->IsSleeping());
249 STK_ASSERT(task->GetHead() == &m_tasks[GetTaskPriority(task)]);
250
252 m_sleep.LinkBack(task);
253 }
void RemoveActive(IKernelTask *task, const Priority prio)
Remove a task from its priority level's runnable list and update the bitmap/cursor.

◆ OnTaskTimeSlice()

virtual bool stk::ITaskSwitchStrategy::OnTaskTimeSlice ( IKernelTask * task)
inlinevirtualinherited

Notification that the running task's time slice expired (KERNEL_TIMESLICE only).

Parameters
[in]taskPointer to the running task, currently in the runnable set.
Returns
true if the strategy rotated to a same-priority peer (the following GetNext() returns it); false to keep running the task (no peer, or the task is not eligible for time-slicing).
Note
Unlike OnTaskYield() this must not release preemption-threshold style holds.
Called from the tick handler. Only invoked when TIMESLICE_API == 1.
See also
SwitchStrategyPreemptionThreshold::OnTaskTimeSlice

Reimplemented in stk::SwitchStrategyPreemptionThreshold< MAX_PRIORITIES, TIMESLICE >, stk::SwitchStrategyPreemptionThreshold< 32 >, and stk::SwitchStrategyPreemptionThreshold< 32, true >.

Definition at line 1461 of file stk_common.h.

1462 {
1463 STK_UNUSED(task);
1464 return false;
1465 }

References STK_UNUSED.

◆ OnTaskWake()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
void stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::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
Unlinks the task from m_sleep and delegates to AddActive() which appends it to m_tasks[priority] and sets the bitmap bit if the level was empty.
Unlike SwitchStrategySmoothWeightedRoundRobin, no priority boost is applied. The waking task re-enters its natural priority level and waits its turn in the round-robin rotation at that level. Its preemption guarantee is provided solely by its fixed priority relative to other runnable levels.

Implements stk::ITaskSwitchStrategy.

Definition at line 264 of file stk_strategy_fpriority.h.

265 {
266 STK_ASSERT(task != nullptr);
267 STK_ASSERT(!task->IsSleeping());
268 STK_ASSERT(task->GetHead() == &m_sleep);
269
270 m_sleep.Unlink(task);
272 }

◆ OnTaskWeightChange()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
void stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::OnTaskWeightChange ( IKernelTask * task,
Weight old_weight )
inlineoverridevirtual

Move a runnable task to a new priority level after its weight changed.

Parameters
[in]taskTask whose weight was just updated.
[in]old_weightPriority level the task occupied before the change.
Note
Removes from the old-priority list (using old_weight to locate it), then re-inserts via AddActive() which reads the new GetWeight(). m_ready_bitmap is updated by both RemoveActive and AddActive.
No-op if old and new priority are identical.
Called from within a hw::CriticalSection.

Reimplemented from stk::ITaskSwitchStrategy.

Definition at line 283 of file stk_strategy_fpriority.h.

284 {
286
289
290 if (task->GetHead() != &m_sleep)
291 {
292 STK_ASSERT(task->GetHead() == &m_tasks[old_prio]);
293
294 // remove from the old priority list
296
297 // re-add to the current priority list
299 }
300 }

◆ OnTaskYield()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
bool stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::OnTaskYield ( IKernelTask * task)
inlineoverridevirtual

Notification that the running task called Yield() (non-HRT kernel modes only).

Parameters
[in]taskPointer to the yielding task, currently in the runnable set.
Returns
true if the strategy handled the yield itself: the task stays runnable (it is NOT put to sleep) and the following GetNext() returns its successor at the same priority level, or the task itself if it is alone at its level (a yield never selects a lower priority level); false if the kernel shall perform the legacy yield, i.e. sleep the task for YIELD_TICKS.
Note
If a higher priority level became ready in the meantime it is selected as usual; the yielding task then only loses its place in its own level's rotation.
Called from within a hw::CriticalSection.

Reimplemented from stk::ITaskSwitchStrategy.

Definition at line 313 of file stk_strategy_fpriority.h.

314 {
316 {
317 STK_ASSERT(task != nullptr);
318
319 bool handled = false;
321
322 if (task->GetHead() == &m_tasks[prio])
323 {
324 m_prev[prio] = task; // GetNext() will return task's successor at this level (or task itself if alone)
325 handled = true;
326 }
327
328 return handled;
329 }
330 else
331 {
333 return false;
334 }
335 }
#define __stk_constexpr_cpp17
constexpr definition for C++17 and above.
Definition stk_defs.h:489

◆ RemoveActive()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
void stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::RemoveActive ( IKernelTask * task,
const Priority prio )
inlineprotected

Remove a task from its priority level's runnable list and update the bitmap/cursor.

Parameters
[in]taskRunnable task to remove.
[in]prioPriority of the task with which it was registered with AddActive.
Note
Cursor update algorithm (same as SwitchStrategyRoundRobin::RemoveActive, applied per priority level):
  • Capture next = task->GetNext() before unlinking.
  • If next != task (other tasks remain at this level) and the cursor m_prev[prio] pointed at the removed task: set m_prev[prio] = next->GetPrev() so GetNext() returns next without skipping it. If the cursor pointed at another task it is left untouched so that the rotation is not disturbed.
  • If next == task (last task at this level): set m_prev[prio] = NULL and clear bit prio in m_ready_bitmap. GetNext() will then select the next highest set bit, falling through to a lower priority level.

Definition at line 380 of file stk_strategy_fpriority.h.

381 {
382 IKernelTask *next = (*task->GetNext());
383
384 m_tasks[prio].Unlink(task);
385
386 // update pointer
387 if (next == task)
388 {
389 m_prev[prio] = nullptr;
390
391 // this will cause a switch to a lower priority task list
392 m_ready_bitmap &= ~(1U << prio);
393 }
394 else if (m_prev[prio] == task)
395 {
396 // cursor was on the removed task: step back so that GetNext() returns its successor
397 m_prev[prio] = (*next->GetPrev());
398 }
399 else
400 {
401 // cursor is on another task: leave the rotation untouched
402 }
403 }
IKernelTask * GetNext() override
Select and return the next task to run.

Referenced by stk::SwitchStrategyFixedPriority< 32 >::OnTaskSleep(), stk::SwitchStrategyFixedPriority< 32 >::OnTaskWeightChange(), and stk::SwitchStrategyFixedPriority< 32 >::RemoveTask().

Here is the caller graph for this function:

◆ RemoveTask()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
void stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::RemoveTask ( IKernelTask * task)
inlineoverridevirtual

Remove task from whichever list it currently occupies.

Parameters
[in]taskTask to remove. Must not be NULL and must belong to either m_tasks[priority] or m_sleep (asserted).
Note
Dispatch checks m_sleep first (reversed from the RR/SWRR pattern). If sleeping, simply unlinks from m_sleep. If runnable, delegates to RemoveActive() which also updates the cursor and clears the bitmap bit if the priority level becomes empty.

Implements stk::ITaskSwitchStrategy.

Definition at line 156 of file stk_strategy_fpriority.h.

157 {
158 STK_ASSERT(task != nullptr);
159 STK_ASSERT(GetSize() != 0U);
160 STK_ASSERT((task->GetHead() == &m_tasks[GetTaskPriority(task)]) || (task->GetHead() == &m_sleep));
161
162 if (task->GetHead() == &m_sleep)
163 {
164 m_sleep.Unlink(task);
165 }
166 else
167 {
169 }
170 }

◆ STK_NONCOPYABLE_CLASS()

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::STK_NONCOPYABLE_CLASS ( SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield > )
private

Member Data Documentation

◆ m_prev

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
IKernelTask* stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::m_prev[MAX_PRIORITIES]
private

Per-priority round-robin cursor. m_prev[i] is the most recently scheduled task at level i, or nullptr when level i is empty. GetNext() advances from this position.

Definition at line 443 of file stk_strategy_fpriority.h.

◆ m_ready_bitmap

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
uint32_t stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::m_ready_bitmap
private

Bitmask of non-empty priority levels: bit i is set when m_tasks[i] has at least one runnable task. Updated by AddActive() (bit set) and RemoveActive() (bit cleared on last removal).

Definition at line 442 of file stk_strategy_fpriority.h.

◆ m_sleep

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
IKernelTask::ListHeadType stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::m_sleep
private

Sleeping (blocked) tasks. Priority is retained in GetWeight() and restored on OnTaskWake().

Definition at line 441 of file stk_strategy_fpriority.h.

◆ m_tasks

template<uint8_t MAX_PRIORITIES, bool NoSleepYield = false>
IKernelTask::ListHeadType stk::SwitchStrategyFixedPriority< MAX_PRIORITIES, NoSleepYield >::m_tasks[MAX_PRIORITIES]
private

Per-priority runnable task lists. m_tasks[i] holds all runnable tasks at priority level i.

Definition at line 440 of file stk_strategy_fpriority.h.


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