19template <u
int8_t TMode, u
int32_t TSize,
class TStrategy,
class TPlatform>
59 const int32_t TASKS = 2;
63 CHECK_EQUAL(TASKS, result);
73 CHECK_TRUE(platform != NULL);
99 CHECK_TEXT(
false,
"duplicate Kernel::Initialize() did not fail");
117 CHECK_TEXT(
false,
"AddTask() did not fail");
134 CHECK_EQUAL_TEXT(0, strategy->
GetSize(),
"Expecting none kernel tasks");
138 CHECK_EQUAL_TEXT(1, strategy->
GetSize(),
"Expecting 1 kernel task");
141 CHECK_TRUE_TEXT(ktask != NULL,
"Expecting one kernel task");
143 CHECK_TRUE_TEXT(ktask->
GetUserTask() == &task,
"Expecting just added user task");
172 CHECK_TEXT(
false,
"expecting to fail adding task because max is 2 but adding 3-rd");
193 CHECK_TEXT(
false,
"expecting to fail adding the same task");
221 CHECK_EQUAL_TEXT(2,
strategy->GetSize(),
"task2 must be added within 1 tick");
244 CHECK_EQUAL_TEXT(1, strategy->
GetSize(),
"expecting task1 be added at this stage");
252 CHECK_EQUAL_TEXT(2, strategy->
GetSize(),
"task2 must be added");
271 CHECK_TEXT(
false,
"expecting to AddTask to fail when non KERNEL_DYNAMIC");
286 kernel.
AddTask(&task1, 1, 1, 0);
292 kernel.
AddTask(&task2, 1, 1, 0);
293 CHECK_TEXT(
false,
"expecting to AddTask to fail when KERNEL_HRT");
316 CHECK_EQUAL_TEXT(&task2, strategy->
GetFirst()->
GetUserTask(),
"Expecting task2 as first (duplicate task1 removal attempt)");
319 CHECK_EQUAL_TEXT(0, strategy->
GetSize(),
"Expecting none tasks");
332 CHECK_TEXT(
false,
"expecting to fail with NULL argument");
353 CHECK_TEXT(
false,
"expecting to fail in KERNEL_STATIC mode");
375 CHECK_TEXT(
false,
"expecting to fail when Kernel has started");
393 CHECK_TEXT(
false,
"expecting to fail with 0 periodicity");
405 CHECK_TEXT(
false,
"expecting to fail with too large periodicity");
422 CHECK_TEXT(
false,
"expecting to fail when not initialized");
441 CHECK_TEXT(
false,
"expecting to fail without tasks");
499 CHECK_TRUE(idle != NULL);
500 CHECK_TRUE(active != NULL);
506 CHECK_EQUAL(active->SP, (
Word)task2.GetStack());
516 CHECK_TRUE(idle != NULL);
517 CHECK_TRUE(active != NULL);
520 CHECK_EQUAL(idle->
SP, (
Word)task2.GetStack());
593 CHECK_EQUAL((
Stack *)NULL, idle);
597template <
class _SwitchStrategy>
630 CHECK_EQUAL((
Stack *)NULL, idle);
669 CHECK_TEXT(
false,
"expecting to fail on unknown stack");
681 CHECK_TEXT(
false,
"expecting to fail on NULL");
757 CHECK_EQUAL(active->
SP, (
Word)task2.GetStack());
763 CHECK_EQUAL(active->
SP, (
Word)task2.GetStack());
875 bool suspended =
false;
894 CHECK_TRUE(suspended);
901 CHECK_TRUE(suspended);
905 CHECK_EQUAL(idle->
SP, (
Word)task2.GetStack());
909 CHECK_EQUAL(idle->
SP, (
Word)task2.GetStack());
916 CHECK_EQUAL(active->SP, (
Word)task2.GetStack());
926 kernel.
AddTask(&task1, 1, 1, 0);
927 kernel.
AddTask(&task2, 2, 1, 0);
967 kernel.
AddTask(&task, 1, 1, 0);
983 kernel.
AddTask(&task, 1, 1, 0);
1019 kernel.
AddTask(&task, 1, 1, 0);
1022 CHECK_TRUE(strategy->
GetSize() != 0);
1029 CHECK_EQUAL(0, strategy->
GetSize());
1065 kernel.
AddTask(&task, 2, 1, 0);
1090 kernel.
AddTask(&task, 2, 1, 0);
1115 kernel.
AddTask(&task1, 2, 2, 3);
1116 kernel.
AddTask(&task2, 3, 3, 0);
1131 CHECK_EQUAL(0, task2.m_deadline_missed);
1134template <
class _SwitchStrategy>
1140 const _SwitchStrategy *strategy =
static_cast<const _SwitchStrategy *
>(kernel.
GetSwitchStrategy());
1143 kernel.
AddTask(&task1, 1, 2, 0);
1144 kernel.
AddTask(&task2, 1, 2, 2);
1162 CHECK_EQUAL(1, strategy->GetSize());
1192 kernel.
AddTask(&task, 1, 1, 1);
1216 CHECK_TRUE_TEXT(ktask !=
nullptr,
"Kernel task must exist");
1222 CHECK_TEXT(
false,
"HRT API can't be called in non-HRT mode");
1234 CHECK_TEXT(
false,
"HRT API can't be called in non-HRT mode");
1246 CHECK_TEXT(
false,
"HRT API can't be called in non-HRT mode");
1269 CHECK_TEXT(
false,
"kernel does not support waiting without KERNEL_SYNC");
1283 CHECK_TRUE_TEXT(wo ==
nullptr,
"expect NULL");
1289 CHECK_TEXT(
false,
"kernel does not support waiting without KERNEL_SYNC");
1303 CHECK_TRUE_TEXT(wo ==
nullptr,
"expect NULL");
1321 CHECK_TEXT(
false,
"sync object must not be NULL");
1345 CHECK_TEXT(
false,
"mutex must not be NULL");
1370 CHECK_TEXT(
false,
"must not be zero wait");
1395 CHECK_TEXT(
false,
"mutex must be locked");
1463 CHECK_EQUAL(2,
platform->m_ticks_count);
1474template <
bool TTickless>
1488 kernel.Initialize();
1489 kernel.AddTask(&task);
1497 CHECK_TRUE(wo !=
nullptr);
1500 CHECK_EQUAL(
true,
mutex.m_locked);
1542 CHECK_TRUE(wo !=
nullptr);
1545 CHECK_EQUAL(
true,
mutex.m_locked);
1558 ITask *tasks[2] = {};
1562 CHECK_COMPARE(i, <, 2);
1568 CHECK_EQUAL(2, count);
1571 CHECK_EQUAL(tasks[0], &task1);
1572 CHECK_EQUAL(tasks[1], &task2);
1578 CHECK_EQUAL(1, count);
1584 CHECK_EQUAL(1, count);
1600 CHECK_TEXT(
false,
"tickless only");
1619 CHECK_TEXT(
false,
"tickless only");
1641 CHECK_EQUAL(9, ticks);
void(* g_RelaxCpuHandler)()
__stk_relax_cpu handler.
Namespace of STK package.
uintptr_t Word
Native processor word type.
void Sleep(Timeout ticks)
Put calling process into a sleep state.
Ticks GetTicks()
Get number of ticks elapsed since kernel start.
int32_t Timeout
Timeout time (ticks).
@ STACK_SLEEP_TRAP
Stack of the Sleep trap.
@ STACK_USER_TASK
Stack of the user task.
void Yield()
Notify scheduler to switch to the next runnable task.
void SleepUntil(Ticks timestamp)
Put calling process into a sleep state until the specified timestamp.
@ PERIODICITY_MAX
Maximum periodicity (microseconds), 99 milliseconds (note: this value is the highest working on a rea...
TId GetTid()
Get task/thread Id of the calling task.
SwitchStrategyRoundRobin SwitchStrategyRR
Shorthand alias for SwitchStrategyRoundRobin.
@ ACCESS_USER
Unprivileged access mode (access to some hardware is restricted, see CPU manual for details).
@ ACCESS_PRIVILEGED
Privileged access mode (access to hardware is fully unrestricted).
@ 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_STATIC
All tasks are static and can not exit.
@ KERNEL_PANIC_BAD_MODE
Kernel is in bad/unsupported mode for the current operation.
@ KERNEL_PANIC_NONE
Panic is absent (no fault).
@ KERNEL_PANIC_BAD_STATE
Kernel entered unexpected (bad) state.
Namespace of the test inventory.
static struct stk::test::TaskSuspendContext g_TaskSuspendContext
static struct stk::test::SyncWaitRelaxCpuContext g_SyncWaitRelaxCpuContext
TestContext g_TestContext
Global instance of the TestContext.
static void TaskSuspendRelaxCpu()
static void SyncWaitRelaxCpu()
static struct stk::test::AddTaskWhenStartedRelaxCpuContext g_AddTaskWhenStartedRelaxCpuContext
IKernelService * g_KernelService
static struct stk::test::HrtTaskDeadlineMissedRelaxCpuContext g_HrtTaskDeadlineMissedRelaxCpuContext
EKernelPanicId g_PanicValue
Panic value.
static void HrtTaskDeadlineMissedRelaxCpu()
static void TestTaskExit()
static void AddTaskWhenStartedRelaxCpu()
static void TestHrtTaskExitDuringSleepState()
Concrete implementation of IKernel.
void ResumeTask(ITask *user_task)
Resume task.
void ScheduleTaskRemoval(ITask *user_task)
Schedule task removal from scheduling (exit).
bool UpdateFsmState(Stack *&idle, Stack *&active)
Update FSM state.
EFsmState
Finite-state machine (FSM) state. Encodes what the kernel is currently doing between two consecutive ...
@ FSM_STATE_NONE
Sentinel / uninitialized value. Set by the constructor, replaced by FSM_STATE_SWITCHING on the first ...
@ FSM_STATE_MAX
Sentinel: number of valid states (used to size the FSM table), denotes uninitialized state.
void SuspendTask(ITask *user_task, bool &suspended)
Suspend task.
EFsmState GetNewFsmState(KernelTask *&next)
Get new FSM state.
void Initialize(uint32_t resolution_us=PERIODICITY_DEFAULT)
Initialize kernel.
EState GetState() const
Get kernel state.
ITaskSwitchStrategy * GetSwitchStrategy()
Get task-switching strategy instance owned by this kernel.
void Start()
Start the scheduler. This call does not return until all tasks have exited (KERNEL_DYNAMIC mode) or i...
void RemoveTask(ITask *user_task)
Remove a previously added task from the kernel before Start().
KernelTask * m_task_now
Currently executing task, or nullptr before Start() or after all tasks exit.
static constexpr uint32_t TASKS_MAX
Maximum number of concurrently registered tasks. Fixed at compile time. Exceeding this limit in AddTa...
IPlatform * GetPlatform()
Get platform driver instance owned by this kernel.
Kernel()
Construct the kernel with all storage zero-initialized and the request flag set to ~0 (indicating uni...
void AddTask(ITask *user_task)
Register task for a soft real-time (SRT) scheduling.
Internal per-slot kernel descriptor that wraps a user ITask instance.
Word SP
Stack Pointer (SP) register (note: must be the first entry in this struct).
EAccessMode mode
Hardware access mode of the owning task (see EAccessMode).
virtual TId GetTid() const =0
Get thread Id of this task.
virtual bool IsTimeout() const =0
Check if task woke up due to a timeout.
Locks bound mutex within a scope of execution. Ensures the mutex is always unlocked when leaving the ...
Interface for a user task.
Scheduling-strategy-facing interface for a kernel task slot.
virtual Timeout GetHrtRelativeDeadline() const =0
Get HRT task's relative deadline.
virtual Timeout GetHrtDeadline() const =0
Get HRT task deadline (max allowed task execution time).
virtual Timeout GetHrtPeriodicity() const =0
Get HRT task execution periodicity.
virtual ITask * GetUserTask()=0
Get user task.
Interface for a platform driver.
Interface for a task switching strategy implementation.
virtual size_t GetSize() const =0
Get number of tasks currently managed by this strategy.
virtual IKernelTask * GetFirst() const =0
Get first task.
Interface for the implementation of the kernel of the scheduler. It supports Soft and Hard Real-Time ...
@ STATE_INACTIVE
Not ready, IKernel::Initialize() must be called.
@ STATE_READY
Ready to start, IKernel::Start() must be called.
@ STATE_SUSPENDED
Scheduling is suspended with IKernelService::Suspend().
@ STATE_RUNNING
Initialized and running, IKernel::Start() was called successfully.
size_t EnumerateTasksT(TCallback &&callback)
Enumerate tasks, invoking a callback for each active task.
static IKernelService * GetInstance()
Get CPU-local instance of the kernel service.
virtual void Resume(Timeout elapsed_ticks)=0
Resume scheduling after a prior Suspend() call.
virtual IWaitObject * Wait(ISyncObject *sobj, IMutex *mutex, Timeout timeout)=0
Put calling process into a waiting state until synchronization object is signaled or timeout occurs.
virtual Timeout Suspend()=0
Suspend scheduling.
Word * GetStack() const
Get pointer to the stack memory.
BaseType::EFsmState GetNewFsmState(typename BaseType::KernelTask *&next) override
Kernel< TMode, TSize, TStrategy, TPlatform > BaseType
void ForceUpdateInvalidFsmState(bool max_val)
const ITaskSwitchStrategy * strategy
AddTaskWhenStartedRelaxCpuContext()
PlatformTestMock * platform
HrtTaskDeadlineMissedRelaxCpuContext()
PlatformTestMock * platform
PlatformTestMock * platform
SyncWaitRelaxCpuContext()
Throwable class for catching assertions from STK_ASSERT_HANDLER().
void EventTaskSwitch(size_t caller_SP)
void ProcessTick()
Process one tick.
void EventTaskExit(Stack *stack)
IWaitObject * EventTaskWait(size_t caller_SP, ISyncObject *sync_obj, IMutex *mutex, Timeout timeout)
IKernelService * m_service
uint32_t m_context_switch_nr
StackInfo m_stack_info[STACK_EXIT_TRAP+1]
uint32_t GetTickResolution() const
Get resolution of the system tick timer in microseconds. Resolution means a number of microseconds be...
uint32_t m_deadline_missed
duration of workload if deadline is missed in HRT mode