tests: thread_stack: add idle stack size scenario

Show that trampolining thread self-aborts to the idle thread
works and that we have sufficiently set the idle stack size
for this, PM hooks, and dynamic kernel object cleanup.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2020-09-22 10:38:29 -07:00 committed by Anas Nashif
commit 9c9312c8c5
3 changed files with 69 additions and 1 deletions

View file

@ -3,3 +3,4 @@ CONFIG_INIT_STACKS=y
CONFIG_THREAD_STACK_INFO=y
CONFIG_APPLICATION_DEFINED_SYSCALL=y
CONFIG_TEST_USERSPACE=y
CONFIG_HEAP_MEM_POOL_SIZE=64

View file

@ -5,3 +5,4 @@ CONFIG_APPLICATION_DEFINED_SYSCALL=y
CONFIG_TEST_USERSPACE=y
CONFIG_BUILTIN_STACK_GUARD=n
CONFIG_MPU_STACK_GUARD=y
CONFIG_HEAP_MEM_POOL_SIZE=64

View file

@ -414,10 +414,76 @@ void test_stack_buffer(void)
STEST_STACKSIZE, false);
}
void no_op_entry(void *p1, void *p2, void *p3)
{
printk("hi! bye!\n");
#ifdef CONFIG_DYNAMIC_OBJECTS
/* Allocate a dynamic kernel object, which gets freed on thread
* cleanup since this thread has the only reference.
*/
struct k_sem *dyn_sem = k_object_alloc(K_OBJ_SEM);
k_sem_init(dyn_sem, 1, 1);
printk("allocated semaphore %p\n", dyn_sem);
#endif
/* thread self-aborts, triggering idle thread cleanup */
}
/**
* @brief Show that the idle thread stack size is correct
*
* The idle thread has to occasionally clean up self-exiting threads.
* Exercise this and show that we didn't overflow, reporting out stack
* usage.
*
* @ingroup kernel_memprotect_tests
*/
void test_idle_stack(void)
{
int ret;
#ifdef CONFIG_SMP
/* 1cpu test case, so all other CPUs are spinning with co-op
* threads blocking them. _current_cpu triggers an assertion.
*/
struct k_thread *idle = arch_curr_cpu()->idle_thread;
#else
struct k_thread *idle = _current_cpu->idle_thread;
#endif
size_t unused_bytes;
/* Spwawn a child thread which self-exits */
k_thread_create(&test_thread, kern_stack, STEST_STACKSIZE,
no_op_entry,
NULL, NULL, NULL,
-1, 0, K_NO_WAIT);
k_thread_join(&test_thread, K_FOREVER);
/* Also sleep for a bit, which also exercises the idle thread
* in case some PM hooks will run
*/
k_sleep(K_MSEC(1));
/* Now measure idle thread stack usage */
ret = k_thread_stack_space_get(idle, &unused_bytes);
zassert_true(ret == 0, "failed to obtain stack space");
zassert_true(unused_bytes > 0, "idle thread stack size %d too low",
CONFIG_IDLE_STACK_SIZE);
printk("unused idle thread stack size: %zu/%d (%zu used)\n",
unused_bytes, CONFIG_IDLE_STACK_SIZE,
CONFIG_IDLE_STACK_SIZE - unused_bytes);
}
void test_main(void)
{
k_thread_system_pool_assign(k_current_get());
/* Run a thread that self-exits, triggering idle cleanup */
ztest_test_suite(userspace,
ztest_1cpu_unit_test(test_stack_buffer)
ztest_1cpu_unit_test(test_stack_buffer),
ztest_1cpu_unit_test(test_idle_stack)
);
ztest_run_test_suite(userspace);
}