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_kernelservice.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// =+========================= KernelService ================================== //
17// ============================================================================ //
18
19TEST_GROUP(KernelService)
20{
21 void setup() {}
22 void teardown()
23 {
24 g_RelaxCpuHandler = NULL;
25 }
26};
27
28TEST(KernelService, GetMsecToTicks)
29{
31 mock.m_ticks = 1;
32
33 mock.m_resolution = 1000;
34 CHECK_EQUAL(10, (int32_t)GetMsFromTicks(10, mock.GetTickResolution()));
35
36 mock.m_resolution = 10000;
37 CHECK_EQUAL(100, (int32_t)GetMsFromTicks(10, mock.GetTickResolution()));
38}
39
40static struct DelayContext
41{
43 {
44 Clear();
45 }
46
48
49 void Clear()
50 {
51 platform = nullptr;
52 }
53
54 void Process()
55 {
56 platform->ProcessTick();
57 }
58}
60
61static void DelayRelaxCpu()
62{
63 g_DelayContext.Process();
64}
65
66TEST(KernelService, Delay)
67{
70
71 kernel.Initialize();
72 kernel.AddTask(&task);
73 kernel.Start();
74
76 g_DelayContext.platform = kernel.GetPlatform();
77
78 Delay(10);
79
80 g_RelaxCpuHandler = NULL;
81
82 CHECK_EQUAL(10, (int32_t)g_KernelService->GetTicks());
83}
84
85TEST(KernelService, DelayMs)
86{
89
90 kernel.Initialize(2000); // decrease resolution to 1 tick = 2 ms
91 kernel.AddTask(&task);
92 kernel.Start();
93
95 g_DelayContext.platform = kernel.GetPlatform();
96
97 DelayMs(10);
98
99 g_RelaxCpuHandler = NULL;
100
101 CHECK_EQUAL(5, (int32_t)g_KernelService->GetTicks());
102}
103
104TEST(KernelService, InitStackFailure)
105{
108 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
109 platform->m_fail_InitStack = true;
110
111 try
112 {
113 g_TestContext.ExpectAssert(true);
114 kernel.Initialize();
115 kernel.AddTask(&task);
116 CHECK_TEXT(false, "AddTask() did not fail");
117 }
118 catch (TestAssertPassed &pass)
119 {
120 CHECK(true);
121 g_TestContext.ExpectAssert(false);
122 }
123}
124
125TEST(KernelService, GetTid)
126{
129 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
130
131 kernel.Initialize();
132 kernel.AddTask(&task);
133 kernel.Start();
134
135 platform->ProcessTick();
136
137 // task/thread id is a pointer to the user task
138 size_t tid = stk::GetTid();
139 CHECK_EQUAL(tid, (size_t)&task);
140}
141
142TEST(KernelService, GetTickResolution)
143{
146 const uint32_t periodicity = PERIODICITY_DEFAULT + 1;
147
148 kernel.Initialize(periodicity);
149 kernel.AddTask(&task);
150 kernel.Start();
151
152 CHECK_EQUAL(periodicity, g_KernelService->GetTickResolution());
153 CHECK_EQUAL(periodicity, stk::GetTickResolution());
154}
155
156TEST(KernelService, GetTicks)
157{
159 TaskMock<ACCESS_USER> task1, task2;
160 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
161
163 kernel.AddTask(&task1);
164 kernel.AddTask(&task2);
165 kernel.Start();
166
167 // ISR calls OnSysTick 1-st time
168 platform->ProcessTick();
169 CHECK_EQUAL(1, (int32_t)g_KernelService->GetTicks());
170 CHECK_EQUAL(1, (int32_t)stk::GetTicks());
171
172 // ISR calls OnSysTick 2-nd time
173 platform->ProcessTick();
174 CHECK_EQUAL(2, (int32_t)g_KernelService->GetTicks());
175 CHECK_EQUAL(2, (int32_t)stk::GetTicks());
176}
177
178TEST(KernelService, GetTimeNowMs)
179{
182 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
183
185 kernel.AddTask(&task1);
186 kernel.Start();
187
188 CHECK_EQUAL(0, (int32_t)stk::GetTimeNowMs());
189
190 // make 1000 ticks
191 for (int32_t i = 0; i < 1000; ++i)
192 platform->ProcessTick();
193
194 // 1000 usec * 1000 ticks = 1000 ms
195 CHECK_EQUAL(1000, (int32_t)stk::GetTimeNowMs());
196}
197
198TEST(KernelService, GetTimeNowMsWith10UsecTick)
199{
202 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
203
204 // set periodicity to 10 microsecond
205 kernel.Initialize(10);
206 kernel.AddTask(&task1);
207 kernel.Start();
208
209 CHECK_EQUAL(0, (int32_t)stk::GetTimeNowMs());
210
211 // make 1000 ticks
212 for (int32_t i = 0; i < 1000; ++i)
213 platform->ProcessTick();
214
215 // 10 usec * 1000 ticks = 10 ms
216 CHECK_EQUAL(10, (int32_t)stk::GetTimeNowMs());
217}
218
220{
222 {
223 Clear();
224 }
225
226 void Clear()
227 {
228 counter = 0;
229 platform = NULL;
230 task1 = NULL;
231 task2 = NULL;
232 }
233
234 uint32_t counter;
237
238 void Process()
239 {
240 Stack *&active = platform->m_stack_active;
241
242 platform->ProcessTick();
243
244 if ((task1 != nullptr) && (task2 != nullptr))
245 {
246 // ISR calls OnSysTick (task1 = active, task2 = idle)
247 if (counter == 0)
248 {
249 CHECK_EQUAL(active->SP, (size_t)task1->GetStack());
250 }
251 else
252 // ISR calls OnSysTick (task1 = idle, task2 = active)
253 if (counter == 1)
254 {
255 CHECK_EQUAL(active->SP, (size_t)task2->GetStack());
256 }
257 else
258 // ISR calls OnSysTick (task1 = active, task2 = idle)
259 if (counter == 2)
260 {
261 CHECK_EQUAL(active->SP, (size_t)task1->GetStack());
262 }
263 else
264 // ISR calls OnSysTick (task1 = idle, task2 = active)
265 if (counter == 3)
266 {
267 CHECK_EQUAL(active->SP, (size_t)task2->GetStack());
268 }
269 }
270
271 ++counter;
272 }
273}
275
277{
279}
280
281TEST(KernelService, SwitchToNext)
282{
284 TaskMock<ACCESS_USER> task1, task2;
285 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
286 Stack *&active = platform->m_stack_active;
287
288 kernel.Initialize();
289 kernel.AddTask(&task1);
290 kernel.AddTask(&task2);
291 kernel.Start();
292
293 // task1 is scheduled first by RR
294 CHECK_EQUAL(active->SP, (size_t)task1.GetStack());
295
296 // ISR calls OnSysTick (task1 = idle, task2 = active)
297 platform->ProcessTick();
298 CHECK_EQUAL(active->SP, (size_t)task2.GetStack());
299
302 g_SwitchToNextRelaxCpuContext.platform = platform;
303 g_SwitchToNextRelaxCpuContext.task1 = &task1;
304 g_SwitchToNextRelaxCpuContext.task2 = &task2;
305
306 // task1 calls SwitchToNext (to test path: IKernelService::SwitchToNext -> IPlatform::SwitchToNext -> Kernel::SwitchToNext)
307 Yield();
308 CHECK_EQUAL(1, platform->m_switch_to_next_nr);
309
310 // task2 is active again
311 CHECK_EQUAL(active->SP, (size_t)task2.GetStack());
312
313 // task2 calls SwitchToNext
314 platform->EventTaskSwitch(active->SP);
315
316 // task1 calls SwitchToNext (task1 = active, task2 = idle)
317 platform->EventTaskSwitch(active->SP + 1); // add shift to test IsMemoryOfSP
318
319 // after a switch task 2 is active again
320 CHECK_EQUAL(active->SP, (size_t)task2.GetStack());
321}
322
323TEST(KernelService, SwitchToNextInactiveTask)
324{
326 TaskMock<ACCESS_USER> task1, task2;
327 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
328 Stack *&active = platform->m_stack_active;
329
330 kernel.Initialize();
331 kernel.AddTask(&task1);
332 kernel.AddTask(&task2);
333 kernel.Start();
334
335 // task1 is scheduled first by RR
336 CHECK_EQUAL(active->SP, (size_t)task1.GetStack());
337
338 // ISR calls OnSysTick (task1 = idle, task2 = active)
339 platform->ProcessTick();
340 CHECK_EQUAL(active->SP, (size_t)task2.GetStack());
341
344 g_SwitchToNextRelaxCpuContext.platform = platform;
345 g_SwitchToNextRelaxCpuContext.task1 = nullptr;
346 g_SwitchToNextRelaxCpuContext.task2 = nullptr;
347
348 platform->EventTaskSwitch(platform->m_stack_idle->SP + 1); // add shift to test IsMemoryOfSP
349}
350
352{
354 {
355 Clear();
356 }
357
358 void Clear()
359 {
360 counter = 0;
361 platform = NULL;
362 task1 = NULL;
363 task2 = NULL;
364 }
365
366 uint32_t counter;
369
370 void Process()
371 {
372 Stack *&active = platform->m_stack_active;
373
374 platform->ProcessTick();
375
376 // ISR calls OnSysTick (task1 = active, task2 = idle)
377 if (counter == 0)
378 {
379 CHECK_EQUAL_TEXT(active->SP, (size_t)task1->GetStack(), "sleep: expecting task1");
380 }
381 else
382 // ISR calls OnSysTick (task1 = idle, task2 = active)
383 if (counter == 1)
384 {
385 CHECK_EQUAL_TEXT(active->SP, (size_t)task2->GetStack(), "sleep: expecting task2");
386 }
387
388 ++counter;
389 }
390}
392
393static void SleepRelaxCpu()
394{
395 g_SleepRelaxCpuContext.Process();
396}
397
398template <class _SwitchStrategy>
399static void TestTaskSleep(bool until)
400{
402 TaskMock<ACCESS_USER> task1, task2;
403 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
404 Stack *&active = platform->m_stack_active;
405
406 kernel.Initialize();
407 kernel.AddTask(&task1);
408 kernel.AddTask(&task2);
409 kernel.Start();
410
411 // on start Round-Robin selects the very first task
412 CHECK_EQUAL_TEXT(active->SP, (size_t)task1.GetStack(), "expecting task1");
413
414 // ISR calls OnSysTick (task1 = idle, task2 = active)
415 platform->ProcessTick();
416 CHECK_EQUAL_TEXT(active->SP, (size_t)task2.GetStack(), "expecting task2");
417
420 g_SleepRelaxCpuContext.platform = platform;
421 g_SleepRelaxCpuContext.task1 = &task1;
422 g_SleepRelaxCpuContext.task2 = &task2;
423
424 // task2 calls Sleep to become idle
425 if (until)
426 {
427 SleepUntil(GetTicks() + 2);
428 }
429 else
430 {
431 Sleep(2);
432 }
433
434 // task2 slept 2 ticks and became active again when became a tail of previously active task1
435 CHECK_EQUAL_TEXT(active->SP, (size_t)task2.GetStack(), "expecting task2 after sleep");
436
437 // ISR calls OnSysTick (task1 = active, task2 = idle)
438 platform->ProcessTick();
439 CHECK_EQUAL_TEXT(active->SP, (size_t)task1.GetStack(), "expecting task1 after next tick");
440}
441
442TEST(KernelService, SleepRR)
443{
445}
446
447TEST(KernelService, SleepSWRR)
448{
450}
451
452TEST(KernelService, SleepFP31)
453{
455}
456
457TEST(KernelService, SleepUntilRR)
458{
460}
461
462TEST(KernelService, SleepUntilSWRR)
463{
465}
466
467TEST(KernelService, SleepUntilFP31)
468{
470}
471
472TEST(KernelService, SleepMsRR)
473{
475 TaskMock<ACCESS_USER> task1, task2;
476 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
477 Stack *&active = platform->m_stack_active;
478
479 kernel.Initialize();
480 kernel.AddTask(&task1);
481 kernel.AddTask(&task2);
482 kernel.Start();
483
484 // on start Round-Robin selects the very first task
485 CHECK_EQUAL_TEXT(active->SP, (size_t)task1.GetStack(), "expecting task1");
486
487 // ISR calls OnSysTick (task1 = idle, task2 = active)
488 platform->ProcessTick();
489 CHECK_EQUAL_TEXT(active->SP, (size_t)task2.GetStack(), "expecting task2");
490
493 g_SleepRelaxCpuContext.platform = platform;
494 g_SleepRelaxCpuContext.task1 = &task1;
495 g_SleepRelaxCpuContext.task2 = &task2;
496
497 // task2 calls Sleep to become idle
498 SleepMs(2);
499
500 // task2 slept 2 ticks and became active again when became a tail of previously active task1
501 CHECK_EQUAL_TEXT(active->SP, (size_t)task2.GetStack(), "expecting task2 after sleep");
502
503 // ISR calls OnSysTick (task1 = active, task2 = idle)
504 platform->ProcessTick();
505 CHECK_EQUAL_TEXT(active->SP, (size_t)task1.GetStack(), "expecting task1 after next tick");
506}
507
508TEST(KernelService, SleepUntilMissDeadline)
509{
511 TaskMock<ACCESS_USER> task1, task2;
512 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
513 Stack *&active = platform->m_stack_active;
514
515 kernel.Initialize();
516 kernel.AddTask(&task1);
517 kernel.AddTask(&task2);
518 kernel.Start();
519
520 // on start Round-Robin selects the very first task
521 CHECK_EQUAL_TEXT(active->SP, (size_t)task1.GetStack(), "expecting task1");
522
523 // ISR calls OnSysTick (task1 = idle, task2 = active)
524 platform->ProcessTick();
525 CHECK_EQUAL_TEXT(active->SP, (size_t)task2.GetStack(), "expecting task2");
526
529 g_SleepRelaxCpuContext.platform = platform;
530 g_SleepRelaxCpuContext.task1 = &task1;
531 g_SleepRelaxCpuContext.task2 = &task2;
532
533 Ticks now = GetTicks();
534
535 // task2 calls Sleep to become idle
536 SleepUntil(now);
537
538 CHECK_EQUAL(now, GetTicks());
539
540 // task2 is still active as it did not sleep
541 CHECK_EQUAL_TEXT(active->SP, (size_t)task2.GetStack(), "expecting task2 after sleep");
542}
543
545{
547 {
548 counter = 0;
549 platform = NULL;
550 task1 = NULL;
551 }
552
553 uint32_t counter;
556
557 void Process()
558 {
559 Stack *&idle = platform->m_stack_idle, *&active = platform->m_stack_active;
560
561 platform->ProcessTick();
562
563 // ISR calls OnSysTick (task1 = idle, sleep_trap = active)
564 if (counter == 0)
565 {
566 CHECK_EQUAL(idle->SP, (size_t)task1->GetStack());
567 CHECK_EQUAL(active->SP, (size_t)platform->m_stack_info[STACK_SLEEP_TRAP].stack->SP);
568 }
569 else
570 if (counter == 1)
571 {
572 // to check FSM_STATE_NONE case
573 }
574 else
575 // ISR calls OnSysTick (task1 = active, sleep_trap = idle)
576 if (counter == 2)
577 {
578 CHECK_EQUAL(active->SP, (size_t)task1->GetStack());
579 CHECK_EQUAL(idle->SP, (size_t)platform->m_stack_info[STACK_SLEEP_TRAP].stack->SP);
580 }
581
582 ++counter;
583 }
584}
586
588{
590}
591
592TEST(KernelService, SleepAllAndWake)
593{
596
597 kernel.Initialize();
598 kernel.AddTask(&task);
599 kernel.Start();
600
602 g_SleepAllAndWakeRelaxCpuContext.platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
604
605 // task1 calls Sleep
606 Sleep(3);
607}
608
610{
612 {
613 counter = 0;
614 platform = NULL;
615 }
616
617 uint32_t counter;
619
620 void Process()
621 {
622 platform->ProcessTick();
623
624 if (counter == 0)
625 {
626 // expecting 2 sleep ticks (Sleep(3) = 1 + 2
627 CHECK_EQUAL(2, platform->m_ticks_count);
628 }
629
630 ++counter;
631 }
632}
634
639
640TEST(KernelService, SleepAndWakeTickless)
641{
644 PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
645
646 kernel.Initialize();
647 kernel.AddTask(&task);
648 kernel.Start();
649
651 g_SleepAndWakeTicklessRelaxCpuContext.platform = platform;
652
653 // task1 calls Sleep
654 Sleep(3);
655
656 // expect 4 ticks (1 + 3 sleep)
657 CHECK_EQUAL(4, platform->m_ticks_count);
658
659 // expect only 2 context switches (1st: Task=Idle, SleepCtx=Active, 2nd: Task=Active, SleepCtx=Idle)
660 CHECK_EQUAL(2, platform->m_context_switch_nr);
661}
662
663// ============================================================================ //
664// =+==================== KernelServiceIsrSafety ============================== //
665// ============================================================================ //
666
667TEST_GROUP(KernelServiceIsrSafety)
668{
669 void setup()
670 {
672 g_InsideISR = true;
673 }
674 void teardown()
675 {
676 g_InsideISR = false;
677 g_DelayContext.Clear();
678 g_RelaxCpuHandler = NULL;
679 }
680};
681
682TEST(KernelServiceIsrSafety, Common)
683{
686
687 kernel.Initialize();
688 kernel.AddTask(&task);
689 kernel.Start();
690
691 g_DelayContext.platform = kernel.GetPlatform();
692
693 try
694 {
695 g_TestContext.ExpectAssert(true);
696 Sleep(10);
697 CHECK_TEXT(false, "Sleep is not allowed inside ISR");
698 }
699 catch (TestAssertPassed &pass)
700 {
701 CHECK(true);
702 g_TestContext.ExpectAssert(false);
703 }
704
705 try
706 {
707 g_TestContext.ExpectAssert(true);
708 SleepUntil(GetTicks() + 10);
709 CHECK_TEXT(false, "SleepUntil is not allowed inside ISR");
710 }
711 catch (TestAssertPassed &pass)
712 {
713 CHECK(true);
714 g_TestContext.ExpectAssert(false);
715 }
716
717 try
718 {
719 g_TestContext.ExpectAssert(true);
720 Delay(10);
721 CHECK_TEXT(false, "Delay is not allowed inside ISR");
722 }
723 catch (TestAssertPassed &pass)
724 {
725 CHECK(true);
726 g_TestContext.ExpectAssert(false);
727 }
728
729 try
730 {
731 g_TestContext.ExpectAssert(true);
732 Yield();
733 CHECK_TEXT(false, "Yield is not allowed inside ISR");
734 }
735 catch (TestAssertPassed &pass)
736 {
737 CHECK(true);
738 g_TestContext.ExpectAssert(false);
739 }
740
741 try
742 {
743 g_TestContext.ExpectAssert(true);
744 GetTid();
745 CHECK_TEXT(false, "GetTid is not allowed inside ISR");
746 }
747 catch (TestAssertPassed &pass)
748 {
749 CHECK(true);
750 g_TestContext.ExpectAssert(false);
751 }
752}
753
754} // namespace stk
755} // namespace test
void(* g_RelaxCpuHandler)()
__stk_relax_cpu handler.
Definition stktest.cpp:17
Namespace of STK package.
static int64_t GetTimeNowMs()
Get current time in milliseconds since kernel start.
Definition stk_helper.h:281
void Sleep(uint32_t ticks)
Put calling process into a sleep state.
Definition stk_helper.h:298
static void DelayMs(uint32_t ms)
Delay calling process by busy-waiting until the deadline expires.
Definition stk_helper.h:353
int64_t GetMsFromTicks(int64_t ticks, int32_t resolution)
Convert ticks to milliseconds.
Definition stk_helper.h:228
Ticks GetTicks()
Get number of ticks elapsed since kernel start.
Definition stk_helper.h:248
int64_t Ticks
Ticks value.
Definition stk_common.h:150
@ STACK_SLEEP_TRAP
Stack of the Sleep trap.
Definition stk_common.h:72
void Yield()
Notify scheduler to switch to the next runnable task.
Definition stk_helper.h:331
void Delay(uint32_t ticks)
Delay calling process by busy-waiting until the deadline expires.
Definition stk_helper.h:342
void SleepUntil(Ticks timestamp)
Put calling process into a sleep state until the specified timestamp.
Definition stk_helper.h:322
@ PERIODICITY_DEFAULT
Default periodicity (microseconds), 1 millisecond.
Definition stk_common.h:82
TId GetTid()
Get task/thread Id of the calling task.
Definition stk_helper.h:217
int32_t GetTickResolution()
Get number of microseconds in one tick.
Definition stk_helper.h:258
static void SleepMs(uint32_t ms)
Put calling process into a sleep state.
Definition stk_helper.h:311
Namespace of the test inventory.
TestContext g_TestContext
Global instance of the TestContext.
Definition stktest.cpp:16
static void SleepAndWakeTicklessRelaxCpu()
static struct stk::test::SwitchToNextRelaxCpuContext g_SwitchToNextRelaxCpuContext
static void SwitchToNextRelaxCpu()
IKernelService * g_KernelService
Definition stktest.cpp:18
static void SleepAllAndWakeRelaxCpu()
static void SleepRelaxCpu()
static struct stk::test::SleepAndWakeTicklessRelaxCpuContext g_SleepAndWakeTicklessRelaxCpuContext
bool g_InsideISR
ISR state.
Definition stktest.cpp:21
TEST_GROUP(Kernel)
static void DelayRelaxCpu()
static struct stk::test::DelayContext g_DelayContext
static struct stk::test::SleepAllAndWakeRelaxCpuContext g_SleepAllAndWakeRelaxCpuContext
TEST(Kernel, MaxTasks)
static struct stk::test::SleepRelaxCpuContext g_SleepRelaxCpuContext
static void TestTaskSleep(bool until)
Concrete implementation of IKernel.
Definition stk.h:83
void Initialize(uint32_t resolution_us=PERIODICITY_DEFAULT)
Prepare kernel for use: reset state, configure the platform, and register the service singleton.
Definition stk.h:805
void Start()
Start the scheduler. This call does not return until all tasks have exited (KERNEL_DYNAMIC mode) or i...
Definition stk.h:921
IPlatform * GetPlatform()
Get platform driver instance owned by this kernel.
Definition stk.h:954
void AddTask(ITask *user_task)
Register task for a soft real-time (SRT) scheduling.
Definition stk.h:832
Stack descriptor.
Definition stk_common.h:181
Word SP
Stack Pointer (SP) register (note: must be the first entry in this struct).
Definition stk_common.h:182
Interface for a platform driver.
Definition stk_common.h:575
Word * GetStack() const
Get pointer to the stack memory.
Definition stk_helper.h:54
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:213
void ProcessTick()
Process one tick.
Definition stktest.h:180
IKernelService mock.
Definition stktest.h:260
int32_t GetTickResolution() const
Get number of microseconds in one tick.
Definition stktest.h:286