94template <u
int8_t TMode, u
int32_t TSize,
class TStrategy,
class TPlatform>
96#ifndef _STK_UNDER_TEST
267 return static_weight;
338 to =
m_hrt[0].periodicity;
361 deadline =
m_hrt[0].deadline;
393 relative_deadline = 0;
396 return relative_deadline;
417 sleep_ticks =
Min(sleep_ticks, task_sleep);
422 sleep_ticks =
Min(sleep_ticks, task_sleep);
427 sleep_ticks =
Min(sleep_ticks, task_sleep);
598 void Wake(
bool timeout)
override
729 #if STK_STACK_NEEDS_TASK_ID
846 bool is_match =
false;
851 if ((SP >= start) && (SP <= end))
860 if (secure_mem !=
nullptr)
865 if ((SP >= s_start) && (SP <= s_end))
895 if (start_delay_tc > 0)
938 m_user->OnDeadlineMissed(duration);
947 m_hrt[0].done =
true;
948 __stk_full_memfence();
956 return (duration >
m_hrt[0].deadline);
986 __stk_full_memfence();
1003 __stk_full_memfence();
1079 const Ticks deadline = now + ticks;
1082 for (; now < deadline; now =
GetTicks())
1110 return m_kernel->m_platform.SleepUntil(timestamp);
1132 m_kernel->m_platform.SwitchToNext();
1139 return m_kernel->m_platform.Wait(sobj, mutex, ticks);
1171 return m_kernel->m_platform.Suspend();
1184 return m_kernel->m_platform.Resume(elapsed_ticks);
1196 m_kernel->OnInheritWeight(tid, weight);
1204 m_kernel->OnRestoreWeight(tid, sobj);
1218 result =
m_kernel->OnSetWeight(tid, weight);
1243 result =
m_kernel->OnSetTimeSlice(tid, ticks);
1318 #if !STK_TICKLESS_IDLE
1320 "STK_TICKLESS_IDLE must be defined to 1 for KERNEL_TICKLESS");
1357 exit_trap =
nullptr;
1415 Timeout start_delay_tc)
override
1447 if (task !=
nullptr)
1476 if (task !=
nullptr)
1478 task->ScheduleRemoval(
this);
1499 KernelTask *self_task =
nullptr;
1515 suspended = !task->IsSleeping();
1516 if (suspended ==
true)
1529 #if STK_SEGGER_SYSVIEW
1540 if (self_task !=
nullptr)
1542 self_task->BusyWaitWhileSleeping(
this);
1566 task->m_state &= ~KernelTask::STATE_SUSPENDED;
1569 if (task->IsSleeping())
1584 if (task !=
nullptr)
1590 bool canceled_wait =
false;
1599 canceled_wait = task->m_wait_obj[0].CancelIfWaiting();
1602 if (!canceled_wait && task->IsSleeping())
1624 if (user_task !=
nullptr)
1634 if (task !=
nullptr)
1636 bool resolved =
false;
1652 const typename KernelTask::WaitObject &wait_obj = task->m_wait_obj[0];
1654 if (wait_obj.IsWaiting())
1657 info.
wait_obj = wait_obj.m_sync_obj;
1666 const Timeout time_sleep = task->m_time_sleep;
1708 for (
size_t i = 0U; i < limit; ++i)
1713 tasks[count++] = &task;
1734 for (
size_t i = 0U; i < limit; ++i)
1739 user_tasks[count++] = task.GetUserTask();
1763 #if STK_SEGGER_SYSVIEW
1764 SEGGER_SYSVIEW_Start();
1770 SendTaskTraceInfo(task);
1802#ifdef _STK_UNDER_TEST
1803 void ScheduleSleepOnActiveTask(
Timeout ticks)
1862 #if STK_STACK_NEEDS_TASK_ID
1876 #if STK_STACK_NEEDS_TASK_ID
1891 KernelTask *new_task =
nullptr;
1904 if (new_task ==
nullptr)
1907 #if defined(NDEBUG) && !defined(_STK_ASSERT_REDIRECT)
1930 #if STK_SEGGER_SYSVIEW
1932 SEGGER_SYSVIEW_OnTaskCreate(task->GetUserStackPtr()->
tid);
1935 SendTaskTraceInfo(task);
1965 task->HrtInit(periodicity_tc, deadline_tc, start_delay_tc);
1979 typename KernelTask::SrtInfo &srt = caller->m_srt[0];
1981 typename KernelTask::AddTaskRequest req = { .user_task = user_task };
1982 srt.add_task_req = &req;
1988 if (srt.add_task_req !=
nullptr)
1996 while (srt.add_task_req !=
nullptr)
2005 template <
typename TaskPtr,
typename Storage>
2008 TaskPtr found_task =
nullptr;
2012 TaskPtr
const task = &task_storage[i];
2014 if (task->GetUserTask() == user_task)
2048 KernelTask *found_task =
nullptr;
2053 if (task->GetUserStackPtr() == stack)
2071 KernelTask *found_task =
nullptr;
2086 if (!task->IsBusy())
2092 if (task->IsMemoryOfSP(SP))
2111 #if STK_SEGGER_SYSVIEW
2112 SEGGER_SYSVIEW_OnTaskTerminate(task->GetUserStackPtr()->
tid);
2116 task->GetUserTask()->
OnExit();
2145 task->m_state &= ~KernelTask::STATE_SLEEP_PENDING;
2159 KernelTask *next =
nullptr;
2168 active = next->GetUserStackPtr();
2172 next->HrtOnSwitchedIn();
2225 #
if STK_TICKLESS_IDLE
2230 #if !STK_TICKLESS_IDLE
2236 const Timeout elapsed_ticks = ticks;
2239 m_service.IncrementTicks(elapsed_ticks);
2242 #if STK_TICKLESS_IDLE
2262 bool switch_context =
false;
2269 if (task->GetTid() ==
id)
2272 if (task->IsSleeping())
2296 return switch_context;
2309 if (task !=
nullptr)
2311 bool handled =
false;
2317 if (!task->IsSleeping())
2321 task->ScheduleYield();
2329 task->BusyWaitWhileYielding(
this);
2358 task->HrtOnWorkCompleted();
2363 task->ScheduleSleep(ticks);
2366 #if STK_SEGGER_SYSVIEW
2373 task->BusyWaitWhileSleeping(
this);
2393 task->ScheduleSleep(
static_cast<Timeout>(
Min(delta, infinite_ticks)));
2396 #if STK_SEGGER_SYSVIEW
2409 task->BusyWaitWhileSleeping(
this);
2423 #if STK_SEGGER_SYSVIEW
2424 SEGGER_SYSVIEW_OnTaskStopExec();
2433 task->ScheduleRemoval(
this);
2455 typename KernelTask::WaitObject &wait_obj = task->m_wait_obj[0];
2464 wait_obj.SetupWait(sync_obj, timeout);
2467 if (sync_obj->
GetHead() ==
nullptr)
2476 #if STK_SEGGER_SYSVIEW
2485 task->BusyWaitWhileSleeping(
this);
2490 const EWaitResult result = wait_obj.GetWaitResult();
2491 wait_obj.ClearState();
2510 return task->GetTid();
2541 STK_ASSERT(TStrategy::WEIGHT_API && TStrategy::PRIORITY_INHERITANCE_API);
2548 const Weight prev_weight = task->GetWeight();
2550 if (prev_weight < weight)
2552 task->SetCurrentWeight(weight);
2553 m_strategy.OnTaskWeightChange(task, prev_weight);
2561 STK_ASSERT(TStrategy::WEIGHT_API && TStrategy::PRIORITY_INHERITANCE_API);
2567 const Weight prev_weight = task->GetWeight();
2568 const Weight prev_base = task->GetBaseWeight();
2570 task->SetBaseWeight(weight);
2573 if ((task->GetCurrentWeight() !=
NO_WEIGHT) && (task->GetCurrentWeight() <= weight))
2580 m_strategy.OnTaskWeightChange(task, prev_weight);
2593 typename KernelTask::TsInfo &ts = task->m_ts[0];
2595 const Timeout prev = ts.quantum;
2612 if ((task !=
nullptr) &&
2614 task->IsBusy() && !task->IsSleeping())
2616 typename KernelTask::TsInfo &ts = task->m_ts[0];
2620 ts.left -= elapsed_ticks;
2637 STK_ASSERT(TStrategy::WEIGHT_API && TStrategy::PRIORITY_INHERITANCE_API);
2642 const Weight prev_weight = task->GetWeight();
2647 m_strategy.OnTaskWeightChange(task, prev_weight);
2681 task->m_state &= ~KernelTask::STATE_YIELD_PENDING;
2728 task->m_state &= ~KernelTask::STATE_YIELD_PENDING;
2732 if (task->IsSleeping())
2737 if (task->IsPendingRemoval())
2739 const size_t tasks_left =
m_strategy.GetSize();
2750 bool just_entered_sleep =
false;
2765 just_entered_sleep = !wake_pending;
2768 if (!just_entered_sleep && !task->IsSleepInfinite())
2771 task->m_time_sleep += elapsed_ticks;
2777 if (!task->IsSleeping())
2791 typename KernelTask::HrtInfo &hrt = task->m_hrt[0];
2793 hrt.duration += elapsed_ticks;
2796 if (task->HrtIsDeadlineMissed(hrt.duration))
2819 if ((sleep_ticks > 1) && task->IsBusy())
2821 sleep_ticks = task->GetSleepTicks(sleep_ticks);
2835 while (itr !=
nullptr)
2866 typename KernelTask::SrtInfo &srt = task->m_srt[0];
2868 if (srt.add_task_req !=
nullptr)
2872 srt.add_task_req =
nullptr;
2873 __stk_full_memfence();
2892 if (next !=
nullptr)
2922#ifdef _STK_UNDER_TEST
2938 KernelTask *
const now =
m_task_now, *next =
nullptr;
2939 bool switch_context =
false;
2946 switch_context =
StateSwitch(now, next, idle, active);
2950 switch_context =
StateSleep(now, next, idle, active);
2954 switch_context =
StateWake(now, next, idle, active);
2958 switch_context =
StateExit(now, next, idle, active);
2969 return switch_context;
2984 bool switch_context =
false;
2989 idle = now->GetUserStackPtr();
2990 active = next->GetUserStackPtr();
3006 if (now->m_hrt[0].done)
3008 now->HrtOnSwitchedOut();
3009 next->HrtOnSwitchedIn();
3013 switch_context =
true;
3016 return switch_context;
3033 active = next->GetUserStackPtr();
3045 next->HrtOnSwitchedIn();
3065 idle = now->GetUserStackPtr();
3072 if (!now->IsPendingRemoval())
3074 now->HrtOnSwitchedOut();
3134#if STK_SEGGER_SYSVIEW
3139 void SendTaskTraceInfo(KernelTask *task)
3143 const SEGGER_SYSVIEW_TASKINFO info =
3145 .TaskID = task->GetUserStackPtr()->tid,
3146 .sName = task->GetUserTask()->GetTraceName(),
3147 .Prio =
static_cast<U32
>(task->GetWeight()),
3148 .StackBase =
hw::PtrToWord(task->GetUserTask()->GetStack()),
3149 .StackSize = (task->GetUserTask()->GetStackSize() *
sizeof(
Word))
3151 SEGGER_SYSVIEW_SendTaskInfo(&info);
3194 STK_STATIC_ASSERT_N(KERNEL_MODE_MUST_BE_SET, (TStrategy::PRIORITY_INHERITANCE_API && TStrategy::WEIGHT_API) ||
3195 !TStrategy::PRIORITY_INHERITANCE_API);
#define STK_UNUSED(X)
Explicitly marks a variable as unused to suppress compiler warnings.
#define STK_STATIC_ASSERT_N(NAME, X)
Compile-time assertion with a user-defined name suffix.
#define __stk_forceinline
Forces compiler to always inline the decorated function, regardless of optimisation level.
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
#define __stk_attr_noinline
Prevents compiler from inlining the decorated function (function prefix).
#define __stk_constexpr_cpp17
constexpr definition for C++17 and above.
#define STK_TICKLESS_TICKS_MAX
Maximum number of kernel ticks the hardware timer may be suppressed in one tickless idle interval whe...
#define STK_STATIC_ASSERT_DESC(X, DESC)
Compile-time assertion with a custom error description. Produces a compilation error if X is false.
#define STK_STACK_MEMORY_FILLER
Sentinel value written to the entire stack region at initialization (stack watermark pattern).
#define STK_VIRT_DTOR
Makes destructors virtual and compliant to strict rules if STK_STRICT_COMPLIANCY=0.
Contains helper implementations which simplify user-side code.
Earliest Deadline First (EDF) task-switching strategy (stk::SwitchStrategyEDF).
Fixed-priority preemptive task-switching strategy with round-robin within each priority level (stk::S...
Rate-Monotonic (RM) and Deadline-Monotonic (DM) task-switching strategies (stk::SwitchStrategyMonoton...
Fixed-priority preemptive strategy with ThreadX-style Preemption-Threshold and optional per-task time...
Round-Robin task-switching strategy (stk::SwitchStrategyRoundRobin / stk::SwitchStrategyRR,...
Smooth Weighted Round-Robin task-switching strategy (stk::SwitchStrategySmoothWeightedRoundRobin / st...
Namespace of STK package.
uintptr_t Word
Native processor word type.
@ ACCESS_PRIVILEGED
Privileged access mode (access to hardware is fully unrestricted).
static constexpr ITask * GetUserTaskFromTid(TId task_id) noexcept
Get task instance from its identifier.
static constexpr Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
EWaitResult
Wait result (see IKernelService::Wait).
@ WAIT_RESULT_FAIL
IKernelService::Wait returned with error without waiting.
@ WAIT_RESULT_CANCELED
The wait was cancelled by another task via IKernel::CancelTaskWait(), independent of signal/timeout.
@ WAIT_RESULT_TIMEOUT
The wake was caused by a timeout expiry.
@ WAIT_RESULT_SIGNAL
The wake was caused by a signal.
@ PERIODICITY_DEFAULT
Default periodicity (microseconds), 1 millisecond.
@ PERIODICITY_MAX
Maximum periodicity (microseconds), 99 milliseconds (note: this value is the highest working on a rea...
int64_t Ticks
Ticks value.
@ KERNEL_PANIC_BAD_MODE
Kernel is in bad/unsupported mode for the current operation.
@ KERNEL_PANIC_BAD_STATE
Kernel entered unexpected (bad) state.
@ TASK_STATE_EXITING
Run() has returned, the slot is released on the next tick (KERNEL_DYNAMIC mode only).
@ TASK_STATE_SLEEPING
Sleeping via Sleep()/SleepUntil(), with a finite or an infinite timeout.
@ TASK_STATE_SUSPENDED
Suspended by IKernel::SuspendTask().
@ TASK_STATE_REMOVED
The task is not bound to a kernel slot (never added, or already removed).
@ TASK_STATE_WAITING
Blocked on a synchronization object (IKernelService::Wait). KERNEL_SYNC mode only.
@ TASK_STATE_READY
Runnable: running, or waiting for the CPU.
int32_t Timeout
Timeout time (ticks).
static void STK_KERNEL_PANIC(stk::EKernelPanicId id)
Called when the kernel detects an unrecoverable internal fault.
@ SYS_TASK_ID_EXIT
Exit trap.
@ SYS_TASK_ID_SLEEP
Sleep trap.
static constexpr Weight DEFAULT_WEIGHT
Weight value: default weight of value (1) (see SwitchStrategySmoothWeightedRoundRobin).
static constexpr T Max(T a, T b) noexcept
Compile-time maximum of two values.
static constexpr Timeout NO_TIME_SLICE
Time-slice quantum value: no time-slicing for the task (it runs until it blocks, yields or is preempt...
static constexpr Weight NO_WEIGHT
Weight value: weight is not set.
Timeout GetInitialSleepTicks()
static constexpr Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
static constexpr TId TID_NONE
Reserved task/thread id representing zero/none thread id.
static constexpr T Min(T a, T b) noexcept
Compile-time minimum of two values.
@ TRACE_EVENT_SLEEP
Task entered a sleep state.
@ TRACE_EVENT_SUSPEND
Task suspended via Suspend.
@ TRACE_EVENT_WAIT
Task suspended on a sync object.
@ STACK_SLEEP_TRAP
Stack of the Sleep trap.
@ STACK_USER_TASK
Stack of the user task.
@ STACK_EXIT_TRAP
Stack of the Exit trap.
Timeout GetInitialSleepTicks< false >()
static constexpr TId GetTidFromUserTask(const ITask *task) noexcept
Get task identifier from ITask instance.
Timeout GetInitialSleepTicks< true >()
uint64_t Cycles
Cycles value.
Word TId
Task (thread) id.
int32_t Weight
Weight value (aka priority).
@ KERNEL_TELEMETRY
Enable introspection functions for diagnostics / telemetry (see IKernel::GetTaskState).
@ KERNEL_TIMESLICE
Time-slicing: running task is rotated behind its same-priority peers when its quantum (see ITask::Get...
@ KERNEL_TICKLESS
Tickless mode. To use this mode STK_TICKLESS_IDLE must be defined to 1 in stk_config....
@ KERNEL_SYNC
Synchronization support (see Event).
@ KERNEL_HRT
Hard Real-Time (HRT) behavior (tasks are scheduled periodically and have an execution deadline,...
@ KERNEL_STATIC
All tasks are static and can not exit.
@ KERNEL_DYNAMIC
Tasks can be added or removed and therefore exit when done.
static void WriteVolatile64(volatile T *addr, T value)
Atomically write a 64-bit volatile value.
static constexpr Word PtrToWord(T *const ptr) noexcept
Cast a pointer to a CPU register-width integer.
static T ReadVolatile64(volatile const T *addr)
Atomically read a 64-bit volatile value.
bool IsInsideISR()
Check whether the CPU is currently executing inside a hardware interrupt service routine (ISR).
Memory-related primitives.
volatile uint8_t m_request
void OnStop() override
Called by the platform driver after a scheduler stop (all tasks have exited).
bool UpdateFsmState(Stack *&idle, Stack *&active)
Update FSM state.
stk::SwitchStrategyFP32 m_strategy
KernelTask * AllocateNewTask(ITask *user_task)
Allocate new instance of KernelTask.
void RequestAddTask(ITask *const user_task)
Request to add new task.
void OnTaskExit(Stack *stack) override
Called from the Thread process when task finished (its Run function exited by return).
EFsmState
Finite-state machine (FSM) state. Encodes what the kernel is currently doing between two consecutive ...
KernelTask * FindTaskByStack(const Stack *stack)
Find kernel task by the bound Stack instance.
KernelTask TaskStorageType[TASKS_MAX]
KernelTask array type used as a storage for the KernelTask instances.
~Kernel()=default
Destructor.
Weight OnSetWeight(TId tid, Weight weight)
bool OnTick(Stack *&idle, Stack *&active, Timeout &ticks) override
Process one scheduler tick. Called from the platform timer/tick ISR.
SleepTrapStack m_sleep_trap[1]
EWaitResult OnTaskWait(Word caller_SP, ISyncObject *sync_obj, IMutex *mutex, Timeout timeout) override
Called from the Thread process when task needs to wait.
volatile EKernelState m_kstate
void OnSuspend(bool suspended) override
Called from the Thread process to suspend scheduling.
SyncObjectList m_sync_list[STK_ALLOCATE_COUNT< TMode, KERNEL_SYNC, 1U, 0U >::Value]
static constexpr Timeout YIELD_TICKS
void ScheduleTaskRemoval(ITask *user_task) override
Schedule task removal from scheduling (exit).
EFsmState GetNewFsmState(KernelTask *&next)
Get new FSM state.
void RemoveTask(ITask *user_task) override
Remove a previously added task from the kernel when it is not started.
StackMemoryWrapper< STACK_SIZE_MIN > ExitTrapStackMemory
Stack memory wrapper type for the exit trap.
void OnRestoreWeight(TId tid, ISyncObject *sobj)
void OnStart(Stack *&active) override
Called by platform driver immediately after a scheduler start (first tick).
static constexpr size_t TASKS_MAX
ExitTrapStack m_exit_trap[STK_ALLOCATE_COUNT< TMode, KERNEL_DYNAMIC, 1U, 0U >::Value]
bool StateWake(KernelTask *now, KernelTask *next, Stack *&idle, Stack *&active)
Wakes up after sleeping.
Timeout OnSetTimeSlice(TId tid, Timeout ticks)
KernelTask * FindTaskBySP(Word SP)
Find kernel task for a Stack Pointer (SP).
void InitTraps()
Initialize stack of the traps.
static constexpr bool IsHrtMode()
void AddTask(ITask *user_task) override
Register task for a soft real-time (SRT) scheduling.
static constexpr bool IsTimesliceMode()
ISyncObject::ListHeadType SyncObjectList
Intrusive list of active ISyncObject instances registered with this kernel. Each sync object in this ...
EFsmEvent
Finite-state machine (FSM) event. Computed by FetchNextEvent() each tick based on strategy output and...
StackMemoryWrapper<((32U))> SleepTrapStackMemory
Stack memory wrapper type for the sleep trap.
size_t EnumerateKernelTasks(ArrayView< IKernelTask * > tasks) override
Enumerate kernel tasks.
static constexpr bool IsSyncMode()
KernelTask * FindTaskByUserTask(const ITask *user_task)
Find kernel task by the bound ITask instance (Non-const version).
static bool IsValidFsmState(EFsmState state)
Check if FSM state is valid.
static constexpr bool IsTelemetryMode()
void OnInheritWeight(TId tid, Weight weight)
void ResumeTask(ITask *user_task) override
Resume task.
void OnTaskSleep(Word caller_SP, Timeout ticks) override
Called by Thread process (via IKernelService::Sleep) for exclusion of the calling process from schedu...
void Start() override
Start the scheduler. This call does not return until all tasks have exited (KERNEL_DYNAMIC mode) or i...
TaskStorageType m_task_storage
static constexpr bool IsTicklessMode()
void RemoveTask(KernelTask *task)
Remove kernel task.
void CancelTaskWait(ITask *user_task) override
Cancel task's in-progress wait on a synchronization object.
void AddKernelTask(KernelTask *task)
Add kernel task to the scheduling strategy.
EKernelState GetState() const override
Get kernel state.
ERequest
Bitmask flags for pending inter-task requests that must be processed by the kernel on the next tick (...
bool StateExit(KernelTask *now, KernelTask *next, Stack *&idle, Stack *&active)
Exits from scheduling.
static TaskPtr FindTaskByUserTaskImpl(const ITask *user_task, Storage &task_storage)
KernelTask * m_task_now
Currently executing task, or nullptr before Start() or after all tasks exit.
IPlatform * GetPlatform() override
Get platform driver instance owned by this kernel.
void AllocateAndAddNewTask(ITask *user_task)
Allocate new instance of KernelTask and add it into the scheduling process.
void OnTaskSwitch(Word caller_SP) override
Called by Thread process (via IKernelService::SwitchToNext) to switch to a next task.
void Initialize(uint32_t resolution_us=PERIODICITY_DEFAULT) override
Initialize kernel.
TPlatform m_platform
Platform driver (SysTick, PendSV, context switch implementation).
void HrtAllocateAndAddNewTask(ITask *user_task, Timeout periodicity_tc, Timeout deadline_tc, Timeout start_delay_tc)
Allocate new instance of KernelTask and add it into the HRT scheduling process.
TId OnGetTid(Word caller_SP) override
Called from the Thread process when for getting task/thread id of the process.
size_t EnumerateTasks(ArrayView< ITask * > user_tasks) override
Enumerate user tasks.
void ProcessTaskPendingSleep(KernelTask *const task)
Timeout UpdateTasks(const Timeout elapsed_ticks)
Update tasks (sleep, requests).
void ScheduleAddTask()
Signal the kernel to process a pending AddTask request on the next tick.
bool GetTaskState(ITask *user_task, TaskStateInfo &info) const override
Get a snapshot of the kernel-side state of a task.
const KernelTask * FindTaskByUserTask(const ITask *user_task) const
Find kernel task by the bound ITask instance (Const version).
bool IsInitialized() const
Check whether Initialize() has been called and completed successfully.
static constexpr bool IsDynamicMode()
bool OnForceContextSwitch(TId id, Stack *&idle, Stack *&active)
Called when task state change forces a context switch (Sleep, SleepUntil, Wait).
void ProcessTaskPendingYield(KernelTask *const task)
ITaskSwitchStrategy * GetSwitchStrategy() override
Get task-switching strategy instance owned by this kernel.
bool StateSwitch(KernelTask *now, KernelTask *next, Stack *&idle, Stack *&active)
Switches contexts.
void AddTask(ITask *user_task, Timeout periodicity_tc, Timeout deadline_tc, Timeout start_delay_tc) override
Register a task for hard real-time (HRT) scheduling.
Kernel()
Construct the kernel with all storage zero-initialized, m_request cleared to REQ_NONE,...
void UpdateTaskRequest()
Update pending task requests.
bool StateSleep(KernelTask *now, KernelTask *next, Stack *&idle, Stack *&active)
Enters into a sleeping mode.
Timeout UpdateTaskState(const Timeout elapsed_ticks)
Update task state: process removals, deliver sleep/wake notifications, advance sleep timers,...
void UpdateSyncObjects(const Timeout elapsed_ticks)
Update synchronization objects.
static constexpr bool IsStaticMode()
void UpdateTimeslice(const Timeout elapsed_ticks)
Charge the running task and rotate it behind its same-priority peers when its slice expires.
bool IsStarted() const
Check whether scheduler is currently running.
bool OnTaskSleepUntil(Word caller_SP, Ticks timestamp) override
Called by Thread process (via IKernelService::SleepUntil) for exclusion of the calling process from s...
const EFsmState m_fsm[FSM_STATE_MAX][FSM_EVENT_MAX]
void SuspendTask(ITask *user_task, bool &suspended) override
Suspend task.
EFsmEvent FetchNextEvent(KernelTask *&next)
Fetch next event for the FSM.
Internal per-slot kernel descriptor that wraps a user ITask instance.
Weight GetBaseWeight() const override
Get base scheduling weight from the user task, ignoring priority inheritance.
Weight GetCurrentWeight() const override
Get current (run-time) scheduling weight.
KernelTask()
Construct a free (unbound) task slot. All fields set to zero/null.
void ScheduleSleep(Timeout ticks)
Put the task into a sleeping state for the specified number of ticks.
void BusyWaitWhileYielding(Kernel *const kernel) const
Request a context switch and wait until the kernel consumes the pending yield.
Timeout GetSleepTicks(Timeout sleep_ticks)
TId GetTid() const
Get task identifier.
void HrtOnSwitchedOut()
Called when task is switched out from the scheduling process.
EStateFlags
Bitmask of transient state flags. Set by the task or the kernel and consumed (cleared) during UpdateT...
@ STATE_REMOVE_PENDING
Task returned from its Run function; slot will be freed on the next tick (KERNEL_DYNAMIC only).
@ STATE_SUSPENDED
Task is suspended by SuspendTask.
@ STATE_YIELD_PENDING
Task called Yield() and the strategy handled it via OnTaskYield() (task stays runnable); cleared by t...
@ STATE_WAKE_PENDING
Task wake is pending (see Wake).
@ STATE_SLEEP_PENDING
Task called Sleep/SleepUntil/Yield; strategy's OnTaskSleep() will be invoked on the next tick (sleep-...
@ STATE_NONE
No pending state flags.
Timeout GetHrtPeriodicity() const override
Get HRT scheduling periodicity.
bool HrtIsDeadlineMissed(Timeout duration) const
Check if deadline missed.
SrtInfo m_srt[STK_ALLOCATE_COUNT< TMode, KERNEL_HRT, 0U, 1U >::Value]
SRT metadata. Zero-size (no memory) in KERNEL_HRT mode.
void ScheduleRemoval(Kernel *const kernel)
Schedule the removal of the task from the kernel on next tick.
Stack m_stack
Stack descriptor (SP register value + access mode + optional tid).
void SetBaseWeight(Weight weight)
Override the base weight at run-time (see IKernelService::SetWeight).
void Bind(TPlatform *platform, ITask *user_task)
Bind this slot to a user task: set access mode, task ID, and initialize the stack.
~KernelTask()=default
Destructor.
Weight m_rt_weight[STK_ALLOCATE_COUNT< TStrategy::WEIGHT_API, 1U, 1U, 0U >::Value]
Run-time weight for weighted-round-robin scheduling. Zero-size for unweighted strategies.
void HrtHardFailDeadline(IPlatform *platform)
Hard-fail HRT task when it missed its deadline.
Weight m_base_weight[STK_ALLOCATE_COUNT< TStrategy::WEIGHT_API, 1U, 1U, 0U >::Value]
Run-time override of ITask::GetWeight() (NO_WEIGHT = not overridden). Zero-size for unweighted strate...
void HrtInit(Timeout periodicity_tc, Timeout deadline_tc, Timeout start_delay_tc)
Initialize task with HRT info.
volatile uint32_t m_state
Bitmask of EStateFlags. Written by task thread, read/cleared by kernel tick.
bool IsSleepInfinite() const
Check whether this task is currently sleeping infinitely.
ITask * m_user
Bound user task, or NULL when slot is free.
Timeout GetHrtRelativeDeadline() const override
Get remaining HRT deadline (ticks left before the deadline expires).
void SetCurrentWeight(Weight weight) override
Update the run-time scheduling weight (weighted strategies only).
void BusyWaitWhileSleeping(Kernel *kernel) const
Block further execution of the task's context while in sleeping state.
Stack GetUserStack() const override
Get stack descriptor for this task slot.
bool IsBusy() const
Check whether this slot is bound to a user task.
bool IsSleeping() const override
Check whether this task is currently sleeping (waiting for a tick or a wake event).
const ITask * GetUserTask() const
Get bound user task (const).
Stack * GetUserStackPtr()
Get pointer to user Stack.
HrtInfo m_hrt[STK_ALLOCATE_COUNT< TMode, KERNEL_HRT, 1U, 0U >::Value]
HRT metadata. Zero-size (no memory) in non-HRT mode.
void HrtOnWorkCompleted()
Called when task process called IKernelService::SwitchToNext to inform Kernel that work is completed.
void Wake() override
Wake this task on the next scheduling tick.
Weight GetWeight() const override
Get static scheduling weight from the user task.
volatile Timeout m_time_sleep
Sleep countdown: negative while sleeping (absolute value = ticks remaining), zero when awake.
bool IsPendingRemoval() const
Check if task is pending removal.
Timeout GetHrtDeadline() const override
Get absolute HRT deadline (ticks elapsed since task was activated).
void Unbind()
Reset this slot to the free (unbound) state, clearing all scheduling metadata.
void HrtOnSwitchedIn()
Called when task is switched into the scheduling process.
bool IsMemoryOfSP(Word SP) const
Check if Stack Pointer (SP) belongs to this task.
TsInfo m_ts[STK_ALLOCATE_COUNT< TMode, KERNEL_TIMESLICE, 1U, 0U >::Value]
Time-slice metadata. Zero-size (no memory) if KERNEL_TIMESLICE is not set.
ITask * GetUserTask() override
Get bound user task.
WaitObject m_wait_obj[STK_ALLOCATE_COUNT< TMode, KERNEL_SYNC, 1U, 0U >::Value]
Embedded wait object for synchronization. Zero-size (no memory) if KERNEL_SYNC is not set.
void ScheduleYield()
Mark the task as yielding (strategy handled Yield() without sleeping the task).
Payload for an in-flight AddTask() request issued by a running task.
ITask * user_task
User task to add. Must remain valid for the lifetime of its kernel slot.
Per-task soft real-time (SRT) metadata.
void Clear()
Clear all fields, ready for slot re-use.
AddTaskRequest * add_task_req
Per-task Hard Real-Time (HRT) scheduling metadata.
void Clear()
Clear all fields, ready for slot re-use or re-activation.
volatile bool done
Set to true when the task signals work completion (via Yield() or on exit). Triggers HrtOnSwitchedOut...
Timeout deadline
Maximum allowed active duration in ticks (relative to switch-in). Exceeding this triggers OnDeadlineM...
Timeout periodicity
Activation period in ticks: the task is re-activated every this many ticks.
Timeout duration
Ticks spent in the active (non-sleeping) state in the current period. Incremented by UpdateTaskState(...
Per-task time-slice (KERNEL_TIMESLICE) metadata.
void Clear()
Clear all fields, ready for slot re-use.
Timeout quantum
Configured slice (ticks), NO_TIME_SLICE if time-slicing is disabled for the task.
void Reload()
Restart the current slice.
volatile Timeout left
Ticks left in the current slice. Written by the tick handler and, under the critical section,...
Concrete implementation of IWaitObject, embedded in each KernelTask slot.
bool IsWaiting() const
Check if busy with waiting.
EWaitResult GetWaitResult() const
Get wait result.
EState GetState() const override
Get current state.
Timeout m_time_wait
Ticks remaining until timeout. Decremented each tick; WAIT_INFINITE means no timeout.
void Wake(bool timeout) override
Wake the waiting task (called by ISyncObject when it signals).
~WaitObject()=default
Destructor.
void Cancel()
Cancel an in-progress wait and wake the owning task early.
bool Tick(Timeout elapsed_ticks) override
Advance the timeout countdown by a number of ticks.
void CancelNoWake()
Cancel an in-progress wait without waking the owning task.
void SetupWait(ISyncObject *sync_obj, Timeout timeout)
Configure and arm this wait object for a new wait operation.
TId GetTid() const override
Get the TId of the task that owns this wait object.
void ClearState()
Clear state.
bool CancelIfWaiting()
Cancel an in-progress wait and wake the owning task early if was waiting.
volatile EState m_state
State of the object, see WaitObject::EState.
ISyncObject * m_sync_obj
Sync object this wait is registered with, or NULL when not waiting.
KernelTask * m_task
Back-pointer to the owning KernelTask. Set once at construction; never changes.
Payload stored in the sync object's kernel-side list entry while a task is waiting.
ISyncObject * sync_obj
Sync object whose Tick() will be called each kernel tick.
KernelService()
Construct an uninitialized service instance (m_platform = null, m_ticks = 0).
Timeout Suspend() override
Suspend scheduling.
void SwitchToNext() override
Notify scheduler to switch to the next task (yield).
volatile Ticks m_ticks
Global tick counter. Written via hw::WriteVolatile64() by IncrementTick() (ISR context); read via hw:...
void Wake(ISyncObject *sobj, bool all) override
Wake one or all tasks currently waiting on a synchronization object.
uint32_t GetSysTimerFrequency() const override
Get system timer frequency.
void Sleep(Timeout ticks) override
Put calling process into a sleep state.
Kernel * m_kernel
Pointer to the Kernel.
Ticks GetTicks() const override
Get number of ticks elapsed since kernel start.
void SleepCancel(TId task_id) override
Cancel sleep of the task.
void Resume(Timeout elapsed_ticks) override
Resume scheduling after a prior Suspend() call.
bool SleepUntil(Ticks timestamp) override
Put calling process into a sleep state until the specified timestamp.
void RestoreWeight(TId tid, ISyncObject *sobj) override
Restore weight of the task to the original value.
~KernelService()=default
Destructor.
void InheritWeight(TId tid, Weight weight) override
Inherit weight for the task.
Cycles GetSysTimerCount() const override
Get system timer count value.
uint32_t GetTickResolution() const override
Get number of microseconds in one tick.
void Delay(Timeout ticks) override
Delay calling process.
Weight SetWeight(TId tid, Weight weight) override
Change the base weight of the task at run-time (replaces ITask::GetWeight() value).
TId GetTid() const override
Get thread Id of the currently running task.
EWaitResult Wait(ISyncObject *sobj, IMutex *mutex, Timeout ticks) override
Put calling process into a waiting state until synchronization object is signaled or timeout occurs.
Timeout SetTimeSlice(TId tid, Timeout ticks) override
Change the time-slice quantum of the task at run-time and reload its slice.
void IncrementTicks(Ticks advance)
Increment counter by value.
void Initialize(Kernel *kernel)
Initialize instance.
Storage bundle for the sleep trap: a Stack descriptor paired with its backing memory.
SleepTrapStackMemory::MemoryType Memory
Memory memory
Backing stack memory array. Size: STK_SLEEP_TRAP_STACK_SIZE elements of Word.
Stack stack
Stack descriptor (SP register value + access mode). Initialized by InitTraps() on every Start().
Storage bundle for the exit trap: a Stack descriptor paired with its backing memory.
Memory memory
Backing stack memory array. Size: STACK_SIZE_MIN elements of Word.
ExitTrapStackMemory::MemoryType Memory
Stack stack
Stack descriptor (SP register value + access mode). Initialized by InitTraps() on every Start().
RAII instance that enters the critical section on construction and exits it on destruction.
Lightweight, non-owning view over a contiguous sequence of elements.
size_t GetSize() const
Get number of elements in the view.
Snapshot of the kernel-side state of a task, filled in by IKernel::GetTaskState().
ETaskState state
Task state.
uint32_t access_mode
Bitfield with hardware access mode of the task (see EAccessMode).
TId tid
Task id (see STK_SEGGER_SYSVIEW, STK_MPU_STACK_GUARD).
Interface for a stack memory region.
virtual size_t GetStackSize() const =0
Get number of elements of the stack memory array.
virtual const Word * GetStack() const =0
Get pointer to the stack memory.
EState
State of the WaitObject.
@ STATE_CANCELLED
Wait was cancelled via Cancel() rather than Wake()/timeout.
@ STATE_TIMEOUT
Wait expired due to timeout rather than a Wake() signal.
@ STATE_SIGNALED
Wake signaled.
@ STATE_WAIT
Wait is active.
Synchronization object interface.
virtual void WakeAll()=0
Wake all tasks currently in the wait list.
DLEntryType ListEntryType
List entry type of ISyncObject elements.
virtual void WakeOne()=0
Wake the first task in the wait list (FIFO order).
DLHeadType ListHeadType
List head type for ISyncObject elements.
static void AddWaitObject(IWaitObject::ListHeadType &wlist, IWaitObject *wobj)
Called by kernel when a new task starts waiting on this event.
Weight FindWeightHigherThan(Weight comp) const
Find higher weight within linked wait objects.
Interface for mutex synchronization primitive.
virtual void Unlock()=0
Unlock the mutex.
virtual void Lock()=0
Lock the mutex.
Interface for a user task.
virtual EAccessMode GetAccessMode() const =0
Get pointer to the stack memory.
virtual void OnExit()
Called by the kernel before removal from the scheduling (see stk::KERNEL_DYNAMIC).
virtual Timeout GetTimeSlice() const
Get time-slice quantum of the task (ticks). KERNEL_TIMESLICE only.
Scheduling-strategy-facing interface for a kernel task slot.
Interface for a platform driver.
virtual void ProcessHardFault()=0
Cause a hard fault of the system.
Interface for a back-end event handler.
Interface for a task switching strategy implementation.
Interface for the implementation of the kernel of the scheduler. It supports Soft and Hard Real-Time ...
Interface for the kernel services exposed to the user processes during run-time when Kernel started s...
static IWaitObject::ListHeadType & GetMutableWaitList(ISyncObject *sobj)
Access helper to the mutable IWaitObject::GetWaitList().
static constexpr size_t Value
Adapts an externally-owned stack memory array to the IStackMemory interface.
StackMemoryDef< _StackSize >::Type MemoryType
DLEntryType * GetNext()
Get the next entry in the list.
DLHeadType * GetHead()
Get the list head this entry currently belongs to.
static __stk_forceinline TTargetType * ListEntryToParent(TSourceType *const lentry)
Safely casts an intrusive list entry to its concrete parent container object type.