SuperTinyKernel™ RTOS 1.05.3
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stktest_kernel.cpp
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#include "stktest.h"
11
12namespace stk {
13namespace test {
14
15// ============================================================================ //
16// ============================== Kernel ====================================== //
17// ============================================================================ //
18
19template <uint8_t TMode, uint32_t TSize, class TStrategy, class TPlatform>
20class KernelMock : public Kernel<TMode, TSize, TStrategy, TPlatform>
21{
23
24public:
26
27 // Override the getter to bypass the ROM table during tests
28 typename BaseType::EFsmState GetNewFsmState(typename BaseType::KernelTask *&next) override
29 {
31 return static_cast<typename BaseType::EFsmState>(m_fsm_state_mock);
32
33 return BaseType::GetNewFsmState(next);
34 }
35
36 void ForceUpdateInvalidFsmState(bool max_val)
37 {
38 m_fsm_state_mock = KernelMock::FSM_STATE_MAX + (max_val ? 0 : 1);
39
40 Stack *idle = nullptr, *active = this->m_task_now->GetUserStack();
41 KernelMock::UpdateFsmState(idle, active);
42 }
43};
44
46{
47 void setup() {}
48 void teardown()
49 {
50 g_TestContext.RethrowAssertException(true);
51 g_TestContext.ExpectAssert(false);
52 g_TestContext.ExpectPanic(false);
54 }
55};
56
57TEST(Kernel, MaxTasks)
58{
59 const int32_t TASKS = 2;
62
63 CHECK_EQUAL(TASKS, result);
64}
65
66TEST(Kernel, State)
67{
70
71 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
72
73 CHECK_TRUE(platform != NULL);
74
75 CHECK_TRUE(kernel.GetState() == IKernel::STATE_INACTIVE);
76
77 kernel.Initialize();
78
79 CHECK_TRUE(kernel.GetState() == IKernel::STATE_READY);
80
81 CHECK_TRUE(IKernelService::GetInstance() != NULL);
82 CHECK_TRUE(IKernelService::GetInstance() == platform->m_service);
83
84 kernel.AddTask(&task);
85 kernel.Start();
86
87 CHECK_TRUE(kernel.GetState() == IKernel::STATE_RUNNING);
88}
89
90TEST(Kernel, InitDoubleFail)
91{
93
94 try
95 {
96 g_TestContext.ExpectAssert(true);
97 kernel.Initialize();
98 kernel.Initialize();
99 CHECK_TEXT(false, "duplicate Kernel::Initialize() did not fail");
100 }
101 catch (TestAssertPassed &pass)
102 {
103 CHECK(true);
104 g_TestContext.ExpectAssert(false);
105 }
106}
107
108TEST(Kernel, AddTaskNoInit)
109{
112
113 try
114 {
115 g_TestContext.ExpectAssert(true);
116 kernel.AddTask(&task);
117 CHECK_TEXT(false, "AddTask() did not fail");
118 }
119 catch (TestAssertPassed &pass)
120 {
121 CHECK(true);
122 g_TestContext.ExpectAssert(false);
123 }
124}
125
126TEST(Kernel, AddTask)
127{
130 const ITaskSwitchStrategy *strategy = kernel.GetSwitchStrategy();
131
132 kernel.Initialize();
133
134 CHECK_EQUAL_TEXT(0, strategy->GetSize(), "Expecting none kernel tasks");
135
136 kernel.AddTask(&task);
137
138 CHECK_EQUAL_TEXT(1, strategy->GetSize(), "Expecting 1 kernel task");
139
140 IKernelTask *ktask = strategy->GetFirst();
141 CHECK_TRUE_TEXT(ktask != NULL, "Expecting one kernel task");
142
143 CHECK_TRUE_TEXT(ktask->GetUserTask() == &task, "Expecting just added user task");
144}
145
146TEST(Kernel, AddTaskInitStack)
147{
150 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
151
152 kernel.Initialize();
153 kernel.AddTask(&task);
154
155 CHECK_EQUAL(&task, platform->m_stack_info[STACK_USER_TASK].task);
156 CHECK_EQUAL((Word)task.GetStack(), platform->m_stack_info[STACK_USER_TASK].stack->SP);
157}
158
159TEST(Kernel, AddTaskFailMaxOut)
160{
162 TaskMock<ACCESS_USER> task1, task2, task3;
163
164 kernel.Initialize();
165
166 try
167 {
168 g_TestContext.ExpectAssert(true);
169 kernel.AddTask(&task1);
170 kernel.AddTask(&task2);
171 kernel.AddTask(&task3);
172 CHECK_TEXT(false, "expecting to fail adding task because max is 2 but adding 3-rd");
173 }
174 catch (TestAssertPassed &pass)
175 {
176 CHECK(true);
177 g_TestContext.ExpectAssert(false);
178 }
179}
180
181TEST(Kernel, AddTaskFailSameTask)
182{
185
186 kernel.Initialize();
187
188 try
189 {
190 g_TestContext.ExpectAssert(true);
191 kernel.AddTask(&task);
192 kernel.AddTask(&task);
193 CHECK_TEXT(false, "expecting to fail adding the same task");
194 }
195 catch (TestAssertPassed &pass)
196 {
197 CHECK(true);
198 g_TestContext.ExpectAssert(false);
199 }
200}
201
203{
205 {
206 counter = 0;
207 platform = NULL;
208 strategy = NULL;
209 }
210
211 uint32_t counter;
214
215 void Process()
216 {
217 platform->ProcessTick();
218
219 if (counter >= 1)
220 {
221 CHECK_EQUAL_TEXT(2, strategy->GetSize(), "task2 must be added within 1 tick");
222 }
223
224 ++counter;
225 }
226}
228
233
234TEST(Kernel, AddTaskWhenStarted)
235{
237 TaskMock<ACCESS_USER> task1, task2;
238 const ITaskSwitchStrategy *strategy = kernel.GetSwitchStrategy();
239
240 kernel.Initialize();
241 kernel.AddTask(&task1);
242 kernel.Start();
243
244 CHECK_EQUAL_TEXT(1, strategy->GetSize(), "expecting task1 be added at this stage");
245
247 g_AddTaskWhenStartedRelaxCpuContext.strategy = strategy;
249
250 kernel.AddTask(&task2);
251
252 CHECK_EQUAL_TEXT(2, strategy->GetSize(), "task2 must be added");
253
254 // AddTask is calling Yield/SwitchToNext which takes 2 ticks
255 CHECK_EQUAL_TEXT(2, g_AddTaskWhenStartedRelaxCpuContext.counter, "should complete within 2 ticks");
256}
257
258TEST(Kernel, AddTaskFailStaticStarted)
259{
261 TaskMock<ACCESS_USER> task1, task2;
262
263 kernel.Initialize();
264 kernel.AddTask(&task1);
265 kernel.Start();
266
267 try
268 {
269 g_TestContext.ExpectAssert(true);
270 kernel.AddTask(&task2);
271 CHECK_TEXT(false, "expecting to AddTask to fail when non KERNEL_DYNAMIC");
272 }
273 catch (TestAssertPassed &pass)
274 {
275 CHECK(true);
276 g_TestContext.ExpectAssert(false);
277 }
278}
279
280TEST(Kernel, AddTaskFailHrtStarted)
281{
283 TaskMock<ACCESS_USER> task1, task2;
284
285 kernel.Initialize();
286 kernel.AddTask(&task1, 1, 1, 0);
287 kernel.Start();
288
289 try
290 {
291 g_TestContext.ExpectAssert(true);
292 kernel.AddTask(&task2, 1, 1, 0);
293 CHECK_TEXT(false, "expecting to AddTask to fail when KERNEL_HRT");
294 }
295 catch (TestAssertPassed &pass)
296 {
297 CHECK(true);
298 g_TestContext.ExpectAssert(false);
299 }
300}
301
302TEST(Kernel, RemoveTask)
303{
305 TaskMock<ACCESS_USER> task1, task2;
306 const ITaskSwitchStrategy *strategy = kernel.GetSwitchStrategy();
307
308 kernel.Initialize();
309 kernel.AddTask(&task1);
310 kernel.AddTask(&task2);
311
312 kernel.RemoveTask(&task1);
313 CHECK_EQUAL_TEXT(&task2, strategy->GetFirst()->GetUserTask(), "Expecting task2 as first");
314
315 kernel.RemoveTask(&task1);
316 CHECK_EQUAL_TEXT(&task2, strategy->GetFirst()->GetUserTask(), "Expecting task2 as first (duplicate task1 removal attempt)");
317
318 kernel.RemoveTask(&task2);
319 CHECK_EQUAL_TEXT(0, strategy->GetSize(), "Expecting none tasks");
320}
321
322TEST(Kernel, RemoveTaskFailNull)
323{
325
326 kernel.Initialize();
327
328 try
329 {
330 g_TestContext.ExpectAssert(true);
331 kernel.RemoveTask((ITask *)NULL);
332 CHECK_TEXT(false, "expecting to fail with NULL argument");
333 }
334 catch (TestAssertPassed &pass)
335 {
336 CHECK(true);
337 g_TestContext.ExpectAssert(false);
338 }
339}
340
341TEST(Kernel, RemoveTaskFailUnsupported)
342{
345
346 kernel.Initialize();
347 kernel.AddTask(&task);
348
349 try
350 {
351 g_TestContext.ExpectAssert(true);
352 kernel.RemoveTask(&task);
353 CHECK_TEXT(false, "expecting to fail in KERNEL_STATIC mode");
354 }
355 catch (TestAssertPassed &pass)
356 {
357 CHECK(true);
358 g_TestContext.ExpectAssert(false);
359 }
360}
361
362TEST(Kernel, RemoveTaskFailStarted)
363{
366
367 kernel.Initialize();
368 kernel.AddTask(&task);
369 kernel.Start();
370
371 try
372 {
373 g_TestContext.ExpectAssert(true);
374 kernel.RemoveTask(&task);
375 CHECK_TEXT(false, "expecting to fail when Kernel has started");
376 }
377 catch (TestAssertPassed &pass)
378 {
379 CHECK(true);
380 g_TestContext.ExpectAssert(false);
381 }
382}
383
384TEST(Kernel, StartInvalidPeriodicity)
385{
388
389 try
390 {
391 g_TestContext.ExpectAssert(true);
392 kernel.Initialize(0);
393 CHECK_TEXT(false, "expecting to fail with 0 periodicity");
394 }
395 catch (TestAssertPassed &pass)
396 {
397 CHECK(true);
398 g_TestContext.ExpectAssert(false);
399 }
400
401 try
402 {
403 g_TestContext.ExpectAssert(true);
404 kernel.Initialize(PERIODICITY_MAX + 1);
405 CHECK_TEXT(false, "expecting to fail with too large periodicity");
406 }
407 catch (TestAssertPassed &pass)
408 {
409 CHECK(true);
410 g_TestContext.ExpectAssert(false);
411 }
412}
413
414TEST(Kernel, StartNotIntialized)
415{
417
418 try
419 {
420 g_TestContext.ExpectAssert(true);
421 kernel.Start();
422 CHECK_TEXT(false, "expecting to fail when not initialized");
423 }
424 catch (TestAssertPassed &pass)
425 {
426 CHECK(true);
427 g_TestContext.ExpectAssert(false);
428 }
429}
430
431TEST(Kernel, StartNoTasks)
432{
434
435 kernel.Initialize();
436
437 try
438 {
439 g_TestContext.ExpectAssert(true);
440 kernel.Start();
441 CHECK_TEXT(false, "expecting to fail without tasks");
442 }
443 catch (TestAssertPassed &pass)
444 {
445 CHECK(true);
446 g_TestContext.ExpectAssert(false);
447 }
448}
449
451{
454 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
455 const uint32_t periodicity = PERIODICITY_MAX - 1;
456
457 kernel.Initialize(periodicity);
458 kernel.AddTask(&task);
459
460 kernel.Start();
461
462 CHECK_TRUE(platform->m_started);
463 CHECK_TRUE(g_KernelService != NULL);
464 CHECK_TRUE(platform->m_stack_active != NULL);
465 CHECK_EQUAL((Word)task.GetStack(), platform->m_stack_active->SP);
466 CHECK_EQUAL(periodicity, platform->GetTickResolution());
467}
468
469TEST(Kernel, StartBeginISR)
470{
473 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
474
475 kernel.Initialize();
476 kernel.AddTask(&task);
477 kernel.Start();
478
479 // expect that first task's access mode is requested by kernel
480 CHECK_EQUAL(ACCESS_PRIVILEGED, platform->m_stack_active->mode);
481}
482
483TEST(Kernel, ContextSwitchOnSysTickISR)
484{
486 TaskMock<ACCESS_USER> task1, task2;
487 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
488 Stack *&idle = platform->m_stack_idle, *&active = platform->m_stack_active;
489
490 kernel.Initialize();
491 kernel.AddTask(&task1);
492 kernel.AddTask(&task2);
493 kernel.Start();
494
495 // ISR calls OnSysTick 1-st time
496 {
497 platform->ProcessTick();
498
499 CHECK_TRUE(idle != NULL);
500 CHECK_TRUE(active != NULL);
501
502 // 1-st task is switched from Active and becomes Idle
503 CHECK_EQUAL(idle->SP, (Word)task1.GetStack());
504
505 // 2-nd task becomes Active
506 CHECK_EQUAL(active->SP, (Word)task2.GetStack());
507
508 // context switch requested
509 CHECK_EQUAL(1, platform->m_context_switch_nr);
510 }
511
512 // ISR calls OnSysTick 2-nd time
513 {
514 platform->ProcessTick();
515
516 CHECK_TRUE(idle != NULL);
517 CHECK_TRUE(active != NULL);
518
519 // 2-st task is switched from Active and becomes Idle
520 CHECK_EQUAL(idle->SP, (Word)task2.GetStack());
521
522 // 1-nd task becomes Active
523 CHECK_EQUAL(active->SP, (Word)task1.GetStack());
524
525 // context switch requested
526 CHECK_EQUAL(2, platform->m_context_switch_nr);
527 }
528}
529
530TEST(Kernel, ContextSwitchAccessModeChange)
531{
535 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
536
537 kernel.Initialize();
538 kernel.AddTask(&task1);
539 kernel.AddTask(&task2);
540 kernel.Start();
541
542 // 1-st task
543 CHECK_EQUAL(ACCESS_USER, platform->m_stack_active->mode);
544
545 // ISR calls OnSysTick
546 platform->ProcessTick();
547
548 // 2-st task
549 CHECK_EQUAL(ACCESS_PRIVILEGED, platform->m_stack_active->mode);
550}
551
552TEST(Kernel, ContextSwitchCorruptedFsmMode)
553{
556 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
557
558 kernel.Initialize();
559 kernel.AddTask(&task);
560 kernel.Start();
561
562 // ISR calls OnSysTick
563 platform->ProcessTick();
564
565 g_TestContext.ExpectPanic(true);
566
567 kernel.ForceUpdateInvalidFsmState(true);
568 platform->ProcessTick();
570
572
573 kernel.ForceUpdateInvalidFsmState(false);
574 platform->ProcessTick();
576}
577
578TEST(Kernel, SingleTask)
579{
582 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
583 Stack *&idle = platform->m_stack_idle, *&active = platform->m_stack_active;
584
585 kernel.Initialize();
586 kernel.AddTask(&task);
587 kernel.Start();
588
589 // ISR calls OnSysTick
590 platform->ProcessTick();
591
592 // expect that with single task nothing changes
593 CHECK_EQUAL((Stack *)NULL, idle);
594 CHECK_EQUAL((Stack *)platform->m_stack_info[STACK_USER_TASK].stack, active);
595}
596
597template <class _SwitchStrategy>
598static void TestTaskExit()
599{
601 TaskMock<ACCESS_PRIVILEGED> task1, task2;
602 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
603 Stack *&idle = platform->m_stack_idle, *&active = platform->m_stack_active;
604
605 kernel.Initialize();
606 kernel.AddTask(&task1);
607 kernel.AddTask(&task2);
608 kernel.Start();
609
610 // ISR calls OnSysTick (task1 = idle, task2 = active)
611 platform->ProcessTick();
612
613 // task2 exited (will schedule its removal)
614 platform->EventTaskExit(active);
615
616 // ISR calls OnSysTick (task2 = idle, task1 = active)
617 platform->ProcessTick();
618
619 // task1 exited (will schedule its removal)
620 platform->EventTaskExit(active);
621
622 // ISR calls OnSysTick
623 platform->ProcessTick();
624
625 // last task is removed
626 platform->ProcessTick();
627 platform->ProcessTick();
628
629 // no Idle tasks left
630 CHECK_EQUAL((Stack *)NULL, idle);
631
632 // Exit trap stack is provided for a long jump to the end of Kernel::Start()
633 CHECK_EQUAL(platform->m_exit_trap, active);
634}
635
636TEST(Kernel, OnTaskExitRR)
637{
639}
640
641TEST(Kernel, OnTaskExitSWRR)
642{
644}
645
646TEST(Kernel, OnTaskExitFP31)
647{
649}
650
651TEST(Kernel, OnTaskExitUnknownOrNull)
652{
655 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
656 Stack unk_stack;
657
658 kernel.Initialize();
659 kernel.AddTask(&task1);
660 kernel.Start();
661
662 // ISR calls OnSysTick (task1 = idle, task2 = active)
663 platform->ProcessTick();
664
665 try
666 {
667 g_TestContext.ExpectAssert(true);
668 platform->EventTaskExit(&unk_stack);
669 CHECK_TEXT(false, "expecting to fail on unknown stack");
670 }
671 catch (TestAssertPassed &pass)
672 {
673 CHECK(true);
674 g_TestContext.ExpectAssert(false);
675 }
676
677 try
678 {
679 g_TestContext.ExpectAssert(true);
680 platform->EventTaskExit(NULL);
681 CHECK_TEXT(false, "expecting to fail on NULL");
682 }
683 catch (TestAssertPassed &pass)
684 {
685 CHECK(true);
686 g_TestContext.ExpectAssert(false);
687 }
688}
689
690TEST(Kernel, OnTaskExitUnsupported)
691{
694 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
695 Stack *&active = platform->m_stack_active;
696
697 kernel.Initialize();
698 kernel.AddTask(&task1);
699 kernel.Start();
700
701 // ISR calls OnSysTick
702 platform->ProcessTick();
703
704 g_TestContext.ExpectPanic(true);
705 platform->EventTaskExit(active);
707}
708
709TEST(Kernel, OnTaskExitScheduleDynamicOnly)
710{
713
714 kernel.Initialize();
715 kernel.AddTask(&task1);
716 kernel.Start();
717
718 try
719 {
720 g_TestContext.ExpectAssert(true);
721 kernel.ScheduleTaskRemoval(&task1);
722 CHECK(false); // dynamic only
723 }
724 catch (TestAssertPassed &pass)
725 {
726 CHECK(true);
727 g_TestContext.ExpectAssert(false);
728 }
729}
730
731TEST(Kernel, OnTaskExitSchedule)
732{
734 TaskMock<ACCESS_PRIVILEGED> task1, task2;
735 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
736 Stack *&active = platform->m_stack_active;
737
738 kernel.Initialize();
739 kernel.AddTask(&task1);
740 kernel.AddTask(&task2);
741 kernel.Start();
742
743 // task1 is active after Start
744 CHECK_EQUAL(active->SP, (Word)task1.GetStack());
745
746 kernel.ScheduleTaskRemoval(&task1);
747
748 // ScheduleTaskRemoval does not change anything, just schedules removal on the next tick
749 CHECK_EQUAL(active->SP, (Word)task1.GetStack());
750
751 // task2 will become active now but kernel could not remove task1 because it was current one,
752 // it will be removed on a next tick
753 platform->ProcessTick();
754
755 // task2 became the active
756 CHECK_EQUAL(2, kernel.GetSwitchStrategy()->GetSize());
757 CHECK_EQUAL(active->SP, (Word)task2.GetStack());
758
759 platform->ProcessTick();
760
761 // task1 was removed by the tick, task2 is the only active
762 CHECK_EQUAL(1, kernel.GetSwitchStrategy()->GetSize());
763 CHECK_EQUAL(active->SP, (Word)task2.GetStack());
764}
765
766TEST(Kernel, OnTaskNotFoundBySP)
767{
770 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
771
772 kernel.Initialize();
773 kernel.AddTask(&task1);
774 kernel.Start();
775
776 platform->ProcessTick();
777
778 try
779 {
780 g_TestContext.ExpectAssert(true);
781 platform->EventTaskSwitch(0xdeadbeef);
782 CHECK(false); // non existent task must not succeed
783 }
784 catch (TestAssertPassed &pass)
785 {
786 CHECK(true);
787 g_TestContext.ExpectAssert(false);
788 }
789}
790
791TEST(Kernel, OnTaskSkipFreedTask)
792{
794 TaskMock<ACCESS_PRIVILEGED> task1, task2;
795 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
796 Stack *&active = platform->m_stack_active;
797
798 kernel.Initialize();
799 kernel.AddTask(&task1);
800 kernel.AddTask(&task2);
801 kernel.Start();
802
803 // task1 exited (will schedule its removal)
804 platform->EventTaskExit(active);
805
806 // 2 ticks to remove exited task1 from scheduling (1st switched to task2, 2nd cleans up task1 exit)
807 platform->ProcessTick();
808 platform->ProcessTick();
809
810 try
811 {
812 g_TestContext.ExpectAssert(true);
813
814 // we loop through all tasks in attempt to find non existent SP (0xdeadbeef)
815 // by this FindTaskBySP() is invoked and will loop thorugh the exited task1's
816 // slot
817 platform->EventTaskSwitch(0xdeadbeef);
818 CHECK(false); // exited task must be successfully skipped by FindTaskBySP()
819 }
820 catch (TestAssertPassed &pass)
821 {
822 CHECK(true);
823 g_TestContext.ExpectAssert(false);
824 }
825}
826
828{
830 {
831 Clear();
832 }
833
838 uint32_t count;
839
840 void Clear()
841 {
842 platform = nullptr;
843 kernel = nullptr;
844 task1 = nullptr;
845 task2 = nullptr;
846 count = 0;
847 }
848
849 void Process()
850 {
851 platform->ProcessTick();
852
853 if (count > 2)
854 {
855 // on first attempt we resume self, then calling Resume for a non-suspended task is noop
856 kernel->ResumeTask(task1);
857 }
858
859 ++count;
860 }
861}
863
865{
866 g_TaskSuspendContext.Process();
867}
868
869TEST(Kernel, TaskSuspend)
870{
872 TaskMock<ACCESS_USER> task1, task2;
873 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
874 Stack *&idle = platform->m_stack_idle, *&active = platform->m_stack_active;
875 bool suspended = false;
876
877 g_TaskSuspendContext.Clear();
878 g_TaskSuspendContext.platform = platform;
879 g_TaskSuspendContext.kernel = &kernel;
880 g_TaskSuspendContext.task1 = &task1;
881 g_TaskSuspendContext.task2 = &task2;
883
884 kernel.Initialize();
885 kernel.AddTask(&task1);
886 kernel.AddTask(&task2);
887 kernel.Start();
888
889 // task1 is active after Start
890 CHECK_EQUAL(active->SP, (Word)task1.GetStack());
891
892 // task1 is calling SuspendTask to suspend self
893 kernel.SuspendTask(&task1, suspended);
894 CHECK_TRUE(suspended);
895
896 // task1 became active after we resumed it TaskSuspendContext::Process
897 CHECK_EQUAL(active->SP, (Word)task1.GetStack());
898
899 // task1 is calling SuspendTask for task2
900 kernel.SuspendTask(&task2, suspended);
901 CHECK_TRUE(suspended);
902
903 // task2 is suspended
904 platform->ProcessTick();
905 CHECK_EQUAL(idle->SP, (Word)task2.GetStack());
906
907 // task2 is suspended
908 platform->ProcessTick();
909 CHECK_EQUAL(idle->SP, (Word)task2.GetStack());
910
911 // task1 is calling ResumeTask for task2
912 kernel.ResumeTask(&task2);
913
914 // task2 becomes active
915 platform->ProcessTick();
916 CHECK_EQUAL(active->SP, (Word)task2.GetStack());
917}
918
920{
922 TaskMock<ACCESS_USER> task1, task2;
923 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
924
925 kernel.Initialize();
926 kernel.AddTask(&task1, 1, 1, 0);
927 kernel.AddTask(&task2, 2, 1, 0);
928 kernel.Start();
929
930 platform->ProcessTick();
931 CHECK_EQUAL(platform->m_stack_active->SP, (Word)task2.GetStack());
932
933 platform->ProcessTick();
934 CHECK_EQUAL(platform->m_stack_active->SP, (Word)task1.GetStack());
935}
936
937TEST(Kernel, HrtAddNonHrt)
938{
941
942 kernel.Initialize();
943
944 try
945 {
946 g_TestContext.ExpectAssert(true);
947 kernel.AddTask(&task);
948 CHECK(false); // non-HRT AddTask not supported in HRT mode"
949 }
950 catch (TestAssertPassed &pass)
951 {
952 CHECK(true);
953 g_TestContext.ExpectAssert(false);
954 }
955}
956
957TEST(Kernel, HrtAddNotAllowedForNonHrtMode)
958{
961
962 kernel.Initialize();
963
964 try
965 {
966 g_TestContext.ExpectAssert(true);
967 kernel.AddTask(&task, 1, 1, 0);
968 CHECK(false); // HRT-related AddTask not supported in non-HRT mode
969 }
970 catch (TestAssertPassed &pass)
971 {
972 CHECK(true);
973 g_TestContext.ExpectAssert(false);
974 }
975}
976
977TEST(Kernel, HrtSleepNotAllowed)
978{
981
982 kernel.Initialize();
983 kernel.AddTask(&task, 1, 1, 0);
984 kernel.Start();
985
986 try
987 {
988 g_TestContext.ExpectAssert(true);
989 Sleep(1);
990 CHECK(false); // IKernelService::Sleep not allowed in HRT mode
991 }
992 catch (TestAssertPassed &pass)
993 {
994 CHECK(true);
995 g_TestContext.ExpectAssert(false);
996 }
997
998 try
999 {
1000 g_TestContext.ExpectAssert(true);
1001 SleepUntil(GetTicks() + 1);
1002 CHECK(false); // IKernelService::SleepUntil not allowed in HRT mode
1003 }
1004 catch (TestAssertPassed &pass)
1005 {
1006 CHECK(true);
1007 g_TestContext.ExpectAssert(false);
1008 }
1009}
1010
1011TEST(Kernel, HrtTaskCompleted)
1012{
1015 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
1016 const ITaskSwitchStrategy *strategy = kernel.GetSwitchStrategy();
1017
1018 kernel.Initialize();
1019 kernel.AddTask(&task, 1, 1, 0);
1020 kernel.Start();
1021
1022 CHECK_TRUE(strategy->GetSize() != 0);
1023
1024 platform->EventTaskExit(platform->m_stack_active);
1025 platform->ProcessTick();
1026
1027 platform->ProcessTick();
1028
1029 CHECK_EQUAL(0, strategy->GetSize());
1030
1031 CHECK_EQUAL(IKernel::STATE_READY, kernel.GetState());
1032}
1033
1035{
1037 {
1038 counter = 0;
1039 platform = NULL;
1040 }
1041
1042 uint32_t counter;
1044
1045 void Process()
1046 {
1047 platform->ProcessTick();
1048 ++counter;
1049 }
1050}
1052
1057
1058TEST(Kernel, HrtTaskDeadlineMissedRR)
1059{
1062 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
1063
1064 kernel.Initialize();
1065 kernel.AddTask(&task, 2, 1, 0);
1066 kernel.Start();
1067
1068 g_HrtTaskDeadlineMissedRelaxCpuContext.platform = platform;
1070
1071 platform->ProcessTick();
1072
1073 // task does not Yield() and thus next tick will overcome the deadline
1074 g_TestContext.ExpectAssert(true);
1075
1076 // 2-nd tick goes outside the deadline
1077 platform->ProcessTick();
1078
1079 CHECK_TRUE(platform->m_hard_fault);
1080 CHECK_EQUAL(2, task.m_deadline_missed);
1081}
1082
1083TEST(Kernel, HrtTaskDeadlineNotMissedRR)
1084{
1087 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
1088
1089 kernel.Initialize();
1090 kernel.AddTask(&task, 2, 1, 0);
1091 kernel.Start();
1092
1093 g_HrtTaskDeadlineMissedRelaxCpuContext.platform = platform;
1095
1096 platform->ProcessTick();
1097
1098 // task completes its work and yields to kernel, its workload is 1 ticks now that is within deadline 1
1099 Yield();
1100
1101 // 2-nd tick continues scheduling normally
1102 platform->ProcessTick();
1103
1104 CHECK_FALSE(platform->m_hard_fault);
1105 CHECK_EQUAL(0, task.m_deadline_missed);
1106}
1107
1108TEST(Kernel, HrtSkipSleepingNextRM)
1109{
1111 TaskMock<ACCESS_USER> task1, task2;
1112 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
1113
1114 kernel.Initialize();
1115 kernel.AddTask(&task1, 2, 2, 3);
1116 kernel.AddTask(&task2, 3, 3, 0);
1117 kernel.Start();
1118
1119 g_HrtTaskDeadlineMissedRelaxCpuContext.platform = platform;
1121
1122 CHECK_EQUAL(platform->m_stack_active->SP, (Word)task2.GetStack());
1123 platform->ProcessTick();
1124 CHECK_EQUAL(platform->m_stack_active->SP, (Word)task2.GetStack());
1125 platform->ProcessTick();
1126 Yield();
1127 CHECK_EQUAL(platform->m_stack_active->SP, (Word)task1.GetStack());
1128
1129 CHECK_FALSE(platform->m_hard_fault);
1130 CHECK_EQUAL(0, task1.m_deadline_missed);
1131 CHECK_EQUAL(0, task2.m_deadline_missed);
1132}
1133
1134template <class _SwitchStrategy>
1136{
1138 TaskMock<ACCESS_USER> task1, task2;
1139 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
1140 const _SwitchStrategy *strategy = static_cast<const _SwitchStrategy *>(kernel.GetSwitchStrategy());
1141
1142 kernel.Initialize();
1143 kernel.AddTask(&task1, 1, 2, 0);
1144 kernel.AddTask(&task2, 1, 2, 2);
1145 kernel.Start();
1146
1147 // task1 is the first
1148 CHECK_EQUAL((Word)task1.GetStack(), platform->m_stack_active->SP);
1149
1150 // task returns (exiting) without calling SwitchToNext
1151 platform->EventTaskExit(platform->m_stack_active);
1152
1153 platform->ProcessTick(); // schedules task removal but task2 is still sleeping
1154
1155 // here scheduler is sleeping because task1 was sent to infinite sleep until removal and task2 is still pending
1156
1157 platform->ProcessTick(); // task2 is still sleeping
1158 platform->ProcessTick(); // switched to task2
1159
1160 CHECK_EQUAL((Word)task2.GetStack(), platform->m_stack_active->SP);
1161
1162 CHECK_EQUAL(1, strategy->GetSize());
1163}
1164
1165TEST(Kernel, HrtTaskExitDuringSleepStateRR)
1166{
1168}
1169
1170TEST(Kernel, HrtTaskExitDuringSleepStateRM)
1171{
1173}
1174
1175TEST(Kernel, HrtTaskExitDuringSleepStateDM)
1176{
1178}
1179
1180TEST(Kernel, HrtTaskExitDuringSleepStateEDF)
1181{
1183}
1184
1185TEST(Kernel, HrtSleepingAwakeningStateChange)
1186{
1189 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
1190
1191 kernel.Initialize();
1192 kernel.AddTask(&task, 1, 1, 1);
1193 kernel.Start();
1194
1195 // due to 1 tick delayed start of the task Kernel enters into a SLEEPING state
1196 CHECK_EQUAL(platform->m_stack_active, platform->m_stack_info[STACK_SLEEP_TRAP].stack);
1197
1198 platform->ProcessTick();
1199
1200 // after a tick task become active and Kernel enters into a AWAKENING state
1201 CHECK_EQUAL(platform->m_stack_idle, platform->m_stack_info[STACK_SLEEP_TRAP].stack);
1202 CHECK_EQUAL(platform->m_stack_active->SP, (Word)task.GetStack());
1203}
1204
1205TEST(Kernel, HrtOnlyAPI)
1206{
1209
1210 kernel.Initialize();
1211 kernel.AddTask(&task);
1212 kernel.Start();
1213
1214 // Obtain kernel task
1215 IKernelTask *ktask = kernel.GetSwitchStrategy()->GetFirst();
1216 CHECK_TRUE_TEXT(ktask != nullptr, "Kernel task must exist");
1217
1218 try
1219 {
1220 g_TestContext.ExpectAssert(true);
1221 ktask->GetHrtRelativeDeadline();
1222 CHECK_TEXT(false, "HRT API can't be called in non-HRT mode");
1223 }
1224 catch (TestAssertPassed &pass)
1225 {
1226 CHECK(true);
1227 g_TestContext.ExpectAssert(false);
1228 }
1229
1230 try
1231 {
1232 g_TestContext.ExpectAssert(true);
1233 ktask->GetHrtPeriodicity();
1234 CHECK_TEXT(false, "HRT API can't be called in non-HRT mode");
1235 }
1236 catch (TestAssertPassed &pass)
1237 {
1238 CHECK(true);
1239 g_TestContext.ExpectAssert(false);
1240 }
1241
1242 try
1243 {
1244 g_TestContext.ExpectAssert(true);
1245 ktask->GetHrtDeadline();
1246 CHECK_TEXT(false, "HRT API can't be called in non-HRT mode");
1247 }
1248 catch (TestAssertPassed &pass)
1249 {
1250 CHECK(true);
1251 g_TestContext.ExpectAssert(false);
1252 }
1253}
1254
1255TEST(Kernel, SyncNotEnabledFailsOnWait)
1256{
1258 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
1260
1261 kernel.Initialize();
1262 kernel.AddTask(&task);
1263 kernel.Start();
1264
1265 try
1266 {
1267 g_TestContext.ExpectAssert(true);
1268 IKernelService::GetInstance()->Wait(nullptr, nullptr, 0);
1269 CHECK_TEXT(false, "kernel does not support waiting without KERNEL_SYNC");
1270 }
1271 catch (TestAssertPassed &pass)
1272 {
1273 CHECK(true);
1274 g_TestContext.ExpectAssert(false);
1275 }
1276
1277 // test return NULL
1278 g_TestContext.ExpectAssert(true);
1279 g_TestContext.RethrowAssertException(false);
1280 IWaitObject *wo = IKernelService::GetInstance()->Wait(nullptr, nullptr, 0);
1281 g_TestContext.RethrowAssertException(true);
1282 g_TestContext.ExpectAssert(false);
1283 CHECK_TRUE_TEXT(wo == nullptr, "expect NULL");
1284
1285 try
1286 {
1287 g_TestContext.ExpectAssert(true);
1288 platform->EventTaskWait(0, nullptr, nullptr, 0);
1289 CHECK_TEXT(false, "kernel does not support waiting without KERNEL_SYNC");
1290 }
1291 catch (TestAssertPassed &pass)
1292 {
1293 CHECK(true);
1294 g_TestContext.ExpectAssert(false);
1295 }
1296
1297 // test return NULL
1298 g_TestContext.ExpectAssert(true);
1299 g_TestContext.RethrowAssertException(false);
1300 wo = platform->EventTaskWait(0, nullptr, nullptr, 0);
1301 g_TestContext.RethrowAssertException(true);
1302 g_TestContext.ExpectAssert(false);
1303 CHECK_TRUE_TEXT(wo == nullptr, "expect NULL");
1304}
1305
1306TEST(Kernel, SyncNoNullSyncObj)
1307{
1310
1312
1313 kernel.Initialize();
1314 kernel.AddTask(&task);
1315 kernel.Start();
1316
1317 try
1318 {
1319 g_TestContext.ExpectAssert(true);
1320 IKernelService::GetInstance()->Wait(nullptr, &mutex, 10);
1321 CHECK_TEXT(false, "sync object must not be NULL");
1322 }
1323 catch (TestAssertPassed &pass)
1324 {
1325 CHECK(true);
1326 g_TestContext.ExpectAssert(false);
1327 }
1328}
1329
1330TEST(Kernel, SyncNoNullMutex)
1331{
1334
1335 SyncObjectMock sobj;
1336
1337 kernel.Initialize();
1338 kernel.AddTask(&task);
1339 kernel.Start();
1340
1341 try
1342 {
1343 g_TestContext.ExpectAssert(true);
1344 IKernelService::GetInstance()->Wait(&sobj, nullptr, 10);
1345 CHECK_TEXT(false, "mutex must not be NULL");
1346 }
1347 catch (TestAssertPassed &pass)
1348 {
1349 CHECK(true);
1350 g_TestContext.ExpectAssert(false);
1351 }
1352}
1353
1354TEST(Kernel, SyncNoZeroWait)
1355{
1358
1360 SyncObjectMock sobj;
1361
1362 kernel.Initialize();
1363 kernel.AddTask(&task);
1364 kernel.Start();
1365
1366 try
1367 {
1368 g_TestContext.ExpectAssert(true);
1369 IKernelService::GetInstance()->Wait(&sobj, &mutex, 0);
1370 CHECK_TEXT(false, "must not be zero wait");
1371 }
1372 catch (TestAssertPassed &pass)
1373 {
1374 CHECK(true);
1375 g_TestContext.ExpectAssert(false);
1376 }
1377}
1378
1379TEST(Kernel, SyncMutexMustBeLocked)
1380{
1383
1385 SyncObjectMock sobj;
1386
1387 kernel.Initialize();
1388 kernel.AddTask(&task);
1389 kernel.Start();
1390
1391 try
1392 {
1393 g_TestContext.ExpectAssert(true);
1394 IKernelService::GetInstance()->Wait(&sobj, &mutex, 10);
1395 CHECK_TEXT(false, "mutex must be locked");
1396 }
1397 catch (TestAssertPassed &pass)
1398 {
1399 CHECK(true);
1400 g_TestContext.ExpectAssert(false);
1401 }
1402}
1403
1404TEST(Kernel, SyncTaskExitAfterWait)
1405{
1407 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
1409
1411 SyncObjectMock sobj;
1412
1413 kernel.Initialize();
1414 kernel.AddTask(&task);
1415 kernel.Start();
1416
1417 {
1418 //MutexMock::ScopedLock guard(mutex);
1419
1420 //IKernelService::GetInstance()->Wait(&sobj, &mutex, 10);
1421 }
1422
1423 // task1 exited (will schedule its removal)
1424 platform->EventTaskExit(platform->m_stack_active);
1425
1426 platform->ProcessTick();
1427
1428 // should be still running here, next tick will result in task exit and kernel stop
1429 CHECK_EQUAL(IKernel::STATE_RUNNING, kernel.GetState());
1430
1431 platform->ProcessTick();
1432
1433 // should be stopped here
1434 CHECK_EQUAL(IKernel::STATE_READY, kernel.GetState());
1435}
1436
1438{
1440 {
1441 Reset();
1442 }
1443
1444 void Reset()
1445 {
1446 counter = 0;
1447 platform = NULL;
1448 check_tickless = ~0;
1449 }
1450
1451 uint32_t counter;
1454
1455 void Process()
1456 {
1457 platform->ProcessTick();
1458 ++counter;
1459
1460 // Wait object affects sleep_ticks, not a task
1461 if (counter == check_tickless)
1462 {
1463 CHECK_EQUAL(2, platform->m_ticks_count);
1464 }
1465 }
1466}
1468
1469static void SyncWaitRelaxCpu()
1470{
1471 g_SyncWaitRelaxCpuContext.Process();
1472}
1473
1474template <bool TTickless>
1476{
1478 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
1480
1482 SyncObjectMock sobj;
1483
1485 g_SyncWaitRelaxCpuContext.platform = platform;
1487
1488 kernel.Initialize();
1489 kernel.AddTask(&task);
1490 kernel.Start();
1491
1493
1495
1496 CHECK_EQUAL(GetTid(), wo->GetTid()); // expect the same thread id as WaitObject belongs to the caller's task
1497 CHECK_TRUE(wo != nullptr); // expect wait object in return after timeout
1498 CHECK_TRUE(wo->IsTimeout()); // expect timeout
1499 CHECK_EQUAL(2, g_SyncWaitRelaxCpuContext.counter); // expect 2 ticks after timeout
1500 CHECK_EQUAL(true, mutex.m_locked); // expect locked mutex after Wait return
1501}
1502
1503TEST(Kernel, SyncWait)
1504{
1506}
1507
1508TEST(Kernel, SyncWaitTickless)
1509{
1511}
1512
1513TEST(Kernel, SyncWaitTicklessDuration)
1514{
1516 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
1518
1520 SyncObjectMock sobj;
1521
1523 g_SyncWaitRelaxCpuContext.platform = platform;
1524 g_SyncWaitRelaxCpuContext.check_tickless = 0; // check first tick
1526
1527 kernel.Initialize();
1528 kernel.AddTask(&task);
1529 kernel.Start();
1530
1532
1533 // sleep_ticks should be equal to 2 on first OnTick call
1535
1536 // in total 4 ticks must be elapsed, including sleep ticks
1537 CHECK_EQUAL(4, platform->m_ticks_count);
1538
1539 // at this stage test should pass successfully by validating sleep_ticks in SyncWaitRelaxCpuContext::Process
1540
1541 CHECK_EQUAL(GetTid(), wo->GetTid());
1542 CHECK_TRUE(wo != nullptr);
1543 CHECK_TRUE(wo->IsTimeout());
1544 CHECK_EQUAL(3, g_SyncWaitRelaxCpuContext.counter);
1545 CHECK_EQUAL(true, mutex.m_locked);
1546}
1547
1548TEST(Kernel, EnumTasks)
1549{
1551 TaskMock<ACCESS_USER> task1, task2;
1552
1553 kernel.Initialize();
1554 kernel.AddTask(&task1);
1555 kernel.AddTask(&task2);
1556 kernel.Start();
1557
1558 ITask *tasks[2] = {};
1559 uint32_t i = 0;
1560
1561 size_t count = kernel.EnumerateTasksT<2>([&](ITask *t) {
1562 CHECK_COMPARE(i, <, 2);
1563 tasks[i++] = t;
1564 return true; // continue
1565 });
1566
1567 // must enumerate all
1568 CHECK_EQUAL(2, count);
1569
1570 // check ordering
1571 CHECK_EQUAL(tasks[0], &task1);
1572 CHECK_EQUAL(tasks[1], &task2);
1573
1574 // expect break of enumeration
1575 count = kernel.EnumerateTasksT<2>([&](ITask */*t*/) {
1576 return false; // break on first entry
1577 });
1578 CHECK_EQUAL(1, count);
1579
1580 // expect only 1 iteration
1581 count = kernel.EnumerateTasksT<1>([&](ITask */*t*/) {
1582 return true;
1583 });
1584 CHECK_EQUAL(1, count);
1585}
1586
1587TEST(Kernel, SuspendResumeTicklessOnly)
1588{
1591
1592 kernel.Initialize();
1593 kernel.AddTask(&task1);
1594 kernel.Start();
1595
1596 try
1597 {
1598 g_TestContext.ExpectAssert(true);
1600 CHECK_TEXT(false, "tickless only");
1601 }
1602 catch (TestAssertPassed &pass)
1603 {
1604 CHECK(true);
1605 g_TestContext.ExpectAssert(false);
1606 }
1607
1608 // shall return 0 in release build
1609 g_TestContext.ExpectAssert(true);
1610 g_TestContext.RethrowAssertException(false);
1611 CHECK_EQUAL(0, stk::IKernelService::GetInstance()->Suspend());
1612 g_TestContext.ExpectAssert(false);
1613 g_TestContext.RethrowAssertException(true);
1614
1615 try
1616 {
1617 g_TestContext.ExpectAssert(true);
1619 CHECK_TEXT(false, "tickless only");
1620 }
1621 catch (TestAssertPassed &pass)
1622 {
1623 CHECK(true);
1624 g_TestContext.ExpectAssert(false);
1625 }
1626}
1627
1628TEST(Kernel, SuspendResume)
1629{
1631 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
1633
1634 kernel.Initialize();
1635 kernel.AddTask(&task1);
1636 kernel.Start();
1637
1638 platform->m_sleep_ticks = 9;
1639
1641 CHECK_EQUAL(9, ticks);
1642
1643 CHECK_EQUAL(IKernel::STATE_SUSPENDED, kernel.GetState());
1644
1646}
1647
1648} // namespace stk
1649} // namespace test
void(* g_RelaxCpuHandler)()
__stk_relax_cpu handler.
Definition stktest.cpp:17
Namespace of STK package.
uintptr_t Word
Native processor word type.
Definition stk_common.h:113
void Sleep(Timeout ticks)
Put calling process into a sleep state.
Definition stk_helper.h:326
Ticks GetTicks()
Get number of ticks elapsed since kernel start.
Definition stk_helper.h:258
int32_t Timeout
Timeout time (ticks).
Definition stk_common.h:123
@ STACK_SLEEP_TRAP
Stack of the Sleep trap.
Definition stk_common.h:72
@ STACK_USER_TASK
Stack of the user task.
Definition stk_common.h:71
void Yield()
Notify scheduler to switch to the next runnable task.
Definition stk_helper.h:359
void SleepUntil(Ticks timestamp)
Put calling process into a sleep state until the specified timestamp.
Definition stk_helper.h:350
@ PERIODICITY_MAX
Maximum periodicity (microseconds), 99 milliseconds (note: this value is the highest working on a rea...
Definition stk_common.h:81
TId GetTid()
Get task/thread Id of the calling task.
Definition stk_helper.h:227
SwitchStrategyRoundRobin SwitchStrategyRR
Shorthand alias for SwitchStrategyRoundRobin.
@ ACCESS_USER
Unprivileged access mode (access to some hardware is restricted, see CPU manual for details).
Definition stk_common.h:32
@ ACCESS_PRIVILEGED
Privileged access mode (access to hardware is fully unrestricted).
Definition stk_common.h:33
@ KERNEL_TICKLESS
Tickless mode. To use this mode STK_TICKLESS_IDLE must be defined to 1 in stk_config....
Definition stk_common.h:45
@ KERNEL_SYNC
Synchronization support (see Event).
Definition stk_common.h:44
@ KERNEL_STATIC
All tasks are static and can not exit.
Definition stk_common.h:41
@ KERNEL_PANIC_BAD_MODE
Kernel is in bad/unsupported mode for the current operation.
Definition stk_common.h:62
@ KERNEL_PANIC_NONE
Panic is absent (no fault).
Definition stk_common.h:53
@ KERNEL_PANIC_BAD_STATE
Kernel entered unexpected (bad) state.
Definition stk_common.h:61
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.
Definition stktest.cpp:16
static void TaskSuspendRelaxCpu()
static void SyncWaitRelaxCpu()
static struct stk::test::AddTaskWhenStartedRelaxCpuContext g_AddTaskWhenStartedRelaxCpuContext
IKernelService * g_KernelService
Definition stktest.cpp:18
static struct stk::test::HrtTaskDeadlineMissedRelaxCpuContext g_HrtTaskDeadlineMissedRelaxCpuContext
EKernelPanicId g_PanicValue
Panic value.
Definition stktest.cpp:20
static void HrtTaskDeadlineMissedRelaxCpu()
static void TestTaskExit()
TEST_GROUP(Kernel)
static void AddTaskWhenStartedRelaxCpu()
static void TestHrtTaskExitDuringSleepState()
TEST(Kernel, MaxTasks)
Namespace of Mutex test.
Concrete implementation of IKernel.
Definition stk.h:81
void ResumeTask(ITask *user_task)
Resume task.
Definition stk.h:1006
void ScheduleTaskRemoval(ITask *user_task)
Schedule task removal from scheduling (exit).
Definition stk.h:945
bool UpdateFsmState(Stack *&idle, Stack *&active)
Update FSM state.
Definition stk.h:1817
EFsmState
Finite-state machine (FSM) state. Encodes what the kernel is currently doing between two consecutive ...
Definition stk.h:1100
@ FSM_STATE_NONE
Sentinel / uninitialized value. Set by the constructor, replaced by FSM_STATE_SWITCHING on the first ...
Definition stk.h:1101
@ FSM_STATE_MAX
Sentinel: number of valid states (used to size the FSM table), denotes uninitialized state.
Definition stk.h:1106
void SuspendTask(ITask *user_task, bool &suspended)
Suspend task.
Definition stk.h:971
EFsmState GetNewFsmState(KernelTask *&next)
Get new FSM state.
Definition stk.h:1806
void Initialize(uint32_t resolution_us=PERIODICITY_DEFAULT)
Initialize kernel.
Definition stk.h:832
EState GetState() const
Get kernel state.
Definition stk.h:1092
ITaskSwitchStrategy * GetSwitchStrategy()
Get task-switching strategy instance owned by this kernel.
Definition stk.h:1088
void Start()
Start the scheduler. This call does not return until all tasks have exited (KERNEL_DYNAMIC mode) or i...
Definition stk.h:1050
void RemoveTask(ITask *user_task)
Remove a previously added task from the kernel before Start().
Definition stk.h:922
KernelTask * m_task_now
Currently executing task, or nullptr before Start() or after all tasks exit.
Definition stk.h:2102
static constexpr uint32_t TASKS_MAX
Maximum number of concurrently registered tasks. Fixed at compile time. Exceeding this limit in AddTa...
Definition stk.h:789
IPlatform * GetPlatform()
Get platform driver instance owned by this kernel.
Definition stk.h:1083
Kernel()
Construct the kernel with all storage zero-initialized and the request flag set to ~0 (indicating uni...
Definition stk.h:798
void AddTask(ITask *user_task)
Register task for a soft real-time (SRT) scheduling.
Definition stk.h:859
Internal per-slot kernel descriptor that wraps a user ITask instance.
Definition stk.h:117
Stack descriptor.
Definition stk_common.h:219
Word SP
Stack Pointer (SP) register (note: must be the first entry in this struct).
Definition stk_common.h:220
EAccessMode mode
Hardware access mode of the owning task (see EAccessMode).
Definition stk_common.h:221
Wait object.
Definition stk_common.h:270
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 ...
Definition stk_common.h:447
Interface for a user task.
Definition stk_common.h:491
Scheduling-strategy-facing interface for a kernel task slot.
Definition stk_common.h:562
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.
Definition stk_common.h:648
Interface for a task switching strategy implementation.
Definition stk_common.h:889
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 ...
Definition stk_common.h:961
@ STATE_INACTIVE
Not ready, IKernel::Initialize() must be called.
Definition stk_common.h:968
@ STATE_READY
Ready to start, IKernel::Start() must be called.
Definition stk_common.h:969
@ STATE_SUSPENDED
Scheduling is suspended with IKernelService::Suspend().
Definition stk_common.h:971
@ STATE_RUNNING
Initialized and running, IKernel::Start() was called successfully.
Definition stk_common.h:970
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.
Definition stktest.cpp:69
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.
Definition stk_helper.h:54
BaseType::EFsmState GetNewFsmState(typename BaseType::KernelTask *&next) override
Kernel< TMode, TSize, TStrategy, TPlatform > BaseType
void ForceUpdateInvalidFsmState(bool max_val)
Throwable class for catching assertions from STK_ASSERT_HANDLER().
Definition stktest.h:67
IPlatform mock.
Definition stktest.h:75
void EventTaskSwitch(size_t caller_SP)
Definition stktest.h:226
void ProcessTick()
Process one tick.
Definition stktest.h:193
void EventTaskExit(Stack *stack)
Definition stktest.h:221
IWaitObject * EventTaskWait(size_t caller_SP, ISyncObject *sync_obj, IMutex *mutex, Timeout timeout)
Definition stktest.h:236
IKernelService * m_service
Definition stktest.h:262
StackInfo m_stack_info[STACK_EXIT_TRAP+1]
Definition stktest.h:274
uint32_t GetTickResolution() const
Get resolution of the system tick timer in microseconds. Resolution means a number of microseconds be...
Definition stktest.h:152
uint32_t m_deadline_missed
duration of workload if deadline is missed in HRT mode
Definition stktest.h:388