From 14b7df7ccceba73b49778d6d8c3ec6e121c33596 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sun, 10 Feb 2019 17:13:55 +0000 Subject: [PATCH] Benchmarks added to Nil test suite. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12654 110e8d01-0319-4d1e-a829-52ad28d1bb01 --- demos/STM32/NIL-STM32F303-DISCOVERY/Makefile | 2 +- .../NIL-STM32F303-DISCOVERY/cfg/chconf.h | 6 +- os/nil/include/ch.h | 39 ++ os/nil/src/ch.c | 4 +- test/nil/configuration.xml | 656 +++++++++++++++++- test/nil/nil_test.mk | 3 +- test/nil/source/test/nil_test_root.c | 4 + test/nil/source/test/nil_test_root.h | 2 + test/nil/source/test/nil_test_sequence_003.c | 5 +- test/nil/source/test/nil_test_sequence_004.c | 5 +- test/nil/source/test/nil_test_sequence_005.c | 18 +- test/nil/source/test/nil_test_sequence_006.c | 5 +- test/nil/source/test/nil_test_sequence_007.c | 640 +++++++++++++++++ test/nil/source/test/nil_test_sequence_007.h | 27 + 14 files changed, 1370 insertions(+), 46 deletions(-) create mode 100644 test/nil/source/test/nil_test_sequence_007.c create mode 100644 test/nil/source/test/nil_test_sequence_007.h diff --git a/demos/STM32/NIL-STM32F303-DISCOVERY/Makefile b/demos/STM32/NIL-STM32F303-DISCOVERY/Makefile index 5bd9437d4..e9caa45fa 100644 --- a/demos/STM32/NIL-STM32F303-DISCOVERY/Makefile +++ b/demos/STM32/NIL-STM32F303-DISCOVERY/Makefile @@ -5,7 +5,7 @@ # Compiler options here. ifeq ($(USE_OPT),) - USE_OPT = -O0 -ggdb -fomit-frame-pointer -falign-functions=16 + USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16 endif # C specific options here (added to USE_OPT). diff --git a/demos/STM32/NIL-STM32F303-DISCOVERY/cfg/chconf.h b/demos/STM32/NIL-STM32F303-DISCOVERY/cfg/chconf.h index 5e49eb114..fe15db689 100644 --- a/demos/STM32/NIL-STM32F303-DISCOVERY/cfg/chconf.h +++ b/demos/STM32/NIL-STM32F303-DISCOVERY/cfg/chconf.h @@ -284,21 +284,21 @@ * * @note The default is @p FALSE. */ -#define CH_DBG_SYSTEM_STATE_CHECK TRUE +#define CH_DBG_SYSTEM_STATE_CHECK FALSE /** * @brief Debug option, parameters checks. * * @note The default is @p FALSE. */ -#define CH_DBG_ENABLE_CHECKS TRUE +#define CH_DBG_ENABLE_CHECKS FALSE /** * @brief System assertions. * * @note The default is @p FALSE. */ -#define CH_DBG_ENABLE_ASSERTS TRUE +#define CH_DBG_ENABLE_ASSERTS FALSE /** * @brief Stack check. diff --git a/os/nil/include/ch.h b/os/nil/include/ch.h index a16aec5a0..bd7a2ae6b 100644 --- a/os/nil/include/ch.h +++ b/os/nil/include/ch.h @@ -1049,6 +1049,29 @@ struct nil_system { port_unlock_from_isr(); \ } +/** + * @brief Puts the current thread to sleep into the specified state. + * + * @param[in] newstate the new thread state or a semaphore pointer + * @return The wakeup message. + * + * @sclass + */ +#define chSchGoSleepS(newstate) chSchGoSleepTimeoutS(newstate, TIME_INFINITE) + +/** + * @brief Wakes up a thread. + * + * @param[in] ntp the thread to be made ready + * @param[in] msg the wakeup message + * + * @sclass + */ +#define chSchWakeupS(ntp, msg) do { \ + chSchReadyI(ntp, msg); \ + chSchRescheduleS(); \ +} while (0) + /** * @brief Evaluates if a reschedule is required. * @@ -1203,6 +1226,22 @@ struct nil_system { #define chVTTimeElapsedSinceX(start) \ chTimeDiffX((start), chVTGetSystemTimeX()) +/** + * @brief Checks if the current system time is within the specified time + * window. + * @note When start==end then the function returns always true because the + * whole time range is specified. + * + * @param[in] start the start of the time window (inclusive) + * @param[in] end the end of the time window (non inclusive) + * @retval true current time within the specified time window. + * @retval false current time not within the specified time window. + * + * @xclass + */ +#define chVTIsSystemTimeWithinX(start, end) \ + chTimeIsInRangeX(chVTGetSystemTimeX(), start, end) + /** * @brief Adds an interval to a system time returning a system time. * diff --git a/os/nil/src/ch.c b/os/nil/src/ch.c index dd994c8a7..0d2c1aa79 100644 --- a/os/nil/src/ch.c +++ b/os/nil/src/ch.c @@ -655,7 +655,7 @@ void chSchRescheduleS(void) { * timeout specification. * @details The thread goes into a sleeping state, if it is not awakened * explicitly within the specified system time then it is forcibly - * awakened with a @p NIL_MSG_TMO low level message. + * awakened with a @p MSG_TIMEOUT low level message. * * @param[in] newstate the new thread state or a semaphore pointer * @param[in] timeout the number of ticks before the operation timeouts. @@ -663,7 +663,7 @@ void chSchRescheduleS(void) { * - @a TIME_INFINITE no timeout. * . * @return The wakeup message. - * @retval NIL_MSG_TMO if a timeout occurred. + * @retval MSG_TIMEOUT if a timeout occurred. * * @sclass */ diff --git a/test/nil/configuration.xml b/test/nil/configuration.xml index d50a37dcc..eeda9d7a4 100644 --- a/test/nil/configuration.xml +++ b/test/nil/configuration.xml @@ -45,10 +45,13 @@ */ #define ALLOWED_DELAY TIME_MS2I(2) +extern THD_WORKING_AREA(wa_common, 128); systime_t test_wait_tick(void);]]> - thread_config_t tc = { chThdGetPriorityX() + 1, "event1", - wa_evtthd1, - THD_WORKING_AREA_END(wa_evtthd1), + wa_common, + THD_WORKING_AREA_END(wa_common), evtthd1, chThdGetSelfX() }; @@ -1076,8 +1075,8 @@ test_assert(m == 0, "stuck event");]]> thread_config_t tc = { chThdGetPriorityX() + 1, "event1", - wa_evtthd1, - THD_WORKING_AREA_END(wa_evtthd1), + wa_common, + THD_WORKING_AREA_END(wa_common), evtthd1, chThdGetSelfX() }; @@ -1176,8 +1175,8 @@ test_assert(m == 0, "stuck event");]]> thread_config_t tc = { chThdGetPriorityX() + 1, "event1", - wa_evtthd1, - THD_WORKING_AREA_END(wa_evtthd1), + wa_common, + THD_WORKING_AREA_END(wa_common), evtthd1, chThdGetSelfX() }; @@ -1311,8 +1310,8 @@ chEvtRegisterMask(&es2, &el2, 4);]]> thread_config_t tc = { chThdGetPriorityX() + 1, "event2", - wa_evtthd2, - THD_WORKING_AREA_END(wa_evtthd2), + wa_common, + THD_WORKING_AREA_END(wa_common), evtthd2, NULL }; @@ -1371,7 +1370,6 @@ test_assert(!chEvtIsListeningI(&es2), "stuck listener");]]> + + + Benchmarks + + + Benchmarks. + + + This module implements a series of system benchmarks. The benchmarks are useful as a stress test and as a reference when comparing ChibiOS/RT with similar systems.<br> +Objective of the test sequence is to provide a performance index for the most critical system subsystems. The performance numbers allow to discover performance regressions between successive ChibiOS/RT releases. + + + + + + u1.msg; + } while (msg == MSG_OK); + chSysUnlock(); +}]]> + + + + + Messages performance #1. + + + A message server thread is created with a lower priority than the client thread, the messages throughput per second is measured and the result printed on the output log. + + + CH_CFG_USE_MESSAGES + + + + + + + + + + + + + + + + The messenger thread is started at a lower priority than the current thread. + + + + + + + + + + + The number of messages exchanged is counted in a one second time window. + + + + + + + + + + + Score is printed. + + + + + + + + + + + + + Messages performance #2. + + + A message server thread is created with an higher priority than the client thread, the messages throughput per second is measured and the result printed on the output log. + + + CH_CFG_USE_MESSAGES + + + + + + + + + + + + + + + + The messenger thread is started at an higher priority than the current thread. + + + + + + + + + + + The number of messages exchanged is counted in a one second time window. + + + + + + + + + + + Score is printed. + + + + + + + + + + + + + Context Switch performance. + + + A thread is created that just performs a @p chSchGoSleepS() into a loop, the thread is awakened as fast is possible by the tester thread.<br> +The Context Switch performance is calculated by measuring the number of iterations after a second of continuous operations. + + + + + + + + + + + + + + + + + + + Starting the target thread at an higher priority level. + + + + + + + + + + + Waking up the thread as fast as possible in a one second time window. + + + + + + + + + + + Stopping the target thread. + + + + + + + + + + + Score is printed. + + + + + + + + + + + + + Threads performance, full cycle. + + + Threads are continuously created and terminated into a loop. A full chThdCreateStatic() / @p chThdExit() / @p chThdWait() cycle is performed in each iteration.<br> +The performance is calculated by measuring the number of iterations after a second of continuous operations. + + + + + + + + + + + + + + + + + + + A thread is created at a lower priority level and its termination detected using @p chThdWait(). The operation is repeated continuously in a one-second time window. + + + + + + + + + + + Score is printed. + + + + + + + + + + + + + Threads performance, create/exit only. + + + Threads are continuously created and terminated into a loop. A partial @p chThdCreateStatic() / @p chThdExit() cycle is performed in each iteration, the @p chThdWait() is not necessary because the thread is created at an higher priority so there is no need to wait for it to terminate.<br> The performance is calculated by measuring the number of iterations after a second of continuous operations. + + + + + + + + + + + + + + + + + + + A thread is created at an higher priority level and let terminate immediately. The operation is repeated continuously in a one-second time window. + + + + + + + + + + + Score is printed. + + + + + + + + + + + + + Semaphores wait/signal performance + + + A counting semaphore is taken/released into a continuous loop, no Context Switch happens because the counter is always non negative.<br> +The performance is calculated by measuring the number of iterations after a second of continuous operations. + + + CH_CFG_USE_SEMAPHORES + + + + + + + + + + + + + + + + A semaphore is teken and released. The operation is repeated continuously in a one-second time window. + + + + + + + + + + + The score is printed. + + + + + + + + + + + + + RAM Footprint. + + + The memory size of the various kernel objects is printed. + + + + + + + + + + + + + + + + + + + The size of the system area is printed. + + + + + + + + + + + The size of a thread structure is printed. + + + + + + + + + + + The size of a semaphore structure is printed. + + + + + + + + + + + The size of an event source is printed. + + + + + + + + + + + The size of an event listener is printed. + + + + + + + + + + + The size of a mailbox is printed. + + + + + + + + + + + + diff --git a/test/nil/nil_test.mk b/test/nil/nil_test.mk index 220765268..63cf566d5 100644 --- a/test/nil/nil_test.mk +++ b/test/nil/nil_test.mk @@ -5,7 +5,8 @@ TESTSRC += ${CHIBIOS}/test/nil/source/test/nil_test_root.c \ ${CHIBIOS}/test/nil/source/test/nil_test_sequence_003.c \ ${CHIBIOS}/test/nil/source/test/nil_test_sequence_004.c \ ${CHIBIOS}/test/nil/source/test/nil_test_sequence_005.c \ - ${CHIBIOS}/test/nil/source/test/nil_test_sequence_006.c + ${CHIBIOS}/test/nil/source/test/nil_test_sequence_006.c \ + ${CHIBIOS}/test/nil/source/test/nil_test_sequence_007.c # Required include directories TESTINC += ${CHIBIOS}/test/nil/source/test diff --git a/test/nil/source/test/nil_test_root.c b/test/nil/source/test/nil_test_root.c index 41480de80..b0139d2c6 100644 --- a/test/nil/source/test/nil_test_root.c +++ b/test/nil/source/test/nil_test_root.c @@ -27,6 +27,7 @@ * - @subpage nil_test_sequence_004 * - @subpage nil_test_sequence_005 * - @subpage nil_test_sequence_006 + * - @subpage nil_test_sequence_007 * . */ @@ -60,6 +61,7 @@ const testsequence_t * const nil_test_suite_array[] = { #if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) &nil_test_sequence_006, #endif + &nil_test_sequence_007, NULL }; @@ -75,6 +77,8 @@ const testsuite_t nil_test_suite = { /* Shared code. */ /*===========================================================================*/ +THD_WORKING_AREA(wa_common, 128); + /* * Delays execution until next system time tick. */ diff --git a/test/nil/source/test/nil_test_root.h b/test/nil/source/test/nil_test_root.h index 8f2062092..d0eb22d3a 100644 --- a/test/nil/source/test/nil_test_root.h +++ b/test/nil/source/test/nil_test_root.h @@ -30,6 +30,7 @@ #include "nil_test_sequence_004.h" #include "nil_test_sequence_005.h" #include "nil_test_sequence_006.h" +#include "nil_test_sequence_007.h" #if !defined(__DOXYGEN__) @@ -57,6 +58,7 @@ extern "C" { */ #define ALLOWED_DELAY TIME_MS2I(2) +extern THD_WORKING_AREA(wa_common, 128); systime_t test_wait_tick(void); #endif /* !defined(__DOXYGEN__) */ diff --git a/test/nil/source/test/nil_test_sequence_003.c b/test/nil/source/test/nil_test_sequence_003.c index 9f8121cc3..f97f589d1 100644 --- a/test/nil/source/test/nil_test_sequence_003.c +++ b/test/nil/source/test/nil_test_sequence_003.c @@ -57,7 +57,6 @@ static semaphore_t sem1, sem2; /* * Signaler thread. */ -static THD_WORKING_AREA(wa_signaler, 128); static THD_FUNCTION(signaler, arg) { (void)arg; @@ -166,8 +165,8 @@ static void nil_test_003_002_setup(void) { thread_config_t tc = { chThdGetPriorityX() - 1, "signaler", - wa_signaler, - THD_WORKING_AREA_END(wa_signaler), + wa_common, + THD_WORKING_AREA_END(wa_common), signaler, NULL }; diff --git a/test/nil/source/test/nil_test_sequence_004.c b/test/nil/source/test/nil_test_sequence_004.c index 423eaa407..82f7d1377 100644 --- a/test/nil/source/test/nil_test_sequence_004.c +++ b/test/nil/source/test/nil_test_sequence_004.c @@ -45,7 +45,6 @@ static thread_reference_t tr1; /* * Resumer thread. */ -static THD_WORKING_AREA(wa_resumer, 128); static THD_FUNCTION(resumer, arg) { (void)arg; @@ -85,8 +84,8 @@ static void nil_test_004_001_setup(void) { thread_config_t tc = { chThdGetPriorityX() - 1, "resumer", - wa_resumer, - THD_WORKING_AREA_END(wa_resumer), + wa_common, + THD_WORKING_AREA_END(wa_common), resumer, NULL }; diff --git a/test/nil/source/test/nil_test_sequence_005.c b/test/nil/source/test/nil_test_sequence_005.c index 9e7eea5f3..d3c300aaf 100644 --- a/test/nil/source/test/nil_test_sequence_005.c +++ b/test/nil/source/test/nil_test_sequence_005.c @@ -62,7 +62,6 @@ static ROMCONST evhandler_t evhndl[] = {h1, h2, h3}; /* * Direct events thread. */ -static THD_WORKING_AREA(wa_evtthd1, 128); static THD_FUNCTION(evtthd1, p) { chThdSleepMilliseconds(50); @@ -72,7 +71,6 @@ static THD_FUNCTION(evtthd1, p) { /* * Broadcaster thread. */ -static THD_WORKING_AREA(wa_evtthd2, 128); static THD_FUNCTION(evtthd2, p) { (void)p; @@ -238,8 +236,8 @@ static void nil_test_005_003_execute(void) { thread_config_t tc = { chThdGetPriorityX() + 1, "event1", - wa_evtthd1, - THD_WORKING_AREA_END(wa_evtthd1), + wa_common, + THD_WORKING_AREA_END(wa_common), evtthd1, chThdGetSelfX() }; @@ -320,8 +318,8 @@ static void nil_test_005_004_execute(void) { thread_config_t tc = { chThdGetPriorityX() + 1, "event1", - wa_evtthd1, - THD_WORKING_AREA_END(wa_evtthd1), + wa_common, + THD_WORKING_AREA_END(wa_common), evtthd1, chThdGetSelfX() }; @@ -409,8 +407,8 @@ static void nil_test_005_005_execute(void) { thread_config_t tc = { chThdGetPriorityX() + 1, "event1", - wa_evtthd1, - THD_WORKING_AREA_END(wa_evtthd1), + wa_common, + THD_WORKING_AREA_END(wa_common), evtthd1, chThdGetSelfX() }; @@ -542,8 +540,8 @@ static void nil_test_005_007_execute(void) { thread_config_t tc = { chThdGetPriorityX() + 1, "event2", - wa_evtthd2, - THD_WORKING_AREA_END(wa_evtthd2), + wa_common, + THD_WORKING_AREA_END(wa_common), evtthd2, NULL }; diff --git a/test/nil/source/test/nil_test_sequence_006.c b/test/nil/source/test/nil_test_sequence_006.c index f3eaa4c7a..a30a0e343 100644 --- a/test/nil/source/test/nil_test_sequence_006.c +++ b/test/nil/source/test/nil_test_sequence_006.c @@ -49,7 +49,6 @@ /* * Messager thread. */ -static THD_WORKING_AREA(wa_messager, 128); static THD_FUNCTION(messager, p) { chMsgSend(p, 'A'); @@ -86,8 +85,8 @@ static void nil_test_006_001_execute(void) { thread_config_t tc = { chThdGetPriorityX() - 1, "messager", - wa_messager, - THD_WORKING_AREA_END(wa_messager), + wa_common, + THD_WORKING_AREA_END(wa_common), messager, chThdGetSelfX() }; diff --git a/test/nil/source/test/nil_test_sequence_007.c b/test/nil/source/test/nil_test_sequence_007.c new file mode 100644 index 000000000..0eb9f169e --- /dev/null +++ b/test/nil/source/test/nil_test_sequence_007.c @@ -0,0 +1,640 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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. +*/ + +#include "hal.h" +#include "nil_test_root.h" + +/** + * @file nil_test_sequence_007.c + * @brief Test Sequence 007 code. + * + * @page nil_test_sequence_007 [7] Benchmarks + * + * File: @ref nil_test_sequence_007.c + * + *

