From e0f8162a8bc1e664f62a25a109285bbd29b6ef8a Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Mon, 22 Feb 2016 11:05:52 -0500 Subject: [PATCH] test: Add nanokernel test_sleep project The 'test_sleep' nanokernel project tests the following functionality: 1. Normal expiration of fiber_sleep() 2. Waking a sleeping fiber via fiber_fiber_wakeup() 3. Waking a sleeping fiber via isr_fiber_wakeup() 4. Waking a sleeping fiber via task_fiber_wakeup() 5. Normal expiration of task_sleep() Change-Id: Ie51997ace9a4413f62d77daacd6dff97b6b3a4dd Signed-off-by: Peter Mitsis --- tests/kernel/test_sleep/Makefile | 5 + tests/kernel/test_sleep/README.txt | 45 ++++++ tests/kernel/test_sleep/prj.conf | 6 + tests/kernel/test_sleep/src/Makefile | 3 + tests/kernel/test_sleep/src/sleep.c | 205 +++++++++++++++++++++++++++ tests/kernel/test_sleep/testcase.ini | 2 + 6 files changed, 266 insertions(+) create mode 100644 tests/kernel/test_sleep/Makefile create mode 100644 tests/kernel/test_sleep/README.txt create mode 100644 tests/kernel/test_sleep/prj.conf create mode 100644 tests/kernel/test_sleep/src/Makefile create mode 100644 tests/kernel/test_sleep/src/sleep.c create mode 100644 tests/kernel/test_sleep/testcase.ini diff --git a/tests/kernel/test_sleep/Makefile b/tests/kernel/test_sleep/Makefile new file mode 100644 index 0000000000..ed33371187 --- /dev/null +++ b/tests/kernel/test_sleep/Makefile @@ -0,0 +1,5 @@ +KERNEL_TYPE = nano +CONF_FILE = prj.conf +BOARD ?= qemu_x86 + +include $(ZEPHYR_BASE)/Makefile.inc diff --git a/tests/kernel/test_sleep/README.txt b/tests/kernel/test_sleep/README.txt new file mode 100644 index 0000000000..5eee5b73f2 --- /dev/null +++ b/tests/kernel/test_sleep/README.txt @@ -0,0 +1,45 @@ +Title: Nanokernel Sleep and Wakeup APIs + +Description: + +This test verifies that the nanokernel sleep and wakeup APIs operate as +expected. + +--------------------------------------------------------------------------- + +Building and Running Project: + +This nanokernel 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: + +tc_start() - Test Nanokernel Sleep and Wakeup APIs + +Nanokernel objects initialized +Test fiber started: id = 0x001030b8 +Helper fiber started: id = 0x001028e8 +Testing normal expiration of fiber_sleep() +Testing fiber_sleep() + fiber_fiber_wakeup() +Testing fiber_sleep() + isr_fiber_wakeup() +Testing fiber_sleep() + task_fiber_wakeup() +Testing nanokernel task_sleep() +=================================================================== +PROJECT EXECUTION SUCCESSFUL diff --git a/tests/kernel/test_sleep/prj.conf b/tests/kernel/test_sleep/prj.conf new file mode 100644 index 0000000000..db8ec41411 --- /dev/null +++ b/tests/kernel/test_sleep/prj.conf @@ -0,0 +1,6 @@ +# Let stack canaries use non-random number generator. +# This option is NOT to be used in production code. + +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NANO_TIMEOUTS=y +CONFIG_IRQ_OFFLOAD=y diff --git a/tests/kernel/test_sleep/src/Makefile b/tests/kernel/test_sleep/src/Makefile new file mode 100644 index 0000000000..478c688c2b --- /dev/null +++ b/tests/kernel/test_sleep/src/Makefile @@ -0,0 +1,3 @@ +ccflags-y += -I${srctree}/tests/include + +obj-y = sleep.o diff --git a/tests/kernel/test_sleep/src/sleep.c b/tests/kernel/test_sleep/src/sleep.c new file mode 100644 index 0000000000..d9d642b51a --- /dev/null +++ b/tests/kernel/test_sleep/src/sleep.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2016 Wind River Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file + * @brief Test nanokernel sleep and wakeup APIs + * + * This module tests the following sleep and wakeup scenarios: + * 1. fiber_sleep() without cancellation + * 2. fiber_sleep() cancelled via fiber_fiber_wakeup() + * 3. fiber_sleep() cancelled via isr_fiber_wakeup() + * 4. fiber_sleep() cancelled via task_fiber_wakeup() + * 5. task_sleep() - no cancellation exists + */ + +#include +#include +#include +#include +#include + +#include + +#define FIBER_STACKSIZE 256 + +#define TEST_FIBER_PRIORITY 4 +#define HELPER_FIBER_PRIORITY 10 + +#define ONE_SECOND (sys_clock_ticks_per_sec) + +static struct nano_sem test_fiber_sem; +static struct nano_sem helper_fiber_sem; +static struct nano_sem task_sem; + +static char __stack test_fiber_stack[FIBER_STACKSIZE]; +static char __stack helper_fiber_stack[FIBER_STACKSIZE]; + +static nano_thread_id_t test_fiber_id; +static nano_thread_id_t helper_fiber_id; + +static bool test_failure = true; /* Assume the test will fail */ + +static void test_objects_init(void) +{ + nano_sem_init(&test_fiber_sem); + nano_sem_init(&helper_fiber_sem); + nano_sem_init(&task_sem); + + TC_PRINT("Nanokernel objects initialized\n"); +} + +static void align_to_tick_boundary(void) +{ + uint32_t tick; + + tick = sys_tick_get_32(); + while (sys_tick_get_32() == tick) { + /* Busy wait to align to tick boundary */ + } +} + +static void test_fiber(int arg1, int arg2) +{ + uint32_t start_tick; + uint32_t end_tick; + + nano_fiber_sem_take(&test_fiber_sem, TICKS_UNLIMITED); + + TC_PRINT("Testing normal expiration of fiber_sleep()\n"); + align_to_tick_boundary(); + + start_tick = sys_tick_get_32(); + fiber_sleep(ONE_SECOND); + end_tick = sys_tick_get_32(); + + if (end_tick != start_tick + ONE_SECOND) { + TC_ERROR(" *** fiber_sleep() slept for %d ticks not %d.", + end_tick - start_tick, ONE_SECOND); + + return; + } + + TC_PRINT("Testing fiber_sleep() + fiber_fiber_wakeup()\n"); + nano_fiber_sem_give(&helper_fiber_sem); /* Activate helper fiber */ + align_to_tick_boundary(); + + start_tick = sys_tick_get_32(); + fiber_sleep(ONE_SECOND); + end_tick = sys_tick_get_32(); + + if (end_tick > start_tick) { + TC_ERROR(" *** fiber_fiber_wakeup() took too long (%d ticks)\n", + end_tick - start_tick); + return; + } + + TC_PRINT("Testing fiber_sleep() + isr_fiber_wakeup()\n"); + nano_fiber_sem_give(&helper_fiber_sem); /* Activate helper fiber */ + align_to_tick_boundary(); + + start_tick = sys_tick_get_32(); + fiber_sleep(ONE_SECOND); + end_tick = sys_tick_get_32(); + + if (end_tick > start_tick) { + TC_ERROR(" *** isr_fiber_wakeup() took too long (%d ticks)\n", + end_tick - start_tick); + return; + } + + TC_PRINT("Testing fiber_sleep() + task_fiber_wakeup()\n"); + nano_task_sem_give(&task_sem); /* Activate task */ + align_to_tick_boundary(); + + start_tick = sys_tick_get_32(); + fiber_sleep(ONE_SECOND); /* Task will execute */ + end_tick = sys_tick_get_32(); + + if (end_tick > start_tick) { + TC_ERROR(" *** task_fiber_wakeup() took too long (%d ticks)\n", + end_tick - start_tick); + return; + } + + test_failure = false; +} + +static void irq_offload_isr(void *arg) +{ + isr_fiber_wakeup((nano_thread_id_t) arg); +} + +static void helper_fiber(int arg1, int arg2) +{ + nano_fiber_sem_take(&helper_fiber_sem, TICKS_UNLIMITED); + + /* Wake the test fiber */ + fiber_fiber_wakeup(test_fiber_id); + nano_fiber_sem_take(&helper_fiber_sem, TICKS_UNLIMITED); + + /* Wake the test fiber from an ISR */ + irq_offload(irq_offload_isr, (void *)test_fiber_id); +} + +void main(void) +{ + int status = TC_FAIL; + uint32_t start_tick; + uint32_t end_tick; + + TC_START("Test Nanokernel Sleep and Wakeup APIs\n"); + + test_objects_init(); + + test_fiber_id = task_fiber_start(test_fiber_stack, FIBER_STACKSIZE, + test_fiber, 0, 0, TEST_FIBER_PRIORITY, 0); + TC_PRINT("Test fiber started: id = 0x%x\n", test_fiber_id); + + helper_fiber_id = task_fiber_start(helper_fiber_stack, FIBER_STACKSIZE, + helper_fiber, 0, 0, HELPER_FIBER_PRIORITY, 0); + TC_PRINT("Helper fiber started: id = 0x%x\n", helper_fiber_id); + + /* Activate test_fiber */ + nano_task_sem_give(&test_fiber_sem); + + /* Wait for test_fiber to activate us */ + nano_task_sem_take(&task_sem, TICKS_UNLIMITED); + + /* Wake the test fiber */ + task_fiber_wakeup(test_fiber_id); + + if (test_failure) { + goto done_tests; + } + + TC_PRINT("Testing nanokernel task_sleep()\n"); + align_to_tick_boundary(); + start_tick = sys_tick_get_32(); + task_sleep(ONE_SECOND); + end_tick = sys_tick_get_32(); + + if (end_tick - start_tick != ONE_SECOND) { + TC_ERROR("task_sleep() slept for %d ticks, not %d\n", + end_tick - start_tick, ONE_SECOND); + goto done_tests; + } + + status = TC_PASS; + +done_tests: + TC_END_REPORT(status); +} diff --git a/tests/kernel/test_sleep/testcase.ini b/tests/kernel/test_sleep/testcase.ini new file mode 100644 index 0000000000..914a14535f --- /dev/null +++ b/tests/kernel/test_sleep/testcase.ini @@ -0,0 +1,2 @@ +[test] +tags = core