tests: arch: add a test case for testing arch_nop() interface
Add a test case to test arch interface arch_nop(), the main focus here is for coverage of the code. arch_nop() is a special implementation and it will behave differently on different platforms. By the way, this also measures how many cycles it spends for platforms that support it. Signed-off-by: Enjia Mai <enjiax.mai@intel.com>
This commit is contained in:
parent
4d994af032
commit
e92ca60b4e
|
@ -60,3 +60,110 @@ void test_irq_offload(void)
|
|||
zassert_equal(sentinel, SENTINEL_VALUE,
|
||||
"irq_offload() didn't work properly");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test the arch_nop() by invoking and measure it.
|
||||
*
|
||||
* @details This test is mainly for coverage of the code. arch_nop()
|
||||
* is a special implementation and it will behave differently on
|
||||
* different platforms. By the way, this also measures how many
|
||||
* cycles it spends for platforms that support it.
|
||||
*
|
||||
* FYI: The potential uses of arch_nop() could be:
|
||||
* - Code alignment: Although in this case it's much more likely the
|
||||
* compiler doing so (or you're in an assembly file, in which case
|
||||
* you're not calling arch_nop() anyway). And this would require
|
||||
* that arch_nop() be ALWAYS_INLINE.
|
||||
* - Giving you a guaranteed place to put a breakpoint / trace trigger
|
||||
* / etc. when debugging. This is on main usage of arch_nop(); it
|
||||
* inherently is generally debugging code removed before actually
|
||||
* pushing.
|
||||
* - Giving you a guaranteed place to put a patchpoint. E.g. ARMv7
|
||||
* allows nop (and a few other instructions) to be modified
|
||||
* concurrently with execution, but not most other instructions.
|
||||
* - Delaying a few instructions, e.g. for tight timing loops on
|
||||
* M-cores.
|
||||
*
|
||||
* Our test here mainly aims at the 4th scenario mentioned above but
|
||||
* also potentially tests the 1st scenario. So no optimization here to
|
||||
* prevent arch_nop() has optimized by the compiler is necessary.
|
||||
*
|
||||
* @ingroup kernel_common_tests
|
||||
*
|
||||
* @see arch_nop()
|
||||
*/
|
||||
__no_optimization void test_nop(void)
|
||||
{
|
||||
uint32_t t_get_time, t_before, t_after, diff;
|
||||
|
||||
t_before = k_cycle_get_32();
|
||||
t_after = k_cycle_get_32();
|
||||
|
||||
/* calculate time spent between two k_cycle_get_32() call */
|
||||
t_get_time = t_after - t_before;
|
||||
|
||||
printk("time k_cycle_get_32() takes %d cycles\n", t_get_time);
|
||||
|
||||
/*
|
||||
* If two k_cycle_get_32() call take zero cycle here, this
|
||||
* means it cannot comes out a correct result, in these
|
||||
* case, we skip this test, such as native posix.
|
||||
*/
|
||||
if (t_get_time == 0) {
|
||||
ztest_test_skip();
|
||||
}
|
||||
|
||||
t_before = k_cycle_get_32();
|
||||
|
||||
arch_nop();
|
||||
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
/* do 4 nop instructions to cost cycles */
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
#elif defined(CONFIG_ARC)
|
||||
/* do 8 nop instructions to cost cycles */
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
#elif defined(CONFIG_SPARC)
|
||||
/* do 9 nop instructions to cost cycles */
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
arch_nop();
|
||||
#elif defined(CONFIG_ARMV8_A)
|
||||
/* the ARMv8-A ARM states the following:
|
||||
* No Operation does nothing, other than advance the value of
|
||||
* the program counter by 4. This instruction can be used for
|
||||
* instruction alignment purposes.
|
||||
* Note: The timing effects of including a NOP instruction in
|
||||
* a program are not guaranteed. It can increase execution time
|
||||
* ,leave it unchanged, or even reduce it. Therefore, NOP
|
||||
* instructions are not suitable for timing loops.
|
||||
*
|
||||
* So we skip the this test, it will get a negative cycles.
|
||||
*/
|
||||
ztest_test_skip();
|
||||
#endif
|
||||
|
||||
t_after = k_cycle_get_32();
|
||||
|
||||
/* Calculate delta time of arch_nop(). */
|
||||
diff = t_after - t_before - t_get_time;
|
||||
printk("arch_nop() takes %d cycles\n", diff);
|
||||
|
||||
/* An arch_nop() call should spend actual cpu cycles */
|
||||
zassert_true(diff > 0,
|
||||
"arch_nop() takes %d cpu cycles", diff);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ extern void test_bitarray_declare(void);
|
|||
extern void test_bitarray_set_clear(void);
|
||||
extern void test_bitarray_alloc_free(void);
|
||||
extern void test_bitarray_region_set_clear(void);
|
||||
extern void test_nop(void);
|
||||
|
||||
/**
|
||||
* @defgroup kernel_common_tests Common Tests
|
||||
|
@ -160,7 +161,8 @@ void test_main(void)
|
|||
ztest_unit_test(test_thread_context),
|
||||
ztest_user_unit_test(test_errno),
|
||||
ztest_unit_test(test_ms_time_duration),
|
||||
ztest_unit_test(test_bounds_check_mitigation)
|
||||
ztest_unit_test(test_bounds_check_mitigation),
|
||||
ztest_unit_test(test_nop)
|
||||
);
|
||||
|
||||
ztest_run_test_suite(common);
|
||||
|
|
Loading…
Reference in a new issue