//$file${src::qf::qf_qact.c} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpc.qm
// File:  ${src::qf::qf_qact.c}
//
// This code has been generated by QM 5.3.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//
// This code is covered by the following QP license:
// License #    : LicenseRef-QL-dual
// Issued to    : Any user of the QP/C real-time embedded framework
// Framework(s) : qpc
// Support ends : 2024-12-31
// License scope:
//
// Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
//
//                    Q u a n t u m  L e a P s
//                    ------------------------
//                    Modern Embedded Software
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <www.gnu.org/licenses/gpl-3.0>
//
// The terms of the closed source Quantum Leaps commercial licenses
// can be found at: <www.state-machine.com/licensing>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qf::qf_qact.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#define QP_IMPL           // this is QP implementation
#include "qp_port.h"      // QP port
#include "qp_pkg.h"       // QP package-scope interface
#include "qsafe.h"        // QP Functional Safety (FuSa) Subsystem
#ifdef Q_SPY              // QS software tracing enabled?
    #include "qs_port.h"  // QS port
    #include "qs_pkg.h"   // QS facilities for pre-defined trace records
#else
    #include "qs_dummy.h" // disable the QS software tracing
#endif // Q_SPY

Q_DEFINE_THIS_MODULE("qf_qact")

//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
#error qpc version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

//$define${QF::QActive::ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

//${QF::QActive::ctor} .......................................................
//! @protected @memberof QActive
void QActive_ctor(QActive * const me,
    QStateHandler const initial)
{
    // clear the whole QActive object, so that the framework can start
    // correctly even if the startup code fails to clear the uninitialized
    // data (as is required by the C Standard).
    QF_bzero_(me, sizeof(*me));

    // NOTE: QActive inherits the abstract QAsm class, but it calls the
    // constructor of the QHsm subclass. This is because QActive inherits
    // the behavior from the QHsm subclass.
    QHsm_ctor((QHsm *)(me), initial);

    // NOTE: this vtable is identical as QHsm, but is provided
    // for the QActive subclass to provide a UNIQUE vptr to distinguish
    // subclasses of QActive (e.g., in the debugger).
    static struct QAsmVtable const vtable = { // QActive virtual table
        &QHsm_init_,
        &QHsm_dispatch_
    #ifdef Q_SPY
        ,&QHsm_getStateHandler_
    #endif
    };
    me->super.vptr = &vtable; // hook vptr to QActive vtable
}
//$enddef${QF::QActive::ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

//$define${QF::QActive::register_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

//${QF::QActive::register_} ..................................................
//! @private @memberof QActive
void QActive_register_(QActive * const me) {
    QF_CRIT_STAT
    QF_CRIT_ENTRY();
    QF_MEM_SYS();

    if (me->pthre == 0U) { // preemption-threshold not defined?
        me->pthre = me->prio; // apply the default
    }

    #ifndef Q_UNSAFE

    Q_REQUIRE_INCRIT(100, (0U < me->prio) && (me->prio <= QF_MAX_ACTIVE)
                      && (QActive_registry_[me->prio] == (QActive *)0)
                      && (me->prio <= me->pthre));

    uint8_t prev_thre = me->pthre;
    uint8_t next_thre = me->pthre;

    uint_fast8_t p;
    for (p = (uint_fast8_t)me->prio - 1U; p > 0U; --p) {
        if (QActive_registry_[p] != (QActive *)0) {
            prev_thre = QActive_registry_[p]->pthre;
            break;
        }
    }
    for (p = (uint_fast8_t)me->prio + 1U; p <= QF_MAX_ACTIVE; ++p) {
        if (QActive_registry_[p] != (QActive *)0) {
            next_thre = QActive_registry_[p]->pthre;
            break;
        }
    }

    Q_ASSERT_INCRIT(190, (prev_thre <= me->pthre)
                          && (me->pthre <= next_thre));
    #endif // Q_UNSAFE

    // register the AO at the QF-prio.
    QActive_registry_[me->prio] = me;

    QF_MEM_APP();
    QF_CRIT_EXIT();
}
//$enddef${QF::QActive::register_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

//$define${QF::QActive::unregister_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

//${QF::QActive::unregister_} ................................................
//! @private @memberof QActive
void QActive_unregister_(QActive * const me) {
    uint_fast8_t const p = (uint_fast8_t)me->prio;

    QF_CRIT_STAT
    QF_CRIT_ENTRY();
    QF_MEM_SYS();

    Q_REQUIRE_INCRIT(200, (0U < p) && (p <= QF_MAX_ACTIVE)
                      && (QActive_registry_[p] == me));
    QActive_registry_[p] = (QActive *)0; // free-up the prio. level
    me->super.state.fun = Q_STATE_CAST(0); // invalidate the state

    QF_MEM_APP();
    QF_CRIT_EXIT();
}
//$enddef${QF::QActive::unregister_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
