ChibiOS/test/nil/configuration.xml

2316 lines
72 KiB
XML

<instance locked="false"
id="org.chibios.spc5.components.portable.chibios_unitary_tests_engine">
<description>
<brief>
<value>ChibiOS/NIL Test Suite.</value>
</brief>
<copyright>
<value><![CDATA[/*
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.
*/]]></value>
</copyright>
<introduction>
<value>Test suite for ChibiOS/NIL. The purpose of this suite is to
perform unit tests on the NIL modules and to converge to 100%
code coverage through successive improvements.</value>
</introduction>
</description>
<global_data_and_code>
<code_prefix>
<value>nil_</value>
</code_prefix>
<global_definitions>
<value><![CDATA[#define TEST_SUITE_NAME "ChibiOS/NIL Test Suite"
/*
* Allowed delay in timeout checks.
*/
#define ALLOWED_DELAY TIME_MS2I(2)
extern THD_WORKING_AREA(wa_common, 128);
systime_t test_wait_tick(void);]]></value>
</global_definitions>
<global_code>
<value><![CDATA[THD_WORKING_AREA(wa_common, 128);
/*
* Delays execution until next system time tick.
*/
systime_t test_wait_tick(void) {
chThdSleep(1);
return chVTGetSystemTimeX();
}]]></value>
</global_code>
</global_data_and_code>
<sequences>
<sequence>
<type index="0">
<value>Internal Tests</value>
</type>
<brief>
<value>Information.</value>
</brief>
<description>
<value>This sequence reports configuration and version
information about the NIL kernel.</value>
</description>
<condition>
<value />
</condition>
<shared_code>
<value><![CDATA[#include "ch.h"]]></value>
</shared_code>
<cases>
<case>
<brief>
<value>Port Info.</value>
</brief>
<description>
<value>Port-related info are reported.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value />
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value />
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>Prints the version string.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[#if defined(PORT_ARCHITECTURE_NAME)
test_print("--- Architecture: ");
test_println(PORT_ARCHITECTURE_NAME);
#endif
#if defined(PORT_CORE_VARIANT_NAME)
test_print("--- Core Variant: ");
test_println(PORT_CORE_VARIANT_NAME);
#endif
#if defined(PORT_COMPILER_NAME)
test_print("--- Compiler: ");
test_println(PORT_COMPILER_NAME);
#endif
#if defined(PORT_INFO)
test_print("--- Port Info: ");
test_println(PORT_INFO);
#endif
#if defined(PORT_NATURAL_ALIGN)
test_print("--- Natural alignment: ");
test_printn(PORT_NATURAL_ALIGN);
test_println("");
#endif
#if defined(PORT_STACK_ALIGN)
test_print("--- Stack alignment: ");
test_printn(PORT_STACK_ALIGN);
test_println("");
#endif
#if defined(PORT_WORKING_AREA_ALIGN)
test_print("--- Working area alignment: ");
test_printn(PORT_WORKING_AREA_ALIGN);
test_println("");
#endif]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Kernel Info.</value>
</brief>
<description>
<value>The version numbers are reported.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value />
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value />
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>Prints the version string.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[test_println("--- Product: ChibiOS/NIL");
test_print("--- Stable Flag: ");
test_printn(CH_KERNEL_STABLE);
test_println("");
test_print("--- Version String: ");
test_println(CH_KERNEL_VERSION);
test_print("--- Major Number: ");
test_printn(CH_KERNEL_MAJOR);
test_println("");
test_print("--- Minor Number: ");
test_printn(CH_KERNEL_MINOR);
test_println("");
test_print("--- Patch Number: ");
test_printn(CH_KERNEL_PATCH);
test_println("");]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Kernel Settings.</value>
</brief>
<description>
<value>The static kernel settings are reported.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value />
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value />
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>Prints the configuration options settings.
</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[test_print("--- CH_CFG_MAX_THREADS: ");
test_printn(CH_CFG_MAX_THREADS);
test_println("");
test_print("--- CH_CFG_AUTOSTART_THREADS: ");
test_printn(CH_CFG_AUTOSTART_THREADS);
test_println("");
test_print("--- CH_CFG_ST_RESOLUTION: ");
test_printn(CH_CFG_ST_RESOLUTION);
test_println("");
test_print("--- CH_CFG_ST_FREQUENCY: ");
test_printn(CH_CFG_ST_FREQUENCY);
test_println("");
test_print("--- CH_CFG_ST_TIMEDELTA: ");
test_printn(CH_CFG_ST_TIMEDELTA);
test_println("");
test_print("--- CH_CFG_USE_WAITEXIT: ");
test_printn(CH_CFG_USE_WAITEXIT);
test_println("");
test_print("--- CH_CFG_USE_SEMAPHORES: ");
test_printn(CH_CFG_USE_SEMAPHORES);
test_println("");
test_print("--- CH_CFG_USE_MUTEXES: ");
test_printn(CH_CFG_USE_MUTEXES);
test_println("");
test_print("--- CH_CFG_USE_EVENTS: ");
test_printn(CH_CFG_USE_EVENTS);
test_println("");
test_print("--- CH_CFG_USE_MESSAGES: ");
test_printn(CH_CFG_USE_MESSAGES);
test_println("");
test_print("--- CH_DBG_STATISTICS: ");
test_printn(CH_DBG_STATISTICS);
test_println("");
test_print("--- CH_DBG_SYSTEM_STATE_CHECK: ");
test_printn(CH_DBG_SYSTEM_STATE_CHECK);
test_println("");
test_print("--- CH_DBG_ENABLE_CHECKS: ");
test_printn(CH_DBG_ENABLE_CHECKS);
test_println("");
test_print("--- CH_DBG_ENABLE_ASSERTS: ");
test_printn(CH_DBG_ENABLE_ASSERTS);
test_println("");
test_print("--- CH_DBG_ENABLE_STACK_CHECK: ");
test_printn(CH_DBG_ENABLE_STACK_CHECK);
test_println("");]]></value>
</code>
</step>
</steps>
</case>
</cases>
</sequence>
<sequence>
<type index="0">
<value>Internal Tests</value>
</type>
<brief>
<value>Time and Intervals Functionality.</value>
</brief>
<description>
<value>This sequence tests the ChibiOS/NIL functionalities
related to time and intervals management.</value>
</description>
<condition>
<value />
</condition>
<shared_code>
<value><![CDATA[#include "ch.h"]]></value>
</shared_code>
<cases>
<case>
<brief>
<value>System Tick Counter functionality.</value>
</brief>
<description>
<value>The functionality of the API @p chVTGetSystemTimeX()
is tested.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value />
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value />
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>A System Tick Counter increment is expected, the
test simply hangs if it does not happen.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[systime_t time = chVTGetSystemTimeX();
while (time == chVTGetSystemTimeX()) {
}]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Time ranges functionality.</value>
</brief>
<description>
<value>The functionality of the API @p chTimeIsInRangeX() is
tested.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value />
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value />
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>Checking case where start == end, it must always
evaluate as not in range.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[
bool b;
b = chTimeIsInRangeX((systime_t)0, (systime_t)0, (systime_t)0);
test_assert(b == false, "in range");
b = chTimeIsInRangeX((systime_t)-1, (systime_t)0, (systime_t)0);
test_assert(b == false, "in range");
b = chTimeIsInRangeX((systime_t)0, (systime_t)-1, (systime_t)-1);
test_assert(b == false, "in range");
b = chTimeIsInRangeX((systime_t)-1, (systime_t)-1, (systime_t)-1);
test_assert(b == false, "in range");
]]></value>
</code>
</step>
<step>
<description>
<value>Checking boundaries for start &lt; end.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[
bool b;
b = chTimeIsInRangeX((systime_t)10, (systime_t)10, (systime_t)100);
test_assert(b == true, "not in range");
b = chTimeIsInRangeX((systime_t)9, (systime_t)10, (systime_t)100);
test_assert(b == false, "in range");
b = chTimeIsInRangeX((systime_t)99, (systime_t)10, (systime_t)100);
test_assert(b == true, "not in range");
b = chTimeIsInRangeX((systime_t)100, (systime_t)10, (systime_t)100);
test_assert(b == false, "in range");
]]></value>
</code>
</step>
<step>
<description>
<value>Checking boundaries for start &gt; end.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[
bool b;
b = chTimeIsInRangeX((systime_t)100, (systime_t)100, (systime_t)10);
test_assert(b == true, "not in range");
b = chTimeIsInRangeX((systime_t)99, (systime_t)100, (systime_t)10);
test_assert(b == false, "in range");
b = chTimeIsInRangeX((systime_t)9, (systime_t)100, (systime_t)10);
test_assert(b == true, "not in range");
b = chTimeIsInRangeX((systime_t)10, (systime_t)100, (systime_t)10);
test_assert(b == false, "in range");
]]></value>
</code>
</step>
</steps>
</case>
</cases>
</sequence>
<sequence>
<type index="0">
<value>Internal Tests</value>
</type>
<brief>
<value>Threads Functionality.</value>
</brief>
<description>
<value>This sequence tests the ChibiOS/NIL functionalities
related to threading.</value>
</description>
<condition>
<value />
</condition>
<shared_code>
<value><![CDATA[#include "ch.h"]]></value>
</shared_code>
<cases>
<case>
<brief>
<value>Thread Sleep functionality.</value>
</brief>
<description>
<value>The functionality of @p chThdSleep() and derivatives
is tested.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value />
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[systime_t time;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>The current system time is read then a sleep is
performed for 100 system ticks and on exit the system
time is verified again.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[time = chVTGetSystemTimeX();
chThdSleep(100);
test_assert_time_window(chTimeAddX(time, 100),
chTimeAddX(time, 100 + 1),
"out of time window");]]></value>
</code>
</step>
<step>
<description>
<value>The current system time is read then a sleep is
performed for 100000 microseconds and on exit the
system time is verified again.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[time = chVTGetSystemTimeX();
chThdSleepMicroseconds(100000);
test_assert_time_window(chTimeAddX(time, TIME_US2I(100000)),
chTimeAddX(time, TIME_US2I(100000) + 1),
"out of time window");]]></value>
</code>
</step>
<step>
<description>
<value>The current system time is read then a sleep is
performed for 100 milliseconds and on exit the system
time is verified again.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[time = chVTGetSystemTimeX();
chThdSleepMilliseconds(100);
test_assert_time_window(chTimeAddX(time, TIME_MS2I(100)),
chTimeAddX(time, TIME_MS2I(100) + 1),
"out of time window");]]></value>
</code>
</step>
<step>
<description>
<value>The current system time is read then a sleep is
performed for 1 second and on exit the system time is
verified again.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[time = chVTGetSystemTimeX();
chThdSleepSeconds(1);
test_assert_time_window(chTimeAddX(time, TIME_S2I(1)),
chTimeAddX(time, TIME_S2I(1) + 1),
"out of time window");]]></value>
</code>
</step>
<step>
<description>
<value>Function chThdSleepUntil() is tested with a
timeline of "now" + 100 ticks.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[time = chVTGetSystemTimeX();
chThdSleepUntil(chTimeAddX(time, 100));
test_assert_time_window(chTimeAddX(time, 100),
chTimeAddX(time, 100 + 1),
"out of time window");]]></value>
</code>
</step>
</steps>
</case>
</cases>
</sequence>
<sequence>
<type index="0">
<value>Internal Tests</value>
</type>
<brief>
<value>Semaphores.</value>
</brief>
<description>
<value>This sequence tests the ChibiOS/NIL functionalities
related to counter semaphores.</value>
</description>
<condition>
<value><![CDATA[CH_CFG_USE_SEMAPHORES == TRUE]]></value>
</condition>
<shared_code>
<value><![CDATA[#include "ch.h"
static thread_t *tp1;
static bool terminate;
static semaphore_t sem1, sem2;
/*
* Signaler thread.
*/
static THD_FUNCTION(signaler, arg) {
(void)arg;
/* Initializing global resources.*/
terminate = false;
chSemObjectInit(&sem1, 0);
chSemObjectInit(&sem2, 0);
while (!terminate) {
chSysLock();
if (chSemGetCounterI(&sem1) < 0)
chSemSignalI(&sem1);
chSemResetI(&sem2, 0);
chSchRescheduleS();
chSysUnlock();
chThdSleepMilliseconds(250);
}
}]]></value>
</shared_code>
<cases>
<case>
<brief>
<value>Semaphore primitives, no state change.</value>
</brief>
<description>
<value>Wait, Signal and Reset primitives are tested. The
testing thread does not trigger a state change.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value><![CDATA[chSemObjectInit(&sem1, 1);]]></value>
</setup_code>
<teardown_code>
<value><![CDATA[chSemReset(&sem1, 0);]]></value>
</teardown_code>
<local_variables>
<value />
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>The function chSemWait() is invoked, after return
the counter and the returned message are tested.
</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[msg_t msg;
msg = chSemWait(&sem1);
test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value");
test_assert(MSG_OK == msg, "wrong returned message");]]></value>
</code>
</step>
<step>
<description>
<value>The function chSemSignal() is invoked, after
return the counter is tested.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chSemSignal(&sem1);
test_assert_lock(chSemGetCounterI(&sem1) == 1, "wrong counter value");]]></value>
</code>
</step>
<step>
<description>
<value>The function chSemReset() is invoked, after
return the counter is tested.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chSemReset(&sem1, 2);
test_assert_lock(chSemGetCounterI(&sem1) == 2, "wrong counter value");]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Semaphore primitives, with state change.</value>
</brief>
<description>
<value>Wait, Signal and Reset primitives are tested. The
testing thread triggers a state change.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value><![CDATA[thread_descriptor_t td = {
.name = "signaler",
.wbase = wa_common,
.wend = THD_WORKING_AREA_END(wa_common),
.prio = chThdGetPriorityX() - 1,
.funcp = signaler,
.arg = NULL
};
tp1 = chThdCreate(&td);]]></value>
</setup_code>
<teardown_code>
<value><![CDATA[terminate = true;
chThdWait(tp1);]]></value>
</teardown_code>
<local_variables>
<value />
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>The function chSemWait() is invoked, after return
the counter and the returned message are tested. The
semaphore is signaled by another thread.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[msg_t msg;
msg = chSemWait(&sem1);
test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value");
test_assert(MSG_OK == msg, "wrong returned message");]]></value>
</code>
</step>
<step>
<description>
<value>The function chSemWait() is invoked, after return
the counter and the returned message are tested. The
semaphore is reset by another thread.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[msg_t msg;
msg = chSemWait(&sem2);
test_assert_lock(chSemGetCounterI(&sem2) == 0,"wrong counter value");
test_assert(MSG_RESET == msg, "wrong returned message");]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Semaphores timeout.</value>
</brief>
<description>
<value>Timeout on semaphores is tested.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value><![CDATA[chSemObjectInit(&sem1, 0);]]></value>
</setup_code>
<teardown_code>
<value><![CDATA[chSemReset(&sem1, 0);]]></value>
</teardown_code>
<local_variables>
<value><![CDATA[systime_t time;
msg_t msg;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>The function chSemWaitTimeout() is invoked a
first time, after return the system time, the counter
and the returned message are tested.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[time = chVTGetSystemTimeX();
msg = chSemWaitTimeout(&sem1, TIME_MS2I(1000));
test_assert_time_window(chTimeAddX(time, TIME_MS2I(1000)),
chTimeAddX(time, TIME_MS2I(1000) + 1),
"out of time window");
test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value");
test_assert(MSG_TIMEOUT == msg, "wrong timeout message");]]></value>
</code>
</step>
<step>
<description>
<value>The function chSemWaitTimeout() is invoked again,
after return the system time, the counter and the
returned message are tested.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[time = chVTGetSystemTimeX();
msg = chSemWaitTimeout(&sem1, TIME_MS2I(1000));
test_assert_time_window(chTimeAddX(time, TIME_MS2I(1000)),
chTimeAddX(time, TIME_MS2I(1000) + 1),
"out of time window");
test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value");
test_assert(MSG_TIMEOUT == msg, "wrong timeout message");]]></value>
</code>
</step>
</steps>
</case>
</cases>
</sequence>
<sequence>
<type index="0">
<value>Internal Tests</value>
</type>
<brief>
<value>Suspend/Resume.</value>
</brief>
<description>
<value>This sequence tests the ChibiOS/NIL functionalities
related to threads suspend/resume.</value>
</description>
<condition>
<value />
</condition>
<shared_code>
<value><![CDATA[static thread_t *tp1;
static bool terminate;
static thread_reference_t tr1;
/*
* Resumer thread.
*/
static THD_FUNCTION(resumer, arg) {
(void)arg;
/* Initializing global resources.*/
terminate = false;
tr1 = NULL;
while (!terminate) {
chThdResume(&tr1, MSG_OK);
chThdSleepMilliseconds(250);
}
}]]></value>
</shared_code>
<cases>
<case>
<brief>
<value>Suspend and Resume functionality.</value>
</brief>
<description>
<value>The functionality of chThdSuspendTimeoutS() and
chThdResumeI() is tested.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value><![CDATA[thread_descriptor_t td = {
.name = "resumer",
.wbase = wa_common,
.wend = THD_WORKING_AREA_END(wa_common),
.prio = chThdGetPriorityX() - 1,
.funcp = resumer,
.arg = NULL
};
tp1 = chThdCreate(&td);]]></value>
</setup_code>
<teardown_code>
<value><![CDATA[terminate = true;
chThdWait(tp1);]]></value>
</teardown_code>
<local_variables>
<value><![CDATA[systime_t time;
msg_t msg;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>The function chThdSuspendTimeoutS() is invoked,
the thread is remotely resumed with message @p MSG_OK.
On return the message and the state of the reference
are tested.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chSysLock();
msg = chThdSuspendTimeoutS(&tr1, TIME_INFINITE);
chSysUnlock();
test_assert(NULL == tr1, "not NULL");
test_assert(MSG_OK == msg,"wrong returned message");]]></value>
</code>
</step>
<step>
<description>
<value>The function chThdSuspendTimeoutS() is invoked,
the thread is not resumed so a timeout must occur. On
return the message and the state of the reference are
tested.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[thread_reference_t tr = NULL;
chSysLock();
time = chVTGetSystemTimeX();
msg = chThdSuspendTimeoutS(&tr, TIME_MS2I(1000));
chSysUnlock();
test_assert_time_window(chTimeAddX(time, TIME_MS2I(1000)),
chTimeAddX(time, TIME_MS2I(1000) + 1),
"out of time window");
test_assert(NULL == tr, "not NULL");
test_assert(MSG_TIMEOUT == msg, "wrong returned message");]]></value>
</code>
</step>
</steps>
</case>
</cases>
</sequence>
<sequence>
<type index="0">
<value>Internal Tests</value>
</type>
<brief>
<value>Event Sources and Event Flags.</value>
</brief>
<description>
<value>This module implements the test sequence for the Events
subsystem.</value>
</description>
<condition>
<value><![CDATA[CH_CFG_USE_EVENTS == TRUE]]></value>
</condition>
<shared_code>
<value><![CDATA[static EVENTSOURCE_DECL(es1);
static EVENTSOURCE_DECL(es2);
static void h1(eventid_t id) {(void)id;test_emit_token('A');}
static void h2(eventid_t id) {(void)id;test_emit_token('B');}
static void h3(eventid_t id) {(void)id;test_emit_token('C');}
static ROMCONST evhandler_t evhndl[] = {h1, h2, h3};
/*
* Direct events thread.
*/
static THD_FUNCTION(evtthd1, p) {
chThdSleepMilliseconds(50);
chEvtSignal((thread_t *)p, 1);
}
/*
* Broadcaster thread.
*/
static THD_FUNCTION(evtthd2, p) {
(void)p;
chEvtBroadcast(&es1);
chThdSleepMilliseconds(50);
chEvtBroadcast(&es2);
}]]></value>
</shared_code>
<cases>
<case>
<brief>
<value>Events registration.</value>
</brief>
<description>
<value>Two event listeners are registered on an event source
and then unregistered in the same order.&lt;br&gt;&#xD;
The test expects that the even source has listeners after
the registrations and after the first unregistration,
then, after the second unegistration, the test expects no
more listeners.
</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value />
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[event_listener_t el1, el2;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>An Event Source is initialized.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chEvtObjectInit(&es1);]]></value>
</code>
</step>
<step>
<description>
<value>Two Event Listeners are registered on the Event
Source, the Event Source is tested to have listeners.
</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chEvtRegisterMask(&es1, &el1, 1);
chEvtRegisterMask(&es1, &el2, 2);
test_assert_lock(chEvtIsListeningI(&es1), "no listener");]]></value>
</code>
</step>
<step>
<description>
<value>An Event Listener is unregistered, the Event
Source must still have listeners.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chEvtUnregister(&es1, &el1);
test_assert_lock(chEvtIsListeningI(&es1), "no listener");]]></value>
</code>
</step>
<step>
<description>
<value>An Event Listener is unregistered, the Event
Source must not have listeners.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chEvtUnregister(&es1, &el2);
test_assert_lock(!chEvtIsListeningI(&es1), "stuck listener");]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Event Flags dispatching.</value>
</brief>
<description>
<value>The test dispatches three event flags and verifies
that the associated event handlers are invoked in
LSb-first order.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);]]></value>
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value />
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>Three evenf flag bits are raised then
chEvtDispatch() is invoked, the sequence of handlers
calls is tested.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chEvtDispatch(evhndl, 7);
test_assert_sequence("ABC", "invalid sequence");]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Events Flags wait using chEvtWaitOne().</value>
</brief>
<description>
<value>Functionality of chEvtWaitOne() is tested under
various scenarios.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);]]></value>
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[eventmask_t m;
systime_t target_time;
thread_t *tp;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>Setting three event flags.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chEvtAddEvents(7);]]></value>
</code>
</step>
<step>
<description>
<value>Calling chEvtWaitOne() three times, each time a
single flag must be returned in order of priority.
</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[m = chEvtWaitOne(ALL_EVENTS);
test_assert(m == 1, "single event error");
m = chEvtWaitOne(ALL_EVENTS);
test_assert(m == 2, "single event error");
m = chEvtWaitOne(ALL_EVENTS);
test_assert(m == 4, "single event error");
m = chEvtGetAndClearEvents(ALL_EVENTS);
test_assert(m == 0, "stuck event");]]></value>
</code>
</step>
<step>
<description>
<value>Getting current time and starting a signaler
thread, the thread will set an event flag after 50mS.
</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[target_time = chTimeAddX(test_wait_tick(), TIME_MS2I(50));
thread_descriptor_t td = {
.name = "event1",
.wbase = wa_common,
.wend = THD_WORKING_AREA_END(wa_common),
.prio = chThdGetPriorityX() + 1,
.funcp = evtthd1,
.arg = chThdGetSelfX()
};
tp = chThdCreate(&td);]]></value>
</code>
</step>
<step>
<description>
<value>Calling chEvtWaitOne() then verifying that the
event has been received after 50mS and that the event
flags mask has been emptied.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[m = chEvtWaitOne(ALL_EVENTS);
test_assert_time_window(target_time,
chTimeAddX(target_time, ALLOWED_DELAY),
"out of time window");
test_assert(m == 1, "event flag error");
m = chEvtGetAndClearEvents(ALL_EVENTS);
test_assert(m == 0, "stuck event");
chThdWait(tp);]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Events Flags wait using chEvtWaitAny().</value>
</brief>
<description>
<value>Functionality of chEvtWaitAny() is tested under
various scenarios.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);]]></value>
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[eventmask_t m;
systime_t target_time;
thread_t *tp;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>Setting two, non contiguous, event flags.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chEvtAddEvents(5);]]></value>
</code>
</step>
<step>
<description>
<value>Calling chEvtWaitAny() one time, the two flags
must be returned.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[m = chEvtWaitAny(ALL_EVENTS);
test_assert(m == 5, "unexpected pending bit");
m = chEvtGetAndClearEvents(ALL_EVENTS);
test_assert(m == 0, "stuck event");]]></value>
</code>
</step>
<step>
<description>
<value>Getting current time and starting a signaler
thread, the thread will set an event flag after 50mS.
</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[target_time = chTimeAddX(test_wait_tick(), TIME_MS2I(50));
thread_descriptor_t td = {
.name = "event1",
.wbase = wa_common,
.wend = THD_WORKING_AREA_END(wa_common),
.prio = chThdGetPriorityX() + 1,
.funcp = evtthd1,
.arg = chThdGetSelfX()
};
tp = chThdCreate(&td);]]></value>
</code>
</step>
<step>
<description>
<value>Calling chEvtWaitAny() then verifying that the
event has been received after 50mS and that the event
flags mask has been emptied.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[m = chEvtWaitAny(ALL_EVENTS);
test_assert_time_window(target_time,
chTimeAddX(target_time, ALLOWED_DELAY),
"out of time window");
test_assert(m == 1, "event flag error");
m = chEvtGetAndClearEvents(ALL_EVENTS);
test_assert(m == 0, "stuck event");
chThdWait(tp);]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Events Flags wait using chEvtWaitAll().</value>
</brief>
<description>
<value>Functionality of chEvtWaitAll() is tested under
various scenarios.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);]]></value>
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[eventmask_t m;
systime_t target_time;
thread_t *tp;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>Setting two, non contiguous, event flags.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chEvtAddEvents(5);]]></value>
</code>
</step>
<step>
<description>
<value>Calling chEvtWaitAll() one time, the two flags
must be returned.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[m = chEvtWaitAll(5);
test_assert(m == 5, "unexpected pending bit");
m = chEvtGetAndClearEvents(ALL_EVENTS);
test_assert(m == 0, "stuck event");]]></value>
</code>
</step>
<step>
<description>
<value>Setting one event flag.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chEvtAddEvents(4);]]></value>
</code>
</step>
<step>
<description>
<value>Getting current time and starting a signaler
thread, the thread will set another event flag after
50mS.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[target_time = chTimeAddX(test_wait_tick(), TIME_MS2I(50));
thread_descriptor_t td = {
.name = "event1",
.wbase = wa_common,
.wend = THD_WORKING_AREA_END(wa_common),
.prio = chThdGetPriorityX() + 1,
.funcp = evtthd1,
.arg = chThdGetSelfX()
};
tp = chThdCreate(&td);]]></value>
</code>
</step>
<step>
<description>
<value>Calling chEvtWaitAll() then verifying that both
event flags have been received after 50mS and that the
event flags mask has been emptied.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[m = chEvtWaitAll(5);
test_assert_time_window(target_time,
chTimeAddX(target_time, ALLOWED_DELAY),
"out of time window");
test_assert(m == 5, "event flags error");
m = chEvtGetAndClearEvents(ALL_EVENTS);
test_assert(m == 0, "stuck event");
chThdWait(tp);]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Events Flags wait timeouts.</value>
</brief>
<description>
<value>Timeout functionality is tested for
chEvtWaitOneTimeout(), chEvtWaitAnyTimeout() and
chEvtWaitAllTimeout().</value>
</description>
<condition>
<value></value>
</condition>
<various_code>
<setup_code>
<value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);]]></value>
</setup_code>
<teardown_code>
<value />
</teardown_code>
F
<local_variables>
<value><![CDATA[eventmask_t m;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>The functions are invoked first with
TIME_IMMEDIATE timeout, the timeout condition is
tested.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[m = chEvtWaitOneTimeout(ALL_EVENTS, TIME_IMMEDIATE);
test_assert(m == 0, "spurious event");
m = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_IMMEDIATE);
test_assert(m == 0, "spurious event");
m = chEvtWaitAllTimeout(ALL_EVENTS, TIME_IMMEDIATE);
test_assert(m == 0, "spurious event");]]></value>
</code>
</step>
<step>
<description>
<value>The functions are invoked first with a 50mS
timeout, the timeout condition is tested.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[m = chEvtWaitOneTimeout(ALL_EVENTS, TIME_MS2I(50));
test_assert(m == 0, "spurious event");
m = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_MS2I(50));
test_assert(m == 0, "spurious event");
m = chEvtWaitAllTimeout(ALL_EVENTS, TIME_MS2I(50));
test_assert(m == 0, "spurious event");]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Broadcasting using chEvtBroadcast().</value>
</brief>
<description>
<value>Functionality of chEvtBroadcast() is tested.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);
chEvtObjectInit(&es1);
chEvtObjectInit(&es2);]]></value>
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[eventmask_t m;
event_listener_t el1, el2;
systime_t target_time;
thread_t *tp;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>Registering on two event sources associating them
with flags 1 and 4.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chEvtRegisterMask(&es1, &el1, 1);
chEvtRegisterMask(&es2, &el2, 4);]]></value>
</code>
</step>
<step>
<description>
<value>Getting current time and starting a broadcaster
thread, the thread broadcast the first Event Source
immediately and the other after 50mS.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[target_time = chTimeAddX(test_wait_tick(), TIME_MS2I(50));
thread_descriptor_t td = {
.name = "event2",
.wbase = wa_common,
.wend = THD_WORKING_AREA_END(wa_common),
.prio = chThdGetPriorityX() + 1,
.funcp = evtthd2,
.arg = NULL
};
tp = chThdCreate(&td);]]></value>
</code>
</step>
<step>
<description>
<value>Calling chEvtWaitAll() then verifying that both
event flags have been received after 50mS and that the
event flags mask has been emptied.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[m = chEvtWaitAll(5);
test_assert_time_window(target_time,
chTimeAddX(target_time, ALLOWED_DELAY),
"out of time window");
m = chEvtGetAndClearEvents(ALL_EVENTS);
test_assert(m == 0, "stuck event");
chThdWait(tp);]]></value>
</code>
</step>
<step>
<description>
<value>Unregistering from the Event Sources.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chEvtUnregister(&es1, &el1);
chEvtUnregister(&es2, &el2);
test_assert(!chEvtIsListeningI(&es1), "stuck listener");
test_assert(!chEvtIsListeningI(&es2), "stuck listener");]]></value>
</code>
</step>
</steps>
</case>
</cases>
</sequence>
<sequence>
<type index="0">
<value>Internal Tests</value>
</type>
<brief>
<value>Synchronous Messages.</value>
</brief>
<description>
<value>This module implements the test sequence for the
Synchronous Messages subsystem.</value>
</description>
<condition>
<value><![CDATA[CH_CFG_USE_MESSAGES == TRUE]]></value>
</condition>
<shared_code>
<value><![CDATA[/*
* Messager thread.
*/
static THD_FUNCTION(messenger, p) {
chMsgSend(p, 'A');
chMsgSend(p, 'B');
chMsgSend(p, 'C');
chMsgSend(p, 'D');
}]]></value>
</shared_code>
<cases>
<case>
<brief>
<value>Messages Server loop.</value>
</brief>
<description>
<value>A messenger thread is spawned that sends four
messages back to the tester thread.&lt;br&gt;&#xD;
The test expect to receive the messages in the correct sequence and
to not find a fifth message waiting.
</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value />
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[thread_t *tp, *tp1;
msg_t msg;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>Starting the messenger thread.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[
thread_descriptor_t td = {
.name = "messenger",
.wbase = wa_common,
.wend = THD_WORKING_AREA_END(wa_common),
.prio = chThdGetPriorityX() - 1,
.funcp = messenger,
.arg = chThdGetSelfX()
};
tp1 = chThdCreate(&td);]]></value>
</code>
</step>
<step>
<description>
<value>Waiting for four messages then testing the
receive order.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[unsigned i;
for (i = 0; i < 4; i++) {
tp = chMsgWait();
msg = chMsgGet(tp);
chMsgRelease(tp, msg);
test_emit_token(msg);
}
chThdWait(tp1);
test_assert_sequence("ABCD", "invalid sequence");]]></value>
</code>
</step>
</steps>
</case>
</cases>
</sequence>
<sequence>
<type index="2">
<value>Benchmarks</value>
</type>
<brief>
<value>Benchmarks.</value>
</brief>
<description>
<value>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.&lt;br&gt;&#xD;
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.
</value>
</description>
<condition>
<value />
</condition>
<shared_code>
<value><![CDATA[#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();
}]]></value>
</shared_code>
<cases>
<case>
<brief>
<value>Messages performance #1.</value>
</brief>
<description>
<value>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.</value>
</description>
<condition>
<value><![CDATA[CH_CFG_USE_MESSAGES == TRUE]]></value>
</condition>
<various_code>
<setup_code>
<value />
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[uint32_t n;
thread_t *tp;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>The messenger thread is started at a lower
priority than the current thread.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[
thread_descriptor_t td = {
.name = "messenger",
.wbase = wa_common,
.wend = THD_WORKING_AREA_END(wa_common),
.prio = chThdGetPriorityX() + 1,
.funcp = bmk_thread1,
.arg = NULL
};
tp = chThdCreate(&td);]]></value>
</code>
</step>
<step>
<description>
<value>The number of messages exchanged is counted in a
one second time window.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[n = msg_loop_test(tp);
chThdWait(tp);]]></value>
</code>
</step>
<step>
<description>
<value>Score is printed.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[test_print("--- Score : ");
test_printn(n);
test_print(" msgs/S, ");
test_printn(n << 1);
test_println(" ctxswc/S");]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Messages performance #2.</value>
</brief>
<description>
<value>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.</value>
</description>
<condition>
<value><![CDATA[CH_CFG_USE_MESSAGES == TRUE]]></value>
</condition>
<various_code>
<setup_code>
<value />
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[uint32_t n;
thread_t *tp;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>The messenger thread is started at an higher
priority than the current thread.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[
thread_descriptor_t td = {
.name = "messenger",
.wbase = wa_common,
.wend = THD_WORKING_AREA_END(wa_common),
.prio = chThdGetPriorityX() - 1,
.funcp = bmk_thread1,
.arg = NULL
};
tp = chThdCreate(&td);]]></value>
</code>
</step>
<step>
<description>
<value>The number of messages exchanged is counted in a
one second time window.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[n = msg_loop_test(tp);
chThdWait(tp);]]></value>
</code>
</step>
<step>
<description>
<value>Score is printed.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[test_print("--- Score : ");
test_printn(n);
test_print(" msgs/S, ");
test_printn(n << 1);
test_println(" ctxswc/S");]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Context Switch performance.</value>
</brief>
<description>
<value>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.&lt;br&gt;&#xD;
The Context Switch performance is calculated by measuring the number
of iterations after a second of continuous operations.
</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value />
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[thread_t *tp;
uint32_t n;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>Starting the target thread at an higher priority
level.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[
thread_descriptor_t td = {
.name = "messenger",
.wbase = wa_common,
.wend = THD_WORKING_AREA_END(wa_common),
.prio = chThdGetPriorityX() - 1,
.funcp = bmk_thread4,
.arg = NULL
};
tp = chThdCreate(&td);]]></value>
</code>
</step>
<step>
<description>
<value>Waking up the thread as fast as possible in a one
second time window.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[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));]]></value>
</code>
</step>
<step>
<description>
<value>Stopping the target thread.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[chSysLock();
chSchWakeupS(tp, MSG_TIMEOUT);
chSysUnlock();
chThdWait(tp);]]></value>
</code>
</step>
<step>
<description>
<value>Score is printed.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[test_print("--- Score : ");
test_printn(n * 2);
test_println(" ctxswc/S");]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Threads performance, full cycle.</value>
</brief>
<description>
<value>Threads are continuously created and terminated into
a loop. A full chThdCreateStatic() / @p chThdExit() / @p
chThdWait() cycle is performed in each
iteration.&lt;br&gt;&#xD;
The performance is calculated by measuring the number of iterations
after a second of continuous operations.
</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value />
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[uint32_t n;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>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.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[systime_t start, end;
thread_descriptor_t td = {
.name = "messenger",
.wbase = wa_common,
.wend = THD_WORKING_AREA_END(wa_common),
.prio = chThdGetPriorityX() + 1,
.funcp = bmk_thread3,
.arg = NULL
};
n = 0;
start = test_wait_tick();
end = chTimeAddX(start, TIME_MS2I(1000));
do {
chThdWait(chThdCreate(&td));
n++;
} while (chVTIsSystemTimeWithinX(start, end));]]></value>
</code>
</step>
<step>
<description>
<value>Score is printed.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[test_print("--- Score : ");
test_printn(n);
test_println(" threads/S");]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Threads performance, create/exit only.</value>
</brief>
<description>
<value>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.&lt;br&gt; The performance is calculated by
measuring the number of iterations after a second of
continuous operations.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value />
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[uint32_t n;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>A thread is created at an higher priority level
and let terminate immediately. The operation is
repeated continuously in a one-second time window.
</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[systime_t start, end;
thread_descriptor_t td = {
.name = "messenger",
.wbase = wa_common,
.wend = THD_WORKING_AREA_END(wa_common),
.prio = chThdGetPriorityX() - 1,
.funcp = bmk_thread3,
.arg = NULL
};
n = 0;
start = test_wait_tick();
end = chTimeAddX(start, TIME_MS2I(1000));
do {
chThdWait(chThdCreate(&td));
n++;
} while (chVTIsSystemTimeWithinX(start, end));]]></value>
</code>
</step>
<step>
<description>
<value>Score is printed.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[test_print("--- Score : ");
test_printn(n);
test_println(" threads/S");]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Semaphores wait/signal performance</value>
</brief>
<description>
<value>A counting semaphore is taken/released into a
continuous loop, no Context Switch happens because the
counter is always non negative.&lt;br&gt;&#xD;
The performance is calculated by measuring the number of iterations
after a second of continuous operations.
</value>
</description>
<condition>
<value><![CDATA[CH_CFG_USE_SEMAPHORES == TRUE]]></value>
</condition>
<various_code>
<setup_code>
<value><![CDATA[chSemObjectInit(&sem1, 1);]]></value>
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[uint32_t n;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>A semaphore is teken and released. The operation
is repeated continuously in a one-second time window.
</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[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));]]></value>
</code>
</step>
<step>
<description>
<value>The score is printed.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[test_print("--- Score : ");
test_printn(n * 4);
test_println(" wait+signal/S");]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>RAM Footprint.</value>
</brief>
<description>
<value>The memory size of the various kernel objects is
printed.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
<value />
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value />
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>The size of the system area is printed.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[test_print("--- OS : ");
test_printn(sizeof(os_instance_t));
test_println(" bytes");]]></value>
</code>
</step>
<step>
<description>
<value>The size of a thread structure is printed.
</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[test_print("--- Thread: ");
test_printn(sizeof(thread_t));
test_println(" bytes");]]></value>
</code>
</step>
<step>
<description>
<value>The size of a semaphore structure is printed.
</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[#if CH_CFG_USE_SEMAPHORES || defined(__DOXYGEN__)
test_print("--- Semaph: ");
test_printn(sizeof(semaphore_t));
test_println(" bytes");
#endif]]></value>
</code>
</step>
<step>
<description>
<value>The size of an event source is printed.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__)
test_print("--- EventS: ");
test_printn(sizeof(event_source_t));
test_println(" bytes");
#endif]]></value>
</code>
</step>
<step>
<description>
<value>The size of an event listener is printed.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__)
test_print("--- EventL: ");
test_printn(sizeof(event_listener_t));
test_println(" bytes");
#endif]]></value>
</code>
</step>
<step>
<description>
<value>The size of a mailbox is printed.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[#if CH_CFG_USE_MAILBOXES || defined(__DOXYGEN__)
test_print("--- MailB.: ");
test_printn(sizeof(mailbox_t));
test_println(" bytes");
#endif]]></value>
</code>
</step>
</steps>
</case>
</cases>
</sequence>
</sequences>
</instance>