8.1.3 postx_() in FreeRTOS port enters critical section twice
Real-Time Event Frameworks based on active objects & state machines
Brought to you by:
quantum-leaps
While integrating 8.1.3, our team has raised the following issue.
Ticket for Quantum Leaps Team
In version 8.1.3, the implementation of the postx_ function in the file ports/freertos/qf_port.cpp looks like this:
bool QActive::postx_(
QEvt const * const e,
std::uint_fast16_t const margin,
void const * const sender) noexcept
{
#ifndef Q_SPY
Q_UNUSED_PAR(sender);
#endif
QF_CRIT_STAT
QF_CRIT_ENTRY(); // !!! enter to the critical section !!!
// the event to post must not be NULL
Q_REQUIRE_INCRIT(100, e != nullptr);
// the number of free slots available in the FreeRTOS queue
std::uint_fast16_t nFree =
static_cast<std::uint_fast16_t>(FREERTOS_QUEUE_GET_FREE());
// should we try to post the event?
bool status = ((margin == QF::NO_MARGIN)
|| (nFree > static_cast<std::uint_fast16_t>(margin))); // !!! suppose the status is FALSE !!!
if (status) { // should try to post the event? // !!! the condition is FALSE !!!
#if (QF_MAX_EPOOL > 0U)
if (e->poolNum_ != 0U) { // is it a mutable event?
QEvt_refCtr_inc_(e); // increment the reference counter
}
#endif // (QF_MAX_EPOOL > 0U)
QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_prio)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object (recipient)
QS_2U8_PRE(e->poolNum_, e->refCtr_); // pool-Num & ref-Count
QS_EQC_PRE(nFree); // # free entries available
QS_EQC_PRE(0U); // min # free entries (unknown)
QS_END_PRE()
QF_CRIT_EXIT(); // exit crit.sect. before calling RTOS API
// post the event to the FreeRTOS event queue, see NOTE3
status = (xQueueSendToBack(
m_eQueue, static_cast<void const *>(&e), 0U) == pdPASS);
}
if (!status) { // event NOT posted?
QF_CRIT_ENTRY(); // !!! enter to the critical section again !!!!
// posting is allowed to fail only when margin != QF_NO_MARGIN
Q_ASSERT_INCRIT(130, margin != QF::NO_MARGIN);
QS_BEGIN_PRE(QS_QF_ACTIVE_POST_ATTEMPT, m_prio)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object (recipient)
QS_2U8_PRE(e->poolNum_, e->refCtr_); // pool-Num & ref-Count
QS_EQC_PRE(nFree); // # free entries available
QS_EQC_PRE(margin); // margin requested
QS_END_PRE()
QF_CRIT_EXIT(); // !!! release the critical section, but only once !!!!
#if (QF_MAX_EPOOL > 0U)
QF::gc(e); // recycle the event to avoid a leak
#endif
}
return status;
}
The sections marked with !!! indicate problem areas. In our case, if there is no space in the queue, interrupts remain disabled after exiting the postx_ function. Is this behavior expected?
Anonymous