Fixed bugs 2789377 and 2789383.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@956 35acf78f-673a-0410-8e92-d51de3d6d3f4
master
gdisirio 2009-05-09 13:06:30 +00:00
parent fa6758bb7a
commit 824e30be80
14 changed files with 168 additions and 44 deletions

View File

@ -83,6 +83,7 @@
* - @subpage test_threads * - @subpage test_threads
* - @subpage test_dynamic * - @subpage test_dynamic
* - @subpage test_msg * - @subpage test_msg
* - @subpage test_mtx
* - @subpage test_events * - @subpage test_events
* - @subpage test_mbox * - @subpage test_mbox
* - @subpage test_queues * - @subpage test_queues
@ -230,8 +231,8 @@
* In ChibiOS/RT the Unlock operations are always performed in Lock-reverse * In ChibiOS/RT the Unlock operations are always performed in Lock-reverse
* order. The Unlock API does not even have a parameter, the mutex to unlock * order. The Unlock API does not even have a parameter, the mutex to unlock
* is taken from an internal stack of owned mutexes. * is taken from an internal stack of owned mutexes.
* This both improves the performance and is required by the priority * This both improves the performance and is required by an efficient
* inheritance mechanism. * implementation of the priority inheritance mechanism.
* *
* <h2>The priority inversion problem</h2> * <h2>The priority inversion problem</h2>
* The mutexes in ChibiOS/RT implements the <b>full</b> priority * The mutexes in ChibiOS/RT implements the <b>full</b> priority

View File

@ -75,6 +75,8 @@ Win32-MinGW - ChibiOS/RT simulator and demo into a WIN32 process,
- FIX: Found new instances of the obsolete function chSysGetTime() in the - FIX: Found new instances of the obsolete function chSysGetTime() in the
C++ wrapper and in the WEB demo (bug 2772237)(backported in stable branch). C++ wrapper and in the WEB demo (bug 2772237)(backported in stable branch).
- FIX: Fixed macro in test.h (bug 2781176)(backported in stable branch). - FIX: Fixed macro in test.h (bug 2781176)(backported in stable branch).
- FIX: Fixed sequence assertion in test.c (bug 2789377)(backported in stable
branch).
- NEW: Abstract I/O Channels mechanism introduced. This mechanism allows to - NEW: Abstract I/O Channels mechanism introduced. This mechanism allows to
access I/O resources through a standard interface and hides implementation access I/O resources through a standard interface and hides implementation
details. The existing serial drivers were modified to offer a standard details. The existing serial drivers were modified to offer a standard

View File

