Menu

#398 8.1.3 postx_() in FreeRTOS port enters critical section twice

QP
open
None
1
1 day ago
1 day ago
Anonymous
No

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?

Discussion

Anonymous
Anonymous

Add attachments
Cancel





MongoDB Logo MongoDB