Description

+ * This module implements a series of system benchmarks. The benchmarks + * are useful as a stress test and as a reference when comparing + * ChibiOS/RT with similar systems.
Objective of the test sequence + * is to provide a performance index for the most critical system + * subsystems. The performance numbers allow to discover performance + * regressions between successive ChibiOS/RT releases. + * + *

Test Cases

+ * - @subpage nil_test_007_001 + * - @subpage nil_test_007_002 + * - @subpage nil_test_007_003 + * - @subpage nil_test_007_004 + * - @subpage nil_test_007_005 + * - @subpage nil_test_007_006 + * - @subpage nil_test_007_007 + * . + */ + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + +#if CH_CFG_USE_SEMAPHORES || defined(__DOXYGEN__) +static semaphore_t sem1; +#endif +#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__) +static mutex_t mtx1; +#endif + +#if CH_CFG_USE_MESSAGES +static THD_FUNCTION(bmk_thread1, p) { + thread_t *tp; + msg_t msg; + + (void)p; + do { + tp = chMsgWait(); + msg = chMsgGet(tp); + chMsgRelease(tp, msg); + } while (msg); +} + +NOINLINE static unsigned int msg_loop_test(thread_t *tp) { + systime_t start, end; + + uint32_t n = 0; + start = test_wait_tick(); + end = chTimeAddX(start, TIME_MS2I(1000)); + do { + (void)chMsgSend(tp, 1); + n++; +#if defined(SIMULATOR) + _sim_check_for_interrupts(); +#endif + } while (chVTIsSystemTimeWithinX(start, end)); + (void)chMsgSend(tp, 0); + return n; +} +#endif + +static THD_FUNCTION(bmk_thread3, p) { + + chThdExit((msg_t)p); +} + +static THD_FUNCTION(bmk_thread4, p) { + msg_t msg; + thread_t *self = chThdGetSelfX(); + + (void)p; + chSysLock(); + do { + chSchGoSleepS(NIL_STATE_SUSPENDED); + msg = self->u1.msg; + } while (msg == MSG_OK); + chSysUnlock(); +} + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) +/** + * @page nil_test_007_001 [7.1] Messages performance #1 + * + *