@ -145,6 +145,7 @@ bool_t _test_assert_sequence(unsigned point, char *expected) {
} }
if (*expected) if (*expected)
return _test_fail(point); return _test_fail(point);
clear_tokens();
return FALSE; return FALSE;
} }
@ -174,16 +175,17 @@ void test_wait_threads(void) {
} }
} }
void test_cpu_pulse(unsigned ms) { #if CH_DBG_THREADS_PROFILING
void test_cpu_pulse(unsigned duration) {
systime_t duration = MS2ST(ms); systime_t end = chThdSelf()->p_time + MS2ST(duration);
systime_t start = chTimeNow(); while (chThdSelf()->p_time < end) {
while (chTimeIsWithin(start, start + duration)) {
#if defined(WIN32) #if defined(WIN32)
ChkIntSources(); ChkIntSources();
#endif #endif
} }
} }
#endif
systime_t test_wait_tick(void) { systime_t test_wait_tick(void) {

View File

@ -62,8 +62,10 @@ extern "C" {
void test_terminate_threads(void); void test_terminate_threads(void);
void test_wait_threads(void); void test_wait_threads(void);
systime_t test_wait_tick(void); systime_t test_wait_tick(void);
void test_cpu_pulse(unsigned ms);
void test_start_timer(unsigned ms); void test_start_timer(unsigned ms);
#if CH_DBG_THREADS_PROFILING
void test_cpu_pulse(unsigned duration);
#endif
#if defined(WIN32) #if defined(WIN32)
void ChkIntSources(void); void ChkIntSources(void);
#endif #endif
@ -72,7 +74,7 @@ extern "C" {
#endif #endif
#define test_fail(point) { \ #define test_fail(point) { \
_test_fail(point); \ _test_fail(point); \
return; \ return; \
} }

View File

@ -30,7 +30,7 @@
* *
* <h2>Objective</h2> * <h2>Objective</h2>
* Objective of the test module is to cover 100% of the dynamic APIs code * Objective of the test module is to cover 100% of the dynamic APIs code
* as a necessary step in order to assess their readyness. * as a necessary step in order to assess their maturity.
* *
* <h2>Preconditions</h2> * <h2>Preconditions</h2>
* The module requires the following kernel options: * The module requires the following kernel options:

View File

@ -29,7 +29,7 @@
* *
* <h2>Objective</h2> * <h2>Objective</h2>
* Objective of the test module is to cover 100% of the @ref Events subsystem * Objective of the test module is to cover 100% of the @ref Events subsystem
* code as a necessary step in order to assess its readyness. * code as a necessary step in order to assess its maturity level.
* *
* <h2>Preconditions</h2> * <h2>Preconditions</h2>
* The module requires the following kernel options: * The module requires the following kernel options:

View File

@ -29,7 +29,7 @@
* *
* <h2>Objective</h2> * <h2>Objective</h2>
* Objective of the test module is to cover 100% of the @ref Heap subsystem * Objective of the test module is to cover 100% of the @ref Heap subsystem
* code as a necessary step in order to assess its readyness. * code as a necessary step in order to assess its maturity level.
* *
* <h2>Preconditions</h2> * <h2>Preconditions</h2>
* The module requires the following kernel options: * The module requires the following kernel options:

View File

@ -29,7 +29,10 @@
* *
* <h2>Objective</h2> * <h2>Objective</h2>
* Objective of the test module is to cover 100% of the @ref Mailboxes * Objective of the test module is to cover 100% of the @ref Mailboxes
* subsystem code as a necessary step in order to assess its readyness. * subsystem code as a necessary step in order to assess its maturity
* level.<br>
* Note that the @ref Mailboxes subsystem depends on the @ref Semaphores
* subsystem that has to met its testing objectives as well.
* *
* <h2>Preconditions</h2> * <h2>Preconditions</h2>
* The module requires the following kernel options: * The module requires the following kernel options:

View File

@ -29,7 +29,7 @@
* *
* <h2>Objective</h2> * <h2>Objective</h2>
* Objective of the test module is to cover 100% of the @ref Messages * Objective of the test module is to cover 100% of the @ref Messages
* subsystem code as a necessary step in order to assess its readyness. * subsystem code as a necessary step in order to assess its maturity level.
* *
* <h2>Preconditions</h2> * <h2>Preconditions</h2>
* The module requires the following kernel options: * The module requires the following kernel options:

View File

@ -21,6 +21,44 @@
#include "test.h" #include "test.h"
/**
* @page test_mtx Mutexes test
*
* <h2>Description</h2>
* This module implements the test sequence for the @ref Mutexes and
* @ref CondVars subsystems.<br>
* Tests on those subsystems are particularly critical because the system-wide
* implications of the Priority Inheritance mechanism.
*
* <h2>Objective</h2>
* Objective of the test module is to cover 100% of the subsystem code
* as a necessary step in order to assess their maturity level.
*
* <h2>Preconditions</h2>
* The module requires the following kernel options:
* - @p CH_USE_MUTEXES
* - @p CH_USE_CONDVARS
* - @p CH_DBG_THREADS_PROFILING
* .
* In case some of the required options are not enabled then some or all tests
* may be skipped.
*
* <h2>Test Cases</h2>
* - @subpage test_mtx_001
* - @subpage test_mtx_002
* - @subpage test_mtx_003
* - @subpage test_mtx_004
* - @subpage test_mtx_005
* - @subpage test_mtx_006
* - @subpage test_mtx_007
* - @subpage test_mtx_008
* .
* @file testmtx.c
* @brief @ref Mutexes and @ref CondVars test source file
* @file testmtx.h
* @brief @ref Mutexes and @ref CondVars test header file
*/
#if CH_USE_MUTEXES #if CH_USE_MUTEXES
#define ALLOWED_DELAY 5 #define ALLOWED_DELAY 5
@ -28,6 +66,15 @@
static Mutex m1, m2; static Mutex m1, m2;
static CondVar c1; static CondVar c1;
/**
* @page test_mtx_001 Priority enqueuing test
*
* <h2>Description</h2>
* Five threads, with increasing priority, are enqueued on a locked mutex then
* the mutex is unlocked.<br>
* The test expects the threads to perform their operations in increasing
* priority order regardless of the initial order.
*/
static char *mtx1_gettest(void) { static char *mtx1_gettest(void) {
return "Mutexes, priority enqueuing test"; return "Mutexes, priority enqueuing test";
@ -68,6 +115,38 @@ const struct testcase testmtx1 = {
mtx1_execute mtx1_execute
}; };
/**
* @page test_mtx_002 Priority inheritance, simple case
*
* <h2>Description</h2>
* Three threads are involved in the classic priority inversion scenario, a
* medium priority thread tries to starve an high priority thread by
* blocking a low priority thread into a mutex lock zone.<br>
* The test expects the threads to perform their operations in increasing
* priority order by rearranging their priorities in order to avoid the
* priority inversion trap.
*
* <h2>Scenario</h2>
* This weird looking diagram should explain what happens in the test case:
* @code
* Time ----> 0 10 20 30 40 50 60 70 80 90 100
* 0 ......AL++++++++++............2+++++++++++AU0---------------++++++G...
* 1 ..................++++++++++++------------------++++++++++++G.........
* 2 .............................AL..........++++++AUG...................
* ^ ^
*
* Legend:
* 0..2 - Priority levels
* +++ - Running
* --- - Ready
* ... - Waiting
* AL - Lock operation on mutex A
* AUn - Unlock operation on mutex A with priority going to level 'n'
* G - Goal
* ^ - Priority transition (boost or return).
* @endcode
*/
static char *mtx2_gettest(void) { static char *mtx2_gettest(void) {
return "Mutexes, priority inheritance, simple case"; return "Mutexes, priority inheritance, simple case";
@ -78,45 +157,48 @@ static void mtx2_setup(void) {
chMtxInit(&m1); chMtxInit(&m1);
} }
static msg_t thread2(void *p) { /* Low priority thread */
static msg_t thread2L(void *p) {
chThdSleepMilliseconds(10);
chMtxLock(&m1); chMtxLock(&m1);
test_cpu_pulse(40);
chMtxUnlock(); chMtxUnlock();
test_emit_token(*(char *)p); test_cpu_pulse(10);
test_emit_token('C');
return 0; return 0;
} }
static msg_t thread3(void *p) { /* Medium priority thread */
static msg_t thread2M(void *p) {
chMtxLock(&m1);
chThdSleepMilliseconds(40);
chMtxUnlock();
test_emit_token(*(char *)p);
return 0;
}
static msg_t thread4(void *p) {
chThdSleepMilliseconds(20); chThdSleepMilliseconds(20);
test_cpu_pulse(50); test_cpu_pulse(40);
test_emit_token(*(char *)p); test_emit_token('B');
return 0; return 0;
} }
/* /* High priority thread */
* Time static msg_t thread2H(void *p) {
* 0 ++++++++++++++++++AL+....2++++++++++++++AU0------------------------------
* 1 .....................++--------------------------------------------------
* 2 .......................++AL.............+++++++++AU++++++++++++++++++++++
*/
static void mtx2_execute(void) {
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()-1, thread2, "A"); chThdSleepMilliseconds(40);
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()-3, thread3, "C"); chMtxLock(&m1);
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()-2, thread4, "B"); test_cpu_pulse(10);
chMtxUnlock();
test_emit_token('A');
return 0;
}
static void mtx2_execute(void) {
systime_t time;
test_wait_tick();
time = chTimeNow();
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()-1, thread2H, 0);
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()-3, thread2L, 0);
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()-2, thread2M, 0);
test_wait_threads(); test_wait_threads();
test_assert_sequence(1, "ABC"); test_assert_sequence(1, "ABC");
test_assert_time_window(2, time + MS2ST(100), time + MS2ST(100) + ALLOWED_DELAY);
} }
const struct testcase testmtx2 = { const struct testcase testmtx2 = {
@ -126,6 +208,38 @@ const struct testcase testmtx2 = {
mtx2_execute mtx2_execute
}; };
/**
* @page test_mtx_003 Priority inheritance, complex case
*
* <h2>Description</h2>
* Five threads are involved in the complex priority inversion scenario,
* please refer to the diagram below for the complete scenario.<br>
* The test expects the threads to perform their operations in increasing
* priority order by rearranging their priorities in order to avoid the
* priority inversion trap.
*
* <h2>Scenario</h2>
* This weird looking diagram should explain what happens in the test case:
* @code
* Time ---->
* 0 10 20 30 40 50
* 0 +++BL++------------------2++++------4+++++BU0--------------------------
* 1 .......++AL++--2+++++++++BL.........4.....++++++++BU4++++AU1-----------
* 2 .............++AL............................................------++AU
* 3 ..............................++++-------------------------------++....
* 4 ..................................++AL...................++++AU++......
* ^ ^
*
* Legend:
* 0..2 - Priority levels
* +++ - Running
* --- - Ready
* ... - Waiting
* AL - Lock operation on mutex A
* AUn - Unlock operation on mutex A with priority going to level 'n'
* ^ - Priority transition (boost or return).
* @endcode
*/
static char *mtx3_gettest(void) { static char *mtx3_gettest(void) {
return "Mutexes, priority inheritance, complex case"; return "Mutexes, priority inheritance, complex case";

View File

@ -32,7 +32,7 @@
* *
* <h2>Objective</h2> * <h2>Objective</h2>
* Objective of the test module is to cover 100% of the @ref IOQueues code * Objective of the test module is to cover 100% of the @ref IOQueues code
* as a necessary step in order to assess its readyness.<br> * as a necessary step in order to assess its maturity level.<br>
* Note that the @ref IOQueues subsystem depends on the @ref Semaphores * Note that the @ref IOQueues subsystem depends on the @ref Semaphores
* subsystem that has to met its testing objectives as well. * subsystem that has to met its testing objectives as well.
* *

View File

@ -32,7 +32,7 @@
* *
* <h2>Objective</h2> * <h2>Objective</h2>
* Objective of the test module is to cover 100% of the @ref Serial code * Objective of the test module is to cover 100% of the @ref Serial code
* as a necessary step in order to assess its readyness.<br> * as a necessary step in order to assess its maturity level.<br>
* Note that the @ref Serial subsystem depends on the @ref Semaphores and * Note that the @ref Serial subsystem depends on the @ref Semaphores and
* @ref Events subsystems that have to met their testing objectives as well. * @ref Events subsystems that have to met their testing objectives as well.
* *

View File

@ -28,12 +28,12 @@
* This module implements the test sequence for the @ref Scheduler, * This module implements the test sequence for the @ref Scheduler,
* @ref Threads and @ref Time subsystems.<br> * @ref Threads and @ref Time subsystems.<br>
* Note that the tests on those subsystems are formally required but most of * Note that the tests on those subsystems are formally required but most of
* their functionality is already demostrated because the test suite itself * their functionality is already demonstrated because the test suite itself
* depends on them, anyway doublecheck is good. * depends on them, anyway double check is good.
* *
* <h2>Objective</h2> * <h2>Objective</h2>
* Objective of the test module is to cover 100% of the subsystems code * Objective of the test module is to cover 100% of the subsystems code
* as a necessary step in order to assess their readyness. * as a necessary step in order to assess their maturity level.
* *
* <h2>Preconditions</h2> * <h2>Preconditions</h2>
* None. * None.

View File

@ -8,11 +8,11 @@ After 1.2.0:
* Abstract I/O channels rather than just serial ports. * Abstract I/O channels rather than just serial ports.
? Move the serial drivers implementations in library. Better keep the core ? Move the serial drivers implementations in library. Better keep the core
as compact as possible. as compact as possible.
X Add tests documentation to the general documentation via doxygen.
- Static object initializers. - Static object initializers.
- Remove any instance of unnamed structures/unions. - Remove any instance of unnamed structures/unions.
- Objects registry in the kernel. - Objects registry in the kernel.
- OSEK-style simple tasks within the idle thread. - OSEK-style simple tasks within the idle thread.
- Add tests documentation to the general documentation via doxygen.
- Code examples into the documentation. - Code examples into the documentation.
- Dedicated syscalls.c support for newlib users. - Dedicated syscalls.c support for newlib users.
- Threads Pools manager in the library. - Threads Pools manager in the library.