diff --git a/tests/kernel/obj_tracing/Makefile b/tests/kernel/obj_tracing/Makefile new file mode 100644 index 00000000000..e70a750a88d --- /dev/null +++ b/tests/kernel/obj_tracing/Makefile @@ -0,0 +1,4 @@ +BOARD ?= qemu_x86 +CONF_FILE = prj.conf + +include ${ZEPHYR_BASE}/Makefile.test diff --git a/tests/kernel/obj_tracing/README.txt b/tests/kernel/obj_tracing/README.txt new file mode 100644 index 00000000000..e8fe0c918da --- /dev/null +++ b/tests/kernel/obj_tracing/README.txt @@ -0,0 +1,43 @@ +Test Description +---------------- + +The object tracing test is a sanity test to verify that the +object tracing API remains healthy. + +It uses the philsophers as an application that implements +multiple threads that are synchronized with semaphores. + +The application initializes their objects and starts the philosophers' +thread interaction. A specific thread, called object monitor, accesses +the object tracing API and reports the number of expected objects. + +The sanity test script expects each test to finish its execution +and then it considers the test completed. For that reason the +philosophers' threads execute a finite number of iterations. After +that the application execution ends. + +Sample Output +-------------- +***** BOOTING ZEPHYR OS vxxxx - BUILD: yyyyy ***** +tc_start() - OBJECT TRACING TEST +SEMAPHORE REF: 0x001031f0 +SEMAPHORE REF: 0x001031dc +SEMAPHORE REF: 0x001031c8 +SEMAPHORE REF: 0x001031b4 +SEMAPHORE REF: 0x001031a0 +SEMAPHORE QUANTITY: 5 +=================================================================== +PASS - object_monitor. +COOP: 0x00102da0 OPTIONS: 0x00, STATE: 0x00 +COOP: 0x00104204 OPTIONS: 0x00, STATE: 0x00 +COOP: 0x00103e04 OPTIONS: 0x00, STATE: 0x00 +COOP: 0x00103a04 OPTIONS: 0x00, STATE: 0x02 +COOP: 0x00103604 OPTIONS: 0x00, STATE: 0x02 +COOP: 0x00103204 OPTIONS: 0x00, STATE: 0x00 +PREMPT: 0x00105340 OPTIONS: 0x00, STATE: 0x02 +COOP: 0x00104e40 OPTIONS: 0x01, STATE: 0x00 +THREAD QUANTITY: 8 +=================================================================== +PASS - test_thread_monitor. +=================================================================== +PROJECT EXECUTION SUCCESSFUL diff --git a/tests/kernel/obj_tracing/prj.conf b/tests/kernel/obj_tracing/prj.conf new file mode 100644 index 00000000000..d3f6822aeb7 --- /dev/null +++ b/tests/kernel/obj_tracing/prj.conf @@ -0,0 +1,3 @@ +CONFIG_DEBUG_TRACING_KERNEL_OBJECTS=y +CONFIG_THREAD_MONITOR=y + diff --git a/tests/kernel/obj_tracing/src/Makefile b/tests/kernel/obj_tracing/src/Makefile new file mode 100644 index 00000000000..e77556a456a --- /dev/null +++ b/tests/kernel/obj_tracing/src/Makefile @@ -0,0 +1,3 @@ +ccflags-y += -I${ZEPHYR_BASE}/tests/include + +obj-y = philosopher.o main.o object_monitor.o diff --git a/tests/kernel/obj_tracing/src/main.c b/tests/kernel/obj_tracing/src/main.c new file mode 100644 index 00000000000..d263d30289a --- /dev/null +++ b/tests/kernel/obj_tracing/src/main.c @@ -0,0 +1,49 @@ +/* phil_task.c - dining philosophers */ + +/* + * Copyright (c) 2011-2016 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "phil.h" + +#define STSIZE 1024 + +extern void phil_entry(void); +extern void object_monitor(void); + +char __stack phil_stack[N_PHILOSOPHERS][STSIZE]; +char __stack mon_stack[STSIZE]; +struct k_sem forks[N_PHILOSOPHERS]; + +/** + * + * @brief Nanokernel entry point + * + */ + +int main(void) +{ + int i; + + for (i = 0; i < N_PHILOSOPHERS; i++) { + k_sem_init(&forks[i], 0, 1); + k_sem_give(&forks[i]); + } + + /* create philosopher threads */ + for (i = 0; i < N_PHILOSOPHERS; i++) { + k_thread_spawn(&phil_stack[i][0], STSIZE, + (k_thread_entry_t)phil_entry, NULL, NULL, NULL, + K_PRIO_COOP(6), 0, K_NO_WAIT); + } + + /* create object counter monitor thread */ + k_thread_spawn(mon_stack, STSIZE, + (k_thread_entry_t)object_monitor, NULL, NULL, NULL, + K_PRIO_COOP(7), 0, K_NO_WAIT); + + return 0; +} diff --git a/tests/kernel/obj_tracing/src/object_monitor.c b/tests/kernel/obj_tracing/src/object_monitor.c new file mode 100644 index 00000000000..d237bafee16 --- /dev/null +++ b/tests/kernel/obj_tracing/src/object_monitor.c @@ -0,0 +1,114 @@ +/* object_monitor.c - object monitor */ + +/* + * Copyright (c) 2016 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "phil.h" + +/** + * + * @brief Thread that traverses, counts and reports + * the kernel objects in the philosophers application. + * + */ + +#define TOTAL_TEST_NUMBER 2 + +/* 1 IPM console fiber if enabled */ +#if defined(CONFIG_IPM_CONSOLE_RECEIVER) && defined(CONFIG_PRINTK) +#define IPM_THREAD 1 +#else +#define IPM_THREAD 0 +#endif /* CONFIG_IPM_CONSOLE_RECEIVER && CONFIG_PRINTK*/ + +/* Must account for: + * N Philosopher threads + * 1 Object monitor thread + * 1 System idle thread + * 1 System workqueue thread + * 1 IPM console thread + */ + +void *force_sys_work_q_in = (void *)&k_sys_work_q; + +#define TOTAL_THREADS (N_PHILOSOPHERS + 3 + IPM_THREAD) + +#define OBJ_LIST_NAME k_sem +#define OBJ_LIST_TYPE struct k_sem + +static inline int test_thread_monitor(void) +{ + int obj_counter = 0; + struct k_thread *thread_list = NULL; + + /* wait a bit to allow any initialization-only threads to terminate */ + k_sleep(100); + + thread_list = (struct k_thread *)SYS_THREAD_MONITOR_HEAD; + while (thread_list != NULL) { + if (thread_list->base.prio == -1) { + TC_PRINT("PREMPT: %p OPTIONS: 0x%02x, STATE: 0x%02x\n", + thread_list, + thread_list->base.user_options, + thread_list->base.thread_state); + } else { + TC_PRINT("COOP: %p OPTIONS: 0x%02x, STATE: 0x%02x\n", + thread_list, + thread_list->base.user_options, + thread_list->base.thread_state); + } + thread_list = + (struct k_thread *)SYS_THREAD_MONITOR_NEXT(thread_list); + obj_counter++; + } + TC_PRINT("THREAD QUANTITY: %d\n", obj_counter); + + if (obj_counter == TOTAL_THREADS) { + TC_END_RESULT(TC_PASS); + return 1; + } + + TC_END_RESULT(TC_FAIL); + return 0; +} + +void object_monitor(void) +{ + int obj_counter; + int test_counter = 0; + void *obj_list = NULL; + + TC_START("OBJECT TRACING TEST"); + + obj_counter = 0; + obj_list = SYS_TRACING_HEAD(OBJ_LIST_TYPE, OBJ_LIST_NAME); + while (obj_list != NULL) { + TC_PRINT("SEMAPHORE REF: %p\n", obj_list); + obj_list = SYS_TRACING_NEXT(OBJ_LIST_TYPE, OBJ_LIST_NAME, + obj_list); + obj_counter++; + } + TC_PRINT("SEMAPHORE QUANTITY: %d\n", obj_counter); + + if (obj_counter == N_PHILOSOPHERS) { + TC_END_RESULT(TC_PASS); + test_counter++; + } else { + TC_END_RESULT(TC_FAIL); + } + + test_counter += test_thread_monitor(); + + if (test_counter == TOTAL_TEST_NUMBER) { + TC_END_REPORT(TC_PASS); + } else { + TC_END_REPORT(TC_FAIL); + } +} diff --git a/tests/kernel/obj_tracing/src/phil.h b/tests/kernel/obj_tracing/src/phil.h new file mode 100644 index 00000000000..585074c7d6f --- /dev/null +++ b/tests/kernel/obj_tracing/src/phil.h @@ -0,0 +1,8 @@ +/* phil.h - dining philosophers header file*/ + +/* + * Copyright (c) 2011-2016 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define N_PHILOSOPHERS 5 diff --git a/tests/kernel/obj_tracing/src/philosopher.c b/tests/kernel/obj_tracing/src/philosopher.c new file mode 100644 index 00000000000..526c411ee5c --- /dev/null +++ b/tests/kernel/obj_tracing/src/philosopher.c @@ -0,0 +1,66 @@ +/* phil_thread.c - dining philosopher */ + +/* + * Copyright (c) 2011-2016 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "phil.h" + +#define FORK(x) (&forks[x]) +#define TAKE(x) k_sem_take(x, K_FOREVER) +#define GIVE(x) k_sem_give(x) + +#define RANDDELAY(x) k_sleep(10 * (x) + 1) + +/* externs */ + +extern struct k_sem forks[N_PHILOSOPHERS]; + + + +/** + * + * @brief Entry point to a philosopher's thread + * + * This routine runs as a task in the microkernel environment + * and as a thread in the nanokernel environment. + * + * @return N/A + */ + +void phil_entry(void) +{ + int counter; + struct k_sem *f1; /* fork #1 */ + struct k_sem *f2; /* fork #2 */ + static int myId; /* next philosopher ID */ + int pri = irq_lock(); /* interrupt lock level */ + int id = myId++; /* current philosopher ID */ + + irq_unlock(pri); + + /* always take the lowest fork first */ + if ((id+1) != N_PHILOSOPHERS) { + f1 = FORK(id); + f2 = FORK(id + 1); + } else { + f1 = FORK(0); + f2 = FORK(id); + } + + for (counter = 0; counter < 5; counter++) { + TAKE(f1); + TAKE(f2); + + RANDDELAY(id); + + GIVE(f2); + GIVE(f1); + + RANDDELAY(id); + } +} diff --git a/tests/kernel/obj_tracing/testcase.ini b/tests/kernel/obj_tracing/testcase.ini new file mode 100644 index 00000000000..0e582453cdd --- /dev/null +++ b/tests/kernel/obj_tracing/testcase.ini @@ -0,0 +1,5 @@ +[test] +tags = core +# Make sure it has enough memory +filter = not ((CONFIG_DEBUG or CONFIG_ASSERT)) and ( CONFIG_SRAM_SIZE >= 32 + or CONFIG_DCCM_SIZE >= 32 or CONFIG_RAM_SIZE >= 32)