Description

+ * A message server thread is created with a lower priority than the + * client thread, the messages throughput per second is measured and + * the result printed on the output log. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_MESSAGES + * . + * + *

Test Steps

+ * - [7.1.1] The messenger thread is started at a lower priority than + * the current thread. + * - [7.1.2] The number of messages exchanged is counted in a one + * second time window. + * - [7.1.3] Score is printed. + * . + */ + +static void nil_test_007_001_execute(void) { + uint32_t n; + thread_t *tp; + + /* [7.1.1] The messenger thread is started at a lower priority than + the current thread.*/ + test_set_step(1); + { + thread_config_t tc = { + chThdGetPriorityX() + 1, + "messenger", + wa_common, + THD_WORKING_AREA_END(wa_common), + bmk_thread1, + NULL + }; + tp = chThdCreate(&tc); + } + + /* [7.1.2] The number of messages exchanged is counted in a one + second time window.*/ + test_set_step(2); + { + n = msg_loop_test(tp); + chThdWait(tp); + } + + /* [7.1.3] Score is printed.*/ + test_set_step(3); + { + test_print("--- Score : "); + test_printn(n); + test_print(" msgs/S, "); + test_printn(n << 1); + test_println(" ctxswc/S"); + } +} + +static const testcase_t nil_test_007_001 = { + "Messages performance #1", + NULL, + NULL, + nil_test_007_001_execute +}; +#endif /* CH_CFG_USE_MESSAGES */ + +#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) +/** + * @page nil_test_007_002 [7.2] Messages performance #2 + * + *

