tests/kernel/common: Extend nested_irq_offload case to do a context switch
Bug #45779 discovered an edge case with nested interrupts on Xtensa where they might select an incorrect thread context to return to instead of the (mandatory!) return to the outer interrupt context. Cleverly adjust the nested_irq_offload to exercise this. It now creates a thread that it knows it will interrupt, then suspends that thread from within the inner/nested interrupt. This guarantees that _current will be different on exit from the second interrupt, which is the case that tripped up Xtensa. Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
parent
58eb132d06
commit
4b9a8a8471
2 changed files with 30 additions and 3 deletions
|
@ -20,6 +20,9 @@
|
||||||
volatile uint32_t sentinel;
|
volatile uint32_t sentinel;
|
||||||
#define SENTINEL_VALUE 0xDEADBEEF
|
#define SENTINEL_VALUE 0xDEADBEEF
|
||||||
|
|
||||||
|
K_THREAD_STACK_DEFINE(offload_stack, 384 + CONFIG_TEST_EXTRA_STACK_SIZE);
|
||||||
|
struct k_thread offload_thread;
|
||||||
|
|
||||||
static void offload_function(const void *param)
|
static void offload_function(const void *param)
|
||||||
{
|
{
|
||||||
uint32_t x = POINTER_TO_INT(param);
|
uint32_t x = POINTER_TO_INT(param);
|
||||||
|
@ -198,6 +201,9 @@ static bool timer_executed, nested_executed;
|
||||||
|
|
||||||
void nestoff_offload(const void *parameter)
|
void nestoff_offload(const void *parameter)
|
||||||
{
|
{
|
||||||
|
/* Suspend the thread we interrupted so we context switch, see below */
|
||||||
|
k_thread_suspend(&offload_thread);
|
||||||
|
|
||||||
nested_executed = true;
|
nested_executed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,6 +220,14 @@ static void nestoff_timer_fn(struct k_timer *timer)
|
||||||
timer_executed = true;
|
timer_executed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void offload_thread_fn(void *p0, void *p1, void *p2)
|
||||||
|
{
|
||||||
|
k_timer_start(&nestoff_timer, K_TICKS(1), K_FOREVER);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
zassert_false(timer_executed, "should not return to this thread");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Invoke irq_offload() from an interrupt and verify that the
|
/* Invoke irq_offload() from an interrupt and verify that the
|
||||||
* resulting nested interrupt doesn't explode
|
* resulting nested interrupt doesn't explode
|
||||||
|
@ -224,14 +238,27 @@ void test_nested_irq_offload(void)
|
||||||
ztest_test_skip();
|
ztest_test_skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
k_thread_priority_set(k_current_get(), 1);
|
||||||
|
|
||||||
k_timer_init(&nestoff_timer, nestoff_timer_fn, NULL);
|
k_timer_init(&nestoff_timer, nestoff_timer_fn, NULL);
|
||||||
|
|
||||||
zassert_false(timer_executed, "timer ran too soon");
|
zassert_false(timer_executed, "timer ran too soon");
|
||||||
zassert_false(nested_executed, "nested irq_offload ran too soon");
|
zassert_false(nested_executed, "nested irq_offload ran too soon");
|
||||||
|
|
||||||
k_timer_start(&nestoff_timer, K_TICKS(1), K_FOREVER);
|
/* Do this in a thread to exercise a regression case: the
|
||||||
k_timer_status_sync(&nestoff_timer);
|
* offload handler will suspend the thread it interrupted,
|
||||||
|
* ensuring that the interrupt returns back to this thread and
|
||||||
|
* effects a context switch of of the nested interrupt (see
|
||||||
|
* #45779). Requires that this be a 1cpu test case,
|
||||||
|
* obviously.
|
||||||
|
*/
|
||||||
|
k_thread_create(&offload_thread,
|
||||||
|
offload_stack, K_THREAD_STACK_SIZEOF(offload_stack),
|
||||||
|
offload_thread_fn, NULL, NULL, NULL,
|
||||||
|
0, 0, K_NO_WAIT);
|
||||||
|
|
||||||
zassert_true(timer_executed, "timer did not run");
|
zassert_true(timer_executed, "timer did not run");
|
||||||
zassert_true(nested_executed, "nested irq_offload did not run");
|
zassert_true(nested_executed, "nested irq_offload did not run");
|
||||||
|
|
||||||
|
k_thread_abort(&offload_thread);
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ void test_main(void)
|
||||||
ztest_test_suite(common,
|
ztest_test_suite(common,
|
||||||
ztest_unit_test(test_bootdelay),
|
ztest_unit_test(test_bootdelay),
|
||||||
ztest_unit_test(test_irq_offload),
|
ztest_unit_test(test_irq_offload),
|
||||||
ztest_unit_test(test_nested_irq_offload),
|
ztest_1cpu_unit_test(test_nested_irq_offload),
|
||||||
ztest_unit_test(test_byteorder_memcpy_swap),
|
ztest_unit_test(test_byteorder_memcpy_swap),
|
||||||
ztest_unit_test(test_byteorder_mem_swap),
|
ztest_unit_test(test_byteorder_mem_swap),
|
||||||
ztest_unit_test(test_sys_get_be64),
|
ztest_unit_test(test_sys_get_be64),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue