Extended state check to all kernel I-class and s-class APIs, corrected some test cases where call protocol rules were not strictly observerd. No the whole test suite pass with the state checker enabled.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3223 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
gdisirio 2011-08-12 11:10:19 +00:00
parent e0309ba973
commit 43752ee8d1
20 changed files with 170 additions and 45 deletions

View File

@ -361,7 +361,7 @@
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_SYSTEM_STATE_CHECK) || defined(__DOXYGEN__) #if !defined(CH_DBG_SYSTEM_STATE_CHECK) || defined(__DOXYGEN__)
#define CH_DBG_SYSTEM_STATE_CHECK FALSE #define CH_DBG_SYSTEM_STATE_CHECK TRUE
#endif #endif
/** /**
@ -372,7 +372,7 @@
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__) #if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
#define CH_DBG_ENABLE_CHECKS FALSE #define CH_DBG_ENABLE_CHECKS TRUE
#endif #endif
/** /**
@ -384,7 +384,7 @@
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__) #if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
#define CH_DBG_ENABLE_ASSERTS FALSE #define CH_DBG_ENABLE_ASSERTS TRUE
#endif #endif
/** /**
@ -395,7 +395,7 @@
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__) #if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__)
#define CH_DBG_ENABLE_TRACE FALSE #define CH_DBG_ENABLE_TRACE TRUE
#endif #endif
/** /**
@ -409,7 +409,7 @@
* @p panic_msg variable set to @p NULL. * @p panic_msg variable set to @p NULL.
*/ */
#if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__) #if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)
#define CH_DBG_ENABLE_STACK_CHECK FALSE #define CH_DBG_ENABLE_STACK_CHECK TRUE
#endif #endif
/** /**
@ -421,7 +421,7 @@
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__) #if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__)
#define CH_DBG_FILL_THREADS FALSE #define CH_DBG_FILL_THREADS TRUE
#endif #endif
/** /**

View File

@ -86,6 +86,8 @@
#define dbg_check_unlock_from_isr() #define dbg_check_unlock_from_isr()
#define dbg_check_enter_isr() #define dbg_check_enter_isr()
#define dbg_check_leave_isr() #define dbg_check_leave_isr()
#define chDbgCheckClassI();
#define chDbgCheckClassS();
#endif #endif
/*===========================================================================*/ /*===========================================================================*/
@ -211,6 +213,8 @@ extern "C" {
void dbg_check_unlock_from_isr(void); void dbg_check_unlock_from_isr(void);
void dbg_check_enter_isr(void); void dbg_check_enter_isr(void);
void dbg_check_leave_isr(void); void dbg_check_leave_isr(void);
void chDbgCheckClassI(void);
void chDbgCheckClassS(void);
#endif #endif
#if CH_DBG_ENABLE_TRACE || defined(__DOXYGEN__) #if CH_DBG_ENABLE_TRACE || defined(__DOXYGEN__)
void _trace_init(void); void _trace_init(void);

View File

@ -86,6 +86,7 @@ void chCondSignal(CondVar *cp) {
*/ */
void chCondSignalI(CondVar *cp) { void chCondSignalI(CondVar *cp) {
chDbgCheckClassI();
chDbgCheck(cp != NULL, "chCondSignalI"); chDbgCheck(cp != NULL, "chCondSignalI");
if (notempty(&cp->c_queue)) if (notempty(&cp->c_queue))
@ -120,6 +121,7 @@ void chCondBroadcast(CondVar *cp) {
*/ */
void chCondBroadcastI(CondVar *cp) { void chCondBroadcastI(CondVar *cp) {
chDbgCheckClassI();
chDbgCheck(cp != NULL, "chCondBroadcastI"); chDbgCheck(cp != NULL, "chCondBroadcastI");
/* Empties the condition variable queue and inserts all the Threads into the /* Empties the condition variable queue and inserts all the Threads into the
@ -177,6 +179,7 @@ msg_t chCondWaitS(CondVar *cp) {
Mutex *mp; Mutex *mp;
msg_t msg; msg_t msg;
chDbgCheckClassS();
chDbgCheck(cp != NULL, "chCondWaitS"); chDbgCheck(cp != NULL, "chCondWaitS");
chDbgAssert(ctp->p_mtxlist != NULL, chDbgAssert(ctp->p_mtxlist != NULL,
"chCondWaitS(), #1", "chCondWaitS(), #1",
@ -261,6 +264,7 @@ msg_t chCondWaitTimeoutS(CondVar *cp, systime_t time) {
Mutex *mp; Mutex *mp;
msg_t msg; msg_t msg;
chDbgCheckClassS();
chDbgCheck((cp != NULL) && (time != TIME_IMMEDIATE), "chCondWaitTimeoutS"); chDbgCheck((cp != NULL) && (time != TIME_IMMEDIATE), "chCondWaitTimeoutS");
chDbgAssert(currp->p_mtxlist != NULL, chDbgAssert(currp->p_mtxlist != NULL,
"chCondWaitTimeoutS(), #1", "chCondWaitTimeoutS(), #1",

View File

@ -35,6 +35,8 @@
* - SV#7, misplaced @p chSysUnlockFromIsr(). * - SV#7, misplaced @p chSysUnlockFromIsr().
* - SV#8, misplaced @p CH_IRQ_PROLOGUE(). * - SV#8, misplaced @p CH_IRQ_PROLOGUE().
* - SV#9, misplaced @p CH_IRQ_EPILOGUE(). * - SV#9, misplaced @p CH_IRQ_EPILOGUE().
* - SV#10, misplaced I-class function.
* - SV#11, misplaced S-class function.
* . * .
* - Trace buffer. * - Trace buffer.
* - Parameters check. * - Parameters check.
@ -153,7 +155,7 @@ void dbg_check_unlock_from_isr(void) {
void dbg_check_enter_isr(void) { void dbg_check_enter_isr(void) {
port_lock_from_isr(); port_lock_from_isr();
if (dbg_isr_cnt < 0) if ((dbg_isr_cnt < 0) || (dbg_lock_cnt != 0))
chDbgPanic("SV#8"); chDbgPanic("SV#8");
dbg_isr_cnt++; dbg_isr_cnt++;
port_unlock_from_isr(); port_unlock_from_isr();
@ -167,12 +169,40 @@ void dbg_check_enter_isr(void) {
void dbg_check_leave_isr(void) { void dbg_check_leave_isr(void) {
port_lock_from_isr(); port_lock_from_isr();
if (dbg_isr_cnt <= 0) if ((dbg_isr_cnt <= 0) || (dbg_lock_cnt != 0))
chDbgPanic("SV#9"); chDbgPanic("SV#9");
dbg_isr_cnt--; dbg_isr_cnt--;
port_unlock_from_isr(); port_unlock_from_isr();
} }
/**
* @brief I-class functions context check.
* @details Verifies that the system is in an appropriate state for invoking
* an I-class API function. A panic is generated if the state is
* not compatible.
*
* @api
*/
void chDbgCheckClassI(void) {
if ((dbg_isr_cnt < 0) || (dbg_lock_cnt <= 0))
chDbgPanic("SV#10");
}
/**
* @brief S-class functions context check.
* @details Verifies that the system is in an appropriate state for invoking
* an S-class API function. A panic is generated if the state is
* not compatible.
*
* @api
*/
void chDbgCheckClassS(void) {
if ((dbg_isr_cnt != 0) || (dbg_lock_cnt <= 0))
chDbgPanic("SV#11");
}
#endif /* CH_DBG_SYSTEM_STATE_CHECK */ #endif /* CH_DBG_SYSTEM_STATE_CHECK */
/*===========================================================================*/ /*===========================================================================*/

View File

@ -185,6 +185,7 @@ void chEvtSignalFlags(Thread *tp, eventmask_t mask) {
*/ */
void chEvtSignalFlagsI(Thread *tp, eventmask_t mask) { void chEvtSignalFlagsI(Thread *tp, eventmask_t mask) {
chDbgCheckClassI();
chDbgCheck(tp != NULL, "chEvtSignalI"); chDbgCheck(tp != NULL, "chEvtSignalI");
tp->p_epending |= mask; tp->p_epending |= mask;
@ -237,6 +238,7 @@ void chEvtBroadcastFlags(EventSource *esp, eventmask_t mask) {
void chEvtBroadcastFlagsI(EventSource *esp, eventmask_t mask) { void chEvtBroadcastFlagsI(EventSource *esp, eventmask_t mask) {
EventListener *elp; EventListener *elp;
chDbgCheckClassI();
chDbgCheck(esp != NULL, "chEvtBroadcastMaskI"); chDbgCheck(esp != NULL, "chEvtBroadcastMaskI");
elp = esp->es_next; elp = esp->es_next;

View File

@ -143,6 +143,7 @@ msg_t chMBPost(Mailbox *mbp, msg_t msg, systime_t time) {
msg_t chMBPostS(Mailbox *mbp, msg_t msg, systime_t time) { msg_t chMBPostS(Mailbox *mbp, msg_t msg, systime_t time) {
msg_t rdymsg; msg_t rdymsg;
chDbgCheckClassS();
chDbgCheck(mbp != NULL, "chMBPostS"); chDbgCheck(mbp != NULL, "chMBPostS");
rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time); rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time);
@ -172,6 +173,7 @@ msg_t chMBPostS(Mailbox *mbp, msg_t msg, systime_t time) {
*/ */
msg_t chMBPostI(Mailbox *mbp, msg_t msg) { msg_t chMBPostI(Mailbox *mbp, msg_t msg) {
chDbgCheckClassI();
chDbgCheck(mbp != NULL, "chMBPostI"); chDbgCheck(mbp != NULL, "chMBPostI");
if (chSemGetCounterI(&mbp->mb_emptysem) <= 0) if (chSemGetCounterI(&mbp->mb_emptysem) <= 0)
@ -234,6 +236,7 @@ msg_t chMBPostAhead(Mailbox *mbp, msg_t msg, systime_t time) {
msg_t chMBPostAheadS(Mailbox *mbp, msg_t msg, systime_t time) { msg_t chMBPostAheadS(Mailbox *mbp, msg_t msg, systime_t time) {
msg_t rdymsg; msg_t rdymsg;
chDbgCheckClassS();
chDbgCheck(mbp != NULL, "chMBPostAheadS"); chDbgCheck(mbp != NULL, "chMBPostAheadS");
rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time); rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time);
@ -263,6 +266,7 @@ msg_t chMBPostAheadS(Mailbox *mbp, msg_t msg, systime_t time) {
*/ */
msg_t chMBPostAheadI(Mailbox *mbp, msg_t msg) { msg_t chMBPostAheadI(Mailbox *mbp, msg_t msg) {
chDbgCheckClassI();
chDbgCheck(mbp != NULL, "chMBPostAheadI"); chDbgCheck(mbp != NULL, "chMBPostAheadI");
if (chSemGetCounterI(&mbp->mb_emptysem) <= 0) if (chSemGetCounterI(&mbp->mb_emptysem) <= 0)
@ -325,6 +329,7 @@ msg_t chMBFetch(Mailbox *mbp, msg_t *msgp, systime_t time) {
msg_t chMBFetchS(Mailbox *mbp, msg_t *msgp, systime_t time) { msg_t chMBFetchS(Mailbox *mbp, msg_t *msgp, systime_t time) {
msg_t rdymsg; msg_t rdymsg;
chDbgCheckClassS();
chDbgCheck((mbp != NULL) && (msgp != NULL), "chMBFetchS"); chDbgCheck((mbp != NULL) && (msgp != NULL), "chMBFetchS");
rdymsg = chSemWaitTimeoutS(&mbp->mb_fullsem, time); rdymsg = chSemWaitTimeoutS(&mbp->mb_fullsem, time);
@ -354,6 +359,7 @@ msg_t chMBFetchS(Mailbox *mbp, msg_t *msgp, systime_t time) {
*/ */
msg_t chMBFetchI(Mailbox *mbp, msg_t *msgp) { msg_t chMBFetchI(Mailbox *mbp, msg_t *msgp) {
chDbgCheckClassI();
chDbgCheck((mbp != NULL) && (msgp != NULL), "chMBFetchI"); chDbgCheck((mbp != NULL) && (msgp != NULL), "chMBFetchI");
if (chSemGetCounterI(&mbp->mb_fullsem) <= 0) if (chSemGetCounterI(&mbp->mb_fullsem) <= 0)

View File

@ -105,6 +105,8 @@ void *chCoreAlloc(size_t size) {
void *chCoreAllocI(size_t size) { void *chCoreAllocI(size_t size) {
void *p; void *p;
chDbgCheckClassI();
size = MEM_ALIGN_NEXT(size); size = MEM_ALIGN_NEXT(size);
if ((size_t)(endmem - nextmem) < size) if ((size_t)(endmem - nextmem) < size)
return NULL; return NULL;

View File

@ -72,6 +72,7 @@ void chPoolInit(MemoryPool *mp, size_t size, memgetfunc_t provider) {
void *chPoolAllocI(MemoryPool *mp) { void *chPoolAllocI(MemoryPool *mp) {
void *objp; void *objp;
chDbgCheckClassI();
chDbgCheck(mp != NULL, "chPoolAllocI"); chDbgCheck(mp != NULL, "chPoolAllocI");
if ((objp = mp->mp_next) != NULL) if ((objp = mp->mp_next) != NULL)
@ -114,6 +115,7 @@ void *chPoolAlloc(MemoryPool *mp) {
void chPoolFreeI(MemoryPool *mp, void *objp) { void chPoolFreeI(MemoryPool *mp, void *objp) {
struct pool_header *php = objp; struct pool_header *php = objp;
chDbgCheckClassI();
chDbgCheck((mp != NULL) && (objp != NULL) && MEM_IS_ALIGNED(objp), chDbgCheck((mp != NULL) && (objp != NULL) && MEM_IS_ALIGNED(objp),
"chPoolFreeI"); "chPoolFreeI");

View File

@ -114,6 +114,7 @@ void chMtxLock(Mutex *mp) {
void chMtxLockS(Mutex *mp) { void chMtxLockS(Mutex *mp) {
Thread *ctp = currp; Thread *ctp = currp;
chDbgCheckClassS();
chDbgCheck(mp != NULL, "chMtxLockS"); chDbgCheck(mp != NULL, "chMtxLockS");
/* Ia the mutex already locked? */ /* Ia the mutex already locked? */
@ -225,6 +226,7 @@ bool_t chMtxTryLock(Mutex *mp) {
*/ */
bool_t chMtxTryLockS(Mutex *mp) { bool_t chMtxTryLockS(Mutex *mp) {
chDbgCheckClassS();
chDbgCheck(mp != NULL, "chMtxTryLockS"); chDbgCheck(mp != NULL, "chMtxTryLockS");
if (mp->m_owner != NULL) if (mp->m_owner != NULL)
@ -309,6 +311,7 @@ Mutex *chMtxUnlockS(void) {
Thread *ctp = currp; Thread *ctp = currp;
Mutex *ump, *mp; Mutex *ump, *mp;
chDbgCheckClassS();
chDbgAssert(ctp->p_mtxlist != NULL, chDbgAssert(ctp->p_mtxlist != NULL,
"chMtxUnlockS(), #1", "chMtxUnlockS(), #1",
"owned mutexes list empty"); "owned mutexes list empty");

View File

@ -108,6 +108,8 @@ void chIQInit(InputQueue *iqp, uint8_t *bp, size_t size, qnotify_t infy) {
*/ */
void chIQResetI(InputQueue *iqp) { void chIQResetI(InputQueue *iqp) {
chDbgCheckClassI();
iqp->q_rdptr = iqp->q_wrptr = iqp->q_buffer; iqp->q_rdptr = iqp->q_wrptr = iqp->q_buffer;
iqp->q_counter = 0; iqp->q_counter = 0;
while (notempty(&iqp->q_waiting)) while (notempty(&iqp->q_waiting))
@ -129,6 +131,8 @@ void chIQResetI(InputQueue *iqp) {
*/ */
msg_t chIQPutI(InputQueue *iqp, uint8_t b) { msg_t chIQPutI(InputQueue *iqp, uint8_t b) {
chDbgCheckClassI();
if (chIQIsFullI(iqp)) if (chIQIsFullI(iqp))
return Q_FULL; return Q_FULL;
@ -284,6 +288,8 @@ void chOQInit(OutputQueue *oqp, uint8_t *bp, size_t size, qnotify_t onfy) {
*/ */
void chOQResetI(OutputQueue *oqp) { void chOQResetI(OutputQueue *oqp) {
chDbgCheckClassI();
oqp->q_rdptr = oqp->q_wrptr = oqp->q_buffer; oqp->q_rdptr = oqp->q_wrptr = oqp->q_buffer;
oqp->q_counter = chQSizeI(oqp); oqp->q_counter = chQSizeI(oqp);
while (notempty(&oqp->q_waiting)) while (notempty(&oqp->q_waiting))
@ -349,6 +355,8 @@ msg_t chOQPutTimeout(OutputQueue *oqp, uint8_t b, systime_t time) {
msg_t chOQGetI(OutputQueue *oqp) { msg_t chOQGetI(OutputQueue *oqp) {
uint8_t b; uint8_t b;
chDbgCheckClassI();
if (chOQIsEmptyI(oqp)) if (chOQIsEmptyI(oqp))
return Q_EMPTY; return Q_EMPTY;

View File

@ -75,7 +75,8 @@ void _scheduler_init(void) {
Thread *chSchReadyI(Thread *tp) { Thread *chSchReadyI(Thread *tp) {
Thread *cp; Thread *cp;
/* Integrity check.*/ /* Integrity checks.*/
chDbgCheckClassI();
chDbgAssert((tp->p_state != THD_STATE_READY) && chDbgAssert((tp->p_state != THD_STATE_READY) &&
(tp->p_state != THD_STATE_FINAL), (tp->p_state != THD_STATE_FINAL),
"chSchReadyI(), #1", "chSchReadyI(), #1",
@ -107,6 +108,8 @@ Thread *chSchReadyI(Thread *tp) {
void chSchGoSleepS(tstate_t newstate) { void chSchGoSleepS(tstate_t newstate) {
Thread *otp; Thread *otp;
chDbgCheckClassS();
(otp = currp)->p_state = newstate; (otp = currp)->p_state = newstate;
#if CH_TIME_QUANTUM > 0 #if CH_TIME_QUANTUM > 0
rlist.r_preempt = CH_TIME_QUANTUM; rlist.r_preempt = CH_TIME_QUANTUM;
@ -173,6 +176,8 @@ static void wakeup(void *p) {
*/ */
msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) { msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) {
chDbgCheckClassS();
if (TIME_INFINITE != time) { if (TIME_INFINITE != time) {
VirtualTimer vt; VirtualTimer vt;
@ -207,6 +212,8 @@ msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) {
#if !defined(PORT_OPTIMIZED_WAKEUPS) || defined(__DOXYGEN__) #if !defined(PORT_OPTIMIZED_WAKEUPS) || defined(__DOXYGEN__)
void chSchWakeupS(Thread *ntp, msg_t msg) { void chSchWakeupS(Thread *ntp, msg_t msg) {
chDbgCheckClassS();
ntp->p_u.rdymsg = msg; ntp->p_u.rdymsg = msg;
/* If the waken thread has a not-greater priority than the current /* If the waken thread has a not-greater priority than the current
one then it is just inserted in the ready list else it made one then it is just inserted in the ready list else it made
@ -237,6 +244,8 @@ void chSchWakeupS(Thread *ntp, msg_t msg) {
void chSchDoRescheduleI(void) { void chSchDoRescheduleI(void) {
Thread *otp; Thread *otp;
chDbgCheckClassI();
#if CH_TIME_QUANTUM > 0 #if CH_TIME_QUANTUM > 0
rlist.r_preempt = CH_TIME_QUANTUM; rlist.r_preempt = CH_TIME_QUANTUM;
#endif #endif
@ -259,6 +268,8 @@ void chSchDoRescheduleI(void) {
#if !defined(PORT_OPTIMIZED_RESCHEDULES) || defined(__DOXYGEN__) #if !defined(PORT_OPTIMIZED_RESCHEDULES) || defined(__DOXYGEN__)
void chSchRescheduleS(void) { void chSchRescheduleS(void) {
chDbgCheckClassS();
if (chSchIsRescRequiredI()) if (chSchIsRescRequiredI())
chSchDoRescheduleI(); chSchDoRescheduleI();
} }

View File

@ -129,8 +129,8 @@ void chSemReset(Semaphore *sp, cnt_t n) {
void chSemResetI(Semaphore *sp, cnt_t n) { void chSemResetI(Semaphore *sp, cnt_t n) {
cnt_t cnt; cnt_t cnt;
chDbgCheckClassI();
chDbgCheck((sp != NULL) && (n >= 0), "chSemResetI"); chDbgCheck((sp != NULL) && (n >= 0), "chSemResetI");
chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) || chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) ||
((sp->s_cnt < 0) && notempty(&sp->s_queue)), ((sp->s_cnt < 0) && notempty(&sp->s_queue)),
"chSemResetI(), #1", "chSemResetI(), #1",
@ -177,8 +177,8 @@ msg_t chSemWait(Semaphore *sp) {
*/ */
msg_t chSemWaitS(Semaphore *sp) { msg_t chSemWaitS(Semaphore *sp) {
chDbgCheckClassS();
chDbgCheck(sp != NULL, "chSemWaitS"); chDbgCheck(sp != NULL, "chSemWaitS");
chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) || chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) ||
((sp->s_cnt < 0) && notempty(&sp->s_queue)), ((sp->s_cnt < 0) && notempty(&sp->s_queue)),
"chSemWaitS(), #1", "chSemWaitS(), #1",
@ -242,8 +242,8 @@ msg_t chSemWaitTimeout(Semaphore *sp, systime_t time) {
*/ */
msg_t chSemWaitTimeoutS(Semaphore *sp, systime_t time) { msg_t chSemWaitTimeoutS(Semaphore *sp, systime_t time) {
chDbgCheckClassS();
chDbgCheck(sp != NULL, "chSemWaitTimeoutS"); chDbgCheck(sp != NULL, "chSemWaitTimeoutS");
chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) || chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) ||
((sp->s_cnt < 0) && notempty(&sp->s_queue)), ((sp->s_cnt < 0) && notempty(&sp->s_queue)),
"chSemWaitTimeoutS(), #1", "chSemWaitTimeoutS(), #1",
@ -271,7 +271,6 @@ msg_t chSemWaitTimeoutS(Semaphore *sp, systime_t time) {
void chSemSignal(Semaphore *sp) { void chSemSignal(Semaphore *sp) {
chDbgCheck(sp != NULL, "chSemSignal"); chDbgCheck(sp != NULL, "chSemSignal");
chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) || chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) ||
((sp->s_cnt < 0) && notempty(&sp->s_queue)), ((sp->s_cnt < 0) && notempty(&sp->s_queue)),
"chSemSignal(), #1", "chSemSignal(), #1",
@ -296,8 +295,8 @@ void chSemSignal(Semaphore *sp) {
*/ */
void chSemSignalI(Semaphore *sp) { void chSemSignalI(Semaphore *sp) {
chDbgCheckClassI();
chDbgCheck(sp != NULL, "chSemSignalI"); chDbgCheck(sp != NULL, "chSemSignalI");
chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) || chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) ||
((sp->s_cnt < 0) && notempty(&sp->s_queue)), ((sp->s_cnt < 0) && notempty(&sp->s_queue)),
"chSemSignalI(), #1", "chSemSignalI(), #1",
@ -327,8 +326,8 @@ void chSemSignalI(Semaphore *sp) {
*/ */
void chSemAddCounterI(Semaphore *sp, cnt_t n) { void chSemAddCounterI(Semaphore *sp, cnt_t n) {
chDbgCheckClassI();
chDbgCheck((sp != NULL) && (n > 0), "chSemAddCounterI"); chDbgCheck((sp != NULL) && (n > 0), "chSemAddCounterI");
chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) || chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) ||
((sp->s_cnt < 0) && notempty(&sp->s_queue)), ((sp->s_cnt < 0) && notempty(&sp->s_queue)),
"chSemAddCounterI(), #1", "chSemAddCounterI(), #1",
@ -361,12 +360,10 @@ msg_t chSemSignalWait(Semaphore *sps, Semaphore *spw) {
msg_t msg; msg_t msg;
chDbgCheck((sps != NULL) && (spw != NULL), "chSemSignalWait"); chDbgCheck((sps != NULL) && (spw != NULL), "chSemSignalWait");
chDbgAssert(((sps->s_cnt >= 0) && isempty(&sps->s_queue)) || chDbgAssert(((sps->s_cnt >= 0) && isempty(&sps->s_queue)) ||
((sps->s_cnt < 0) && notempty(&sps->s_queue)), ((sps->s_cnt < 0) && notempty(&sps->s_queue)),
"chSemSignalWait(), #1", "chSemSignalWait(), #1",
"inconsistent semaphore"); "inconsistent semaphore");
chDbgAssert(((spw->s_cnt >= 0) && isempty(&spw->s_queue)) || chDbgAssert(((spw->s_cnt >= 0) && isempty(&spw->s_queue)) ||
((spw->s_cnt < 0) && notempty(&spw->s_queue)), ((spw->s_cnt < 0) && notempty(&spw->s_queue)),
"chSemSignalWait(), #2", "chSemSignalWait(), #2",

View File

@ -128,6 +128,8 @@ void chSysInit(void) {
*/ */
void chSysTimerHandlerI(void) { void chSysTimerHandlerI(void) {
chDbgCheckClassI();
#if CH_TIME_QUANTUM > 0 #if CH_TIME_QUANTUM > 0
/* Running thread has not used up quantum yet? */ /* Running thread has not used up quantum yet? */
if (rlist.r_preempt > 0) if (rlist.r_preempt > 0)

View File

@ -154,6 +154,8 @@ Thread *chThdCreateI(void *wsp, size_t size,
/* Thread structure is layed out in the lower part of the thread workspace */ /* Thread structure is layed out in the lower part of the thread workspace */
Thread *tp = wsp; Thread *tp = wsp;
chDbgCheckClassI();
chDbgCheck((wsp != NULL) && (size >= THD_WA_SIZE(0)) && chDbgCheck((wsp != NULL) && (size >= THD_WA_SIZE(0)) &&
(prio <= HIGHPRIO) && (pf != NULL), (prio <= HIGHPRIO) && (pf != NULL),
"chThdCreateI"); "chThdCreateI");

View File

@ -70,6 +70,7 @@ void _vt_init(void) {
void chVTSetI(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par) { void chVTSetI(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par) {
VirtualTimer *p; VirtualTimer *p;
chDbgCheckClassI();
chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (time != TIME_IMMEDIATE), chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (time != TIME_IMMEDIATE),
"chVTSetI"); "chVTSetI");
@ -98,6 +99,7 @@ void chVTSetI(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par) {
*/ */
void chVTResetI(VirtualTimer *vtp) { void chVTResetI(VirtualTimer *vtp) {
chDbgCheckClassI();
chDbgCheck(vtp != NULL, "chVTResetI"); chDbgCheck(vtp != NULL, "chVTResetI");
chDbgAssert(vtp->vt_func != NULL, chDbgAssert(vtp->vt_func != NULL,
"chVTResetI(), #1", "chVTResetI(), #1",

View File

@ -126,6 +126,22 @@ extern "C" {
return; \ return; \
} }
/**
* @brief Test assertion with lock.
*
* @param[in] point numeric assertion identifier
* @param[in] condition a boolean expression that must be verified to be true
* @param[in] msg failure message
*/
#define test_assert_lock(point, condition, msg) { \
chSysLock(); \
if (_test_assert(point, condition)) { \
chSysUnlock(); \
return; \
} \
chSysUnlock(); \
}
/** /**
* @brief Test sequence assertion. * @brief Test sequence assertion.
* *

View File

@ -465,10 +465,12 @@ static void bmk9_execute(void) {
test_wait_tick(); test_wait_tick();
test_start_timer(1000); test_start_timer(1000);
do { do {
chSysLock();
chIQPutI(&iq, 0); chIQPutI(&iq, 0);
chIQPutI(&iq, 1); chIQPutI(&iq, 1);
chIQPutI(&iq, 2); chIQPutI(&iq, 2);
chIQPutI(&iq, 3); chIQPutI(&iq, 3);
chSysUnlock();
(void)chIQGet(&iq); (void)chIQGet(&iq);
(void)chIQGet(&iq); (void)chIQGet(&iq);
(void)chIQGet(&iq); (void)chIQGet(&iq);

View File

@ -101,19 +101,23 @@ static void mbox1_execute(void) {
*/ */
msg1 = chMBPost(&mb1, 'X', 1); msg1 = chMBPost(&mb1, 'X', 1);
test_assert(4, msg1 == RDY_TIMEOUT, "wrong wake-up message"); test_assert(4, msg1 == RDY_TIMEOUT, "wrong wake-up message");
chSysLock();
msg1 = chMBPostI(&mb1, 'X'); msg1 = chMBPostI(&mb1, 'X');
chSysUnlock();
test_assert(5, msg1 == RDY_TIMEOUT, "wrong wake-up message"); test_assert(5, msg1 == RDY_TIMEOUT, "wrong wake-up message");
msg1 = chMBPostAhead(&mb1, 'X', 1); msg1 = chMBPostAhead(&mb1, 'X', 1);
test_assert(6, msg1 == RDY_TIMEOUT, "wrong wake-up message"); test_assert(6, msg1 == RDY_TIMEOUT, "wrong wake-up message");
chSysLock();
msg1 = chMBPostAheadI(&mb1, 'X'); msg1 = chMBPostAheadI(&mb1, 'X');
chSysUnlock();
test_assert(7, msg1 == RDY_TIMEOUT, "wrong wake-up message"); test_assert(7, msg1 == RDY_TIMEOUT, "wrong wake-up message");
/* /*
* Testing final conditions. * Testing final conditions.
*/ */
test_assert(8, chMBGetFreeCountI(&mb1) == 0, "still empty"); test_assert_lock(8, chMBGetFreeCountI(&mb1) == 0, "still empty");
test_assert(9, chMBGetUsedCountI(&mb1) == MB_SIZE, "not full"); test_assert_lock(9, chMBGetUsedCountI(&mb1) == MB_SIZE, "not full");
test_assert(10, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned"); test_assert_lock(10, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned");
/* /*
* Testing dequeuing. * Testing dequeuing.
@ -140,19 +144,22 @@ static void mbox1_execute(void) {
*/ */
msg1 = chMBFetch(&mb1, &msg2, 1); msg1 = chMBFetch(&mb1, &msg2, 1);
test_assert(17, msg1 == RDY_TIMEOUT, "wrong wake-up message"); test_assert(17, msg1 == RDY_TIMEOUT, "wrong wake-up message");
chSysLock();
msg1 = chMBFetchI(&mb1, &msg2); msg1 = chMBFetchI(&mb1, &msg2);
chSysUnlock();
test_assert(18, msg1 == RDY_TIMEOUT, "wrong wake-up message"); test_assert(18, msg1 == RDY_TIMEOUT, "wrong wake-up message");
/* /*
* Testing final conditions. * Testing final conditions.
*/ */
test_assert(19, chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); test_assert_lock(19, chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty");
test_assert(20, chMBGetUsedCountI(&mb1) == 0, "still full"); test_assert_lock(20, chMBGetUsedCountI(&mb1) == 0, "still full");
test_assert(21, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned"); test_assert_lock(21, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned");
/* /*
* Testing I-Class. * Testing I-Class.
*/ */
chSysLock()
msg1 = chMBPostI(&mb1, 'A'); msg1 = chMBPostI(&mb1, 'A');
test_assert(22, msg1 == RDY_OK, "wrong wake-up message"); test_assert(22, msg1 == RDY_OK, "wrong wake-up message");
msg1 = chMBPostI(&mb1, 'B'); msg1 = chMBPostI(&mb1, 'B');
@ -162,16 +169,20 @@ static void mbox1_execute(void) {
msg1 = chMBPostI(&mb1, 'D'); msg1 = chMBPostI(&mb1, 'D');
test_assert(25, msg1 == RDY_OK, "wrong wake-up message"); test_assert(25, msg1 == RDY_OK, "wrong wake-up message");
msg1 = chMBPostI(&mb1, 'E'); msg1 = chMBPostI(&mb1, 'E');
chSysUnlock()
test_assert(26, msg1 == RDY_OK, "wrong wake-up message"); test_assert(26, msg1 == RDY_OK, "wrong wake-up message");
test_assert(27, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned"); test_assert(27, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned");
for (i = 0; i < MB_SIZE; i++) { for (i = 0; i < MB_SIZE; i++) {
chSysLock();
msg1 = chMBFetchI(&mb1, &msg2); msg1 = chMBFetchI(&mb1, &msg2);
chSysUnlock();
test_assert(28, msg1 == RDY_OK, "wrong wake-up message"); test_assert(28, msg1 == RDY_OK, "wrong wake-up message");
test_emit_token(msg2); test_emit_token(msg2);
} }
test_assert_sequence(29, "ABCDE"); test_assert_sequence(29, "ABCDE");
test_assert(30, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned"); test_assert(30, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned");
chSysLock();
msg1 = chMBPostAheadI(&mb1, 'E'); msg1 = chMBPostAheadI(&mb1, 'E');
test_assert(31, msg1 == RDY_OK, "wrong wake-up message"); test_assert(31, msg1 == RDY_OK, "wrong wake-up message");
msg1 = chMBPostAheadI(&mb1, 'D'); msg1 = chMBPostAheadI(&mb1, 'D');
@ -181,10 +192,13 @@ static void mbox1_execute(void) {
msg1 = chMBPostAheadI(&mb1, 'B'); msg1 = chMBPostAheadI(&mb1, 'B');
test_assert(34, msg1 == RDY_OK, "wrong wake-up message"); test_assert(34, msg1 == RDY_OK, "wrong wake-up message");
msg1 = chMBPostAheadI(&mb1, 'A'); msg1 = chMBPostAheadI(&mb1, 'A');
chSysUnlock();
test_assert(35, msg1 == RDY_OK, "wrong wake-up message"); test_assert(35, msg1 == RDY_OK, "wrong wake-up message");
test_assert(36, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned"); test_assert(36, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned");
for (i = 0; i < MB_SIZE; i++) { for (i = 0; i < MB_SIZE; i++) {
chSysLock();
msg1 = chMBFetchI(&mb1, &msg2); msg1 = chMBFetchI(&mb1, &msg2);
chSysUnlock();
test_assert(37, msg1 == RDY_OK, "wrong wake-up message"); test_assert(37, msg1 == RDY_OK, "wrong wake-up message");
test_emit_token(msg2); test_emit_token(msg2);
} }
@ -199,10 +213,10 @@ static void mbox1_execute(void) {
/* /*
* Re-testing final conditions. * Re-testing final conditions.
*/ */
test_assert(40, chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); test_assert_lock(40, chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty");
test_assert(41, chMBGetUsedCountI(&mb1) == 0, "still full"); test_assert_lock(41, chMBGetUsedCountI(&mb1) == 0, "still full");
test_assert(42, mb1.mb_buffer == mb1.mb_wrptr, "write pointer not aligned to base"); test_assert_lock(42, mb1.mb_buffer == mb1.mb_wrptr, "write pointer not aligned to base");
test_assert(43, mb1.mb_buffer == mb1.mb_rdptr, "read pointer not aligned to base"); test_assert_lock(43, mb1.mb_buffer == mb1.mb_rdptr, "read pointer not aligned to base");
} }
ROMCONST struct testcase testmbox1 = { ROMCONST struct testcase testmbox1 = {

View File

@ -96,46 +96,54 @@ static void queues1_execute(void) {
size_t n; size_t n;
/* Initial empty state */ /* Initial empty state */
test_assert(1, chIQIsEmptyI(&iq), "not empty"); test_assert_lock(1, chIQIsEmptyI(&iq), "not empty");
/* Queue filling */ /* Queue filling */
chSysLock();
for (i = 0; i < TEST_QUEUES_SIZE; i++) for (i = 0; i < TEST_QUEUES_SIZE; i++)
chIQPutI(&iq, 'A' + i); chIQPutI(&iq, 'A' + i);
test_assert(2, chIQIsFullI(&iq), "still has space"); chSysUnlock();
test_assert(3, chIQPutI(&iq, 0) == Q_FULL, "failed to report Q_FULL"); test_assert_lock(2, chIQIsFullI(&iq), "still has space");
test_assert_lock(3, chIQPutI(&iq, 0) == Q_FULL, "failed to report Q_FULL");
/* Queue emptying */ /* Queue emptying */
for (i = 0; i < TEST_QUEUES_SIZE; i++) for (i = 0; i < TEST_QUEUES_SIZE; i++)
test_emit_token(chIQGet(&iq)); test_emit_token(chIQGet(&iq));
test_assert(4, chIQIsEmptyI(&iq), "still full"); test_assert_lock(4, chIQIsEmptyI(&iq), "still full");
test_assert_sequence(5, "ABCD"); test_assert_sequence(5, "ABCD");
/* Queue filling again */ /* Queue filling again */
chSysLock();
for (i = 0; i < TEST_QUEUES_SIZE; i++) for (i = 0; i < TEST_QUEUES_SIZE; i++)
chIQPutI(&iq, 'A' + i); chIQPutI(&iq, 'A' + i);
chSysUnlock();
/* Reading the whole thing */ /* Reading the whole thing */
n = chIQReadTimeout(&iq, wa[1], TEST_QUEUES_SIZE * 2, TIME_IMMEDIATE); n = chIQReadTimeout(&iq, wa[1], TEST_QUEUES_SIZE * 2, TIME_IMMEDIATE);
test_assert(6, n == TEST_QUEUES_SIZE, "wrong returned size"); test_assert(6, n == TEST_QUEUES_SIZE, "wrong returned size");
test_assert(7, chIQIsEmptyI(&iq), "still full"); test_assert_lock(7, chIQIsEmptyI(&iq), "still full");
/* Queue filling again */ /* Queue filling again */
chSysLock();
for (i = 0; i < TEST_QUEUES_SIZE; i++) for (i = 0; i < TEST_QUEUES_SIZE; i++)
chIQPutI(&iq, 'A' + i); chIQPutI(&iq, 'A' + i);
chSysUnlock();
/* Partial reads */ /* Partial reads */
n = chIQReadTimeout(&iq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE); n = chIQReadTimeout(&iq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE);
test_assert(8, n == TEST_QUEUES_SIZE / 2, "wrong returned size"); test_assert(8, n == TEST_QUEUES_SIZE / 2, "wrong returned size");
n = chIQReadTimeout(&iq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE); n = chIQReadTimeout(&iq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE);
test_assert(9, n == TEST_QUEUES_SIZE / 2, "wrong returned size"); test_assert(9, n == TEST_QUEUES_SIZE / 2, "wrong returned size");
test_assert(10, chIQIsEmptyI(&iq), "still full"); test_assert_lock(10, chIQIsEmptyI(&iq), "still full");
/* Testing reset */ /* Testing reset */
chSysLock();
chIQPutI(&iq, 0); chIQPutI(&iq, 0);
chIQResetI(&iq); chIQResetI(&iq);
test_assert(11, chIQGetFullI(&iq) == 0, "still full"); chSysUnlock();
test_assert_lock(11, chIQGetFullI(&iq) == 0, "still full");
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+1, thread1, NULL); threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+1, thread1, NULL);
test_assert(12, chIQGetFullI(&iq) == 0, "not empty"); test_assert_lock(12, chIQGetFullI(&iq) == 0, "not empty");
test_wait_threads(); test_wait_threads();
/* Timeout */ /* Timeout */
@ -175,38 +183,46 @@ static void queues2_execute(void) {
size_t n; size_t n;
/* Initial empty state */ /* Initial empty state */
test_assert(1, chOQIsEmptyI(&oq), "not empty"); test_assert_lock(1, chOQIsEmptyI(&oq), "not empty");
/* Queue filling */ /* Queue filling */
for (i = 0; i < TEST_QUEUES_SIZE; i++) for (i = 0; i < TEST_QUEUES_SIZE; i++)
chOQPut(&oq, 'A' + i); chOQPut(&oq, 'A' + i);
test_assert(2, chOQIsFullI(&oq), "still has space"); test_assert_lock(2, chOQIsFullI(&oq), "still has space");
/* Queue emptying */ /* Queue emptying */
for (i = 0; i < TEST_QUEUES_SIZE; i++) for (i = 0; i < TEST_QUEUES_SIZE; i++) {
test_emit_token(chOQGetI(&oq)); char c;
test_assert(3, chOQIsEmptyI(&oq), "still full");
chSysLock();
c = chOQGetI(&oq);
chSysUnlock();
test_emit_token(c);
}
test_assert_lock(3, chOQIsEmptyI(&oq), "still full");
test_assert_sequence(4, "ABCD"); test_assert_sequence(4, "ABCD");
test_assert(5, chOQGetI(&oq) == Q_EMPTY, "failed to report Q_EMPTY"); test_assert_lock(5, chOQGetI(&oq) == Q_EMPTY, "failed to report Q_EMPTY");
/* Writing the whole thing */ /* Writing the whole thing */
n = chOQWriteTimeout(&oq, wa[1], TEST_QUEUES_SIZE * 2, TIME_IMMEDIATE); n = chOQWriteTimeout(&oq, wa[1], TEST_QUEUES_SIZE * 2, TIME_IMMEDIATE);
test_assert(6, n == TEST_QUEUES_SIZE, "wrong returned size"); test_assert(6, n == TEST_QUEUES_SIZE, "wrong returned size");
test_assert(7, chOQIsFullI(&oq), "not full"); test_assert_lock(7, chOQIsFullI(&oq), "not full");
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+1, thread2, NULL); threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+1, thread2, NULL);
test_assert(8, chOQGetFullI(&oq) == TEST_QUEUES_SIZE, "not empty"); test_assert_lock(8, chOQGetFullI(&oq) == TEST_QUEUES_SIZE, "not empty");
test_wait_threads(); test_wait_threads();
/* Testing reset */ /* Testing reset */
chSysLock();
chOQResetI(&oq); chOQResetI(&oq);
test_assert(9, chOQGetFullI(&oq) == 0, "still full"); chSysUnlock();
test_assert_lock(9, chOQGetFullI(&oq) == 0, "still full");
/* Partial writes */ /* Partial writes */
n = chOQWriteTimeout(&oq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE); n = chOQWriteTimeout(&oq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE);
test_assert(10, n == TEST_QUEUES_SIZE / 2, "wrong returned size"); test_assert(10, n == TEST_QUEUES_SIZE / 2, "wrong returned size");
n = chOQWriteTimeout(&oq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE); n = chOQWriteTimeout(&oq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE);
test_assert(11, n == TEST_QUEUES_SIZE / 2, "wrong returned size"); test_assert(11, n == TEST_QUEUES_SIZE / 2, "wrong returned size");
test_assert(12, chOQIsFullI(&oq), "not full"); test_assert_lock(12, chOQIsFullI(&oq), "not full");
/* Timeout */ /* Timeout */
test_assert(13, chOQPutTimeout(&oq, 0, 10) == Q_TIMEOUT, "wrong timeout return"); test_assert(13, chOQPutTimeout(&oq, 0, 10) == Q_TIMEOUT, "wrong timeout return");

View File

@ -104,7 +104,9 @@ static void sem1_execute(void) {
test_assert_sequence(1, "ABCDE"); test_assert_sequence(1, "ABCDE");
#endif #endif
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+5, thread1, "A"); threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+5, thread1, "A");
chSysLock();
chSemAddCounterI(&sem1, 2); chSemAddCounterI(&sem1, 2);
chSysUnlock();
test_wait_threads(); test_wait_threads();
test_assert(2, chSemGetCounterI(&sem1) == 1, "invalid counter"); test_assert(2, chSemGetCounterI(&sem1) == 1, "invalid counter");
} }