Description

+ * A message server thread is created with an higher priority than the + * client thread, the messages throughput per second is measured and + * the result printed on the output log. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_MESSAGES + * . + * + *

Test Steps

+ * - [7.2.1] The messenger thread is started at an higher priority than + * the current thread. + * - [7.2.2] The number of messages exchanged is counted in a one + * second time window. + * - [7.2.3] Score is printed. + * . + */ + +static void nil_test_007_002_execute(void) { + uint32_t n; + thread_t *tp; + + /* [7.2.1] The messenger thread is started at an higher priority than + the current thread.*/ + test_set_step(1); + { + thread_config_t tc = { + chThdGetPriorityX() - 1, + "messenger", + wa_common, + THD_WORKING_AREA_END(wa_common), + bmk_thread1, + NULL + }; + tp = chThdCreate(&tc); + } + + /* [7.2.2] The number of messages exchanged is counted in a one + second time window.*/ + test_set_step(2); + { + n = msg_loop_test(tp); + chThdWait(tp); + } + + /* [7.2.3] Score is printed.*/ + test_set_step(3); + { + test_print("--- Score : "); + test_printn(n); + test_print(" msgs/S, "); + test_printn(n << 1); + test_println(" ctxswc/S"); + } +} + +static const testcase_t nil_test_007_002 = { + "Messages performance #2", + NULL, + NULL, + nil_test_007_002_execute +}; +#endif /* CH_CFG_USE_MESSAGES */ + +/** + * @page nil_test_007_003 [7.3] Context Switch performance + * + *

