From b636625a2b3376fd75d826da5a8d77bfa260b710 Mon Sep 17 00:00:00 2001 From: Jithu Joseph Date: Thu, 12 Jan 2017 12:56:40 -0800 Subject: tests: benchmark: sys_kernel: Porting to unified This change ports tests/legacy/benchmark/sys_kernel stuff to use unified APIs. Change-Id: If6fbaa5586502205e9f4dc6e79ff1c1a1c1b8102 Signed-off-by: Jithu Joseph --- tests/benchmark/sys_kernel/Makefile | 4 + tests/benchmark/sys_kernel/README.txt | 177 +++++++++++++++++++ tests/benchmark/sys_kernel/prj.conf | 7 + tests/benchmark/sys_kernel/src/Makefile | 7 + tests/benchmark/sys_kernel/src/lifo.c | 262 +++++++++++++++++++++++++++++ tests/benchmark/sys_kernel/src/mwfifo.c | 261 ++++++++++++++++++++++++++++ tests/benchmark/sys_kernel/src/sema.c | 189 +++++++++++++++++++++ tests/benchmark/sys_kernel/src/stack.c | 242 ++++++++++++++++++++++++++ tests/benchmark/sys_kernel/src/syskernel.c | 192 +++++++++++++++++++++ tests/benchmark/sys_kernel/src/syskernel.h | 61 +++++++ tests/benchmark/sys_kernel/testcase.ini | 6 + 11 files changed, 1408 insertions(+) create mode 100644 tests/benchmark/sys_kernel/Makefile create mode 100644 tests/benchmark/sys_kernel/README.txt create mode 100644 tests/benchmark/sys_kernel/prj.conf create mode 100644 tests/benchmark/sys_kernel/src/Makefile create mode 100644 tests/benchmark/sys_kernel/src/lifo.c create mode 100644 tests/benchmark/sys_kernel/src/mwfifo.c create mode 100644 tests/benchmark/sys_kernel/src/sema.c create mode 100644 tests/benchmark/sys_kernel/src/stack.c create mode 100644 tests/benchmark/sys_kernel/src/syskernel.c create mode 100644 tests/benchmark/sys_kernel/src/syskernel.h create mode 100644 tests/benchmark/sys_kernel/testcase.ini diff --git a/tests/benchmark/sys_kernel/Makefile b/tests/benchmark/sys_kernel/Makefile new file mode 100644 index 000000000..e70a750a8 --- /dev/null +++ b/tests/benchmark/sys_kernel/Makefile @@ -0,0 +1,4 @@ +BOARD ?= qemu_x86 +CONF_FILE = prj.conf + +include ${ZEPHYR_BASE}/Makefile.test diff --git a/tests/benchmark/sys_kernel/README.txt b/tests/benchmark/sys_kernel/README.txt new file mode 100644 index 000000000..269d2effb --- /dev/null +++ b/tests/benchmark/sys_kernel/README.txt @@ -0,0 +1,177 @@ +Title: kernel Object Performance + +Description: + +The SysKernel test measures the performance of semaphore, +lifo, fifo and stack objects. + +-------------------------------------------------------------------------------- + +Building and Running Project: + +This project outputs to the console. It can be built and executed +on QEMU as follows: + + make qemu + +-------------------------------------------------------------------------------- + +Troubleshooting: + +Problems caused by out-dated project information can be addressed by +issuing one of the following commands then rebuilding the project: + + make clean # discard results of previous builds + # but keep existing configuration info +or + make pristine # discard results of previous builds + # and restore pre-defined configuration info + +-------------------------------------------------------------------------------- + +Sample Output: + +MODULE: kernel API test +KERNEL VERSION: 0x1066300 + +Each test below is repeated 5000 times; +average time for one iteration is displayed. + +TEST CASE: Semaphore #1 +TEST COVERAGE: + k_sem_init + k_sem_take(TICKS_UNLIMITED) + k_sem_give +Starting test. Please wait... +TEST RESULT: SUCCESSFUL +DETAILS: Average time for 1 iteration: NNNN nSec +END TEST CASE + +TEST CASE: Semaphore #2 +TEST COVERAGE: + k_sem_init + k_sem_take(TICKS_NONE) + k_yield + k_sem_give +Starting test. Please wait... +TEST RESULT: SUCCESSFUL +DETAILS: Average time for 1 iteration: NNNN nSec +END TEST CASE + +TEST CASE: Semaphore #3 +TEST COVERAGE: + k_sem_init + k_sem_take(TICKS_UNLIMITED) + k_sem_give + k_sem_give + k_sem_take(TICKS_UNLIMITED) +Starting test. Please wait... +TEST RESULT: SUCCESSFUL +DETAILS: Average time for 1 iteration: NNNN nSec +END TEST CASE + +TEST CASE: LIFO #1 +TEST COVERAGE: + k_lifo_init + k_lifo_get(K_FOREVER) + k_lifo_put +Starting test. Please wait... +TEST RESULT: SUCCESSFUL +DETAILS: Average time for 1 iteration: NNNN nSec +END TEST CASE + +TEST CASE: LIFO #2 +TEST COVERAGE: + k_lifo_init + k_lifo_get(K_FOREVER) + k_lifo_get(TICKS_NONE) + k_lifo_put + k_yield +Starting test. Please wait... +TEST RESULT: SUCCESSFUL +DETAILS: Average time for 1 iteration: NNNN nSec +END TEST CASE + +TEST CASE: LIFO #3 +TEST COVERAGE: + k_lifo_init + k_lifo_get(K_FOREVER) + k_lifo_put + k_lifo_get(K_FOREVER) + k_lifo_put +Starting test. Please wait... +TEST RESULT: SUCCESSFUL +DETAILS: Average time for 1 iteration: NNNN nSec +END TEST CASE + +TEST CASE: FIFO #1 +TEST COVERAGE: + k_fifo_init + k_fifo_get(K_FOREVER) + k_fifo_put +Starting test. Please wait... +TEST RESULT: SUCCESSFUL +DETAILS: Average time for 1 iteration: NNNN nSec +END TEST CASE + +TEST CASE: FIFO #2 +TEST COVERAGE: + k_fifo_init + k_fifo_get(K_FOREVER) + k_fifo_get(TICKS_NONE) + k_fifo_put + k_yield +Starting test. Please wait... +TEST RESULT: SUCCESSFUL +DETAILS: Average time for 1 iteration: NNNN nSec +END TEST CASE + +TEST CASE: FIFO #3 +TEST COVERAGE: + k_fifo_init + k_fifo_get(K_FOREVER) + k_fifo_put + k_fifo_get(K_FOREVER) + k_fifo_put +Starting test. Please wait... +TEST RESULT: SUCCESSFUL +DETAILS: Average time for 1 iteration: NNNN nSec +END TEST CASE + +TEST CASE: Stack #1 +TEST COVERAGE: + k_stack_init + k_stack_pop(TICKS_UNLIMITED) + k_stack_push +Starting test. Please wait... +TEST RESULT: SUCCESSFUL +DETAILS: Average time for 1 iteration: NNNN nSec +END TEST CASE + +TEST CASE: Stack #2 +TEST COVERAGE: + k_stack_init + k_stack_pop(TICKS_UNLIMITED) + k_stack_pop + k_stack_push + k_yield +Starting test. Please wait... +TEST RESULT: SUCCESSFUL +DETAILS: Average time for 1 iteration: NNNN nSec +END TEST CASE + +TEST CASE: Stack #3 +TEST COVERAGE: + k_stack_init + k_stack_pop(TICKS_UNLIMITED) + k_stack_push + k_stack_pop(TICKS_UNLIMITED) + k_stack_push +Starting test. Please wait... +TEST RESULT: SUCCESSFUL +DETAILS: Average time for 1 iteration: NNNN nSec +END TEST CASE + +PROJECT EXECUTION SUCCESSFUL +QEMU: Terminated + diff --git a/tests/benchmark/sys_kernel/prj.conf b/tests/benchmark/sys_kernel/prj.conf new file mode 100644 index 000000000..701871dc9 --- /dev/null +++ b/tests/benchmark/sys_kernel/prj.conf @@ -0,0 +1,7 @@ +# all printf, fprintf to stdout go to console +CONFIG_STDOUT_CONSOLE=y + +# eliminate timer interrupts during the benchmark +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1 + +CONFIG_MAIN_STACK_SIZE=16384 diff --git a/tests/benchmark/sys_kernel/src/Makefile b/tests/benchmark/sys_kernel/src/Makefile new file mode 100644 index 000000000..842415603 --- /dev/null +++ b/tests/benchmark/sys_kernel/src/Makefile @@ -0,0 +1,7 @@ +ccflags-y = -I${ZEPHYR_BASE}/tests/include + +obj-y = lifo.o \ + mwfifo.o \ + sema.o \ + stack.o \ + syskernel.o diff --git a/tests/benchmark/sys_kernel/src/lifo.c b/tests/benchmark/sys_kernel/src/lifo.c new file mode 100644 index 000000000..0a48be22d --- /dev/null +++ b/tests/benchmark/sys_kernel/src/lifo.c @@ -0,0 +1,262 @@ +/* lifo.c */ + +/* + * Copyright (c) 1997-2010, 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "syskernel.h" + +struct k_lifo lifo1; +struct k_lifo lifo2; + +static struct k_fifo sync_fifo; /* for synchronization */ + +/** + * + * @brief Initialize LIFOs for the test + * + * @return N/A + */ +void lifo_test_init(void) +{ + k_lifo_init(&lifo1); + k_lifo_init(&lifo2); +} + + +/** + * + * @brief Lifo test thread + * + * @param par1 Ignored parameter. + * @param par2 Number of test loops. + * + * @return N/A + */ +void lifo_thread1(void *par1, void *par2, void *par3) +{ + int i; + int element_a[2]; + int element_b[2]; + int *pelement; + int num_loops = (int) par2; + + ARG_UNUSED(par1); + + for (i = 0; i < num_loops / 2; i++) { + pelement = (int *)k_lifo_get(&lifo1, + K_FOREVER); + if (pelement[1] != 2 * i) { + break; + } + element_a[1] = 2 * i; + k_lifo_put(&lifo2, element_a); + pelement = (int *)k_lifo_get(&lifo1, + K_FOREVER); + if (pelement[1] != 2 * i + 1) { + break; + } + element_b[1] = 2 * i + 1; + k_lifo_put(&lifo2, element_b); + } + /* wait till it is safe to end: */ + k_fifo_get(&sync_fifo, K_FOREVER); +} + + +/** + * + * @brief Lifo test thread + * + * @param par1 Address of the counter. + * @param par2 Number of test cycles. + * + * @return N/A + */ +void lifo_thread2(void *par1, void *par2, void *par3) +{ + int i; + int element[2]; + int *pelement; + int *pcounter = (int *)par1; + int num_loops = (int) par2; + + for (i = 0; i < num_loops; i++) { + element[1] = i; + k_lifo_put(&lifo1, element); + pelement = (int *)k_lifo_get(&lifo2, + K_FOREVER); + if (pelement[1] != i) { + break; + } + (*pcounter)++; + } + /* wait till it is safe to end: */ + k_fifo_get(&sync_fifo, K_FOREVER); +} + +/** + * + * @brief Lifo test thread + * + * @param par1 Address of the counter. + * @param par2 Number of test loops. + * + * @return N/A + */ +void lifo_thread3(void *par1, void *par2, void *par3) +{ + int i; + int element[2]; + int *pelement; + int *pcounter = (int *)par1; + int num_loops = (int) par2; + + for (i = 0; i < num_loops; i++) { + element[1] = i; + k_lifo_put(&lifo1, element); + while ((pelement = k_lifo_get(&lifo2, + K_NO_WAIT)) == NULL) { + k_yield(); + } + if (pelement[1] != i) { + break; + } + (*pcounter)++; + } + /* wait till it is safe to end: */ + k_fifo_get(&sync_fifo, K_FOREVER); +} + +/** + * + * @brief The main test entry + * + * @return 1 if success and 0 on failure + */ +int lifo_test(void) +{ + uint32_t t; + int i = 0; + int return_value = 0; + int element[2]; + int j; + + k_fifo_init(&sync_fifo); + + /* test get/wait & put thread functions between co-op threads */ + fprintf(output_file, sz_test_case_fmt, + "LIFO #1"); + fprintf(output_file, sz_description, + "\n\tk_lifo_init" + "\n\tk_lifo_get(K_FOREVER)" + "\n\tk_lifo_put"); + printf(sz_test_start_fmt); + + lifo_test_init(); + + t = BENCH_START(); + + k_thread_spawn(thread_stack1, STACK_SIZE, lifo_thread1, + NULL, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + + k_thread_spawn(thread_stack2, STACK_SIZE, lifo_thread2, + (void *) &i, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + + t = TIME_STAMP_DELTA_GET(t); + + return_value += check_result(i, t); + + /* threads have done their job, they can stop now safely: */ + for (j = 0; j < 2; j++) { + k_fifo_put(&sync_fifo, (void *) element); + } + + /* test get/yield & put thread functions between co-op threads */ + fprintf(output_file, sz_test_case_fmt, + "LIFO #2"); + fprintf(output_file, sz_description, + "\n\tk_lifo_init" + "\n\tk_lifo_get(K_FOREVER)" + "\n\tk_lifo_get(TICKS_NONE)" + "\n\tk_lifo_put" + "\n\tk_yield"); + printf(sz_test_start_fmt); + + lifo_test_init(); + + t = BENCH_START(); + + i = 0; + + k_thread_spawn(thread_stack1, STACK_SIZE, lifo_thread1, + NULL, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + + k_thread_spawn(thread_stack2, STACK_SIZE, lifo_thread3, + (void *) &i, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + + t = TIME_STAMP_DELTA_GET(t); + + return_value += check_result(i, t); + + /* threads have done their job, they can stop now safely: */ + for (j = 0; j < 2; j++) { + k_fifo_put(&sync_fifo, (void *) element); + } + + /* test get wait & put functions between co-op and premptive threads */ + fprintf(output_file, sz_test_case_fmt, + "LIFO #3"); + fprintf(output_file, sz_description, + "\n\tk_lifo_init" + "\n\tk_lifo_get(K_FOREVER)" + "\n\tk_lifo_put" + "\n\tk_lifo_get(K_FOREVER)" + "\n\tk_lifo_put"); + printf(sz_test_start_fmt); + + lifo_test_init(); + + t = BENCH_START(); + + k_thread_spawn(thread_stack1, STACK_SIZE, lifo_thread1, + NULL, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + for (i = 0; i < NUMBER_OF_LOOPS / 2; i++) { + int element[2]; + int *pelement; + + element[1] = 2 * i; + k_lifo_put(&lifo1, element); + element[1] = 2 * i + 1; + k_lifo_put(&lifo1, element); + + pelement = (int *)k_lifo_get(&lifo2, + K_FOREVER); + if (pelement[1] != 2 * i + 1) { + break; + } + pelement = (int *)k_lifo_get(&lifo2, + K_FOREVER); + if (pelement[1] != 2 * i) { + break; + } + } + + t = TIME_STAMP_DELTA_GET(t); + + return_value += check_result(i * 2, t); + + /* threads have done their job, they can stop now safely: */ + for (j = 0; j < 2; j++) { + k_fifo_put(&sync_fifo, (void *) element); + } + + return return_value; +} diff --git a/tests/benchmark/sys_kernel/src/mwfifo.c b/tests/benchmark/sys_kernel/src/mwfifo.c new file mode 100644 index 000000000..cccac0066 --- /dev/null +++ b/tests/benchmark/sys_kernel/src/mwfifo.c @@ -0,0 +1,261 @@ +/* fifo.c */ + +/* + * Copyright (c) 1997-2010, 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include "syskernel.h" + +struct k_fifo fifo1; +struct k_fifo fifo2; + +static struct k_fifo sync_fifo; /* for synchronization */ + + +/** + * + * @brief Initialize FIFOs for the test + * + * @return N/A + */ +void fifo_test_init(void) +{ + k_fifo_init(&fifo1); + k_fifo_init(&fifo2); +} + + +/** + * + * @brief Fifo test thread + * + * @param par1 Ignored parameter. + * @param par2 Number of test loops. + * + * @return N/A + */ +void fifo_thread1(void *par1, void *par2, void *par3) +{ + int i; + int element[2]; + int *pelement; + int num_loops = (int) par2; + + ARG_UNUSED(par1); + ARG_UNUSED(par3); + for (i = 0; i < num_loops; i++) { + pelement = (int *)k_fifo_get(&fifo1, + K_FOREVER); + if (pelement[1] != i) { + break; + } + element[1] = i; + k_fifo_put(&fifo2, element); + } + /* wait till it is safe to end: */ + k_fifo_get(&sync_fifo, K_FOREVER); +} + + +/** + * + * @brief Fifo test thread + * + * @param par1 Address of the counter. + * @param par2 Number of test cycles. + * + * @return N/A + */ +void fifo_thread2(void *par1, void *par2, void *par3) +{ + int i; + int element[2]; + int *pelement; + int *pcounter = (int *) par1; + int num_loops = (int) par2; + + ARG_UNUSED(par3); + + for (i = 0; i < num_loops; i++) { + element[1] = i; + k_fifo_put(&fifo1, element); + pelement = (int *)k_fifo_get(&fifo2, + K_FOREVER); + if (pelement[1] != i) { + break; + } + (*pcounter)++; + } + /* wait till it is safe to end: */ + k_fifo_get(&sync_fifo, K_FOREVER); +} + + +/** + * + * @brief Fifo test thread + * + * @param par1 Address of the counter. + * @param par2 Number of test cycles. + * + * @return N/A + */ +void fifo_thread3(void *par1, void *par2, void *par3) +{ + int i; + int element[2]; + int *pelement; + int *pcounter = (int *)par1; + int num_loops = (int) par2; + + ARG_UNUSED(par3); + + for (i = 0; i < num_loops; i++) { + element[1] = i; + k_fifo_put(&fifo1, element); + while ((pelement = k_fifo_get(&fifo2, + K_NO_WAIT)) == NULL) { + k_yield(); + } + if (pelement[1] != i) { + break; + } + (*pcounter)++; + } + /* wait till it is safe to end: */ + k_fifo_get(&sync_fifo, K_FOREVER); +} + + +/** + * + * @brief The main test entry + * + * @return 1 if success and 0 on failure + */ +int fifo_test(void) +{ + uint32_t t; + int i = 0; + int return_value = 0; + int element[2]; + int j; + + k_fifo_init(&sync_fifo); + + /* test get wait & put thread functions between co-op threads */ + fprintf(output_file, sz_test_case_fmt, + "FIFO #1"); + fprintf(output_file, sz_description, + "\n\tk_fifo_init" + "\n\tk_fifo_get(K_FOREVER)" + "\n\tk_fifo_put"); + printf(sz_test_start_fmt); + + fifo_test_init(); + + t = BENCH_START(); + + k_thread_spawn(thread_stack1, STACK_SIZE, fifo_thread1, + NULL, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + k_thread_spawn(thread_stack2, STACK_SIZE, fifo_thread2, + (void *) &i, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + + t = TIME_STAMP_DELTA_GET(t); + + return_value += check_result(i, t); + + /* threads have done their job, they can stop now safely: */ + for (j = 0; j < 2; j++) { + k_fifo_put(&sync_fifo, (void *) element); + } + + /* test get/yield & put thread functions between co-op threads */ + fprintf(output_file, sz_test_case_fmt, + "FIFO #2"); + fprintf(output_file, sz_description, + "\n\tk_fifo_init" + "\n\tk_fifo_get(K_FOREVER)" + "\n\tk_fifo_get(TICKS_NONE)" + "\n\tk_fifo_put" + "\n\tk_yield"); + printf(sz_test_start_fmt); + + fifo_test_init(); + + t = BENCH_START(); + + i = 0; + k_thread_spawn(thread_stack1, STACK_SIZE, fifo_thread1, + NULL, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + k_thread_spawn(thread_stack2, STACK_SIZE, fifo_thread3, + (void *) &i, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + + t = TIME_STAMP_DELTA_GET(t); + + return_value += check_result(i, t); + + /* threads have done their job, they can stop now safely: */ + for (j = 0; j < 2; j++) { + k_fifo_put(&sync_fifo, (void *) element); + } + + /* test get wait & put functions between co-op and premptive threads */ + fprintf(output_file, sz_test_case_fmt, + "FIFO #3"); + fprintf(output_file, sz_description, + "\n\tk_fifo_init" + "\n\tk_fifo_get(K_FOREVER)" + "\n\tk_fifo_put" + "\n\tk_fifo_get(K_FOREVER)" + "\n\tk_fifo_put"); + printf(sz_test_start_fmt); + + fifo_test_init(); + + t = BENCH_START(); + + k_thread_spawn(thread_stack1, STACK_SIZE, fifo_thread1, + NULL, (void *) (NUMBER_OF_LOOPS / 2), NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + k_thread_spawn(thread_stack2, STACK_SIZE, fifo_thread1, + NULL, (void *) (NUMBER_OF_LOOPS / 2), NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + for (i = 0; i < NUMBER_OF_LOOPS / 2; i++) { + int element[2]; + int *pelement; + + element[1] = i; + k_fifo_put(&fifo1, element); + element[1] = i; + k_fifo_put(&fifo1, element); + + pelement = (int *)k_fifo_get(&fifo2, + K_FOREVER); + if (pelement[1] != i) { + break; + } + pelement = (int *)k_fifo_get(&fifo2, + K_FOREVER); + if (pelement[1] != i) { + break; + } + } + t = TIME_STAMP_DELTA_GET(t); + + return_value += check_result(i * 2, t); + + /* threads have done their job, they can stop now safely: */ + for (j = 0; j < 2; j++) { + k_fifo_put(&sync_fifo, (void *) element); + } + + return return_value; +} diff --git a/tests/benchmark/sys_kernel/src/sema.c b/tests/benchmark/sys_kernel/src/sema.c new file mode 100644 index 000000000..77d4660d4 --- /dev/null +++ b/tests/benchmark/sys_kernel/src/sema.c @@ -0,0 +1,189 @@ +/* sema.c */ + +/* + * Copyright (c) 1997-2010, 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "syskernel.h" + +struct k_sem sem1; +struct k_sem sem2; + +/** + * + * @brief Initialize semaphores for the test + * + * @return N/A + */ +void sema_test_init(void) +{ + k_sem_init(&sem1, 0, 1); + k_sem_init(&sem2, 0, 1); +} + + +/** + * + * @brief Semaphore test thread + * + * @param par1 Ignored parameter. + * @param par2 Number of test loops. + * + * @return N/A + */ +void sema_thread1(void *par1, void *par2, void *par3) +{ + int i; + int num_loops = (int) par2; + + ARG_UNUSED(par1); + ARG_UNUSED(par3); + + for (i = 0; i < num_loops; i++) { + k_sem_take(&sem1, K_FOREVER); + k_sem_give(&sem2); + } +} + + +/** + * + * @brief Semaphore test thread + * + * @param par1 Address of the counter. + * @param par2 Number of test cycles. + * + * @return N/A + */ +void sema_thread2(void *par1, void *par2, void *par3) +{ + int i; + int *pcounter = (int *)par1; + int num_loops = (int) par2; + + ARG_UNUSED(par3); + + for (i = 0; i < num_loops; i++) { + k_sem_give(&sem1); + k_sem_take(&sem2, K_FOREVER); + (*pcounter)++; + } +} + +/** + * + * @brief Semaphore test thread + * + * @param par1 Address of the counter. + * @param par2 Number of test cycles. + * + * @return N/A + */ +void sema_thread3(void *par1, void *par2, void *par3) +{ + int i; + int *pcounter = (int *)par1; + int num_loops = (int) par2; + + ARG_UNUSED(par3); + + for (i = 0; i < num_loops; i++) { + k_sem_give(&sem1); + while (k_sem_take(&sem2, K_NO_WAIT) != 0) { + k_yield(); + } + (*pcounter)++; + } +} + + +/** + * + * @brief The main test entry + * + * @return 1 if success and 0 on failure + */ +int sema_test(void) +{ + uint32_t t; + int i = 0; + int return_value = 0; + + fprintf(output_file, sz_test_case_fmt, + "Semaphore #1"); + fprintf(output_file, sz_description, + "\n\tk_sem_init" + "\n\tk_sem_take(TICKS_UNLIMITED)" + "\n\tk_sem_give"); + printf(sz_test_start_fmt); + + sema_test_init(); + + t = BENCH_START(); + + k_thread_spawn(thread_stack1, STACK_SIZE, sema_thread1, + NULL, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + k_thread_spawn(thread_stack2, STACK_SIZE, sema_thread2, + (void *) &i, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + + t = TIME_STAMP_DELTA_GET(t); + + return_value += check_result(i, t); + + fprintf(output_file, sz_test_case_fmt, + "Semaphore #2"); + fprintf(output_file, sz_description, + "\n\tk_sem_init" + "\n\tk_sem_take(TICKS_NONE)" + "\n\tk_yield" + "\n\tk_sem_give"); + printf(sz_test_start_fmt); + + sema_test_init(); + i = 0; + + t = BENCH_START(); + + k_thread_spawn(thread_stack1, STACK_SIZE, sema_thread1, + NULL, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + k_thread_spawn(thread_stack2, STACK_SIZE, sema_thread3, + (void *) &i, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + + t = TIME_STAMP_DELTA_GET(t); + + return_value += check_result(i, t); + + fprintf(output_file, sz_test_case_fmt, + "Semaphore #3"); + fprintf(output_file, sz_description, + "\n\tk_sem_init" + "\n\tk_sem_take(TICKS_UNLIMITED)" + "\n\tk_sem_give" + "\n\tk_sem_give" + "\n\tk_sem_take(TICKS_UNLIMITED)"); + printf(sz_test_start_fmt); + + sema_test_init(); + + t = BENCH_START(); + + k_thread_spawn(thread_stack1, STACK_SIZE, sema_thread1, + NULL, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + for (i = 0; i < NUMBER_OF_LOOPS; i++) { + k_sem_give(&sem1); + k_sem_take(&sem2, K_FOREVER); + } + + t = TIME_STAMP_DELTA_GET(t); + + return_value += check_result(i, t); + + return return_value; +} diff --git a/tests/benchmark/sys_kernel/src/stack.c b/tests/benchmark/sys_kernel/src/stack.c new file mode 100644 index 000000000..9ae966621 --- /dev/null +++ b/tests/benchmark/sys_kernel/src/stack.c @@ -0,0 +1,242 @@ +/* stack.c */ + +/* + * Copyright (c) 1997-2010, 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "syskernel.h" + +struct k_stack stack_1; +struct k_stack stack_2; + +uint32_t stack1[2]; +uint32_t stack2[2]; + +/** + * + * @brief Initialize stacks for the test + * + * @return N/A + * + */ +void stack_test_init(void) +{ + k_stack_init(&stack_1, stack1, 2); + k_stack_init(&stack_2, stack2, 2); +} + + +/** + * + * @brief Stack test thread + * + * @param par1 Ignored parameter. + * @param par2 Number of test loops. + * + * @return N/A + * + */ +void stack_thread1(void *par1, void *par2, void *par3) +{ + int num_loops = ((int) par2 / 2); + int i; + uint32_t data; + + ARG_UNUSED(par1); + ARG_UNUSED(par3); + + for (i = 0; i < num_loops; i++) { + k_stack_pop(&stack_1, &data, K_FOREVER); + if (data != 2 * i) { + break; + } + data = 2 * i; + k_stack_push(&stack_2, data); + k_stack_pop(&stack_1, &data, K_FOREVER); + if (data != 2 * i + 1) { + break; + } + data = 2 * i + 1; + k_stack_push(&stack_2, data); + } +} + + +/** + * + * @brief Stack test thread + * + * @param par1 Address of the counter. + * @param par2 Number of test cycles. + * + * @return N/A + * + */ +void stack_thread2(void *par1, void *par2, void *par3) +{ + int i; + uint32_t data; + int *pcounter = (int *)par1; + int num_loops = (int) par2; + + ARG_UNUSED(par3); + + for (i = 0; i < num_loops; i++) { + data = i; + k_stack_push(&stack_1, data); + k_stack_pop(&stack_2, &data, K_FOREVER); + if (data != i) { + break; + } + (*pcounter)++; + } +} + + +/** + * + * @brief Stack test thread + * + * @param par1 Address of the counter. + * @param par2 Number of test cycles. + * + * @return N/A + * + */ +void stack_thread3(void *par1, void *par2, void *par3) +{ + int i; + uint32_t data; + int *pcounter = (int *)par1; + int num_loops = (int) par2; + + ARG_UNUSED(par3); + + for (i = 0; i < num_loops; i++) { + data = i; + k_stack_push(&stack_1, data); + data = 0xffffffff; + + while (k_stack_pop(&stack_2, &data, + K_NO_WAIT) != 0) { + k_yield(); + } + if (data != i) { + break; + } + (*pcounter)++; + } +} + + +/** + * + * @brief The main test entry + * + * @return 1 if success and 0 on failure + * + */ +int stack_test(void) +{ + uint32_t t; + int i = 0; + int return_value = 0; + + /* test get wait & put stack functions between co-op threads */ + fprintf(output_file, sz_test_case_fmt, + "Stack #1"); + fprintf(output_file, sz_description, + "\n\tk_stack_init" + "\n\tk_stack_pop(TICKS_UNLIMITED)" + "\n\tk_stack_push"); + printf(sz_test_start_fmt); + + stack_test_init(); + + t = BENCH_START(); + + k_thread_spawn(thread_stack1, STACK_SIZE, stack_thread1, + 0, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + k_thread_spawn(thread_stack2, STACK_SIZE, stack_thread2, + (void *) &i, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + + t = TIME_STAMP_DELTA_GET(t); + + return_value += check_result(i, t); + + /* test get/yield & put stack functions between co-op threads */ + fprintf(output_file, sz_test_case_fmt, + "Stack #2"); + fprintf(output_file, sz_description, + "\n\tk_stack_init" + "\n\tk_stack_pop(TICKS_UNLIMITED)" + "\n\tk_stack_pop" + "\n\tk_stack_push" + "\n\tk_yield"); + printf(sz_test_start_fmt); + + stack_test_init(); + + t = BENCH_START(); + + i = 0; + k_thread_spawn(thread_stack1, STACK_SIZE, stack_thread1, + 0, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + k_thread_spawn(thread_stack2, STACK_SIZE, stack_thread3, + (void *) &i, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + + t = TIME_STAMP_DELTA_GET(t); + + return_value += check_result(i, t); + + /* test get wait & put stack functions across co-op and premptive + * threads + */ + fprintf(output_file, sz_test_case_fmt, + "Stack #3"); + fprintf(output_file, sz_description, + "\n\tk_stack_init" + "\n\tk_stack_pop(TICKS_UNLIMITED)" + "\n\tk_stack_push" + "\n\tk_stack_pop(TICKS_UNLIMITED)" + "\n\tk_stack_push"); + printf(sz_test_start_fmt); + + stack_test_init(); + + t = BENCH_START(); + + k_thread_spawn(thread_stack1, STACK_SIZE, stack_thread1, + 0, (void *) NUMBER_OF_LOOPS, NULL, + K_PRIO_COOP(3), 0, K_NO_WAIT); + + for (i = 0; i < NUMBER_OF_LOOPS / 2; i++) { + uint32_t data; + + data = 2 * i; + k_stack_push(&stack_1, data); + data = 2 * i + 1; + k_stack_push(&stack_1, data); + + k_stack_pop(&stack_2, &data, K_FOREVER); + if (data != 2 * i + 1) { + break; + } + k_stack_pop(&stack_2, &data, K_FOREVER); + if (data != 2 * i) { + break; + } + } + + t = TIME_STAMP_DELTA_GET(t); + + return_value += check_result(i * 2, t); + + return return_value; +} diff --git a/tests/benchmark/sys_kernel/src/syskernel.c b/tests/benchmark/sys_kernel/src/syskernel.c new file mode 100644 index 000000000..a29a916c8 --- /dev/null +++ b/tests/benchmark/sys_kernel/src/syskernel.c @@ -0,0 +1,192 @@ +/* syskernel.c */ + +/* + * Copyright (c) 1997-2010, 2012-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "syskernel.h" + +#include + +char __stack thread_stack1[STACK_SIZE]; +char __stack thread_stack2[STACK_SIZE]; + +char Msg[256]; + +FILE *output_file; + +const char sz_success[] = "SUCCESSFUL"; +const char sz_partial[] = "PARTIAL"; +const char sz_fail[] = "FAILED"; + +const char sz_module_title_fmt[] = "\nMODULE: %s"; +const char sz_module_result_fmt[] = "\n\nPROJECT EXECUTION %s\n"; +const char sz_module_end_fmt[] = "\nEND MODULE"; + +const char sz_date_fmt[] = "\nBUILD_DATE: %s %s"; +const char sz_kernel_ver_fmt[] = "\nKERNEL VERSION: 0x%x"; +const char sz_description[] = "\nTEST COVERAGE: %s"; + +const char sz_test_case_fmt[] = "\n\nTEST CASE: %s"; +const char sz_test_start_fmt[] = "\nStarting test. Please wait..."; +const char sz_case_result_fmt[] = "\nTEST RESULT: %s"; +const char sz_case_details_fmt[] = "\nDETAILS: %s"; +const char sz_case_end_fmt[] = "\nEND TEST CASE"; +const char sz_case_timing_fmt[] = "%ld nSec"; + +/* time necessary to read the time */ +uint32_t tm_off; + +/** + * + * @brief Get the time ticks before test starts + * + * Routine does necessary preparations for the test to start + * + * @return N/A + */ +void begin_test(void) +{ + /* + * Invoke bench_test_start in order to be able to use + * tCheck static variable. + */ + bench_test_start(); +} + +/** + * + * @brief Checks number of tests and calculate average time + * + * @return 1 if success and 0 on failure + * + * @param i Number of tests. + * @param t Time in ticks for the whole test. + */ +int check_result(int i, uint32_t t) +{ + /* + * bench_test_end checks tCheck static variable. + * bench_test_start modifies it + */ + if (bench_test_end() != 0) { + fprintf(output_file, sz_case_result_fmt, sz_fail); + fprintf(output_file, sz_case_details_fmt, + "timer tick happened. Results are inaccurate"); + fprintf(output_file, sz_case_end_fmt); + return 0; + } + if (i != NUMBER_OF_LOOPS) { + fprintf(output_file, sz_case_result_fmt, sz_fail); + fprintf(output_file, sz_case_details_fmt, "loop counter = "); + fprintf(output_file, "%i !!!", i); + fprintf(output_file, sz_case_end_fmt); + return 0; + } + fprintf(output_file, sz_case_result_fmt, sz_success); + fprintf(output_file, sz_case_details_fmt, + "Average time for 1 iteration: "); + fprintf(output_file, sz_case_timing_fmt, + SYS_CLOCK_HW_CYCLES_TO_NS_AVG(t, NUMBER_OF_LOOPS)); + + fprintf(output_file, sz_case_end_fmt); + return 1; +} + + +/** + * + * @brief Check for a key press + * + * @return 1 when a keyboard key is pressed, or 0 if no keyboard support + */ +int kbhit(void) +{ + return 0; +} + + +/** + * + * @brief Prepares the test output + * + * @param continuously Run test till the user presses the key. + * + * @return N/A + */ + +void init_output(int *continuously) +{ + ARG_UNUSED(continuously); + + /* + * send all printf and fprintf to console + */ + output_file = stdout; +} + + +/** + * + * @brief Close output for the test + * + * @return N/A + */ +void output_close(void) +{ +} + +/** + * + * @brief Perform all selected benchmarks + * + * @return N/A + */ +void main(void) +{ + int continuously = 0; + int test_result; + + init_output(&continuously); + bench_test_init(); + + do { + fprintf(output_file, sz_module_title_fmt, + "kernel API test"); + fprintf(output_file, sz_kernel_ver_fmt, + sys_kernel_version_get()); + fprintf(output_file, + "\n\nEach test below is repeated %d times;\n" + "average time for one iteration is displayed.", + NUMBER_OF_LOOPS); + + test_result = 0; + + test_result += sema_test(); + test_result += lifo_test(); + test_result += fifo_test(); + test_result += stack_test(); + + if (test_result) { + /* sema/lifo/fifo/stack account for 12 tests in total */ + if (test_result == 12) { + fprintf(output_file, sz_module_result_fmt, + sz_success); + } else { + fprintf(output_file, sz_module_result_fmt, + sz_partial); + } + } else { + fprintf(output_file, sz_module_result_fmt, sz_fail); + } + TC_PRINT_RUNID; + + } while (continuously && !kbhit()); + + output_close(); +} diff --git a/tests/benchmark/sys_kernel/src/syskernel.h b/tests/benchmark/sys_kernel/src/syskernel.h new file mode 100644 index 000000000..6bee48c59 --- /dev/null +++ b/tests/benchmark/sys_kernel/src/syskernel.h @@ -0,0 +1,61 @@ +/* syskernel.h */ + +/* + * Copyright (c) 1997-2010, 2014 Wind River Systems, Inc. + * + *SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef SYSKERNEK_H +#define SYSKERNEK_H + +#include + +#include +#include + +#define STACK_SIZE 2048 +#define NUMBER_OF_LOOPS 5000 + +extern char thread_stack1[STACK_SIZE]; +extern char thread_stack2[STACK_SIZE]; + +extern FILE *output_file; + +extern const char sz_success[]; +extern const char sz_partial[]; +extern const char sz_fail[]; + +extern const char sz_module_title_fmt[]; +extern const char sz_module_result_fmt[]; +extern const char sz_module_end_fmt[]; + +extern const char sz_product_fmt[]; +extern const char sz_kernel_ver_fmt[]; +extern const char sz_description[]; + +extern const char sz_test_case_fmt[]; +extern const char sz_test_start_fmt[]; +extern const char sz_case_result_fmt[]; +extern const char sz_case_details_fmt[]; +extern const char sz_case_end_fmt[]; +extern const char sz_case_timing_fmt[]; + +int check_result(int i, uint32_t ticks); + +int sema_test(void); +int lifo_test(void); +int fifo_test(void); +int stack_test(void); +void begin_test(void); + +static inline uint32_t BENCH_START(void) +{ + uint32_t et; + + begin_test(); + et = TIME_STAMP_DELTA_GET(0); + return et; +} + +#endif /* SYSKERNEK_H */ diff --git a/tests/benchmark/sys_kernel/testcase.ini b/tests/benchmark/sys_kernel/testcase.ini new file mode 100644 index 000000000..70b3bd210 --- /dev/null +++ b/tests/benchmark/sys_kernel/testcase.ini @@ -0,0 +1,6 @@ +[test] +tags = benchmark +arch_whitelist = x86 +filter = not ((CONFIG_DEBUG or CONFIG_ASSERT)) and ( CONFIG_SRAM_SIZE >= 32 + or CONFIG_DCCM_SIZE >= 32 or CONFIG_RAM_SIZE >= 32) + -- cgit v1.2.3