Benchmarks added to Nil test suite.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12654 110e8d01-0319-4d1e-a829-52ad28d1bb01
This commit is contained in:
parent
d6fa7fed19
commit
14b7df7ccc
|
@ -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).
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -45,10 +45,13 @@
|
|||
*/
|
||||
#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[/*
|
||||
<value><![CDATA[THD_WORKING_AREA(wa_common, 128);
|
||||
|
||||
/*
|
||||
* Delays execution until next system time tick.
|
||||
*/
|
||||
systime_t test_wait_tick(void) {
|
||||
|
@ -449,7 +452,6 @@ static semaphore_t sem1, sem2;
|
|||
/*
|
||||
* Signaler thread.
|
||||
*/
|
||||
static THD_WORKING_AREA(wa_signaler, 128);
|
||||
static THD_FUNCTION(signaler, arg) {
|
||||
|
||||
(void)arg;
|
||||
|
@ -550,8 +552,8 @@ test_assert_lock(chSemGetCounterI(&sem1) == 2, "wrong counter value");]]></value
|
|||
<value><![CDATA[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
|
||||
};
|
||||
|
@ -680,7 +682,6 @@ static thread_reference_t tr1;
|
|||
/*
|
||||
* Resumer thread.
|
||||
*/
|
||||
static THD_WORKING_AREA(wa_resumer, 128);
|
||||
static THD_FUNCTION(resumer, arg) {
|
||||
|
||||
(void)arg;
|
||||
|
@ -711,8 +712,8 @@ static THD_FUNCTION(resumer, arg) {
|
|||
<value><![CDATA[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
|
||||
};
|
||||
|
@ -793,7 +794,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);
|
||||
|
@ -803,7 +803,6 @@ static THD_FUNCTION(evtthd1, p) {
|
|||
/*
|
||||
* Broadcaster thread.
|
||||
*/
|
||||
static THD_WORKING_AREA(wa_evtthd2, 128);
|
||||
static THD_FUNCTION(evtthd2, p) {
|
||||
|
||||
(void)p;
|
||||
|
@ -987,8 +986,8 @@ test_assert(m == 0, "stuck event");]]></value>
|
|||
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");]]></value>
|
|||
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");]]></value>
|
|||
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);]]></value>
|
|||
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");]]></value>
|
|||
<value><![CDATA[/*
|
||||
* Messager thread.
|
||||
*/
|
||||
static THD_WORKING_AREA(wa_messager, 128);
|
||||
static THD_FUNCTION(messager, p) {
|
||||
|
||||
chMsgSend(p, 'A');
|
||||
|
@ -1416,8 +1414,8 @@ msg_t msg;]]></value>
|
|||
<value><![CDATA[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()
|
||||
};
|
||||
|
@ -1448,6 +1446,624 @@ test_assert_sequence("ABCD", "invalid sequence");]]></value>
|
|||
</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.<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.</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>CH_CFG_USE_MESSAGES</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_config_t tc = {
|
||||
chThdGetPriorityX() + 1,
|
||||
"messenger",
|
||||
wa_common,
|
||||
THD_WORKING_AREA_END(wa_common),
|
||||
bmk_thread1,
|
||||
NULL
|
||||
};
|
||||
tp = chThdCreate(&tc);]]></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>CH_CFG_USE_MESSAGES</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_config_t tc = {
|
||||
chThdGetPriorityX() - 1,
|
||||
"messenger",
|
||||
wa_common,
|
||||
THD_WORKING_AREA_END(wa_common),
|
||||
bmk_thread1,
|
||||
NULL
|
||||
};
|
||||
tp = chThdCreate(&tc);]]></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.<br>
|
||||
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_config_t tc = {
|
||||
chThdGetPriorityX() - 1,
|
||||
"messenger",
|
||||
wa_common,
|
||||
THD_WORKING_AREA_END(wa_common),
|
||||
bmk_thread4,
|
||||
NULL
|
||||
};
|
||||
tp = chThdCreate(&tc);]]></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.<br>
|
||||
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_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));]]></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.<br> 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_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));]]></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.<br>
|
||||
The performance is calculated by measuring the number of iterations after a second of continuous operations.</value>
|
||||
</description>
|
||||
<condition>
|
||||
<value>CH_CFG_USE_SEMAPHORES</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("--- System: ");
|
||||
test_printn(sizeof(nil_system_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>
|
||||
</instances>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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()
|
||||
};
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* 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.
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @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
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* 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.
|
||||
*
|
||||
* <h2>Conditions</h2>
|
||||
* This test is only executed if the following preprocessor condition
|
||||
* evaluates to true:
|
||||
* - CH_CFG_USE_MESSAGES
|
||||
* .
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [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
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* 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.
|
||||
*
|
||||
* <h2>Conditions</h2>
|
||||
* This test is only executed if the following preprocessor condition
|
||||
* evaluates to true:
|
||||
* - CH_CFG_USE_MESSAGES
|
||||
* .
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [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
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* 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.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [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
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* 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.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [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
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* 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.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [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
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* 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.
|
||||
*
|
||||
* <h2>Conditions</h2>
|
||||
* This test is only executed if the following preprocessor condition
|
||||
* evaluates to true:
|
||||
* - CH_CFG_USE_SEMAPHORES
|
||||
* .
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [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
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The memory size of the various kernel objects is printed.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [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
|
||||
};
|
|
@ -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 */
|
Loading…
Reference in New Issue