Description

+ * A thread is created that just performs a @p chSchGoSleepS() into a + * loop, the thread is awakened as fast is possible by the tester + * thread.
The Context Switch performance is calculated by + * measuring the number of iterations after a second of continuous + * operations. + * + *

Test Steps

+ * - [7.3.1] Starting the target thread at an higher priority level. + * - [7.3.2] Waking up the thread as fast as possible in a one second + * time window. + * - [7.3.3] Stopping the target thread. + * - [7.3.4] Score is printed. + * . + */ + +static void nil_test_007_003_execute(void) { + thread_t *tp; + uint32_t n; + + /* [7.3.1] Starting the target thread at an higher priority level.*/ + test_set_step(1); + { + thread_config_t tc = { + chThdGetPriorityX() - 1, + "messenger", + wa_common, + THD_WORKING_AREA_END(wa_common), + bmk_thread4, + NULL + }; + tp = chThdCreate(&tc); + } + + /* [7.3.2] Waking up the thread as fast as possible in a one second + time window.*/ + test_set_step(2); + { + systime_t start, end; + + n = 0; + start = test_wait_tick(); + end = chTimeAddX(start, TIME_MS2I(1000)); + do { + chSysLock(); + chSchWakeupS(tp, MSG_OK); + chSchWakeupS(tp, MSG_OK); + chSchWakeupS(tp, MSG_OK); + chSchWakeupS(tp, MSG_OK); + chSysUnlock(); + n += 4; + } while (chVTIsSystemTimeWithinX(start, end)); + } + + /* [7.3.3] Stopping the target thread.*/ + test_set_step(3); + { + chSysLock(); + chSchWakeupS(tp, MSG_TIMEOUT); + chSysUnlock(); + chThdWait(tp); + } + + /* [7.3.4] Score is printed.*/ + test_set_step(4); + { + test_print("--- Score : "); + test_printn(n * 2); + test_println(" ctxswc/S"); + } +} + +static const testcase_t nil_test_007_003 = { + "Context Switch performance", + NULL, + NULL, + nil_test_007_003_execute +}; + +/** + * @page nil_test_007_004 [7.4] Threads performance, full cycle + * + *

Description

+ * Threads are continuously created and terminated into a loop. A full + * chThdCreateStatic() / @p chThdExit() / @p chThdWait() cycle is + * performed in each iteration.
The performance is calculated by + * measuring the number of iterations after a second of continuous + * operations. + * + *

Test Steps

+ * - [7.4.1] A thread is created at a lower priority level and its + * termination detected using @p chThdWait(). The operation is + * repeated continuously in a one-second time window. + * - [7.4.2] Score is printed. + * . + */ + +static void nil_test_007_004_execute(void) { + uint32_t n; + + /* [7.4.1] A thread is created at a lower priority level and its + termination detected using @p chThdWait(). The operation is + repeated continuously in a one-second time window.*/ + test_set_step(1); + { + systime_t start, end; + thread_config_t tc = { + chThdGetPriorityX() + 1, + "messenger", + wa_common, + THD_WORKING_AREA_END(wa_common), + bmk_thread3, + NULL + }; + + n = 0; + start = test_wait_tick(); + end = chTimeAddX(start, TIME_MS2I(1000)); + do { + chThdWait(chThdCreate(&tc)); + n++; + } while (chVTIsSystemTimeWithinX(start, end)); + } + + /* [7.4.2] Score is printed.*/ + test_set_step(2); + { + test_print("--- Score : "); + test_printn(n); + test_println(" threads/S"); + } +} + +static const testcase_t nil_test_007_004 = { + "Threads performance, full cycle", + NULL, + NULL, + nil_test_007_004_execute +}; + +/** + * @page nil_test_007_005 [7.5] Threads performance, create/exit only + * + *

Description

+ * Threads are continuously created and terminated into a loop. A + * partial @p chThdCreateStatic() / @p chThdExit() cycle is performed + * in each iteration, the @p chThdWait() is not necessary because the + * thread is created at an higher priority so there is no need to wait + * for it to terminate.
The performance is calculated by measuring + * the number of iterations after a second of continuous operations. + * + *

Test Steps

+ * - [7.5.1] A thread is created at an higher priority level and let + * terminate immediately. The operation is repeated continuously in a + * one-second time window. + * - [7.5.2] Score is printed. + * . + */ + +static void nil_test_007_005_execute(void) { + uint32_t n; + + /* [7.5.1] A thread is created at an higher priority level and let + terminate immediately. The operation is repeated continuously in a + one-second time window.*/ + test_set_step(1); + { + systime_t start, end; + thread_config_t tc = { + chThdGetPriorityX() - 1, + "messenger", + wa_common, + THD_WORKING_AREA_END(wa_common), + bmk_thread3, + NULL + }; + + n = 0; + start = test_wait_tick(); + end = chTimeAddX(start, TIME_MS2I(1000)); + do { + chThdWait(chThdCreate(&tc)); + n++; + } while (chVTIsSystemTimeWithinX(start, end)); + } + + /* [7.5.2] Score is printed.*/ + test_set_step(2); + { + test_print("--- Score : "); + test_printn(n); + test_println(" threads/S"); + } +} + +static const testcase_t nil_test_007_005 = { + "Threads performance, create/exit only", + NULL, + NULL, + nil_test_007_005_execute +}; + +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) +/** + * @page nil_test_007_006 [7.6] Semaphores wait/signal performance + * + *

Description

+ * A counting semaphore is taken/released into a continuous loop, no + * Context Switch happens because the counter is always non + * negative.
The performance is calculated by measuring the number + * of iterations after a second of continuous operations. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_SEMAPHORES + * . + * + *

Test Steps

+ * - [7.6.1] A semaphore is teken and released. The operation is + * repeated continuously in a one-second time window. + * - [7.6.2] The score is printed. + * . + */ + +static void nil_test_007_006_setup(void) { + chSemObjectInit(&sem1, 1); +} + +static void nil_test_007_006_execute(void) { + uint32_t n; + + /* [7.6.1] A semaphore is teken and released. The operation is + repeated continuously in a one-second time window.*/ + test_set_step(1); + { + systime_t start, end; + + n = 0; + start = test_wait_tick(); + end = chTimeAddX(start, TIME_MS2I(1000)); + do { + chSemWait(&sem1); + chSemSignal(&sem1); + chSemWait(&sem1); + chSemSignal(&sem1); + chSemWait(&sem1); + chSemSignal(&sem1); + chSemWait(&sem1); + chSemSignal(&sem1); + n++; +#if defined(SIMULATOR) + _sim_check_for_interrupts(); +#endif + } while (chVTIsSystemTimeWithinX(start, end)); + } + + /* [7.6.2] The score is printed.*/ + test_set_step(2); + { + test_print("--- Score : "); + test_printn(n * 4); + test_println(" wait+signal/S"); + } +} + +static const testcase_t nil_test_007_006 = { + "Semaphores wait/signal performance", + nil_test_007_006_setup, + NULL, + nil_test_007_006_execute +}; +#endif /* CH_CFG_USE_SEMAPHORES */ + +/** + * @page nil_test_007_007 [7.7] RAM Footprint + * + *

Description

+ * The memory size of the various kernel objects is printed. + * + *

Test Steps

+ * - [7.7.1] The size of the system area is printed. + * - [7.7.2] The size of a thread structure is printed. + * - [7.7.3] The size of a semaphore structure is printed. + * - [7.7.4] The size of an event source is printed. + * - [7.7.5] The size of an event listener is printed. + * - [7.7.6] The size of a mailbox is printed. + * . + */ + +static void nil_test_007_007_execute(void) { + + /* [7.7.1] The size of the system area is printed.*/ + test_set_step(1); + { + test_print("--- System: "); + test_printn(sizeof(nil_system_t)); + test_println(" bytes"); + } + + /* [7.7.2] The size of a thread structure is printed.*/ + test_set_step(2); + { + test_print("--- Thread: "); + test_printn(sizeof(thread_t)); + test_println(" bytes"); + } + + /* [7.7.3] The size of a semaphore structure is printed.*/ + test_set_step(3); + { +#if CH_CFG_USE_SEMAPHORES || defined(__DOXYGEN__) + test_print("--- Semaph: "); + test_printn(sizeof(semaphore_t)); + test_println(" bytes"); +#endif + } + + /* [7.7.4] The size of an event source is printed.*/ + test_set_step(4); + { +#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__) + test_print("--- EventS: "); + test_printn(sizeof(event_source_t)); + test_println(" bytes"); +#endif + } + + /* [7.7.5] The size of an event listener is printed.*/ + test_set_step(5); + { +#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__) + test_print("--- EventL: "); + test_printn(sizeof(event_listener_t)); + test_println(" bytes"); +#endif + } + + /* [7.7.6] The size of a mailbox is printed.*/ + test_set_step(6); + { +#if CH_CFG_USE_MAILBOXES || defined(__DOXYGEN__) + test_print("--- MailB.: "); + test_printn(sizeof(mailbox_t)); + test_println(" bytes"); +#endif + } +} + +static const testcase_t nil_test_007_007 = { + "RAM Footprint", + NULL, + NULL, + nil_test_007_007_execute +}; + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Array of test cases. + */ +const testcase_t * const nil_test_sequence_007_array[] = { +#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) + &nil_test_007_001, +#endif +#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) + &nil_test_007_002, +#endif + &nil_test_007_003, + &nil_test_007_004, + &nil_test_007_005, +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) + &nil_test_007_006, +#endif + &nil_test_007_007, + NULL +}; + +/** + * @brief Benchmarks. + */ +const testsequence_t nil_test_sequence_007 = { + "Benchmarks", + nil_test_sequence_007_array +}; diff --git a/test/nil/source/test/nil_test_sequence_007.h b/test/nil/source/test/nil_test_sequence_007.h new file mode 100644 index 000000000..5d0aa97d9 --- /dev/null +++ b/test/nil/source/test/nil_test_sequence_007.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 nil_test_sequence_007.h + * @brief Test Sequence 007 header. + */ + +#ifndef NIL_TEST_SEQUENCE_007_H +#define NIL_TEST_SEQUENCE_007_H + +extern const testsequence_t nil_test_sequence_007; + +#endif /* NIL_TEST_SEQUENCE_007_H */