From df116c8410cd701a594dec5886bd4e3d1e866ce4 Mon Sep 17 00:00:00 2001 From: MMS Date: Sat, 18 Jan 2025 18:33:40 -0500 Subject: [PATCH] 8.0.2 --- LICENSES/LicenseRef-QL-dual.qlc | 6 +- README.md | 124 +- examples | 2 +- include/qequeue.hpp | 54 +- include/qk.hpp | 121 +- include/qmpool.hpp | 82 +- include/qp.hpp | 625 +-- include/qp_pkg.hpp | 52 +- include/qpcpp.hpp | 137 +- include/qs_dummy.hpp | 13 +- include/qsafe.h | 159 +- include/qstamp.hpp | 17 +- include/qv.hpp | 70 +- ports/arm-cm/config/qp_config.hpp | 16 +- ports/arm-cm/qk/armclang/qk_port.cpp | 3 +- ports/arm-cm/qk/armclang/qp_port.hpp | 2 +- ports/arm-cm/qk/armclang/qs_port.hpp | 34 +- ports/arm-cm/qk/gnu/qk_port.cpp | 3 +- ports/arm-cm/qk/gnu/qp_port.hpp | 2 +- ports/arm-cm/qk/gnu/qs_port.hpp | 34 +- ports/arm-cm/qk/iar/qk_port.cpp | 3 +- ports/arm-cm/qk/iar/qp_port.hpp | 2 +- ports/arm-cm/qk/iar/qs_port.hpp | 34 +- ports/arm-cm/qv/armclang/qp_port.hpp | 2 +- ports/arm-cm/qv/armclang/qs_port.hpp | 34 +- ports/arm-cm/qv/armclang/qv_port.cpp | 3 +- ports/arm-cm/qv/gnu/qp_port.hpp | 2 +- ports/arm-cm/qv/gnu/qs_port.hpp | 34 +- ports/arm-cm/qv/gnu/qv_port.cpp | 3 +- ports/arm-cm/qv/iar/qp_port.hpp | 2 +- ports/arm-cm/qv/iar/qs_port.hpp | 34 +- ports/arm-cm/qv/iar/qv_port.cpp | 3 +- ports/arm-cr/config/qp_config.hpp | 4 +- ports/arm-cr/qk/gnu/qp_port.hpp | 8 +- ports/arm-cr/qk/gnu/qs_port.hpp | 34 +- ports/arm-cr/qk/iar/qp_port.hpp | 8 +- ports/arm-cr/qk/iar/qs_port.hpp | 34 +- ports/arm-cr/qk/ti/qp_port.hpp | 8 +- ports/arm-cr/qk/ti/qs_port.hpp | 34 +- ports/arm-cr/qv/gnu/qp_port.hpp | 8 +- ports/arm-cr/qv/gnu/qs_port.hpp | 34 +- ports/arm-cr/qv/iar/qp_port.hpp | 8 +- ports/arm-cr/qv/iar/qs_port.hpp | 34 +- ports/arm-cr/qv/ti/qp_port.hpp | 8 +- ports/arm-cr/qv/ti/qs_port.hpp | 34 +- ports/config/qp_config.hpp | 4 +- ports/embos/qf_port.cpp | 28 +- ports/embos/qp_port.hpp | 8 +- ports/embos/qs_port.hpp | 34 +- ports/freertos/qf_port.cpp | 474 +- ports/freertos/qp_port.hpp | 8 +- ports/freertos/qs_port.hpp | 34 +- ports/msp430/qk/qp_port.hpp | 8 +- ports/msp430/qk/qs_port.hpp | 34 +- ports/msp430/qutest/qp_port.hpp | 35 +- ports/msp430/qutest/qs_port.hpp | 34 +- ports/msp430/qv/qp_port.hpp | 8 +- ports/msp430/qv/qs_port.hpp | 34 +- ports/posix-qv/qf_port.cpp | 44 +- ports/posix-qv/qp_port.hpp | 15 +- ports/posix-qv/qs_port.cpp | 36 +- ports/posix-qv/qs_port.hpp | 34 +- ports/posix/qf_port.cpp | 32 +- ports/posix/qp_port.hpp | 8 +- ports/posix/qs_port.cpp | 36 +- ports/posix/qs_port.hpp | 34 +- ports/qep-only/qp_port.hpp | 8 +- ports/threadx/qf_port.cpp | 29 +- ports/threadx/qp_port.hpp | 20 +- ports/threadx/qs_port.hpp | 40 +- ports/uc-os2/qf_port.cpp | 28 +- ports/uc-os2/qp_port.hpp | 8 +- ports/uc-os2/qs_port.hpp | 40 +- ports/win32-qv/qf_port.cpp | 21 - ports/win32-qv/qp_port.hpp | 15 +- ports/win32-qv/qs_port.cpp | 9 +- ports/win32-qv/qs_port.hpp | 6 - ports/win32/qf_port.cpp | 6 - ports/win32/qp_port.hpp | 11 +- ports/win32/qs_port.cpp | 9 +- ports/win32/qs_port.hpp | 6 - qpcpp.qm | 6731 -------------------------- qpcpp_8.0.1.sha1 | 162 - qpcpp_8.0.2.sha1 | 163 + qpcpp_sha1.bat | 13 +- src/qf/qep_hsm.cpp | 799 ++- src/qf/qep_msm.cpp | 489 +- src/qf/qf_act.cpp | 87 +- src/qf/qf_actq.cpp | 414 +- src/qf/qf_defer.cpp | 61 +- src/qf/qf_dyn.cpp | 130 +- src/qf/qf_mem.cpp | 216 +- src/qf/qf_ps.cpp | 126 +- src/qf/qf_qact.cpp | 66 +- src/qf/qf_qeq.cpp | 192 +- src/qf/qf_qmact.cpp | 29 +- src/qf/qf_time.cpp | 376 +- src/qk/qk.cpp | 295 +- src/qs/qstamp.cpp | 36 +- src/qv/qv.cpp | 149 +- zephyr/qf_port.cpp | 28 +- zephyr/qp_port.hpp | 8 +- zephyr/qs_port.hpp | 35 +- zephyr/qutest_port.cpp | 32 +- 104 files changed, 2456 insertions(+), 11387 deletions(-) delete mode 100644 qpcpp.qm delete mode 100644 qpcpp_8.0.1.sha1 create mode 100644 qpcpp_8.0.2.sha1 diff --git a/LICENSES/LicenseRef-QL-dual.qlc b/LICENSES/LicenseRef-QL-dual.qlc index 721f329af..02a8494cb 100644 --- a/LICENSES/LicenseRef-QL-dual.qlc +++ b/LICENSES/LicenseRef-QL-dual.qlc @@ -9,8 +9,8 @@ Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial -The QP/C++ software is dual-licensed under the terms of the open-source -GNU General Public License (GPL) or under the terms of one of the closed- +This software is dual-licensed under the terms of the open-source GNU +General Public License (GPL) or under the terms of one of the closed- source Quantum Leaps commercial licenses. Redistributions in source code must retain this top-level comment block. @@ -25,4 +25,4 @@ closed-source distribution. Quantum Leaps contact information: -#48B37CF39D4FD9DE279250B31FD388AFD0BE9B40 \ No newline at end of file +#E73B85325051C864FE0E4C672EF7577CB16A80DA \ No newline at end of file diff --git a/README.md b/README.md index 9858e1948..0ccf99c3e 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,39 @@ git clone https://github.com/QuantumLeaps/qpcpp --recurse-submodules --depth 1 Alternatively, you can also download one of the stable [QP/C++ Releases][QP-Rel]. +# About QP/C++ Real-Time Embedded Framework +QP/C++ real-time embedded framework (RTEF) is a lightweight implementation of +the [Active Object (a.k.a. Actor) model of computation][AOmod] specifically +tailored for deeply embedded real-time systems, such as microcontrollers (MCUs). +QP/C++ is both a software infrastructure for building applications consisting +of Active Objects (Actors) and a runtime environment for executing the Active +Objects in a deterministic, real-time fashion. Additionally, QP/C++ Framework +supports Hierarchical State Machines with which to specify the behavior of +Active Objects [UML 2.5], [Sutter:10], [ROOM:94]. The QP/C++ Framework can be +viewed as a modern, asynchronous, and truly event driven real-time operating +system (RTOS). + +## QP Framework Family +QP/C++ framework is part of the larger QP family consisting of the following +QP editions: + +|QP Edition | Language | API | Safety Functions |Certification Artifacts| Licensing +|:----------|:-----------:|:-----------------|:-------------------|:----------------|:--------- +| QP/C | C (C11) |same as SafeQP/C |Selected Assertions |Req/Arch/Design | [dual][Lic] +| SafeQP/C | C (C11) |same as QP/C |All Safety Functions|Certification Kit| [commercial][Com] +| QP/C++ | C++ (C++17) |same as SafeQP/C++|Selected Assertions |Req/Arch/Design | [dual][Lic] +| SafeQP/C++| C++ (C++17) |same as QP/C++ |All Safety Functions|Certification Kit| [commercial][Com] + +[The documentation](#documentation) of all QP editions includes the +[Requirements][SRS], [Architecture][SAS], and [Design Specifications][SDS], +which are the best source of information about the underlying concepts, +functionality, architecture, and design of the QP Frameworks and the QP +Applications based on the frameworks. + +> **NOTE:** The **SafeQP** frameworks additionally contain **Safety Functions** +required to achieve the higher safety integrity levels and come with much more +extensive [Certification Kits][Cert]. + # Getting Started with QP/C++ The most recommended way of obtaining QP/C++ is by downloading the @@ -25,7 +58,7 @@ The main advantage of obtaining QP/C++ bundled together like that is that you get all components, tools and examples ready to go. ### Getting Started Resources -- ["QP/C++ Tutorial"][Tutorial] +- ["QP/C++ Tutorial"][Tut] describes a series of progressively advanced QP/C++ example applications. - [Video: "Getting Started with QP Real-Time Embedded Frameworks"][Video] @@ -67,69 +100,11 @@ have been **removed from the open-source GPL distribution**: the active Support Term. Please contact [Quantum Leaps technical support][Sup] to get the complete QP/C++ framework distribution. -> NOTE: To request **evaluation** of the complete QP/C++ framework, please contact +> **NOTE:** To request **evaluation** of the complete QP/C++ framework, please contact Quantum Leaps at: https://www.state-machine.com/contact -# About QP/C++ -QP/C++ (Quantum Platform in C++) is a lightweight, open source -[Real-Time Embedded Framework (RTEF)][RTEF] for building modern embedded -software as systems of asynchronous, event-driven [Active Objects][Active] -(actors). The [QP/C++] framework is a member of a [QP] family consisting of -[QP/C++] and [QP/C] frameworks, which are strictly quality controlled, -thoroughly documented, and [commercially licensable][Lic]. - -## Safer Model of Concurrency -The [QP] framework family implements the -[Active Object model of computation][AO_model], which is **inherently safer** -than the traditional "shared state concurrency" based on explicit mutual -exclusion and managing RTOS threads by blocking. The Active Object model -supports and automatically enforces the following best practices -of concurrent programming: - -- Keep data isolated and bound to Active Objects' threads. Threads should -hide (**encapsulate**) their private data and other resources, and not -share them with the rest of the system. - -- Communicate among Active Object threads **asynchronously** via [Event -objects][Event]. Using asynchronous events keeps the threads running truly -independently, **without blocking** on each other. - -- Active Object threads should spend their lifetime responding to incoming -events, so their mainline should consist of an **event-loop** that handles -events one at a time (to completion), thus avoiding any concurrency hazards -within an Active Object thread itself. - -This architecture also provides higher level of abstraction and the *correct* -abstractions to effectively apply [Hierarchical State Machines][HSM], -**modeling** and **code generation** to deeply embedded real-time systems. - -## Hierarchical State Machines -The behavior of Active Objects is specified in QP/C++ by means of -[Hierarchical State Machines][HSM] (UML statecharts). The framework -supports manual coding of UML state machines in C as well as automatic -**code generation** by means of the free [QM modeling tool][QM]. - -## Built-in Real-Time Kernels -The QP/C++ framework can run on standalone on single-chip microcontrollers, -without any traditional RTOS. The framework contains a selection of -**built-in real-time kernels**, such as the [non-preemptive QV kernel][QV], -the [preemptive non-blocking QK kernel][QK], and the preemptive, -[dual-mode QXK kernel][QXK] that provides all the features you might expect -from a traditional RTOS. Native QP ports and ready-to-use examples are provided -for major CPUs, such as ARM Cortex-M (M0/M0+/M3/M4/M7/M23/M33/...). - -## Traditional RTOS/OS -QP/C++ can also work with a traditional RTOS, such as ThreadX, embOS, FreeRTOS, -uC/OS-II and Zephyr, as well as with (embedded) Linux (POSIX) and Windows. - -## Popularity and Maturity -With 20 years of continuous development, [400+ commercial licensees][Cust], -and many times more open source users worldwide, the QP frameworks are the -most popular such offering on the market. They power countless electronic -products ranging from implantable medical devices to complex weapon systems. - - -# QP/C++ Documentation + +# Documentation The online HTML documentation for the **latest** version of QP/C++ is located at: https://www.state-machine.com/qpcpp @@ -159,20 +134,25 @@ If you like this project, please give it a star (in the upper-right corner of yo [QP]: [QP/C]: [QP/C++]: - [QS/C++]: - [QV]: - [QK]: - [QXK]: + [Cert]: [QM]: [QTools]: - [QP-Rel]: - [Active]: - [AO_model]: - [Event]: - [HSM]: [Lic]: + [Com]: [Cust]: [Sup]: [AN]: - [Tutorial]: [Video]: + [QS]: + [QV]: + [QK]: + [QXK]: + [SRS]: + [SAS]: + [SDS]: + [Active]: + [AOmod]: + [Event]: + [HSM]: + [Tut]: + [QP-Rel]: diff --git a/examples b/examples index 01aad80e4..f8e601d60 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 01aad80e4c6f69089ecf7ddc328cad2870505a6e +Subproject commit f8e601d60a88d04bd49e01bb725efd6e13131c1a diff --git a/include/qequeue.hpp b/include/qequeue.hpp index 143dc415b..029526cfb 100644 --- a/include/qequeue.hpp +++ b/include/qequeue.hpp @@ -1,10 +1,6 @@ -//$file${include::qequeue.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${include::qequeue.hpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${include::qequeue.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #ifndef QEQUEUE_HPP_ #define QEQUEUE_HPP_ @@ -46,17 +41,16 @@ namespace QP { #elif (QF_EQUEUE_CTR_SIZE == 2U) using QEQueueCtr = std::uint16_t; #else - #error "QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1U or 2U" + #error QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1U or 2U #endif class QEvt; // forward declaration } // namespace QP -//$declare${QF::QEQueue} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +//============================================================================ namespace QP { -//${QF::QEQueue} ............................................................. class QEQueue { private: QEvt const * volatile m_frontEvt; @@ -65,22 +59,6 @@ class QEQueue { QEQueueCtr volatile m_head; QEQueueCtr volatile m_tail; QEQueueCtr volatile m_nFree; - -#ifndef Q_UNSAFE - std::uintptr_t m_frontEvt_dis; -#endif // ndef Q_UNSAFE - -#ifndef Q_UNSAFE - QEQueueCtr m_head_dis; -#endif // ndef Q_UNSAFE - -#ifndef Q_UNSAFE - QEQueueCtr m_tail_dis; -#endif // ndef Q_UNSAFE - -#ifndef Q_UNSAFE - QEQueueCtr m_nFree_dis; -#endif // ndef Q_UNSAFE QEQueueCtr m_nMin; // friends... @@ -97,16 +75,10 @@ class QEQueue { m_head(0U), m_tail(0U), m_nFree(0U), - #ifndef Q_UNSAFE - m_frontEvt_dis(static_cast(~0U)), - m_head_dis(static_cast(~0U)), - m_tail_dis(static_cast(~0U)), - m_nFree_dis(static_cast(~0U)), - #endif m_nMin(0U) {} void init( - QEvt const * qSto[], + QEvt const * * const qSto, std::uint_fast16_t const qLen) noexcept; bool post( QEvt const * const e, @@ -120,11 +92,7 @@ class QEQueue { return m_nFree; } QEQueueCtr getNMin() const noexcept { - #ifndef Q_UNSAFE return m_nMin; - #else - return 0U; - #endif } bool isEmpty() const noexcept { return m_frontEvt == nullptr; @@ -133,9 +101,11 @@ class QEQueue { private: QEQueue(QEQueue const & other) = delete; QEQueue & operator=(QEQueue const & other) = delete; + void postFIFO_( + QEvt const * const e, + void const * const sender); }; // class QEQueue } // namespace QP -//$enddecl${QF::QEQueue} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #endif // QEQUEUE_HPP_ diff --git a/include/qk.hpp b/include/qk.hpp index 10068a196..6c8c3d8a8 100644 --- a/include/qk.hpp +++ b/include/qk.hpp @@ -1,10 +1,6 @@ -//$file${include::qk.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${include::qk.hpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,41 +26,19 @@ // Quantum Leaps contact information: // // -// -//$endhead${include::qk.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #ifndef QK_HPP_ #define QK_HPP_ -//$declare${QK::QSchedStatus} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { -//${QK::QSchedStatus} ........................................................ using QSchedStatus = std::uint_fast8_t; } // namespace QP -//$enddecl${QK::QSchedStatus} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$declare${QK::QK-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QK { - -//${QK::QK-base::schedLock} .................................................. -QSchedStatus schedLock(std::uint_fast8_t const ceiling) noexcept; - -//${QK::QK-base::schedUnlock} ................................................ -void schedUnlock(QSchedStatus const prevCeil) noexcept; - -//${QK::QK-base::onIdle} ..................................................... -void onIdle(); - -} // namespace QK -} // namespace QP -//$enddecl${QK::QK-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ extern "C" { -//$declare${QK-extern-C} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -//${QK-extern-C::QK_Attr} .................................................... class QK_Attr { public: QP::QPSet readySet; @@ -73,49 +47,37 @@ class QK_Attr { std::uint_fast8_t actThre; std::uint_fast8_t lockCeil; std::uint_fast8_t intNest; - -#ifndef Q_UNSAFE - QP::QPSet readySet_dis; -#endif // ndef Q_UNSAFE - -#ifndef Q_UNSAFE - std::uint_fast8_t actPrio_dis; -#endif // ndef Q_UNSAFE - -#ifndef Q_UNSAFE - std::uint_fast8_t nextPrio_dis; -#endif // ndef Q_UNSAFE - -#ifndef Q_UNSAFE - std::uint_fast8_t actThre_dis; -#endif // ndef Q_UNSAFE - -#ifndef Q_UNSAFE - std::uint_fast8_t lockCeil_dis; -#endif // ndef Q_UNSAFE }; // class QK_Attr -//${QK-extern-C::QK_priv_} ................................................... extern QK_Attr QK_priv_; -//${QK-extern-C::QK_sched_} .................................................. std::uint_fast8_t QK_sched_() noexcept; -//${QK-extern-C::QK_activate_} ............................................... +std::uint_fast8_t QK_sched_act_( + QP::QActive const * const act, + std::uint_fast8_t const pthre_in) noexcept; + void QK_activate_() noexcept; -//$enddecl${QK-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + } // extern "C" +//============================================================================ +namespace QP { +namespace QK { + +QSchedStatus schedLock(std::uint_fast8_t const ceiling) noexcept; +void schedUnlock(QSchedStatus const prevCeil) noexcept; +void onIdle(); + +} // namespace QK +} // namespace QP + //============================================================================ // interface used only for internal implementation, but not in applications #ifdef QP_IMPL -//$declare${QK-impl} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - -//${QK-impl::QF_SCHED_STAT_} ................................................. +// scheduler locking for QK... #define QF_SCHED_STAT_ QSchedStatus lockStat_; - -//${QK-impl::QF_SCHED_LOCK_} ................................................. #define QF_SCHED_LOCK_(ceil_) do { \ if (QK_ISR_CONTEXT_()) { \ lockStat_ = 0xFFU; \ @@ -124,63 +86,32 @@ void QK_activate_() noexcept; } \ } while (false) -//${QK-impl::QF_SCHED_UNLOCK_} ............................................... #define QF_SCHED_UNLOCK_() do { \ if (lockStat_ != 0xFFU) { \ QK::schedUnlock(lockStat_); \ } \ } while (false) -//${QK-impl::QACTIVE_EQUEUE_WAIT_} ........................................... +// QActive event queue customization for QK... #define QACTIVE_EQUEUE_WAIT_(me_) (static_cast(0)) - -//${QK-impl::QACTIVE_EQUEUE_SIGNAL_} ......................................... -#ifndef Q_UNSAFE #define QACTIVE_EQUEUE_SIGNAL_(me_) do { \ QK_priv_.readySet.insert( \ static_cast((me_)->m_prio)); \ - QK_priv_.readySet.update_(&QK_priv_.readySet_dis); \ if (!QK_ISR_CONTEXT_()) { \ if (QK_sched_() != 0U) { \ QK_activate_(); \ } \ } \ } while (false) -#endif // ndef Q_UNSAFE -//${QK-impl::QACTIVE_EQUEUE_SIGNAL_} ......................................... -#ifdef Q_UNSAFE -#define QACTIVE_EQUEUE_SIGNAL_(me_) do { \ - QK_priv_.readySet.insert( \ - static_cast((me_)->m_prio)); \ - if (!QK_ISR_CONTEXT_()) { \ - if (QK_sched_() != 0U) { \ - QK_activate_(); \ - } \ - } \ -} while (false) -#endif // def Q_UNSAFE -//$enddecl${QK-impl} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$declare${QF_EPOOL-impl} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - -//${QF_EPOOL-impl::QF_EPOOL_TYPE_} ........................................... +// QF event pool customization for QK... #define QF_EPOOL_TYPE_ QMPool - -//${QF_EPOOL-impl::QF_EPOOL_INIT_} ........................................... #define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \ (p_).init((poolSto_), (poolSize_), (evtSize_)) - -//${QF_EPOOL-impl::QF_EPOOL_EVENT_SIZE_} ..................................... #define QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize()) - -//${QF_EPOOL-impl::QF_EPOOL_GET_} ............................................ #define QF_EPOOL_GET_(p_, e_, m_, qsId_) \ ((e_) = static_cast((p_).get((m_), (qsId_)))) - -//${QF_EPOOL-impl::QF_EPOOL_PUT_} ............................................ #define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_))) -//$enddecl${QF_EPOOL-impl} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #endif // QP_IMPL diff --git a/include/qmpool.hpp b/include/qmpool.hpp index d7a3749d3..85248247b 100644 --- a/include/qmpool.hpp +++ b/include/qmpool.hpp @@ -1,10 +1,6 @@ -//$file${include::qmpool.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${include::qmpool.hpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${include::qmpool.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #ifndef QMPOOL_HPP_ #define QMPOOL_HPP_ @@ -42,6 +37,12 @@ #define QF_MPOOL_CTR_SIZE 2U #endif +#define QF_MPOOL_EL(evType_) struct { \ + void * sto_[((sizeof(evType_) - 1U) / sizeof(void *)) + \ + (sizeof(evType_) < (2U * sizeof(void *)) ? 2U : 1U)]; \ +} + +//============================================================================ namespace QP { #if (QF_MPOOL_SIZ_SIZE == 1U) @@ -51,7 +52,7 @@ namespace QP { #elif (QF_MPOOL_SIZ_SIZE == 4U) using QMPoolSize = std::uint32_t; #else - #error "QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U" + #error QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U #endif #if (QF_MPOOL_CTR_SIZE == 1U) @@ -61,54 +62,22 @@ namespace QP { #elif (QF_MPOOL_CTR_SIZE == 4U) using QMPoolCtr = std::uint32_t; #else - #error "QF_MPOOL_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U" + #error QF_MPOOL_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U #endif -} // namespace QP - -#define QF_MPOOL_EL(evType_) struct { \ - QP::QFreeBlock sto_[((sizeof(evType_) - 1U) / (2U * sizeof(void *))) + 1U]; \ -} - -//$declare${QF::QFreeBlock} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QF::QFreeBlock} .......................................................... -class QFreeBlock { -private: - QFreeBlock * m_next; - -#ifndef Q_UNSAFE - std::uintptr_t m_next_dis; -#endif // ndef Q_UNSAFE - friend class QMPool; -}; // class QFreeBlock - -} // namespace QP -//$enddecl${QF::QFreeBlock} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$declare${QF::QMPool} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QF::QMPool} .............................................................. +//============================================================================ class QMPool { private: - QFreeBlock * m_start; - QFreeBlock * m_end; - QFreeBlock * volatile m_free_head; + void * * m_start; + void * * m_end; + void * * volatile m_freeHead; QMPoolSize m_blockSize; QMPoolCtr m_nTot; QMPoolCtr volatile m_nFree; - -#ifndef Q_UNSAFE QMPoolCtr m_nMin; -#endif // ndef Q_UNSAFE - -#ifndef Q_UNSAFE - std::uintptr_t m_free_head_dis; -#endif // ndef Q_UNSAFE #ifndef Q_UNSAFE + std::uintptr_t m_freeHead_dis; QMPoolCtr m_nFree_dis; #endif // ndef Q_UNSAFE @@ -116,13 +85,13 @@ class QMPool { QMPool() : m_start(nullptr), m_end(nullptr), - m_free_head(nullptr), + m_freeHead(nullptr), m_blockSize(0U), m_nTot(0U), - m_nFree(0U) + m_nFree(0U), + m_nMin(0U) #ifndef Q_UNSAFE - ,m_nMin(0U), - m_free_head_dis(static_cast(~0U)), + ,m_freeHead_dis(static_cast(~0U)), m_nFree_dis(static_cast(~0U)) #endif {} @@ -136,7 +105,9 @@ class QMPool { void put( void * const block, std::uint_fast8_t const qsId) noexcept; - QMPoolSize getBlockSize() const noexcept; + QMPoolSize getBlockSize() const noexcept { + return m_blockSize; + } QMPoolCtr getNMin() const noexcept { #ifndef Q_UNSAFE return m_nMin; @@ -168,6 +139,5 @@ class QMPool { }; // class QMPool } // namespace QP -//$enddecl${QF::QMPool} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #endif // QMPOOL_HPP_ diff --git a/include/qp.hpp b/include/qp.hpp index 787146940..1eca3408d 100644 --- a/include/qp.hpp +++ b/include/qp.hpp @@ -1,10 +1,6 @@ -//$file${include::qp.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${include::qp.hpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,17 +26,18 @@ // Quantum Leaps contact information: // // -// -//$endhead${include::qp.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #ifndef QP_HPP_ #define QP_HPP_ //============================================================================ -#define QP_VERSION_STR "8.0.1" -#define QP_VERSION 801U -#define QP_RELEASE 0x703931CEU +#define QP_VERSION_STR "8.0.2" +#define QP_VERSION 802U +// =802 =250120 +#define QP_RELEASE 0x6AEAB45DU //============================================================================ +// default configuration settings //! @cond INTERNAL #ifndef Q_SIGNAL_SIZE @@ -88,50 +85,41 @@ #endif //! @endcond -//============================================================================ -//$declare${glob-types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +//============================================================================ +// global types/utilities -//${glob-types::int_t} ....................................................... using int_t = int; -//${glob-types::enum_t} ...................................................... using enum_t = int; - -//${glob-types::float32_t} ................................................... using float32_t = float; - -//${glob-types::float64_t} ................................................... using float64_t = double; -//$enddecl${glob-types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$declare${QEP} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +#define Q_UNUSED_PAR(par_) (static_cast(par_)) +#define Q_DIM(array_) (sizeof(array_) / sizeof((array_)[0U])) +#define Q_UINT2PTR_CAST(type_, uint_) (reinterpret_cast(uint_)) + +//============================================================================ + namespace QP { -//${QEP::versionStr[]} ....................................................... -//! the current QP version number string in ROM, based on #QP_VERSION_STR -constexpr char const versionStr[] {QP_VERSION_STR}; +extern char const versionStr[24]; -//${QEP::QSignal} ............................................................ +// QSignal type #if (Q_SIGNAL_SIZE == 1U) -using QSignal = std::uint8_t; -#endif // (Q_SIGNAL_SIZE == 1U) - -//${QEP::QSignal} ............................................................ -#if (Q_SIGNAL_SIZE == 2U) -using QSignal = std::uint16_t; -#endif // (Q_SIGNAL_SIZE == 2U) + using QSignal = std::uint8_t; +#elif (Q_SIGNAL_SIZE == 2U) + using QSignal = std::uint16_t; +#elif (Q_SIGNAL_SIZE == 4U) + using QSignal = std::uint32_t; +#endif -//${QEP::QSignal} ............................................................ -#if (Q_SIGNAL_SIZE == 4U) -using QSignal = std::uint32_t; -#endif // (Q_SIGNAL_SIZE == 4U) +//============================================================================ -//${QEP::QEvt} ............................................................... class QEvt { public: QSignal sig; - std::uint8_t evtTag_; + std::uint8_t poolNum_; std::uint8_t volatile refCtr_; public: @@ -140,44 +128,33 @@ class QEvt { public: explicit constexpr QEvt(QSignal const s) noexcept : sig(s), - evtTag_(0x01U), - refCtr_(0x0EU) + poolNum_(0x00U), + refCtr_(0xE0U) {} + QEvt() = delete; void init() noexcept { // no event parameters to initialize } void init(DynEvt const dummy) noexcept { - static_cast(dummy); + Q_UNUSED_PAR(dummy); // no event parameters to initialize } - bool verify_() const noexcept { - std::uint8_t rc = refCtr_; - return (rc <= 2U*QF_MAX_ACTIVE) - && (((evtTag_ ^ rc) & 0x0FU) == 0x0FU); - } - std::uint_fast8_t getPoolNum_() const noexcept { - return static_cast(evtTag_ >> 4U); - } }; // class QEvt -//${QEP::QState} ............................................................. -using QState = std::uint_fast8_t; +using QEvtPtr = QEvt const *; -//${QEP::QStateHandler} ...................................................... -using QStateHandler = QState (*)(void * const me, QEvt const * const e); +//============================================================================ +// QEP (hierarchical event processor) types -//${QEP::QActionHandler} ..................................................... -using QActionHandler = QState (*)(void * const me); +using QState = std::uint_fast8_t; -//${QEP::QXThread} ........................................................... -// forward declaration -class QXThread; +class QXThread; // forward declaration -//${QEP::QXThreadHandler} .................................................... +using QStateHandler = QState (*)(void * const me, QEvt const * const e); +using QActionHandler = QState (*)(void * const me); using QXThreadHandler = void (*)(QXThread * const me); -//${QEP::QMState} ............................................................ struct QMState { QMState const *superstate; QStateHandler const stateHandler; @@ -186,29 +163,22 @@ struct QMState { QActionHandler const initAction; }; -//${QEP::QMTranActTable} ..................................................... struct QMTranActTable { QMState const *target; QActionHandler const act[1]; }; -//${QEP::QAsmAttr} ........................................................... union QAsmAttr { QStateHandler fun; QActionHandler act; QXThreadHandler thr; QMState const *obj; QMTranActTable const *tatbl; -#ifndef Q_UNSAFE - std::uintptr_t uint; -#endif - constexpr QAsmAttr() : fun(nullptr) {} }; -//${QEP::Q_USER_SIG} ......................................................... constexpr enum_t Q_USER_SIG {4}; -//${QEP::QAsm} ............................................................... +//============================================================================ class QAsm { protected: QAsmAttr m_state; @@ -217,8 +187,7 @@ class QAsm { public: //! All possible return values from state-handlers - //! @note - //! The order is important for algorithmic correctness. + //! NOTE: The ordering is important for algorithmic correctness. enum QStateRet : QState { // unhandled and need to "bubble up" Q_RET_SUPER, //!< event passed to superstate to handle @@ -289,6 +258,7 @@ class QAsm { return m_state.fun; } #endif // def Q_SPY + static QState top( void * const me, QEvt const * const e) noexcept @@ -357,7 +327,7 @@ class QAsm { #endif // ndef Q_SPY }; // class QAsm -//${QEP::QHsm} ............................................................... +//============================================================================ class QHsm : public QP::QAsm { protected: explicit QHsm(QStateHandler const initial) noexcept; @@ -382,12 +352,21 @@ class QHsm : public QP::QAsm { #endif // def Q_SPY private: - std::int_fast8_t hsm_tran( + std::int_fast8_t tran_simple_( + QStateHandler * const path, + std::uint_fast8_t const qsId); + + std::int_fast8_t tran_complex_( + QStateHandler * const path, + std::uint_fast8_t const qsId); + + void enter_target_( QStateHandler * const path, + std::int_fast8_t const depth, std::uint_fast8_t const qsId); }; // class QHsm -//${QEP::QMsm} ............................................................... +//============================================================================ class QMsm : public QP::QAsm { protected: explicit QMsm(QStateHandler const initial) noexcept; @@ -428,147 +407,84 @@ class QMsm : public QP::QAsm { }; // class QMsm } // namespace QP -//$enddecl${QEP} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$declare${QEP-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +//============================================================================ +// QEP-macros -//${QEP-macros::Q_STATE_DECL} ................................................ #define Q_STATE_DECL(state_) \ QP::QState state_ ## _h(QP::QEvt const * const e); \ static QP::QState state_(void * const me, QP::QEvt const * const e) -//${QEP-macros::Q_STATE_DEF} ................................................. #define Q_STATE_DEF(subclass_, state_) \ QP::QState subclass_::state_(void * const me, QP::QEvt const * const e) { \ return static_cast(me)->state_ ## _h(e); } \ QP::QState subclass_::state_ ## _h(QP::QEvt const * const e) -//${QEP-macros::Q_HANDLED} ................................................... #define Q_HANDLED() (Q_RET_HANDLED) - -//${QEP-macros::Q_UNHANDLED} ................................................. #define Q_UNHANDLED() (Q_RET_UNHANDLED) -//${QEP-macros::Q_EVT_CAST} .................................................. #define Q_EVT_CAST(subclass_) (static_cast(e)) +#define Q_STATE_CAST(handler_) (reinterpret_cast(handler_)) -//${QEP-macros::Q_STATE_CAST} ................................................ -#define Q_STATE_CAST(handler_) \ - (reinterpret_cast(handler_)) - -//${QEP-macros::QM_STATE_DECL} ............................................... #define QM_STATE_DECL(state_) \ QP::QState state_ ## _h(QP::QEvt const * const e); \ static QP::QState state_(void * const me, QP::QEvt const * const e); \ static QP::QMState const state_ ## _s -//${QEP-macros::QM_ACTION_DECL} .............................................. #define QM_ACTION_DECL(action_) \ QP::QState action_ ## _h(); \ static QP::QState action_(void * const me) -//${QEP-macros::QM_STATE_DEF} ................................................ #define QM_STATE_DEF(subclass_, state_) \ QP::QState subclass_::state_(void * const me, QP::QEvt const * const e) {\ return static_cast(me)->state_ ## _h(e); } \ QP::QState subclass_::state_ ## _h(QP::QEvt const * const e) -//${QEP-macros::QM_ACTION_DEF} ............................................... #define QM_ACTION_DEF(subclass_, action_) \ QP::QState subclass_::action_(void * const me) { \ return static_cast(me)->action_ ## _h(); } \ QP::QState subclass_::action_ ## _h() -//${QEP-macros::QM_HANDLED} .................................................. -#define QM_HANDLED() (Q_RET_HANDLED) - -//${QEP-macros::QM_UNHANDLED} ................................................ +#define QM_HANDLED() (Q_RET_HANDLED) #define QM_UNHANDLED() (Q_RET_HANDLED) +#define QM_SUPER() (Q_RET_SUPER) +#define QM_STATE_NULL (nullptr) +#define Q_ACTION_NULL (nullptr) -//${QEP-macros::QM_SUPER} .................................................... -#define QM_SUPER() (Q_RET_SUPER) - -//${QEP-macros::QM_STATE_NULL} ............................................... -#define QM_STATE_NULL (nullptr) - -//${QEP-macros::Q_ACTION_NULL} ............................................... -#define Q_ACTION_NULL (nullptr) - -//${QEP-macros::Q_UNUSED_PAR} ................................................ -#define Q_UNUSED_PAR(par_) (static_cast(par_)) - -//${QEP-macros::Q_DIM} ....................................................... -#define Q_DIM(array_) (sizeof(array_) / sizeof((array_)[0U])) - -//${QEP-macros::Q_UINT2PTR_CAST} ............................................. -#define Q_UINT2PTR_CAST(type_, uint_) (reinterpret_cast(uint_)) - -//${QEP-macros::INIT} ........................................................ -#ifdef Q_SPY -#define INIT(qsId_) init((qsId_)) -#endif // def Q_SPY - -//${QEP-macros::INIT} ........................................................ -#ifndef Q_SPY -#define INIT(dummy) init(0U) -#endif // ndef Q_SPY - -//${QEP-macros::DISPATCH} .................................................... #ifdef Q_SPY -#define DISPATCH(e_, qsId_) dispatch((e_), (qsId_)) -#endif // def Q_SPY - -//${QEP-macros::DISPATCH} .................................................... -#ifndef Q_SPY -#define DISPATCH(e_, dummy) dispatch((e_), 0U) + #define INIT(qsId_) init((qsId_)) + #define DISPATCH(e_, qsId_) dispatch((e_), (qsId_)) +#else + #define INIT(dummy) init(0U) + #define DISPATCH(e_, dummy) dispatch((e_), 0U) #endif // ndef Q_SPY -//$enddecl${QEP-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$declare${QF::types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +//============================================================================ namespace QP { -//${QF::types::QPrioSpec} .................................................... using QPrioSpec = std::uint16_t; -//${QF::types::QEvtPtr} ...................................................... -using QEvtPtr = QEvt const *; - -//${QF::types::QTimeEvtCtr} .................................................. #if (QF_TIMEEVT_CTR_SIZE == 1U) -using QTimeEvtCtr = std::uint8_t; -#endif // (QF_TIMEEVT_CTR_SIZE == 1U) - -//${QF::types::QTimeEvtCtr} .................................................. -#if (QF_TIMEEVT_CTR_SIZE == 2U) -using QTimeEvtCtr = std::uint16_t; -#endif // (QF_TIMEEVT_CTR_SIZE == 2U) - -//${QF::types::QTimeEvtCtr} .................................................. -#if (QF_TIMEEVT_CTR_SIZE == 4U) -using QTimeEvtCtr = std::uint32_t; -#endif // (QF_TIMEEVT_CTR_SIZE == 4U) + using QTimeEvtCtr = std::uint8_t; +#elif (QF_TIMEEVT_CTR_SIZE == 2U) + using QTimeEvtCtr = std::uint16_t; +#elif (QF_TIMEEVT_CTR_SIZE == 4U) + using QTimeEvtCtr = std::uint32_t; +#endif // (QF_TIMEEVT_CTR_SIZE == 4U) -//${QF::types::QPSetBits} .................................................... #if (QF_MAX_ACTIVE <= 8U) -using QPSetBits = std::uint8_t; -#endif // (QF_MAX_ACTIVE <= 8U) + using QPSetBits = std::uint8_t; +#elif (8U < QF_MAX_ACTIVE) && (QF_MAX_ACTIVE <= 16U) + using QPSetBits = std::uint16_t; +#elif (16 < QF_MAX_ACTIVE) + using QPSetBits = std::uint32_t; +#endif // (16 < QF_MAX_ACTIVE) -//${QF::types::QPSetBits} .................................................... -#if (8U < QF_MAX_ACTIVE) && (QF_MAX_ACTIVE <= 16U) -using QPSetBits = std::uint16_t; -#endif // (8U < QF_MAX_ACTIVE) && (QF_MAX_ACTIVE <= 16U) - -//${QF::types::QPSetBits} .................................................... -#if (16 < QF_MAX_ACTIVE) -using QPSetBits = std::uint32_t; -#endif // (16 < QF_MAX_ACTIVE) - -//${QF::types::QF_LOG2} ...................................................... #ifndef QF_LOG2 -std::uint_fast8_t QF_LOG2(QP::QPSetBits x) noexcept; + std::uint_fast8_t QF_LOG2(QP::QPSetBits const bitmask) noexcept; #endif // ndef QF_LOG2 -//${QF::types::QPSet} ........................................................ +//============================================================================ class QPSet { private: QPSetBits m_bits[((QF_MAX_ACTIVE + (8U*sizeof(QPSetBits))) - 1U)/(8U*sizeof(QPSetBits))]; @@ -576,126 +492,95 @@ class QPSet { public: void setEmpty() noexcept { m_bits[0] = 0U; - #if (QF_MAX_ACTIVE > 32) +#if (QF_MAX_ACTIVE > 32) m_bits[1] = 0U; - #endif +#endif } bool isEmpty() const noexcept { - #if (QF_MAX_ACTIVE <= 32U) +#if (QF_MAX_ACTIVE <= 32U) return (m_bits[0] == 0U); - #else +#else return (m_bits[0] == 0U) ? (m_bits[1] == 0U) : false; - #endif +#endif } bool notEmpty() const noexcept { - #if (QF_MAX_ACTIVE <= 32U) +#if (QF_MAX_ACTIVE <= 32U) return (m_bits[0] != 0U); - #else +#else return (m_bits[0] != 0U) ? true : (m_bits[1] != 0U); - #endif +#endif } bool hasElement(std::uint_fast8_t const n) const noexcept { - #if (QF_MAX_ACTIVE <= 32U) +#if (QF_MAX_ACTIVE <= 32U) return (m_bits[0] & (static_cast(1U) << (n - 1U))) != 0U; - #else +#else return (n <= 32U) ? ((m_bits[0] & (static_cast(1U) << (n - 1U))) != 0U) : ((m_bits[1] & (static_cast(1U) << (n - 33U))) != 0U); - #endif +#endif } void insert(std::uint_fast8_t const n) noexcept { - #if (QF_MAX_ACTIVE <= 32U) +#if (QF_MAX_ACTIVE <= 32U) m_bits[0] = (m_bits[0] | (static_cast(1U) << (n - 1U))); - #else +#else if (n <= 32U) { m_bits[0] = (m_bits[0] | (static_cast(1U) << (n - 1U))); } else { m_bits[1] = (m_bits[1] | (static_cast(1U) << (n - 33U))); } - #endif +#endif } void remove(std::uint_fast8_t const n) noexcept { - #if (QF_MAX_ACTIVE <= 32U) +#if (QF_MAX_ACTIVE <= 32U) m_bits[0] = (m_bits[0] & static_cast(~(1U << (n - 1U)))); - #else +#else if (n <= 32U) { (m_bits[0] = (m_bits[0] & ~(static_cast(1U) << (n - 1U)))); } else { (m_bits[1] = (m_bits[1] & ~(static_cast(1U) << (n - 33U)))); } - #endif +#endif } std::uint_fast8_t findMax() const noexcept { - #if (QF_MAX_ACTIVE <= 32U) +#if (QF_MAX_ACTIVE <= 32U) return QF_LOG2(m_bits[0]); - #else +#else return (m_bits[1] != 0U) ? (QF_LOG2(m_bits[1]) + 32U) : (QF_LOG2(m_bits[0])); - #endif +#endif } -#ifndef Q_UNSAFE - void update_(QPSet * const dis) const noexcept { - dis->m_bits[0] = ~m_bits[0]; - #if (QF_MAX_ACTIVE > 32U) - dis->m_bits[1] = ~m_bits[1]; - #endif - } -#endif // ndef Q_UNSAFE - -#ifndef Q_UNSAFE - bool verify_(QPSet const * const dis) const noexcept { - #if (QF_MAX_ACTIVE <= 32U) - return m_bits[0] == static_cast(~dis->m_bits[0]); - #else - return (m_bits[0] == static_cast(~dis->m_bits[0])) - && (m_bits[1] == static_cast(~dis->m_bits[1])); - #endif - } -#endif // ndef Q_UNSAFE }; // class QPSet -//${QF::types::QSubscrList} .................................................. +//============================================================================ class QSubscrList { private: QPSet m_set; -#ifndef Q_UNSAFE - QPSet m_set_dis; -#endif // ndef Q_UNSAFE - // friends... friend class QActive; }; // class QSubscrList -//${QF::types::QPtrDis} ...................................................... +//============================================================================ class QPtrDis { private: std::uintptr_t m_ptr_dis; // friends... friend class QTimeEvt; - - // friends... friend class QXThread; public: QPtrDis(void const * const ptr = nullptr) noexcept; }; // class QPtrDis -//${QF::types::QEQueue} ...................................................... -class QEQueue; - -} // namespace QP -//$enddecl${QF::types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +class QEQueue; // forward declaration -//$declare${QF::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -//${QF::QActive} ............................................................. +//============================================================================ class QActive : public QP::QAsm { protected: std::uint8_t m_prio; @@ -714,14 +599,6 @@ class QActive : public QP::QAsm { #endif // def QACTIVE_EQUEUE_TYPE public: - -#ifndef Q_UNSAFE - std::uint8_t m_prio_dis; -#endif // ndef Q_UNSAFE - -#ifndef Q_UNSAFE - std::uint8_t m_pthre_dis; -#endif // ndef Q_UNSAFE static QActive * registry_[QF_MAX_ACTIVE + 1U]; static QSubscrList * subscrList_; static enum_t maxPubSignal_; @@ -745,11 +622,6 @@ class QActive : public QP::QAsm { { m_state.fun = Q_STATE_CAST(&top); m_temp.fun = initial; - - #ifndef Q_UNSAFE - m_prio_dis = static_cast(~m_prio); - m_pthre_dis = static_cast(~m_pthre); - #endif } public: @@ -873,15 +745,14 @@ class QActive : public QP::QAsm { void * par, void const * sender) noexcept; #endif // def QF_ISR_API -}; // class QActive - -} // namespace QP -//$enddecl${QF::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$declare${QF::QMActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { +private: + void postFIFO_( + QEvt const * const e, + void const * const sender); +}; // class QActive -//${QF::QMActive} ............................................................ +//============================================================================ class QMActive : public QP::QActive { protected: QMActive(QStateHandler const initial) noexcept; @@ -917,26 +788,13 @@ class QMActive : public QP::QActive { } }; // class QMActive -} // namespace QP -//$enddecl${QF::QMActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$declare${QF::QTimeEvt} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -//${QF::QTimeEvt} ............................................................ +//============================================================================ class QTimeEvt : public QP::QEvt { private: QTimeEvt * volatile m_next; - -#ifndef Q_UNSAFE - std::uintptr_t m_next_dis; -#endif // ndef Q_UNSAFE void * m_act; QTimeEvtCtr volatile m_ctr; - -#ifndef Q_UNSAFE - QTimeEvtCtr m_ctr_dis; -#endif // ndef Q_UNSAFE QTimeEvtCtr m_interval; std::uint8_t m_tickRate; std::uint8_t m_flags; @@ -944,10 +802,6 @@ class QTimeEvt : public QP::QEvt { public: static QTimeEvt timeEvtHead_[QF_MAX_TICK_RATE]; -#ifndef Q_UNSAFE - static QPtrDis timeEvtHead_dis_[QF_MAX_TICK_RATE]; -#endif // ndef Q_UNSAFE - private: friend class QXThread; @@ -1002,15 +856,13 @@ class QTimeEvt : public QP::QEvt { QTimeEvt() noexcept; QTimeEvt(QTimeEvt const & other) = delete; QTimeEvt & operator=(QTimeEvt const & other) = delete; + QTimeEvt *expire_( + QTimeEvt * const prev_link, + QActive const * const act, + std::uint_fast8_t const tickRate) noexcept; }; // class QTimeEvt -} // namespace QP -//$enddecl${QF::QTimeEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$declare${QF::QTicker} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QF::QTicker} ............................................................. +//============================================================================ class QTicker : public QP::QActive { public: explicit QTicker(std::uint_fast8_t const tickRate) noexcept; @@ -1026,29 +878,17 @@ class QTicker : public QP::QActive { void trig_(void const * const sender) noexcept; }; // class QTicker -} // namespace QP -//$enddecl${QF::QTicker} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$declare${QF::QF-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { +//============================================================================ namespace QF { -//${QF::QF-base::init} ....................................................... void init(); - -//${QF::QF-base::stop} ....................................................... void stop(); -//${QF::QF-base::run} ........................................................ int_t run(); -//${QF::QF-base::onStartup} .................................................. void onStartup(); - -//${QF::QF-base::onCleanup} .................................................. void onCleanup(); -//${QF::QF-base::psInit} ..................................................... //! @deprecated inline void psInit( QSubscrList * const subscrSto, @@ -1057,7 +897,6 @@ inline void psInit( QActive::psInit(subscrSto, maxSignal); } -//${QF::QF-base::publish_} ................................................... //! @deprecated inline void publish_( QEvt const * const e, @@ -1067,7 +906,6 @@ inline void publish_( QActive::publish_(e, sender, qsId); } -//${QF::QF-base::tick} ....................................................... //! @deprecated inline void tick( std::uint_fast8_t const tickRate, @@ -1076,103 +914,71 @@ inline void tick( QTimeEvt::tick(tickRate, sender); } -//${QF::QF-base::getQueueMin} ................................................ //! @deprecated inline std::uint_fast16_t getQueueMin(std::uint_fast8_t const prio) noexcept { return QActive::getQueueMin(prio); } -//${QF::QF-base::NO_MARGIN} .................................................. constexpr std::uint_fast16_t NO_MARGIN {0xFFFFU}; -} // namespace QF -} // namespace QP -//$enddecl${QF::QF-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$declare${QF::QF-dyn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QF { - -//${QF::QF-dyn::poolInit} .................................................... +//============================================================================ +// QF dynamic memory facilities void poolInit( void * const poolSto, std::uint_fast32_t const poolSize, std::uint_fast16_t const evtSize) noexcept; -//${QF::QF-dyn::poolGetMaxBlockSize} ......................................... std::uint_fast16_t poolGetMaxBlockSize() noexcept; - -//${QF::QF-dyn::getPoolMin} .................................................. std::uint_fast16_t getPoolMin(std::uint_fast8_t const poolNum) noexcept; - -//${QF::QF-dyn::newX_} ....................................................... QEvt * newX_( std::uint_fast16_t const evtSize, std::uint_fast16_t const margin, enum_t const sig) noexcept; - -//${QF::QF-dyn::gc} .......................................................... void gc(QEvt const * const e) noexcept; - -//${QF::QF-dyn::newRef_} ..................................................... QEvt const * newRef_( QEvt const * const e, QEvt const * const evtRef) noexcept; -//${QF::QF-dyn::deleteRef_} .................................................. void deleteRef_(QEvt const * const evtRef) noexcept; -//${QF::QF-dyn::q_new} ....................................................... #ifndef QEVT_PAR_INIT -template -inline evtT_ * q_new(enum_t const sig) { - return static_cast( - QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, sig)); -} -#endif // ndef QEVT_PAR_INIT - -//${QF::QF-dyn::q_new} ....................................................... -#ifdef QEVT_PAR_INIT -template -inline evtT_ * q_new( - enum_t const sig, - Args... args) -{ - evtT_ *e = static_cast( - QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, sig)); - e->init(args...); // e cannot be nullptr - return e; -} -#endif // def QEVT_PAR_INIT - -//${QF::QF-dyn::q_new_x} ..................................................... -#ifndef QEVT_PAR_INIT -template -inline evtT_ * q_new_x( - std::uint_fast16_t const margin, - enum_t const sig) -{ - return static_cast(QP::QF::newX_(sizeof(evtT_), margin, sig)); -} -#endif // ndef QEVT_PAR_INIT - -//${QF::QF-dyn::q_new_x} ..................................................... -#ifdef QEVT_PAR_INIT -template -inline evtT_ * q_new_x( - std::uint_fast16_t const margin, - enum_t const sig, - Args... args) -{ - evtT_ *e = static_cast(QP::QF::newX_(sizeof(evtT_), margin, sig)); - if (e != nullptr) { - e->init(args...); + template + inline evtT_ * q_new(enum_t const sig) { + return static_cast( + QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, sig)); + } + template + inline evtT_ * q_new_x( + std::uint_fast16_t const margin, + enum_t const sig) + { + return static_cast(QP::QF::newX_(sizeof(evtT_), margin, sig)); + } +#else + template + inline evtT_ * q_new( + enum_t const sig, + Args... args) + { + evtT_ *e = static_cast( + QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, sig)); + e->init(args...); // e cannot be nullptr + return e; + } + template + inline evtT_ * q_new_x( + std::uint_fast16_t const margin, + enum_t const sig, + Args... args) + { + evtT_ *e = static_cast(QP::QF::newX_(sizeof(evtT_), margin, sig)); + if (e != nullptr) { + e->init(args...); + } + return e; } - return e; -} #endif // def QEVT_PAR_INIT -//${QF::QF-dyn::q_new_ref} ................................................... template inline void q_new_ref( QP::QEvt const * const e, @@ -1181,32 +987,25 @@ inline void q_new_ref( evtRef = static_cast(QP::QF::newRef_(e, evtRef)); } -//${QF::QF-dyn::q_delete_ref} ................................................ template inline void q_delete_ref(evtT_ const *& evtRef) { QP::QF::deleteRef_(evtRef); evtRef = nullptr; } -//${QF::QF-dyn::newXfromISR_} ................................................ #ifdef QF_ISR_API QEvt * newXfromISR_( std::uint_fast16_t const evtSize, std::uint_fast16_t const margin, enum_t const sig) noexcept; -#endif // def QF_ISR_API - -//${QF::QF-dyn::gcFromISR} ................................................... -#ifdef QF_ISR_API void gcFromISR(QEvt const * e) noexcept; #endif // def QF_ISR_API } // namespace QF } // namespace QP -//$enddecl${QF::QF-dyn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ extern "C" { -//$declare${QF-extern-C} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv //${QF-extern-C::QF_onContextSw} ............................................. #ifdef QF_ON_CONTEXT_SW @@ -1214,113 +1013,55 @@ void QF_onContextSw( QP::QActive * prev, QP::QActive * next); #endif // def QF_ON_CONTEXT_SW -//$enddecl${QF-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } // extern "C" -//$declare${QF-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +//============================================================================ +// QF base facilities -//${QF-macros::Q_PRIO} ....................................................... #define Q_PRIO(prio_, pthre_) \ (static_cast((prio_) | (pthre_) << 8U)) -//${QF-macros::Q_NEW} ........................................................ #ifndef QEVT_PAR_INIT -#define Q_NEW(evtT_, sig_) (QP::QF::q_new((sig_))) -#endif // ndef QEVT_PAR_INIT + #define Q_NEW(evtT_, sig_) (QP::QF::q_new((sig_))) + #define Q_NEW_X(evtT_, margin_, sig_) (QP::QF::q_new_x((margin_), (sig_))) +#else + #define Q_NEW(evtT_, sig_, ...) (QP::QF::q_new((sig_), __VA_ARGS__)) + #define Q_NEW_X(evtT_, margin_, sig_, ...) (QP::QF::q_new_x((margin_), (sig_), __VA_ARGS__)) +#endif // QEVT_PAR_INIT -//${QF-macros::Q_NEW} ........................................................ -#ifdef QEVT_PAR_INIT -#define Q_NEW(evtT_, sig_, ...) (QP::QF::q_new((sig_), __VA_ARGS__)) -#endif // def QEVT_PAR_INIT - -//${QF-macros::Q_NEW_X} ...................................................... -#ifndef QEVT_PAR_INIT -#define Q_NEW_X(evtT_, margin_, sig_) (QP::QF::q_new_x((margin_), (sig_))) -#endif // ndef QEVT_PAR_INIT - -//${QF-macros::Q_NEW_X} ...................................................... -#ifdef QEVT_PAR_INIT -#define Q_NEW_X(evtT_, margin_, sig_, ...) (QP::QF::q_new_x((margin_), (sig_), __VA_ARGS__)) -#endif // def QEVT_PAR_INIT - -//${QF-macros::Q_NEW_REF} .................................................... #define Q_NEW_REF(evtRef_, evtT_) (QP::QF::q_new_ref(e, (evtRef_))) - -//${QF-macros::Q_DELETE_REF} ................................................. #define Q_DELETE_REF(evtRef_) do { \ QP::QF::deleteRef_((evtRef_)); \ (evtRef_) = nullptr; \ } while (false) -//${QF-macros::PUBLISH} ...................................................... #ifdef Q_SPY -#define PUBLISH(e_, sender_) \ - publish_((e_), (sender_), (sender_)->getPrio()) -#endif // def Q_SPY - -//${QF-macros::PUBLISH} ...................................................... -#ifndef Q_SPY -#define PUBLISH(e_, dummy) publish_((e_), nullptr, 0U) + #define PUBLISH(e_, sender_) \ + publish_((e_), (sender_), (sender_)->getPrio()) + #define POST(e_, sender_) post_((e_), QP::QF::NO_MARGIN, (sender_)) + #define POST_X(e_, margin_, sender_) \ + post_((e_), (margin_), (sender_)) + #define TICK_X(tickRate_, sender_) tick((tickRate_), (sender_)) + #define TRIG(sender_) trig_((sender_)) +#else + #define PUBLISH(e_, dummy) publish_((e_), nullptr, 0U) + #define POST(e_, dummy) post_((e_), QP::QF::NO_MARGIN, nullptr) + #define POST_X(e_, margin_, dummy) post_((e_), (margin_), nullptr) + #define TICK_X(tickRate_, dummy) tick((tickRate_), nullptr) + #define TRIG(sender_) trig_(nullptr) #endif // ndef Q_SPY -//${QF-macros::POST} ......................................................... -#ifdef Q_SPY -#define POST(e_, sender_) post_((e_), QP::QF::NO_MARGIN, (sender_)) -#endif // def Q_SPY - -//${QF-macros::POST} ......................................................... -#ifndef Q_SPY -#define POST(e_, dummy) post_((e_), QP::QF::NO_MARGIN, nullptr) -#endif // ndef Q_SPY - -//${QF-macros::POST_X} ....................................................... -#ifdef Q_SPY -#define POST_X(e_, margin_, sender_) \ - post_((e_), (margin_), (sender_)) -#endif // def Q_SPY - -//${QF-macros::POST_X} ....................................................... -#ifndef Q_SPY -#define POST_X(e_, margin_, dummy) post_((e_), (margin_), nullptr) -#endif // ndef Q_SPY - -//${QF-macros::TICK_X} ....................................................... -#ifdef Q_SPY -#define TICK_X(tickRate_, sender_) tick((tickRate_), (sender_)) -#endif // def Q_SPY - -//${QF-macros::TICK_X} ....................................................... -#ifndef Q_SPY -#define TICK_X(tickRate_, dummy) tick((tickRate_), nullptr) -#endif // ndef Q_SPY - -//${QF-macros::TICK} ......................................................... #define TICK(sender_) TICK_X(0U, (sender_)) -//${QF-macros::TRIG} ......................................................... -#ifdef Q_SPY -#define TRIG(sender_) trig_((sender_)) -#endif // def Q_SPY - -//${QF-macros::TRIG} ......................................................... -#ifndef Q_SPY -#define TRIG(sender_) trig_(nullptr) -#endif // ndef Q_SPY - -//${QF-macros::QF_CRIT_EXIT_NOP} ............................................. #ifndef QF_CRIT_EXIT_NOP -#define QF_CRIT_EXIT_NOP() (static_cast(0)) + #define QF_CRIT_EXIT_NOP() (static_cast(0)) #endif // ndef QF_CRIT_EXIT_NOP -//${QF-macros::QF_MEM_SYS} ................................................... -#ifndef QF_MEM_SYS -#define QF_MEM_SYS() (static_cast(0)) -#endif // ndef QF_MEM_SYS +//============================================================================ +// memory protection facilities -//${QF-macros::QF_MEM_APP} ................................................... -#ifndef QF_MEM_APP -#define QF_MEM_APP() (static_cast(0)) -#endif // ndef QF_MEM_APP -//$enddecl${QF-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#ifdef QF_MEM_ISOLATE + #error Memory isolation not supported in this QP edition, need SafeQP +#endif // def QF_MEM_ISOLATE #endif // QP_HPP_ diff --git a/include/qp_pkg.hpp b/include/qp_pkg.hpp index dc69110d3..0806a4843 100644 --- a/include/qp_pkg.hpp +++ b/include/qp_pkg.hpp @@ -1,10 +1,6 @@ -//$file${include::qp_pkg.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${include::qp_pkg.hpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,68 +26,54 @@ // Quantum Leaps contact information: // // -// -//$endhead${include::qp_pkg.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #ifndef QP_PKG_HPP_ #define QP_PKG_HPP_ -//$declare${QF::QF-pkg} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +//============================================================================ +#define QF_CONST_CAST_(type_, ptr_) const_cast(ptr_) +#define Q_PTR2UINT_CAST_(ptr_) (reinterpret_cast(ptr_)) +#define QF_PTR_RANGE_(x_, min_, max_) (((min_) <= (x_)) && ((x_) <= (max_))) + +//============================================================================ namespace QP { namespace QF { -//${QF::QF-pkg::Attr} ........................................................ class Attr { public: #if (QF_MAX_EPOOL > 0U) QF_EPOOL_TYPE_ ePool_[QF_MAX_EPOOL]; -#endif // (QF_MAX_EPOOL > 0U) - -#if (QF_MAX_EPOOL > 0U) std::uint_fast8_t maxPool_; -#endif // (QF_MAX_EPOOL > 0U) - -#if (QF_MAX_EPOOL == 0U) +#else std::uint8_t dummy; #endif // (QF_MAX_EPOOL == 0U) }; // class Attr -//${QF::QF-pkg::priv_} ....................................................... extern QF::Attr priv_; -//${QF::QF-pkg::bzero_} ...................................................... void bzero_( void * const start, std::uint_fast16_t const len) noexcept; } // namespace QF -} // namespace QP -//$enddecl${QF::QF-pkg} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -#define QF_CONST_CAST_(type_, ptr_) const_cast(ptr_) -#define Q_PTR2UINT_CAST_(ptr_) (reinterpret_cast(ptr_)) -#define QF_PTR_RANGE_(x_, min_, max_) (((min_) <= (x_)) && ((x_) <= (max_))) - -namespace QP { +//============================================================================ // Bitmasks are for the QTimeEvt::flags attribute constexpr std::uint8_t QTE_FLAG_IS_LINKED {1U << 7U}; constexpr std::uint8_t QTE_FLAG_WAS_DISARMED {1U << 6U}; +//============================================================================ inline void QEvt_refCtr_inc_(QEvt const * const e) noexcept { + // NOTE: this function must be called inside a critical section std::uint8_t rc = e->refCtr_ + 1U; (QF_CONST_CAST_(QEvt*, e))->refCtr_ = rc; // cast away 'const' -#ifndef Q_UNSAFE - (QF_CONST_CAST_(QEvt*, e))->evtTag_ = (e->evtTag_ & 0xF0U) | ((~rc) & 0x0FU); -#endif } inline void QEvt_refCtr_dec_(QEvt const * const e) noexcept { + // NOTE: this function must be called inside a critical section std::uint8_t rc = e->refCtr_ - 1U; (QF_CONST_CAST_(QEvt*, e))->refCtr_ = rc; // cast away 'const' -#ifndef Q_UNSAFE - (QF_CONST_CAST_(QEvt*, e))->evtTag_ = (e->evtTag_ & 0xF0U) | ((~rc) & 0x0FU); -#endif } } // namespace QP diff --git a/include/qpcpp.hpp b/include/qpcpp.hpp index 2f3c62169..0fc1f9109 100644 --- a/include/qpcpp.hpp +++ b/include/qpcpp.hpp @@ -1,10 +1,6 @@ -//$file${include::qpcpp.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${include::qpcpp.hpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${include::qpcpp.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #ifndef QPCPP_HPP_ #define QPCPP_HPP_ @@ -47,11 +42,11 @@ //============================================================================ #ifndef QP_API_VERSION #define QP_API_VERSION 0 -#endif // QP_API_VERSION +#endif // QP_API_VERSION // QP API compatibility layer... //============================================================================ -#if (QP_API_VERSION < 750) +#if (QP_API_VERSION < 800) #define QM_SM_STATE_DECL(subm_, state_) error "submachines no longer supported" #define qm_super_sub(sm_state_) error "submachines no longer supported" @@ -64,7 +59,7 @@ #define QEVT_PAR_INIT #endif -//! @deprecated plain 'char' is no longer forbidden in MISRA/AUTOSAR-C++ +//! @deprecated plain 'char' is no longer forbidden in MISRA-C++:2023 using char_t = char; //! @deprecated assertion failure handler @@ -111,123 +106,11 @@ using char_t = char; #define Q_ALLEGE(expr_) Q_ALLEGE_ID(__LINE__, (expr_)) //! Static (compile-time) assertion. -//! //! @deprecated //! Use Q_ASSERT_STATIC() or better yet `static_assert()` instead. -//! #define Q_ASSERT_COMPILE(expr_) Q_ASSERT_STATIC(expr_) -//! @deprecated use QP::QF::NO_MARGIN instead -#define QF_NO_MARGIN QP::QF::NO_MARGIN - -//============================================================================ -#if (QP_API_VERSION < 691) - -//! @deprecated enable the QS global filter -#define QS_FILTER_ON(rec_) QS_GLB_FILTER((rec_)) - -//! @deprecated disable the QS global filter -#define QS_FILTER_OFF(rec_) QS_GLB_FILTER(-(rec_)) -//! @deprecated enable the QS local filter for SM (state machine) object -#define QS_FILTER_SM_OBJ(obj_) (static_cast(0)) - -//! @deprecated enable the QS local filter for AO (active objects) -#define QS_FILTER_AO_OBJ(obj_) (static_cast(0)) - -//! @deprecated enable the QS local filter for MP (memory pool) object -#define QS_FILTER_MP_OBJ(obj_) (static_cast(0)) - -//! @deprecated enable the QS local filter for EQ (event queue) object -#define QS_FILTER_EQ_OBJ(obj_) (static_cast(0)) - -//! @deprecated enable the QS local filter for TE (time event) object -#define QS_FILTER_TE_OBJ(obj_) (static_cast(0)) - -#ifdef Q_SPY - -//! @deprecated local Filter for a generic application object `obj_`. -#define QS_FILTER_AP_OBJ(obj_) \ - (QP::QS::filt_.loc_AP = (obj_)) - -//! @deprecated begin of a user QS record, instead use QS_BEGIN_ID() -#define QS_BEGIN(rec_, obj_) \ - if (QS_GLB_FILTER_(rec_) && \ - ((QP::QS::filt_.loc[QP::QS::AP_OBJ] == nullptr) \ - || (QP::QS::filt_.loc_AP == (obj_)))) \ - { \ - QS_CRIT_STAT \ - QS_CRIT_ENTRY(); \ - QP::QS::beginRec_(static_cast(rec_)); \ - QS_TIME_PRE(); - -//! @deprecated output hex-formatted std::uint32_t to the QS record -#define QS_U32_HEX(width_, data_) \ - (QP::QS::u32_fmt_(static_cast( \ - (static_cast((width_) << 4)) | QS_HEX_FMT), (data_))) - -#else - -#define QS_FILTER_AP_OBJ(obj_) (static_cast(0)) -#define QS_BEGIN(rec_, obj_) if (false) { -#define QS_U32_HEX(width_, data_) (Q_UNUSED_PAR(0)) - -#endif // def Q_SPY - -//============================================================================ -#if (QP_API_VERSION < 680) - -//! @deprecated -//! Macro to specify a tran. in the "me->" impl-strategy. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! you call tran(Q_STATE_CAST(target_)). -#define Q_TRAN(target_) (me->tran(Q_STATE_CAST(target_))) - -//! @deprecated -//! Macro to specify a tran-to-history in the "me->" impl-strategy. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! you call tran_hist(Q_STATE_CAST(hist_)). -#define Q_TRAN_HIST(hist_) (me->tran_hist((hist_))) - -//! @deprecated -//! Macro to specify the superstate in the "me->" impl-strategy. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! you call super(state_)). -#define Q_SUPER(state_) (me->super(Q_STATE_CAST(state_))) - -//! @deprecated -//! Macro to call in a QM state entry-handler. Applicable only to QMSMs. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_entry(Q_STATE_CAST(state_)). -#define QM_ENTRY(state_) (me->qm_entry((state_))) - -//! @deprecated -//! Macro to call in a QM state exit-handler. Applicable only to QMSMs. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_exit(Q_STATE_CAST(state_)). -#define QM_EXIT(state_) (me->qm_exit((state_))) - -//! @deprecated -//! Macro to call in a QM state-handler when it executes a tran. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_tran((tatbl_)). -#define QM_TRAN(tatbl_) (me->qm_tran((tatbl_))) - -//! @deprecated -//! Macro to call in a QM state-handler when it executes an initial tran. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_tran_init((tatbl_)). -#define QM_TRAN_INIT(tatbl_) (me->qm_tran_init((tatbl_))) - -//! @deprecated -//! Macro to call in a QM state-handler when it executes a tran-to-history. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_tran_hist((history_), (tatbl_)). -#define QM_TRAN_HIST(history_, tatbl_) \ - (me->qm_tran_hist((history_), (tatbl_))) - -#endif // QP_API_VERSION < 680 -#endif // QP_API_VERSION < 691 -#endif // QP_API_VERSION < 750 +#endif // QP_API_VERSION < 800 #endif // QPCPP_HPP_ diff --git a/include/qs_dummy.hpp b/include/qs_dummy.hpp index 8c4da7e67..0cbdfc2fc 100644 --- a/include/qs_dummy.hpp +++ b/include/qs_dummy.hpp @@ -1,5 +1,6 @@ //============================================================================ -// QP/C++ Spy software tracing target-resident component +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -7,10 +8,9 @@ // ------------------------ // Modern Embedded Software // -// // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -31,11 +31,11 @@ #define QS_DUMMY_HPP_ #ifdef Q_SPY - #error "Q_SPY must NOT be defined to include qs_dummy.hpp" + error Q_SPY must NOT be defined to include qs_dummy.hpp #endif #ifdef Q_UTEST - #error "Q_UTEST must NOT be defined to include qs_dummy.hpp" + error Q_UTEST must NOT be defined to include qs_dummy.hpp #endif #define QS_INIT(arg_) (true) @@ -166,9 +166,6 @@ void QS_onTestLoop(void); #define QS_CRIT_ENTRY() static_cast(0) #define QS_CRIT_EXIT() static_cast(0) - #define QS_MEM_SYS() static_cast(0) - #define QS_MEM_APP() static_cast(0) - #define QS_TR_CRIT_ENTRY() static_cast(0) #define QS_TR_CRIT_EXIT() static_cast(0) #define QS_TR_ISR_ENTRY(isrnest_, prio_) static_cast(0) diff --git a/include/qsafe.h b/include/qsafe.h index 43e772ac9..df6bf21a7 100644 --- a/include/qsafe.h +++ b/include/qsafe.h @@ -1,82 +1,58 @@ -//$file${include::qsafe.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpc.qm -// File: ${include::qsafe.h} -// -// This code has been generated by QM 6.1.1 . -// 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: +//============================================================================ +// SafeQP/C Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // 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: +// SPDX-License-Identifier: LicenseRef-QL-commercial // -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is licensed under the terms of the Quantum Leaps commercial +// licenses. Please contact Quantum Leaps for more information about the +// available licensing options. // -// Redistributions in source code must retain this top-level comment block. -// Plagiarizing this software to sidestep the license obligations is illegal. +// RESTRICTIONS +// You may NOT : +// (a) redistribute, encumber, sell, rent, lease, sublicense, or otherwise +// transfer rights in this software, +// (b) remove or alter any trademark, logo, copyright or other proprietary +// notices, legends, symbols or labels present in this software, +// (c) plagiarize this software to sidestep the licensing obligations. // -// Contact information: +// Quantum Leaps contact information: // // -// -//$endhead${include::qsafe.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #ifndef QSAFE_H_ #define QSAFE_H_ -#ifdef __cplusplus -extern "C" { -#endif - // QF-FuSa enabled =========================================================== #ifndef Q_UNSAFE #ifndef QF_CRIT_STAT -#define QF_CRIT_STAT + #define QF_CRIT_STAT #endif #ifndef QF_CRIT_ENTRY -#define QF_CRIT_ENTRY() ((void)0) + #define QF_CRIT_ENTRY() ((void)0) #endif #ifndef QF_CRIT_EXIT -#define QF_CRIT_EXIT() ((void)0) + #define QF_CRIT_EXIT() ((void)0) #endif -//$declare${QP-FuSa::enabled} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - -//${QP-FuSa::enabled::Q_DEFINE_THIS_MODULE} .................................. #define Q_DEFINE_THIS_MODULE(name_) \ static char const Q_this_module_[] = name_; -//${QP-FuSa::enabled::Q_ASSERT_INCRIT} ....................................... -#define Q_ASSERT_INCRIT(id_, expr_) \ +#define Q_ASSERT_INCRIT(id_, expr_) \ ((expr_) ? ((void)0) : Q_onError(&Q_this_module_[0], (id_))) -//${QP-FuSa::enabled::Q_ERROR_INCRIT} ........................................ -#define Q_ERROR_INCRIT(id_) \ +#define Q_ERROR_INCRIT(id_) \ (Q_onError(&Q_this_module_[0], (id_))) -//${QP-FuSa::enabled::Q_ASSERT_ID} ........................................... #define Q_ASSERT_ID(id_, expr_) do { \ QF_CRIT_STAT \ QF_CRIT_ENTRY(); \ @@ -84,98 +60,63 @@ extern "C" { QF_CRIT_EXIT(); \ } while (false) -//${QP-FuSa::enabled::Q_ERROR_ID} ............................................ #define Q_ERROR_ID(id_) do { \ QF_CRIT_STAT \ QF_CRIT_ENTRY(); \ Q_onError(&Q_this_module_[0], (id_)); \ QF_CRIT_EXIT(); \ } while (false) -//$enddecl${QP-FuSa::enabled} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // QF-FuSa disabled ========================================================== #else -//$declare${QP-FuSa::disabled} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -//${QP-FuSa::disabled::Q_DEFINE_THIS_MODULE} ................................. #define Q_DEFINE_THIS_MODULE(name_) - -//${QP-FuSa::disabled::Q_ASSERT_INCRIT} ...................................... #define Q_ASSERT_INCRIT(id_, expr_) ((void)0) - -//${QP-FuSa::disabled::Q_ERROR_INCRIT} ....................................... #define Q_ERROR_INCRIT(id_) ((void)0) - -//${QP-FuSa::disabled::Q_ASSERT_ID} .......................................... #define Q_ASSERT_ID(id_, expr_) ((void)0) - -//${QP-FuSa::disabled::Q_ERROR_ID} ........................................... #define Q_ERROR_ID(id_) ((void)0) -//$enddecl${QP-FuSa::disabled} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#endif - -//============================================================================ -//$declare1${QP-FuSa} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - -//${QP-FuSa::Q_DEFINE_THIS_FILE} ............................................. -#define Q_DEFINE_THIS_FILE Q_DEFINE_THIS_MODULE(__FILE__) -//${QP-FuSa::Q_ASSERT} ....................................................... -#define Q_ASSERT(expr_) Q_ASSERT_ID(__LINE__, (expr_)) +#endif // QF-FuSa disabled -//${QP-FuSa::Q_ERROR} ........................................................ -#define Q_ERROR() Q_ERROR_ID(__LINE__) - -//${QP-FuSa::Q_REQUIRE_ID} ................................................... -#define Q_REQUIRE_ID(id_, expr_) Q_ASSERT_ID((id_), (expr_)) - -//${QP-FuSa::Q_REQUIRE} ...................................................... -#define Q_REQUIRE(expr_) Q_ASSERT(expr_) - -//${QP-FuSa::Q_REQUIRE_INCRIT} ............................................... -#define Q_REQUIRE_INCRIT(id_, expr_) Q_ASSERT_INCRIT((id_), (expr_)) - -//${QP-FuSa::Q_ENSURE_ID} .................................................... -#define Q_ENSURE_ID(id_, expr_) Q_ASSERT_ID((id_), (expr_)) - -//${QP-FuSa::Q_ENSURE} ....................................................... -#define Q_ENSURE(expr_) Q_ASSERT(expr_) - -//${QP-FuSa::Q_ENSURE_INCRIT} ................................................ -#define Q_ENSURE_INCRIT(id_, expr_) Q_ASSERT_INCRIT((id_), (expr_)) - -//${QP-FuSa::Q_INVARIANT_ID} ................................................. -#define Q_INVARIANT_ID(id_, expr_) Q_ASSERT_ID((id_), (expr_)) - -//${QP-FuSa::Q_INVARIANT} .................................................... -#define Q_INVARIANT(expr_) Q_ASSERT(expr_) - -//${QP-FuSa::Q_INVARIANT_INCRIT} ............................................. +//============================================================================ +#define Q_DEFINE_THIS_FILE Q_DEFINE_THIS_MODULE(__FILE__) +#define Q_ASSERT(expr_) Q_ASSERT_ID(__LINE__, (expr_)) +#define Q_ERROR() Q_ERROR_ID(__LINE__) +#define Q_REQUIRE_ID(id_, expr_) Q_ASSERT_ID((id_), (expr_)) +#define Q_REQUIRE(expr_) Q_ASSERT(expr_) +#define Q_REQUIRE_INCRIT(id_, expr_) Q_ASSERT_INCRIT((id_), (expr_)) +#define Q_ENSURE_ID(id_, expr_) Q_ASSERT_ID((id_), (expr_)) +#define Q_ENSURE(expr_) Q_ASSERT(expr_) +#define Q_ENSURE_INCRIT(id_, expr_) Q_ASSERT_INCRIT((id_), (expr_)) +#define Q_INVARIANT_ID(id_, expr_) Q_ASSERT_ID((id_), (expr_)) +#define Q_INVARIANT(expr_) Q_ASSERT(expr_) #define Q_INVARIANT_INCRIT(id_, expr_) Q_ASSERT_INCRIT((id_), (expr_)) -//${QP-FuSa::Q_ASSERT_STATIC} ................................................ -#define Q_ASSERT_STATIC(expr_) extern char Q_static_assert_[(expr_) ? 1 : -1] +#ifndef Q_ASSERT_STATIC + #define Q_ASSERT_STATIC(expr_) extern char Q_static_assert_[(expr_) ? 1 : -1] +#endif // ndef Q_ASSERT_STATIC -//${QP-FuSa::Q_NORETURN} ..................................................... #ifndef Q_NORETURN -#define Q_NORETURN _Noreturn void + #define Q_NORETURN _Noreturn void #endif // ndef Q_NORETURN -//${QP-FuSa::int_t} .......................................................... +// Is this header file used outside QP? #ifndef QP_VERSION -typedef int int_t; + #define Q_DIM(array_) (sizeof(array_) / sizeof((array_)[0U])) #endif // ndef QP_VERSION -//${QP-FuSa::Q_onError} ...................................................... -Q_NORETURN Q_onError( - char const * const module, - int_t const id); +//============================================================================ +#ifdef __cplusplus +extern "C" { +#endif -//${QP-FuSa::Q_DIM} .......................................................... #ifndef QP_VERSION -#define Q_DIM(array_) (sizeof(array_) / sizeof((array_)[0U])) + typedef int int_t; #endif // ndef QP_VERSION -//$enddecl${QP-FuSa} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Q_NORETURN Q_onError( + char const * const module, + int_t const id); #ifdef __cplusplus } diff --git a/include/qstamp.hpp b/include/qstamp.hpp index dbf1f5655..d3c6d2fe5 100644 --- a/include/qstamp.hpp +++ b/include/qstamp.hpp @@ -1,10 +1,6 @@ -//$file${include::qstamp.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${include::qstamp.hpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${include::qstamp.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #ifndef QSTAMP_HPP_ #define QSTAMP_HPP_ diff --git a/include/qv.hpp b/include/qv.hpp index ca4f21c20..f45bbf25c 100644 --- a/include/qv.hpp +++ b/include/qv.hpp @@ -1,10 +1,6 @@ -//$file${include::qv.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${include::qv.hpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,97 +26,53 @@ // Quantum Leaps contact information: // // -// -//$endhead${include::qv.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #ifndef QV_HPP_ #define QV_HPP_ -//$declare${QV::QV-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { namespace QV { -//${QV::QV-base::Attr} ....................................................... +//============================================================================ class Attr { public: QPSet readySet; std::uint_fast8_t schedCeil; - -#ifndef Q_UNSAFE - QPSet readySet_dis; -#endif // ndef Q_UNSAFE - -#ifndef Q_UNSAFE - std::uint_fast8_t schedCeil_dis; -#endif // ndef Q_UNSAFE }; // class Attr -//${QV::QV-base::priv_} ...................................................... extern QV::Attr priv_; -//${QV::QV-base::schedDisable} ............................................... void schedDisable(std::uint_fast8_t const ceiling); -//${QV::QV-base::schedEnable} ................................................ void schedEnable(); -//${QV::QV-base::onIdle} ..................................................... void onIdle(); } // namespace QV } // namespace QP -//$enddecl${QV::QV-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //============================================================================ // interface used only for internal implementation, but not in applications #ifdef QP_IMPL -//$declare${QV-impl} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - -//${QV-impl::QF_SCHED_STAT_} ................................................. +// scheduler locking for QV (not needed)... #define QF_SCHED_STAT_ - -//${QV-impl::QF_SCHED_LOCK_} ................................................. #define QF_SCHED_LOCK_(dummy) (static_cast(0)) +#define QF_SCHED_UNLOCK_() (static_cast(0)) -//${QV-impl::QF_SCHED_UNLOCK_} ............................................... -#define QF_SCHED_UNLOCK_() (static_cast(0)) - -//${QV-impl::QACTIVE_EQUEUE_WAIT_} ........................................... +// QActive event queue customization for QV... #define QACTIVE_EQUEUE_WAIT_(me_) (static_cast(0)) - -//${QV-impl::QACTIVE_EQUEUE_SIGNAL_} ......................................... -#ifndef Q_UNSAFE -#define QACTIVE_EQUEUE_SIGNAL_(me_) \ - QV::priv_.readySet.insert((me_)->m_prio); \ - QV::priv_.readySet.update_(&QV::priv_.readySet_dis) -#endif // ndef Q_UNSAFE - -//${QV-impl::QACTIVE_EQUEUE_SIGNAL_} ......................................... -#ifdef Q_UNSAFE #define QACTIVE_EQUEUE_SIGNAL_(me_) \ (QV::priv_.readySet.insert((me_)->m_prio)) -#endif // def Q_UNSAFE -//$enddecl${QV-impl} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$declare${QF_EPOOL-impl} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -//${QF_EPOOL-impl::QF_EPOOL_TYPE_} ........................................... +// QF event pool customization for QV... #define QF_EPOOL_TYPE_ QMPool - -//${QF_EPOOL-impl::QF_EPOOL_INIT_} ........................................... #define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \ (p_).init((poolSto_), (poolSize_), (evtSize_)) - -//${QF_EPOOL-impl::QF_EPOOL_EVENT_SIZE_} ..................................... #define QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize()) - -//${QF_EPOOL-impl::QF_EPOOL_GET_} ............................................ #define QF_EPOOL_GET_(p_, e_, m_, qsId_) \ ((e_) = static_cast((p_).get((m_), (qsId_)))) - -//${QF_EPOOL-impl::QF_EPOOL_PUT_} ............................................ #define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_))) -//$enddecl${QF_EPOOL-impl} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #endif // QP_IMPL diff --git a/ports/arm-cm/config/qp_config.hpp b/ports/arm-cm/config/qp_config.hpp index c1beeede1..6634ca10f 100644 --- a/ports/arm-cm/config/qp_config.hpp +++ b/ports/arm-cm/config/qp_config.hpp @@ -3,13 +3,13 @@ // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software +// 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 // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -35,9 +35,9 @@ // QP API compatibility version (QP_API_VERSION) // <0=> 0 (Maximum compatibility) // <691=>691 (QP 6.9.1 or newer) -// <734=>7.3.4 (QP 7.3.4 or newer) +// <750=>750 (QP 7.5.0 or newer) // <9999=>9999 (Latest only) -// QP API backwards compatibility with the QP/C API version. +// QP API backwards compatibility with the QP API version. // Lower QP_API_VERSION values enable backwards compatibility // with lower (older) QP API versions. // For example, QP_API_VERSION==691 will enable the compatibility @@ -191,7 +191,7 @@ // // Enable memory isolation (QF_MEM_ISOLATE) -// Memory isolation (requires MPU) +// Memory isolation (supported in SafeQP only, requires MPU) // NOTE: implies QF_ON_CONTEXT_SW. //#define QF_MEM_ISOLATE // @@ -201,11 +201,13 @@ //.......................................................................... // QV/QK/QXK built-in kernels (ARM Cortex-M) +#if (__ARM_ARCH > 6) // Kernel uses critical section based on BASEPRI (QF_USE_BASEPRI) // If not selected, critical section will be based on PRIMASK // NOTE: The BASEPRI threshold can be adjusted in the "Text Editor" mode. //#define QF_USE_BASEPRI 0x3F // +#endif // (__ARM_ARCH > 6) // QK Kernel uses IRQ for return-from-preemption // NOTE: Use "editor mode" to edit QK_USE_IRQ_NUM diff --git a/ports/arm-cm/qk/armclang/qk_port.cpp b/ports/arm-cm/qk/armclang/qk_port.cpp index d592a6a2b..31464c1ac 100644 --- a/ports/arm-cm/qk/armclang/qk_port.cpp +++ b/ports/arm-cm/qk/armclang/qk_port.cpp @@ -1,5 +1,6 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) +// // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s @@ -8,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // diff --git a/ports/arm-cm/qk/armclang/qp_port.hpp b/ports/arm-cm/qk/armclang/qp_port.hpp index c0e37fd1f..b9a347655 100644 --- a/ports/arm-cm/qk/armclang/qp_port.hpp +++ b/ports/arm-cm/qk/armclang/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // diff --git a/ports/arm-cm/qk/armclang/qs_port.hpp b/ports/arm-cm/qk/armclang/qs_port.hpp index 7da8a41ae..41a5ea1b1 100644 --- a/ports/arm-cm/qk/armclang/qs_port.hpp +++ b/ports/arm-cm/qk/armclang/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/arm-cm/qk/gnu/qk_port.cpp b/ports/arm-cm/qk/gnu/qk_port.cpp index ff8a77a86..a80b64511 100644 --- a/ports/arm-cm/qk/gnu/qk_port.cpp +++ b/ports/arm-cm/qk/gnu/qk_port.cpp @@ -1,5 +1,6 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) +// // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s @@ -8,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // diff --git a/ports/arm-cm/qk/gnu/qp_port.hpp b/ports/arm-cm/qk/gnu/qp_port.hpp index c0e37fd1f..b9a347655 100644 --- a/ports/arm-cm/qk/gnu/qp_port.hpp +++ b/ports/arm-cm/qk/gnu/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // diff --git a/ports/arm-cm/qk/gnu/qs_port.hpp b/ports/arm-cm/qk/gnu/qs_port.hpp index 7da8a41ae..41a5ea1b1 100644 --- a/ports/arm-cm/qk/gnu/qs_port.hpp +++ b/ports/arm-cm/qk/gnu/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/arm-cm/qk/iar/qk_port.cpp b/ports/arm-cm/qk/iar/qk_port.cpp index 3fb52a887..e62c374ea 100644 --- a/ports/arm-cm/qk/iar/qk_port.cpp +++ b/ports/arm-cm/qk/iar/qk_port.cpp @@ -1,5 +1,6 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) +// // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s @@ -8,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // diff --git a/ports/arm-cm/qk/iar/qp_port.hpp b/ports/arm-cm/qk/iar/qp_port.hpp index c028aa576..80885bdf6 100644 --- a/ports/arm-cm/qk/iar/qp_port.hpp +++ b/ports/arm-cm/qk/iar/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // diff --git a/ports/arm-cm/qk/iar/qs_port.hpp b/ports/arm-cm/qk/iar/qs_port.hpp index 7da8a41ae..41a5ea1b1 100644 --- a/ports/arm-cm/qk/iar/qs_port.hpp +++ b/ports/arm-cm/qk/iar/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/arm-cm/qv/armclang/qp_port.hpp b/ports/arm-cm/qv/armclang/qp_port.hpp index 76997b93a..d73bf6778 100644 --- a/ports/arm-cm/qv/armclang/qp_port.hpp +++ b/ports/arm-cm/qv/armclang/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // diff --git a/ports/arm-cm/qv/armclang/qs_port.hpp b/ports/arm-cm/qv/armclang/qs_port.hpp index 7da8a41ae..41a5ea1b1 100644 --- a/ports/arm-cm/qv/armclang/qs_port.hpp +++ b/ports/arm-cm/qv/armclang/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/arm-cm/qv/armclang/qv_port.cpp b/ports/arm-cm/qv/armclang/qv_port.cpp index ecc44ad4b..8e6957b68 100644 --- a/ports/arm-cm/qv/armclang/qv_port.cpp +++ b/ports/arm-cm/qv/armclang/qv_port.cpp @@ -1,5 +1,6 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) +// // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s @@ -8,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // diff --git a/ports/arm-cm/qv/gnu/qp_port.hpp b/ports/arm-cm/qv/gnu/qp_port.hpp index 5b8ee2ac5..958356c7c 100644 --- a/ports/arm-cm/qv/gnu/qp_port.hpp +++ b/ports/arm-cm/qv/gnu/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // diff --git a/ports/arm-cm/qv/gnu/qs_port.hpp b/ports/arm-cm/qv/gnu/qs_port.hpp index 7da8a41ae..41a5ea1b1 100644 --- a/ports/arm-cm/qv/gnu/qs_port.hpp +++ b/ports/arm-cm/qv/gnu/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/arm-cm/qv/gnu/qv_port.cpp b/ports/arm-cm/qv/gnu/qv_port.cpp index 4ff3c9dcb..a60cf18d6 100644 --- a/ports/arm-cm/qv/gnu/qv_port.cpp +++ b/ports/arm-cm/qv/gnu/qv_port.cpp @@ -1,5 +1,6 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) +// // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s @@ -8,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // diff --git a/ports/arm-cm/qv/iar/qp_port.hpp b/ports/arm-cm/qv/iar/qp_port.hpp index ef520f3f0..45c7c0686 100644 --- a/ports/arm-cm/qv/iar/qp_port.hpp +++ b/ports/arm-cm/qv/iar/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // diff --git a/ports/arm-cm/qv/iar/qs_port.hpp b/ports/arm-cm/qv/iar/qs_port.hpp index 7da8a41ae..41a5ea1b1 100644 --- a/ports/arm-cm/qv/iar/qs_port.hpp +++ b/ports/arm-cm/qv/iar/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/arm-cm/qv/iar/qv_port.cpp b/ports/arm-cm/qv/iar/qv_port.cpp index 6f8aa16f9..4da334c70 100644 --- a/ports/arm-cm/qv/iar/qv_port.cpp +++ b/ports/arm-cm/qv/iar/qv_port.cpp @@ -1,5 +1,6 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) +// // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s @@ -8,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // diff --git a/ports/arm-cr/config/qp_config.hpp b/ports/arm-cr/config/qp_config.hpp index 1a50a5f82..54601e978 100644 --- a/ports/arm-cr/config/qp_config.hpp +++ b/ports/arm-cr/config/qp_config.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -191,7 +191,7 @@ // // Enable memory isolation (QF_MEM_ISOLATE) -// Memory isolation (requires MPU) +// Memory isolation (supported in SafeQP only, requires MPU) // NOTE: implies QF_ON_CONTEXT_SW. //#define QF_MEM_ISOLATE // diff --git a/ports/arm-cr/qk/gnu/qp_port.hpp b/ports/arm-cr/qk/gnu/qp_port.hpp index 2b25d6f0c..b73355693 100644 --- a/ports/arm-cr/qk/gnu/qp_port.hpp +++ b/ports/arm-cr/qk/gnu/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-11-22 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to ARM Cortex-R, preemptive QK kernel, GNU-ARM - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ diff --git a/ports/arm-cr/qk/gnu/qs_port.hpp b/ports/arm-cr/qk/gnu/qs_port.hpp index 7da8a41ae..41a5ea1b1 100644 --- a/ports/arm-cr/qk/gnu/qs_port.hpp +++ b/ports/arm-cr/qk/gnu/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/arm-cr/qk/iar/qp_port.hpp b/ports/arm-cr/qk/iar/qp_port.hpp index 61e739b49..c3e411c0c 100644 --- a/ports/arm-cr/qk/iar/qp_port.hpp +++ b/ports/arm-cr/qk/iar/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to ARM Cortex-R, preemptive QK kernel, IAR-ARM - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ diff --git a/ports/arm-cr/qk/iar/qs_port.hpp b/ports/arm-cr/qk/iar/qs_port.hpp index 7da8a41ae..41a5ea1b1 100644 --- a/ports/arm-cr/qk/iar/qs_port.hpp +++ b/ports/arm-cr/qk/iar/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/arm-cr/qk/ti/qp_port.hpp b/ports/arm-cr/qk/ti/qp_port.hpp index 349cff322..7c849ccf5 100644 --- a/ports/arm-cr/qk/ti/qp_port.hpp +++ b/ports/arm-cr/qk/ti/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to ARM Cortex-R, preemptive QK kernel, TI-ARM - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ diff --git a/ports/arm-cr/qk/ti/qs_port.hpp b/ports/arm-cr/qk/ti/qs_port.hpp index 7da8a41ae..41a5ea1b1 100644 --- a/ports/arm-cr/qk/ti/qs_port.hpp +++ b/ports/arm-cr/qk/ti/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/arm-cr/qv/gnu/qp_port.hpp b/ports/arm-cr/qv/gnu/qp_port.hpp index ef332ef03..d7ceeb07a 100644 --- a/ports/arm-cr/qv/gnu/qp_port.hpp +++ b/ports/arm-cr/qv/gnu/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-11-22 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C port to ARM Cortex-R, cooperative QV kernel, GNU-ARM - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ diff --git a/ports/arm-cr/qv/gnu/qs_port.hpp b/ports/arm-cr/qv/gnu/qs_port.hpp index 7da8a41ae..41a5ea1b1 100644 --- a/ports/arm-cr/qv/gnu/qs_port.hpp +++ b/ports/arm-cr/qv/gnu/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/arm-cr/qv/iar/qp_port.hpp b/ports/arm-cr/qv/iar/qp_port.hpp index 09205bcf1..816ee80a6 100644 --- a/ports/arm-cr/qv/iar/qp_port.hpp +++ b/ports/arm-cr/qv/iar/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to Cortex-R, cooperative QV kernel, IAR-ARM - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ diff --git a/ports/arm-cr/qv/iar/qs_port.hpp b/ports/arm-cr/qv/iar/qs_port.hpp index 7da8a41ae..41a5ea1b1 100644 --- a/ports/arm-cr/qv/iar/qs_port.hpp +++ b/ports/arm-cr/qv/iar/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/arm-cr/qv/ti/qp_port.hpp b/ports/arm-cr/qv/ti/qp_port.hpp index b238f144b..5e1eedb43 100644 --- a/ports/arm-cr/qv/ti/qp_port.hpp +++ b/ports/arm-cr/qv/ti/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to ARM Cortex-R, cooperative QV kernel, TI-ARM - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ diff --git a/ports/arm-cr/qv/ti/qs_port.hpp b/ports/arm-cr/qv/ti/qs_port.hpp index 7da8a41ae..41a5ea1b1 100644 --- a/ports/arm-cr/qv/ti/qs_port.hpp +++ b/ports/arm-cr/qv/ti/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/config/qp_config.hpp b/ports/config/qp_config.hpp index 193b5bf88..93d870bd2 100644 --- a/ports/config/qp_config.hpp +++ b/ports/config/qp_config.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -191,7 +191,7 @@ // // Enable memory isolation (QF_MEM_ISOLATE) -// Memory isolation (requires MPU) +// Memory isolation (supported in SafeQP only, requires MPU) // NOTE: implies QF_ON_CONTEXT_SW. //#define QF_MEM_ISOLATE // diff --git a/ports/embos/qf_port.cpp b/ports/embos/qf_port.cpp index 7149d48bf..ff192607d 100644 --- a/ports/embos/qf_port.cpp +++ b/ports/embos/qf_port.cpp @@ -7,7 +7,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -25,12 +25,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-26 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QF/C++ port to embOS RTOS kernel, generic C++11 compiler - #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -206,9 +200,6 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, QF_CRIT_ENTRY(); Q_REQUIRE_INCRIT(200, e != nullptr); -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(201, e->verify_()); -#endif // ndef Q_UNSAFE std::uint_fast16_t nFree = static_cast(m_eQueue.maxMsg - m_eQueue.nofMsg); @@ -237,12 +228,13 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, 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->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(nFree); // # free entries QS_EQC_PRE(0U); // min # free entries (unknown) QS_END_PRE() - if (e->getPoolNum_() != 0U) { // is it a pool event? + if (e->poolNum_ != 0U) { // is it a pool event? + Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); // increment the reference counter } QF_CRIT_EXIT(); @@ -260,7 +252,7 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, 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->getPoolNum_(), e->refCtr_); // poolNum & refCtr + QS_2U8_PRE(e->poolNum_, e->refCtr_); // poolNum & refCtr QS_EQC_PRE(nFree); // # free entries QS_EQC_PRE(margin); // margin requested QS_END_PRE() @@ -275,20 +267,18 @@ void QActive::postLIFO(QEvt const * const e) noexcept { QF_CRIT_ENTRY(); Q_REQUIRE_INCRIT(300, e != nullptr); -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(301, e->verify_()); -#endif // ndef Q_UNSAFE QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio) QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(m_eQueue.maxMsg - m_eQueue.nofMsg); // # free entries QS_EQC_PRE(0U); // min # free entries (unknown) QS_END_PRE() - if (e->getPoolNum_() != 0U) { // is it a pool event? + if (e->poolNum_ != 0U) { // is it a pool event? + Q_ASSERT_INCRIT(305, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); // increment the reference counter } QF_CRIT_EXIT(); @@ -311,7 +301,7 @@ QEvt const *QActive::get_() noexcept { QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr + QS_2U8_PRE(e->poolNum_, e->refCtr_); // poolNum & refCtr QS_EQC_PRE(m_eQueue.maxMsg - m_eQueue.nofMsg); // # free QS_END_PRE() QS_CRIT_EXIT(); diff --git a/ports/embos/qp_port.hpp b/ports/embos/qp_port.hpp index e23d478f4..bd6708b24 100644 --- a/ports/embos/qp_port.hpp +++ b/ports/embos/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to embOS RTOS (v5), generic C++11 compiler - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ diff --git a/ports/embos/qs_port.hpp b/ports/embos/qs_port.hpp index 7da8a41ae..41a5ea1b1 100644 --- a/ports/embos/qs_port.hpp +++ b/ports/embos/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/freertos/qf_port.cpp b/ports/freertos/qf_port.cpp index 5d5eafcb7..e64c41326 100644 --- a/ports/freertos/qf_port.cpp +++ b/ports/freertos/qf_port.cpp @@ -1,4 +1,7 @@ //============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 +// // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s @@ -7,7 +10,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -15,22 +18,15 @@ // Plagiarizing this software to sidestep the license obligations is illegal. // // NOTE: -// The GPL (see ) does NOT permit the -// incorporation of the QP/C software into proprietary programs. Please -// contact Quantum Leaps for commercial licensing options, which expressly -// supersede the GPL and are designed explicitly for licensees interested -// in using QP/C in closed-source proprietary applications. +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. // // Quantum Leaps contact information: // // //============================================================================ -//! @date Last updated on: 2024-10-29 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QF/C++ port to FreeRTOS 10.x, generic C++11 compiler - #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-level interface @@ -43,11 +39,11 @@ #endif // Q_SPY #if ( configSUPPORT_STATIC_ALLOCATION == 0 ) -#error "This QP/C++ port to FreeRTOS requires configSUPPORT_STATIC_ALLOCATION" + #error This QP/C++ port to FreeRTOS requires configSUPPORT_STATIC_ALLOCATION #endif #if ( configMAX_PRIORITIES < QF_MAX_ACTIVE ) -#error "FreeRTOS configMAX_PRIORITIES must not be less than QF_MAX_ACTIVE" + #error FreeRTOS configMAX_PRIORITIES must not be less than QF_MAX_ACTIVE #endif namespace { // unnamed local namespace @@ -181,7 +177,7 @@ void QActive::start( // The FreeRTOS priority of the AO thread can be specified in two ways: // - // 1. Implictily based on the AO's priority (by the formula specified + // 1. Implicitly based on the AO's priority (by the formula specified // in the macro FREERTOS_TASK_PRIO(), see qp_port.h). This option // is chosen, when the higher-byte of the prioSpec parameter is set // to zero. @@ -195,7 +191,7 @@ void QActive::start( // so it is the responsibility of the application to ensure that // it is consistent with the AO's priority. An example of // inconsistent setting would be assigning FreeRTOS priorities that - // would result in a different relative priritization of AO's threads + // would result in a different relative prioritization of AO's threads // than indicated by the AO priorities assigned. // UBaseType_t freertos_prio = (prioSpec >> 8U); @@ -257,46 +253,48 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, QF_CRIT_ENTRY(); Q_REQUIRE_INCRIT(200, e != nullptr); -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(201, e->verify_()); -#endif // ndef Q_UNSAFE // the number of free slots available in the queue std::uint_fast16_t nFree = static_cast(FREERTOS_QUEUE_GET_FREE()); - bool status; + // required margin available? + bool status = false; // assume that event cannot be posted if (margin == QF::NO_MARGIN) { - if (nFree > 0U) { + if (nFree > 0U) { // free entries available in the queue? status = true; // can post } - else { - status = false; // cannot post + else { // no free entries available + // The queue overflows, but QF_NO_MARGIN indicates that + // the "event delivery guarantee" is required. Q_ERROR_INCRIT(210); // must be able to post the event } } - else if (nFree > margin) { + else if (nFree > margin) { // enough free entries? status = true; // can post } else { - status = false; // cannot post + // empty } - if (status) { // can post the event? +#if (QF_MAX_EPOOL > 0U) + if (e->poolNum_ != 0U) { // is it a mutable event? + Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE)); + QEvt_refCtr_inc_(e); // increment the reference counter + } +#endif // (QF_MAX_EPOOL > 0U) + if (status) { // can post the event? 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->getPoolNum_(), e->refCtr_); + 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_); QS_EQC_PRE(static_cast(nFree)); // # free entries - QS_EQC_PRE(0U); // min # free entries (unknown) + QS_EQC_PRE(0U); // min # free entries (unknown) QS_END_PRE() - if (e->getPoolNum_() != 0U) { // is it a pool event? - QEvt_refCtr_inc_(e); // increment the reference counter - } QF_CRIT_EXIT(); BaseType_t err = xQueueSendToBack( @@ -305,49 +303,56 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, QF_CRIT_ENTRY(); // posting to the FreeRTOS message queue must succeed, see NOTE3 Q_ASSERT_INCRIT(220, err == pdPASS); + QF_CRIT_EXIT(); #ifdef Q_UNSAFE Q_UNUSED_PAR(err); #endif } - else { // cannot post the event - + else { // event cannot be posted 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->getPoolNum_(), e->refCtr_); + 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_); QS_EQC_PRE(static_cast(nFree)); // # free entries - QS_EQC_PRE(margin); // margin requested + QS_EQC_PRE(margin); // margin requested QS_END_PRE() + + QF_CRIT_EXIT(); + +#if (QF_MAX_EPOOL > 0U) + QF::gc(e); // recycle the event to avoid a leak +#endif // (QF_MAX_EPOOL > 0U) } - QF_CRIT_EXIT(); return status; } + //............................................................................ void QActive::postLIFO(QEvt const * const e) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); Q_REQUIRE_INCRIT(300, e != nullptr); -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(301, e->verify_()); -#endif // ndef Q_UNSAFE + +#if (QF_MAX_EPOOL > 0U) + if (e->poolNum_ != 0U) { // is it a mutable event? + Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE)); + QEvt_refCtr_inc_(e); // increment the reference counter + } +#endif // (QF_MAX_EPOOL > 0U) QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio) QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->evtTag_, e->refCtr_); // pool Id & refCtr of the evt + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(static_cast(FREERTOS_QUEUE_GET_FREE())); QS_EQC_PRE(0U); // min # free entries (unknown) QS_END_PRE() - if (e->getPoolNum_() != 0U) { // is it a pool event? - QEvt_refCtr_inc_(e); // increment the reference counter - } QF_CRIT_EXIT(); BaseType_t err = xQueueSendToFront( @@ -370,10 +375,10 @@ QEvt const *QActive::get_(void) noexcept { QS_CRIT_STAT QS_CRIT_ENTRY(); QS_BEGIN_PRE(QS_QF_ACTIVE_GET, m_prio) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(e->sig); // the signal of this event - QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); // pool Id&ref Count + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(static_cast(FREERTOS_QUEUE_GET_FREE())); QS_END_PRE() QS_CRIT_EXIT(); @@ -390,76 +395,80 @@ bool QActive::postFromISR(QEvt const * const e, { UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - Q_REQUIRE_INCRIT(500, e != nullptr); -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(501, e->verify_()); -#endif // ndef Q_UNSAFE + Q_REQUIRE_INCRIT(400, e != nullptr); - // find the number of free slots available in the queue + // the number of free slots available in the FreeRTOS queue std::uint_fast16_t const nFree = static_cast(FREERTOS_QUEUE_GET_FREE()); - bool status; + // required margin available? + bool status = false; // assume that event cannot be posted if (margin == QF::NO_MARGIN) { - if (nFree > 0U) { + if (nFree > 0U) { // free entries available in the queue? status = true; // can post } - else { - status = false; // cannot post - Q_ERROR_INCRIT(510); // must be able to post the event + else { // no free entries available + // The queue overflows, but QF_NO_MARGIN indicates that + // the "event delivery guarantee" is required. + Q_ERROR_INCRIT(410); // must be able to post the event } } - else if (nFree > margin) { + else if (nFree > margin) { // enough free entries? status = true; // can post } else { - status = false; // cannot post + // empty } - if (status) { // can post the event? +#if (QF_MAX_EPOOL > 0U) + if (e->poolNum_ != 0U) { // is it a mutable event? + Q_ASSERT_INCRIT(405, e->refCtr_ < (2U * QF_MAX_ACTIVE)); + QEvt_refCtr_inc_(e); // increment the reference counter + } +#endif // (QF_MAX_EPOOL > 0U) + if (status) { // can post the event? 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->getPoolNum_(), e->refCtr_); - QS_EQC_PRE(nFree); // # free entries available - QS_EQC_PRE(0U); // min # free entries (unknown) + 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_); + QS_EQC_PRE(nFree); // # free entries available + QS_EQC_PRE(0U); // min # free entries (unknown) QS_END_PRE() - if (e->getPoolNum_() != 0U) { // is it a pool event? - QEvt_refCtr_inc_(e); // increment the reference counter - } portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); BaseType_t err = xQueueSendToBackFromISR(m_eQueue, static_cast(&e), static_cast(par)); - // posting to the FreeRTOS message queue must succeed uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - Q_ASSERT_INCRIT(520, err == pdPASS); + // posting to the FreeRTOS message queue must succeed, see NOTE3 + Q_ASSERT_INCRIT(420, err == pdPASS); portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); #ifdef Q_UNSAFE Q_UNUSED_PAR(err); #endif } - else { - + else { // event cannot be posted 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->getPoolNum_(), e->refCtr_); - QS_EQC_PRE(nFree); // # free entries available - QS_EQC_PRE(margin); // margin requested + 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_); + QS_EQC_PRE(nFree); // # free entries available + QS_EQC_PRE(margin); // margin requested QS_END_PRE() + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); +#if (QF_MAX_EPOOL > 0U) QF::gcFromISR(e); // recycle the event to avoid a leak +#endif // (QF_MAX_EPOOL > 0U) } return status; @@ -469,152 +478,140 @@ void QActive::publishFromISR(QEvt const *e, void *par, void const * const sender) noexcept { - Q_REQUIRE_INCRIT(600, e != nullptr); -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(601, e->verify_()); -#endif // ndef Q_UNSAFE + Q_REQUIRE_INCRIT(500, e != nullptr); QSignal const sig = e->sig; UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); // the published signal must be within the configured range - Q_REQUIRE_INCRIT(610, sig < QActive::maxPubSignal_); - Q_REQUIRE_INCRIT(611, - subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis)); + Q_REQUIRE_INCRIT(510, sig < QActive::maxPubSignal_); QS_BEGIN_PRE(QS_QF_PUBLISH, 0U) QS_TIME_PRE(); // the timestamp QS_OBJ_PRE(sender); // the sender object QS_SIG_PRE(sig); // the signal of the event - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_END_PRE() - // is it a dynamic event? - if (e->getPoolNum_() != 0U) { - // NOTE: The reference counter of a dynamic event is incremented to + // is it a mutable event? + if (e->poolNum_ != 0U) { + // NOTE: The reference counter of a mutable event is incremented to // prevent premature recycling of the event while the multicasting // is still in progress. At the end of the function, the garbage // collector step (QF::gcFromISR()) decrements the reference counter // and recycles the event if the counter drops to zero. This covers // the case when the event was published without any subscribers. + Q_ASSERT_INCRIT(505, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); } - // make a local, modifiable copy of the subscriber list + // make a local, modifiable copy of the subscriber set QPSet subscrSet = QActive::subscrList_[sig].m_set; + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); if (subscrSet.notEmpty()) { // any subscribers? // the highest-prio subscriber std::uint_fast8_t p = subscrSet.findMax(); + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + // no need to lock the scheduler in the ISR context - do { // loop over all subscribers - // the prio of the AO must be registered with the framework - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - Q_ASSERT_INCRIT(620, registry_[p] != nullptr); - portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); + QActive *a = registry_[p]; + Q_ASSERT_INCRIT(520, a != nullptr); - // POST_FROM_ISR() asserts if the queue overflows - registry_[p]->POST_FROM_ISR(e, par, sender); + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); + + //QF_SCHED_LOCK_(p); // no scheduler locking in FreeRTOS + do { // loop over all subscribers + // QACTIVE_POST() asserts internally if the queue overflows + a->POST_FROM_ISR(e, par, sender); subscrSet.remove(p); // remove the handled subscriber - if (subscrSet.notEmpty()) { // still more subscribers? + if (subscrSet.notEmpty()) { // still more subscribers? p = subscrSet.findMax(); // the highest-prio subscriber + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + + a = registry_[p]; + // the AO must be registered with the framework + Q_ASSERT_INCRIT(530, a != nullptr); + + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); } else { p = 0U; // no more subscribers } } while (p != 0U); - // no need to unlock the scheduler in the ISR context + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + Q_ASSERT_INCRIT(590, p == 0U); // all subscribers processed + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); + + //QF_SCHED_UNLOCK_(); // no scheduler locking in FreeRTOS } +#if (QF_MAX_EPOOL > 0U) // The following garbage collection step decrements the reference counter // and recycles the event if the counter drops to zero. This covers both // cases when the event was published with or without any subscribers. QF::gcFromISR(e); +#endif // (QF_MAX_EPOOL > 0U) } + //............................................................................ void QTimeEvt::tickFromISR(std::uint_fast8_t const tickRate, void *pxHigherPriorityTaskWoken, void const * const sender) noexcept { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(sender); - #endif +#endif UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - Q_REQUIRE_INCRIT(700, tickRate < Q_DIM(timeEvtHead_)); + Q_REQUIRE_INCRIT(600, tickRate < Q_DIM(timeEvtHead_)); QTimeEvt *prev = &timeEvtHead_[tickRate]; +#ifdef Q_SPY QS_BEGIN_PRE(QS_QF_TICK, 0U) prev->m_ctr = (prev->m_ctr + 1U); QS_TEC_PRE(prev->m_ctr); // tick ctr QS_U8_PRE(tickRate); // tick rate QS_END_PRE() +#endif // def Q_SPY // scan the linked-list of time events at this rate... - std::uint_fast8_t lbound = 2U*QF_MAX_ACTIVE; // fixed upper loop bound - for (; lbound > 0U; --lbound) { - Q_ASSERT_INCRIT(710, prev != nullptr); // sanity check + while (true) { + Q_ASSERT_INCRIT(610, prev != nullptr); // sanity check QTimeEvt *te = prev->m_next; // advance down the time evt. list -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(711, - Q_PTR2UINT_CAST_(te) == - static_cast(~prev->m_next_dis)); -#endif // ndef Q_UNSAFE if (te == nullptr) { // end of the list? - // any new time events armed since the last QTimeEvt_tick_()? - if (timeEvtHead_[tickRate].m_act != nullptr) { -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(712, - Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) == - static_cast( - ~timeEvtHead_dis_[tickRate].m_ptr_dis)); -#endif // ndef Q_UNSAFE - prev->m_next = timeEvtHead_[tickRate].toTimeEvt(); - timeEvtHead_[tickRate].m_act = nullptr; -#ifndef Q_UNSAFE - prev->m_next_dis = - static_cast( - ~Q_PTR2UINT_CAST_(prev->m_next)); - timeEvtHead_dis_[tickRate].m_ptr_dis = - static_cast(~Q_PTR2UINT_CAST_(nullptr)); -#endif // ndef Q_UNSAFE - - te = prev->m_next; // switch to the new list - } - else { // all currently armed time events are processed + // NO any new time events armed since the last QTimeEvt_tick_()? + if (timeEvtHead_[tickRate].m_act == nullptr) { break; // terminate the for-loop } + + prev->m_next = timeEvtHead_[tickRate].toTimeEvt(); + timeEvtHead_[tickRate].m_act = nullptr; + + te = prev->m_next; // switch to the new list } // the time event 'te' must be valid - Q_ASSERT_INCRIT(720, te != nullptr); - Q_INVARIANT_INCRIT(721, te->verify_()); + Q_ASSERT_INCRIT(640, te != nullptr); QTimeEvtCtr ctr = te->m_ctr; -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(722, ctr == - static_cast(~te->m_ctr_dis)); -#endif // ndef Q_UNSAFE if (ctr == 0U) { // time event scheduled for removal? prev->m_next = te->m_next; -#ifndef Q_UNSAFE - prev->m_next_dis = - static_cast(~Q_PTR2UINT_CAST_(te->m_next)); -#endif // ndef Q_UNSAFE // mark time event 'te' as NOT linked te->m_flags &= static_cast(~QTE_FLAG_IS_LINKED); - // do NOT advance the prev pointer // exit crit. section to reduce latency @@ -622,42 +619,7 @@ void QTimeEvt::tickFromISR(std::uint_fast8_t const tickRate, } else if (ctr == 1U) { // is time event about to expire? QActive * const act = te->toActive(); - if (te->m_interval != 0U) { // periodic time evt? - te->m_ctr = te->m_interval; // rearm the time event -#ifndef Q_UNSAFE - te->m_ctr_dis = static_cast(~te->m_interval); -#endif // ndef Q_UNSAFE - prev = te; // advance to this time event - } - else { // one-shot time event: automatically disarm - te->m_ctr = 0U; - prev->m_next = te->m_next; -#ifndef Q_UNSAFE - te->m_ctr_dis = - static_cast(~static_cast(0U)); - prev->m_next_dis = - static_cast(~Q_PTR2UINT_CAST_(te->m_next)); -#endif // ndef Q_UNSAFE - - // mark time event 'te' as NOT linked - te->m_flags &= - static_cast(~QTE_FLAG_IS_LINKED); - // do NOT advance the prev pointer - - QS_BEGIN_PRE(QS_QF_TIMEEVT_AUTO_DISARM, act->m_prio) - QS_OBJ_PRE(te); // this time event object - QS_OBJ_PRE(act); // the target AO - QS_U8_PRE(tickRate); // tick rate - QS_END_PRE() - } - - QS_BEGIN_PRE(QS_QF_TIMEEVT_POST, act->m_prio) - QS_TIME_PRE(); // timestamp - QS_OBJ_PRE(te); // the time event object - QS_SIG_PRE(te->sig); // signal of this time event - QS_OBJ_PRE(act); // the target AO - QS_U8_PRE(tickRate); // tick rate - QS_END_PRE() + prev = te->expire_(prev, act, tickRate); portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); @@ -669,9 +631,6 @@ void QTimeEvt::tickFromISR(std::uint_fast8_t const tickRate, else { // time event keeps timing out --ctr; // decrement the tick counter te->m_ctr = ctr; // update the original -#ifndef Q_UNSAFE - te->m_ctr_dis = static_cast(~ctr); -#endif // ndef Q_UNSAFE prev = te; // advance to this time event @@ -681,16 +640,15 @@ void QTimeEvt::tickFromISR(std::uint_fast8_t const tickRate, uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); } - Q_ENSURE_INCRIT(890, lbound > 0U); - portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); } + //............................................................................ QEvt *QF::newXfromISR_(std::uint_fast16_t const evtSize, std::uint_fast16_t const margin, enum_t const sig) noexcept { - // find the pool index that fits the requested event size... + // find the pool number that fits the requested event size... std::uint_fast8_t poolNum = 0U; // zero-based poolNum initially for (; poolNum < priv_.maxPool_; ++poolNum) { if (evtSize <= QF_EPOOL_EVENT_SIZE_(priv_.ePool_[poolNum])) { @@ -702,28 +660,29 @@ QEvt *QF::newXfromISR_(std::uint_fast16_t const evtSize, // precondition: // - cannot run out of registered pools - Q_REQUIRE_INCRIT(800, poolNum < priv_.maxPool_); + Q_REQUIRE_INCRIT(700, poolNum < priv_.maxPool_); ++poolNum; // convert to 1-based poolNum portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); // get event e (port-dependent)... + QEvt *e; #ifdef Q_SPY - QEvt *e = static_cast( + e = static_cast( priv_.ePool_[poolNum - 1U].getFromISR(((margin != QF::NO_MARGIN) ? margin : 0U), static_cast(QS_EP_ID) + poolNum)); #else - QEvt *e = static_cast( + e = static_cast( priv_.ePool_[poolNum - 1U].getFromISR(((margin != QF::NO_MARGIN) ? margin : 0U), 0U)); #endif if (e != nullptr) { // was e allocated correctly? - e->sig = static_cast(sig); // set the signal - e->refCtr_ = 0U; - e->evtTag_ = static_cast((poolNum << 4U) | 0x0FU); + e->sig = static_cast(sig); // set the signal + e->poolNum_ = poolNum; + e->refCtr_ = 0U; #ifdef Q_SPY uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); @@ -742,7 +701,7 @@ QEvt *QF::newXfromISR_(std::uint_fast16_t const evtSize, // This assertion means that the event allocation failed, // and this failure cannot be tolerated. The most frequent // reason is an event leak in the application. - Q_ASSERT_INCRIT(820, margin != QF::NO_MARGIN); + Q_ASSERT_INCRIT(720, margin != QF::NO_MARGIN); QS_BEGIN_PRE(QS_QF_NEW_ATTEMPT, static_cast(QS_EP_ID) + poolNum) @@ -762,12 +721,9 @@ QEvt *QF::newXfromISR_(std::uint_fast16_t const evtSize, void QF::gcFromISR(QEvt const * const e) noexcept { UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - Q_REQUIRE_INCRIT(700, e != nullptr); -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(701, e->verify_()); -#endif + Q_REQUIRE_INCRIT(800, e != nullptr); - std::uint_fast8_t const poolNum = e->getPoolNum_(); + std::uint_fast8_t const poolNum = e->poolNum_; if (poolNum != 0U) { // is it a pool event (mutable)? @@ -780,6 +736,7 @@ void QF::gcFromISR(QEvt const * const e) noexcept { QS_2U8_PRE(poolNum, e->refCtr_); QS_END_PRE() + Q_ASSERT_INCRIT(805, e->refCtr_ > 0U); QEvt_refCtr_dec_(e); // decrement the ref counter portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); @@ -790,19 +747,19 @@ void QF::gcFromISR(QEvt const * const e) noexcept { static_cast(QS_EP_ID) + poolNum) QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of the event - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);//poolNum & refCtr + QS_2U8_PRE(poolNum, e->refCtr_); QS_END_PRE() // pool number must be in range - Q_ASSERT_INCRIT(710, (poolNum <= priv_.maxPool_) + Q_ASSERT_INCRIT(810, (poolNum <= priv_.maxPool_) && (poolNum <= QF_MAX_EPOOL)); - portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); + // NOTE: casting 'const' away is legit because 'e' is a pool event #ifdef Q_SPY // cast 'const' away in (QEvt *)e is OK because it's a pool event priv_.ePool_[poolNum - 1U].putFromISR(QF_CONST_CAST_(QEvt*, e), - static_cast(QS_EP_ID) + e->getPoolNum_()); + static_cast(QS_EP_ID) + e->poolNum_); #else priv_.ePool_[poolNum - 1U].putFromISR(QF_CONST_CAST_(QEvt*, e), 0U); #endif @@ -816,81 +773,57 @@ void QF::gcFromISR(QEvt const * const e) noexcept { void *QMPool::getFromISR(std::uint_fast16_t const margin, std::uint_fast8_t const qsId) noexcept { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(qsId); - #endif +#endif UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); // get volatile into temporaries - QFreeBlock *fb = m_free_head; + void * *pfb = static_cast(m_freeHead); // pointer to free block QMPoolCtr nFree = m_nFree; - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(801, Q_PTR2UINT_CAST_(fb) - == static_cast(~m_free_head_dis)); - Q_INVARIANT_INCRIT(802, nFree == static_cast(~m_nFree_dis)); - #endif // ndef Q_UNSAFE - // have more free blocks than the requested margin? if (nFree > static_cast(margin)) { - Q_ASSERT_INCRIT(810, fb != nullptr); - - QFreeBlock * const fb_next = fb->m_next; + Q_ASSERT_INCRIT(910, pfb != nullptr); - #ifndef Q_UNSAFE - // the free block must have integrity (duplicate inverse storage) - Q_INVARIANT_INCRIT(811, Q_PTR2UINT_CAST_(fb_next) - == static_cast(~fb->m_next_dis)); - #endif // ndef Q_UNSAFE + void ** const pfb_next = static_cast(pfb[0]); // fast temporary --nFree; // one less free block if (nFree == 0U) { // is the pool becoming empty? // pool is becoming empty, so the next free block must be NULL - Q_ASSERT_INCRIT(820, fb_next == nullptr); + Q_ASSERT_INCRIT(920, pfb_next == nullptr); - m_nFree = 0U; - #ifndef Q_UNSAFE - m_nFree_dis = static_cast(~m_nFree); - m_nMin = 0U; // remember that the pool got empty - #endif // ndef Q_UNSAFE + m_nFree = 0U; // no more free blocks + m_nMin = 0U; // remember that the pool got empty } - else { - m_nFree = nFree; // update the original - #ifndef Q_UNSAFE - m_nFree_dis = static_cast(~nFree); + else { // the pool is NOT empty - // The pool is not empty, so the next free-block pointer - // must be in range. - Q_INVARIANT_INCRIT(830, - QF_PTR_RANGE_(fb_next, m_start, m_end)); + // the next free-block pointer must be in range + Q_INVARIANT_INCRIT(930, + QF_PTR_RANGE_(pfb_next, m_start, m_end)); - // is the # free blocks the new minimum so far? - if (m_nMin > nFree) { + m_nFree = nFree; // update the original + if (m_nMin > nFree) { // is this the new minimum? m_nMin = nFree; // remember the minimum so far } - #endif // ndef Q_UNSAFE } - m_free_head = fb_next; // set the head to the next free block - #ifndef Q_UNSAFE - m_free_head_dis = - static_cast(~Q_PTR2UINT_CAST_(fb_next)); - #endif // ndef Q_UNSAFE + m_freeHead = pfb_next; // set the head to the next free block + + // change the allocated block contents so that it is different + // than a free block inside the pool. + pfb[0] = &m_end[1]; // invalid location beyond the end QS_BEGIN_PRE(QS_QF_MPOOL_GET, qsId) QS_TIME_PRE(); // timestamp QS_OBJ_PRE(this); // this memory pool - QS_MPC_PRE(nFree); // # of free blocks in the pool - #ifndef Q_UNSAFE + QS_MPC_PRE(nFree); // # free blocks in the pool QS_MPC_PRE(m_nMin); // min # free blocks ever in the pool - #else - QS_MPC_PRE(0U); // min # free blocks (not available) - #endif // ndef Q_UNSAFE QS_END_PRE() } else { // don't have enough free blocks at this point - fb = nullptr; + pfb = nullptr; QS_BEGIN_PRE(QS_QF_MPOOL_GET_ATTEMPT, qsId) QS_TIME_PRE(); // timestamp @@ -902,43 +835,32 @@ void *QMPool::getFromISR(std::uint_fast16_t const margin, portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); - return fb; // return the block or nullptr to the caller + return pfb; // return the block or nullptr to the caller } //............................................................................ void QMPool::putFromISR(void *block, std::uint_fast8_t const qsId) noexcept { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(qsId); - #endif +#endif - QFreeBlock * const fb = static_cast(block); + void * * const pfb = static_cast(block); UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); // get volatile into temporaries - QFreeBlock * const free_head = m_free_head; + void ** const freeHead = static_cast(m_freeHead); QMPoolCtr nFree = m_nFree; - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(901, Q_PTR2UINT_CAST_(free_head) - == static_cast(~m_free_head_dis)); - Q_INVARIANT_INCRIT(902, nFree == static_cast(~m_nFree_dis)); - #endif // ndef Q_UNSAFE - - Q_REQUIRE_INCRIT(910, nFree < m_nTot); - Q_REQUIRE_INCRIT(911, QF_PTR_RANGE_(fb, m_start, m_end)); + Q_REQUIRE_INCRIT(1000, nFree < m_nTot); + Q_REQUIRE_INCRIT(1010, QF_PTR_RANGE_(pfb, m_start, m_end)); ++nFree; // one more free block in this pool - m_free_head = fb; // set as new head of the free list + m_freeHead = pfb; // set as new head of the free list m_nFree = nFree; - fb->m_next = free_head; // link into the list - #ifndef Q_UNSAFE - m_free_head_dis = static_cast(~Q_PTR2UINT_CAST_(fb)); - m_nFree_dis = static_cast(~nFree); - fb->m_next_dis = static_cast(~Q_PTR2UINT_CAST_(free_head)); - #endif + pfb[0] = freeHead; // link into the list QS_BEGIN_PRE(QS_QF_MPOOL_PUT, qsId) QS_TIME_PRE(); // timestamp diff --git a/ports/freertos/qp_port.hpp b/ports/freertos/qp_port.hpp index 6aa0f6c37..ff7bc9c04 100644 --- a/ports/freertos/qp_port.hpp +++ b/ports/freertos/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to FreeRTOS 10.x generic C++11 compiler - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ diff --git a/ports/freertos/qs_port.hpp b/ports/freertos/qs_port.hpp index 7da8a41ae..41a5ea1b1 100644 --- a/ports/freertos/qs_port.hpp +++ b/ports/freertos/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/msp430/qk/qp_port.hpp b/ports/msp430/qk/qp_port.hpp index bc058a10d..658e52e37 100644 --- a/ports/msp430/qk/qp_port.hpp +++ b/ports/msp430/qk/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to MSP430, preemptive QK kernel - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ diff --git a/ports/msp430/qk/qs_port.hpp b/ports/msp430/qk/qs_port.hpp index b5fecfe1b..ec8f9768c 100644 --- a/ports/msp430/qk/qs_port.hpp +++ b/ports/msp430/qk/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 16-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/msp430/qutest/qp_port.hpp b/ports/msp430/qutest/qp_port.hpp index 3807f8e3a..55c4f9148 100644 --- a/ports/msp430/qutest/qp_port.hpp +++ b/ports/msp430/qutest/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ to MSP40, QUTEST unit test harness, generic C++11 compiler - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ @@ -42,12 +36,8 @@ // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void -// QF configuration for QK -- data members of the QActive class... - // QActive event queue type #define QACTIVE_EQUEUE_TYPE QEQueue -// QACTIVE_OS_OBJ_TYPE not used in this port -// QACTIVE_THREAD_TYPE not used in this port // QF interrupt disable/enable #define QF_INT_DISABLE() (++QP::QF::intLock_) @@ -74,33 +64,28 @@ //============================================================================ // interface used only inside QF implementation, but not in applications + #ifdef QP_IMPL // QUTest scheduler locking (not used) #define QF_SCHED_STAT_ - #define QF_SCHED_LOCK_(dummy) ((void)0) - #define QF_SCHED_UNLOCK_() ((void)0) + #define QF_SCHED_LOCK_(dummy) (static_cast(0)) + #define QF_SCHED_UNLOCK_() (static_cast(0)) - // native event queue operations + // native QEQueue operations #define QACTIVE_EQUEUE_WAIT_(me_) (static_cast(0)) + #define QACTIVE_EQUEUE_SIGNAL_(me_) \ + (QP::QS::tstPriv_.readySet.insert( \ + static_cast((me_)->m_prio))) -#ifndef Q_UNSAFE - #define QACTIVE_EQUEUE_SIGNAL_(me_) \ - QF::readySet_.insert(static_cast((me_)->m_prio)); - QF::readySet_.update_(&QF::readySet_dis) -#else - #define QACTIVE_EQUEUE_SIGNAL_(me_) \ - QF::readySet_.insert(static_cast((me_)->m_prio)) -#endif - - // native QF event pool operations + // native QMPool operations #define QF_EPOOL_TYPE_ QMPool #define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \ (p_).init((poolSto_), (poolSize_), (evtSize_)) #define QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize()) #define QF_EPOOL_GET_(p_, e_, m_, qsId_) \ ((e_) = static_cast((p_).get((m_), (qsId_)))) - #define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_))) + #define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_))) #endif // QP_IMPL diff --git a/ports/msp430/qutest/qs_port.hpp b/ports/msp430/qutest/qs_port.hpp index b5fecfe1b..ec8f9768c 100644 --- a/ports/msp430/qutest/qs_port.hpp +++ b/ports/msp430/qutest/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 16-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/msp430/qv/qp_port.hpp b/ports/msp430/qv/qp_port.hpp index e6e29258e..cfdbe8ce7 100644 --- a/ports/msp430/qv/qp_port.hpp +++ b/ports/msp430/qv/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to MSP430, cooperative QV kernel - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ diff --git a/ports/msp430/qv/qs_port.hpp b/ports/msp430/qv/qs_port.hpp index b5fecfe1b..ec8f9768c 100644 --- a/ports/msp430/qv/qs_port.hpp +++ b/ports/msp430/qv/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 16-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/posix-qv/qf_port.cpp b/ports/posix-qv/qf_port.cpp index 6c40e563f..c26cf1d8e 100644 --- a/ports/posix-qv/qf_port.cpp +++ b/ports/posix-qv/qf_port.cpp @@ -1,32 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) -// Copyright (C) 2005 Quantum Leaps, LLC . // -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // -// 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. +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software // -// The terms of the open source GNU General Public License version 3 -// can be found at: +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: // // //============================================================================ -//! @date Last updated on: 2024-09-19 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QF/C++ port to POSIX-QV (single-threaded) // expose features from the 2008 POSIX standard (IEEE Standard 1003.1-2008) #define _POSIX_C_SOURCE 200809L @@ -188,9 +188,6 @@ void init() { pthread_cond_init(&condVar_, NULL); readySet_.setEmpty(); -#ifndef Q_UNSAFE - readySet_.update_(&readySet_dis_); -#endif // lock memory so we're never swapped out to disk //mlockall(MCL_CURRENT | MCL_FUTURE); // un-comment when supported @@ -282,9 +279,6 @@ int run() { QF_CRIT_ENTRY(); if (a->getEQueue().isEmpty()) { // empty queue? readySet_.remove(p); -#ifndef Q_UNSAFE - readySet_.update_(&readySet_dis_); -#endif } } else { @@ -318,9 +312,6 @@ void stop() { // unblock the event-loop so it can terminate readySet_.insert(1U); -#ifndef Q_UNSAFE - readySet_.update_(&readySet_dis_); -#endif pthread_cond_signal(&condVar_); } //............................................................................ @@ -406,9 +397,6 @@ void QActive::stop() { QF_CRIT_STAT QF_CRIT_ENTRY(); QF::readySet_.remove(m_prio); -#ifndef Q_UNSAFE - QF::readySet_.update_(&QF::readySet_dis_); -#endif QF_CRIT_EXIT(); unregister_(); diff --git a/ports/posix-qv/qp_port.hpp b/ports/posix-qv/qp_port.hpp index 578521bd5..105792ba8 100644 --- a/ports/posix-qv/qp_port.hpp +++ b/ports/posix-qv/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to POSIX-QV (signgle threaded), generic C++11 - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ @@ -97,16 +91,9 @@ void onClockTick(); // QF event queue customization for POSIX-QV... #define QACTIVE_EQUEUE_WAIT_(me_) (static_cast(0)) -#ifndef Q_UNSAFE #define QACTIVE_EQUEUE_SIGNAL_(me_) \ QF::readySet_.insert((me_)->m_prio); \ - QF::readySet_.update_(&QF::readySet_dis_); \ pthread_cond_signal(&QP::QF::condVar_) -#else - #define QACTIVE_EQUEUE_SIGNAL_(me_) \ - QF::readySet_.insert((me_)->m_prio); \ - pthread_cond_signal(&QP::QF::condVar_) -#endif // native QF event pool operations #define QF_EPOOL_TYPE_ QMPool diff --git a/ports/posix-qv/qs_port.cpp b/ports/posix-qv/qs_port.cpp index a0a72ab5b..cc0495fdd 100644 --- a/ports/posix-qv/qs_port.cpp +++ b/ports/posix-qv/qs_port.cpp @@ -1,38 +1,38 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // -// 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. +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software // -// The terms of the open source GNU General Public License version 3 -// can be found at: +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-07-18 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to POSIX // expose features from the 2008 POSIX standard (IEEE Standard 1003.1-2008) #define _POSIX_C_SOURCE 200809L #ifndef Q_SPY - #error "Q_SPY must be defined to compile qs_port.cpp" + #error Q_SPY must be defined to compile qs_port.cpp #endif // Q_SPY #define QP_IMPL // this is QP implementation diff --git a/ports/posix-qv/qs_port.hpp b/ports/posix-qv/qs_port.hpp index c66fa9711..a8db52e43 100644 --- a/ports/posix-qv/qs_port.hpp +++ b/ports/posix-qv/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to POSIX/Win32 - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/posix/qf_port.cpp b/ports/posix/qf_port.cpp index 77751cf51..f3954c204 100644 --- a/ports/posix/qf_port.cpp +++ b/ports/posix/qf_port.cpp @@ -1,32 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) -// Copyright (C) 2005 Quantum Leaps, LLC . // -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // -// 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. +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software // -// The terms of the open source GNU General Public License version 3 -// can be found at: +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: // // //============================================================================ -//! @date Last updated on: 2024-09-19 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QF/C++ port to POSIX (multithreaded with P-threads) // expose features from the 2008 POSIX standard (IEEE Standard 1003.1-2008) #define _POSIX_C_SOURCE 200809L diff --git a/ports/posix/qp_port.hpp b/ports/posix/qp_port.hpp index b773b98ad..5386743f5 100644 --- a/ports/posix/qp_port.hpp +++ b/ports/posix/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to POSIX (multithreaded with P-threads), generic C++11 - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ diff --git a/ports/posix/qs_port.cpp b/ports/posix/qs_port.cpp index a0a72ab5b..cc0495fdd 100644 --- a/ports/posix/qs_port.cpp +++ b/ports/posix/qs_port.cpp @@ -1,38 +1,38 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // -// 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. +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software // -// The terms of the open source GNU General Public License version 3 -// can be found at: +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-07-18 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to POSIX // expose features from the 2008 POSIX standard (IEEE Standard 1003.1-2008) #define _POSIX_C_SOURCE 200809L #ifndef Q_SPY - #error "Q_SPY must be defined to compile qs_port.cpp" + #error Q_SPY must be defined to compile qs_port.cpp #endif // Q_SPY #define QP_IMPL // this is QP implementation diff --git a/ports/posix/qs_port.hpp b/ports/posix/qs_port.hpp index c66fa9711..a8db52e43 100644 --- a/ports/posix/qs_port.hpp +++ b/ports/posix/qs_port.hpp @@ -1,38 +1,32 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) // +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to POSIX/Win32 - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/qep-only/qp_port.hpp b/ports/qep-only/qp_port.hpp index 78ca54379..6491b2ef7 100644 --- a/ports/qep-only/qp_port.hpp +++ b/ports/qep-only/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C dummy port - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ diff --git a/ports/threadx/qf_port.cpp b/ports/threadx/qf_port.cpp index bff26435d..4c4a26656 100644 --- a/ports/threadx/qf_port.cpp +++ b/ports/threadx/qf_port.cpp @@ -7,7 +7,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -25,12 +25,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-26 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QF/C++ port to ThreadX (a.k.a. Azure RTOS), generic C++11 compiler - #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -165,9 +159,6 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, QF_CRIT_ENTRY(); Q_REQUIRE_INCRIT(200, e != nullptr); -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(201, e->verify_()); -#endif // ndef Q_UNSAFE std::uint_fast16_t nFree = static_cast(m_eQueue.tx_queue_available_storage); @@ -196,12 +187,13 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, 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->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(nFree); // # free entries available QS_EQC_PRE(0U); // min # free entries (unknown) QS_END_PRE() - if (e->getPoolNum_() != 0U) { // is it a pool event? + if (e->poolNum_ != 0U) { // is it a pool event? + Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); // increment the reference counter } QF_CRIT_EXIT(); @@ -220,7 +212,7 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, 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->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(nFree); // # free entries QS_EQC_PRE(0U); // min # free entries (unknown) QS_END_PRE() @@ -236,21 +228,18 @@ void QActive::postLIFO(QEvt const * const e) noexcept { QF_CRIT_ENTRY(); Q_REQUIRE_INCRIT(300, e != nullptr); -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(301, e->verify_()); -#endif // ndef Q_UNSAFE - QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio) QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(m_eQueue.tx_queue_available_storage); // # free QS_EQC_PRE(0U); // min # free entries (unknown) QS_END_PRE() - if (e->getPoolNum_() != 0U) { // is it a pool event? + if (e->poolNum_ != 0U) { // is it a pool event? + Q_ASSERT_INCRIT(305, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); // increment the reference counter } QF_CRIT_EXIT(); @@ -276,7 +265,7 @@ QEvt const *QActive::get_(void) noexcept { QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(m_eQueue.tx_queue_available_storage); // # free QS_END_PRE() QF_CRIT_EXIT(); diff --git a/ports/threadx/qp_port.hpp b/ports/threadx/qp_port.hpp index fd669ca32..93d7ec845 100644 --- a/ports/threadx/qp_port.hpp +++ b/ports/threadx/qp_port.hpp @@ -1,15 +1,13 @@ //============================================================================ -// QP/C++ Real-Time Embedded Framework (RTEF) -// // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software +// 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 // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +25,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to ThreadX (a.k.a, Azure RTOS), generic C++11 compiler - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ @@ -51,9 +43,9 @@ #define QF_TX_PRIO_OFFSET 2U #ifndef QF_MAX_ACTIVE -#define QF_MAX_ACTIVE (TX_MAX_PRIORITIES - QF_TX_PRIO_OFFSET) + #define QF_MAX_ACTIVE (TX_MAX_PRIORITIES - QF_TX_PRIO_OFFSET) #else -#error "QF_MAX_ACTIVE shouild not be externally defined in QP-ThreadX port" + #error QF_MAX_ACTIVE shouild not be externally defined in QP-ThreadX port #endif // mapping between QF-priority and TX-priority, see NOTE1 diff --git a/ports/threadx/qs_port.hpp b/ports/threadx/qs_port.hpp index 7da8a41ae..112a6c0f2 100644 --- a/ports/threadx/qs_port.hpp +++ b/ports/threadx/qs_port.hpp @@ -1,38 +1,30 @@ //============================================================================ -// QP/C++ Real-Time Embedded Framework (RTEF) -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // -// 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. +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software // -// The terms of the open source GNU General Public License version 3 -// can be found at: +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/uc-os2/qf_port.cpp b/ports/uc-os2/qf_port.cpp index ecb945e5a..31eddb08f 100644 --- a/ports/uc-os2/qf_port.cpp +++ b/ports/uc-os2/qf_port.cpp @@ -7,7 +7,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -25,12 +25,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-26 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QF/C++ port to uC-OS2 RTOS, generic C++11 compiler - #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -207,9 +201,6 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, QF_CRIT_ENTRY(); Q_REQUIRE_INCRIT(200, e != nullptr); -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(201, e->verify_()); -#endif std::uint_fast16_t const nFree = static_cast( reinterpret_cast(m_eQueue)->OSQSize @@ -239,12 +230,13 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, 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->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(nFree); // # free entries QS_EQC_PRE(0U); // min # free entries (unknown) QS_END_PRE() - if (e->getPoolNum_() != 0U) { // is it a pool event? + if (e->poolNum_ != 0U) { // is it a pool event? + Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); // increment the reference counter } QF_CRIT_EXIT(); @@ -267,7 +259,7 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, 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->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(nFree); // # free entries available QS_EQC_PRE(margin); // margin requested QS_END_PRE() @@ -283,22 +275,20 @@ void QActive::postLIFO(QEvt const * const e) noexcept { QF_CRIT_ENTRY(); Q_REQUIRE_INCRIT(300, e != nullptr); -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(301, e->verify_()); -#endif QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio) QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); // # free entries QS_EQC_PRE(reinterpret_cast(m_eQueue)->OSQSize - reinterpret_cast(m_eQueue)->OSQEntries); QS_EQC_PRE(0U); // min # free entries (unknown) QS_END_PRE() - if (e->getPoolNum_() != 0U) { // is it a pool event? + if (e->poolNum_ != 0U) { // is it a pool event? + Q_ASSERT_INCRIT(305, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); // increment the reference counter } QF_CRIT_EXIT(); @@ -328,7 +318,7 @@ QEvt const *QActive::get_(void) noexcept { QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); // # free entries QS_EQC_PRE(reinterpret_cast(m_eQueue)->OSQSize - reinterpret_cast(m_eQueue)->OSQEntries); diff --git a/ports/uc-os2/qp_port.hpp b/ports/uc-os2/qp_port.hpp index 4a14d975e..be78ee7d5 100644 --- a/ports/uc-os2/qp_port.hpp +++ b/ports/uc-os2/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to uC-OS2 RTOS, generic C++11 compiler - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ diff --git a/ports/uc-os2/qs_port.hpp b/ports/uc-os2/qs_port.hpp index 7da8a41ae..112a6c0f2 100644 --- a/ports/uc-os2/qs_port.hpp +++ b/ports/uc-os2/qs_port.hpp @@ -1,38 +1,30 @@ //============================================================================ -// QP/C++ Real-Time Embedded Framework (RTEF) -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // -// 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. +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software // -// The terms of the open source GNU General Public License version 3 -// can be found at: +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/win32-qv/qf_port.cpp b/ports/win32-qv/qf_port.cpp index d026cad75..57c34e2b9 100644 --- a/ports/win32-qv/qf_port.cpp +++ b/ports/win32-qv/qf_port.cpp @@ -22,12 +22,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-19 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QF/C++ port to Win32 (single-threaded, like the QV kernel) - #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -114,10 +108,6 @@ void init() { win32Event_ = CreateEvent(NULL, FALSE, FALSE, NULL); readySet_.setEmpty(); -#ifndef Q_UNSAFE - readySet_.update_(&readySet_dis_); -#endif - } //............................................................................ @@ -149,8 +139,6 @@ int run() { QS_END_PRE() while (l_isRunning) { - Q_ASSERT_INCRIT(300, readySet_.verify_(&readySet_dis_)); - // find the maximum priority AO ready to run if (readySet_.notEmpty()) { std::uint_fast8_t p = readySet_.findMax(); @@ -169,9 +157,6 @@ int run() { QF_CRIT_ENTRY(); if (a->getEQueue().isEmpty()) { // empty queue? readySet_.remove(p); -#ifndef Q_UNSAFE - readySet_.update_(&readySet_dis_); -#endif } } else { @@ -200,9 +185,6 @@ void stop() { // unblock the event-loop so it can terminate readySet_.insert(1U); -#ifndef Q_UNSAFE - readySet_.update_(&readySet_dis_); -#endif SetEvent(win32Event_); } //............................................................................ @@ -272,9 +254,6 @@ void QActive::stop() { QF_CRIT_STAT QF_CRIT_ENTRY(); QF::readySet_.remove(m_prio); -#ifndef Q_UNSAFE - QF::readySet_.update_(&QF::readySet_dis_); -#endif QF_CRIT_EXIT(); unregister_(); // remove this AO from QF diff --git a/ports/win32-qv/qp_port.hpp b/ports/win32-qv/qp_port.hpp index 59d3de561..bec863ccb 100644 --- a/ports/win32-qv/qp_port.hpp +++ b/ports/win32-qv/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to Win32-QV (single-threaded), generic C++11 - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ @@ -104,16 +98,9 @@ void onClockTick(); // QF event queue customization for Win32-QV... #define QACTIVE_EQUEUE_WAIT_(me_) (static_cast(0)) -#ifndef Q_UNSAFE #define QACTIVE_EQUEUE_SIGNAL_(me_) \ QF::readySet_.insert((me_)->m_prio); \ - QF::readySet_.update_(&QF::readySet_dis_); \ static_cast(SetEvent(QP::QF::win32Event_)) -#else - #define QACTIVE_EQUEUE_SIGNAL_(me_) \ - QF::readySet_.insert((me_)->m_prio); \ - static_cast(SetEvent(QP::QF::win32Event_)) -#endif // native QF event pool operations #define QF_EPOOL_TYPE_ QMPool diff --git a/ports/win32-qv/qs_port.cpp b/ports/win32-qv/qs_port.cpp index 4419df6b8..ad34052f8 100644 --- a/ports/win32-qv/qs_port.cpp +++ b/ports/win32-qv/qs_port.cpp @@ -22,15 +22,8 @@ // // //============================================================================ -//! @date Last updated on: 2024-06-11 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to Win32 API -//! - #ifndef Q_SPY - #error "Q_SPY must be defined to compile qs_port.cpp" + #error Q_SPY must be defined to compile qs_port.cpp #endif // Q_SPY #define QP_IMPL // this is QP implementation diff --git a/ports/win32-qv/qs_port.hpp b/ports/win32-qv/qs_port.hpp index c66fa9711..fafa7063a 100644 --- a/ports/win32-qv/qs_port.hpp +++ b/ports/win32-qv/qs_port.hpp @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to POSIX/Win32 - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/ports/win32/qf_port.cpp b/ports/win32/qf_port.cpp index 01e593586..254146542 100644 --- a/ports/win32/qf_port.cpp +++ b/ports/win32/qf_port.cpp @@ -22,12 +22,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-19 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QF/C++ port to Win32 (multithreaded) - #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface diff --git a/ports/win32/qp_port.hpp b/ports/win32/qp_port.hpp index 22c75c195..9209c7285 100644 --- a/ports/win32/qp_port.hpp +++ b/ports/win32/qp_port.hpp @@ -9,7 +9,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to Win32 (multithreaded), generic C++11 - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ @@ -104,7 +98,8 @@ void onClockTick(); #define QACTIVE_EQUEUE_WAIT_(me_) \ while ((me_)->m_eQueue.m_frontEvt == nullptr) { \ QF_CRIT_EXIT(); \ - static_cast(WaitForSingleObject((me_)->m_osObject, INFINITE)); \ + static_cast(WaitForSingleObject( \ + (me_)->m_osObject, INFINITE)); \ QF_CRIT_ENTRY(); \ } diff --git a/ports/win32/qs_port.cpp b/ports/win32/qs_port.cpp index 4419df6b8..ad34052f8 100644 --- a/ports/win32/qs_port.cpp +++ b/ports/win32/qs_port.cpp @@ -22,15 +22,8 @@ // // //============================================================================ -//! @date Last updated on: 2024-06-11 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to Win32 API -//! - #ifndef Q_SPY - #error "Q_SPY must be defined to compile qs_port.cpp" + #error Q_SPY must be defined to compile qs_port.cpp #endif // Q_SPY #define QP_IMPL // this is QP implementation diff --git a/ports/win32/qs_port.hpp b/ports/win32/qs_port.hpp index c66fa9711..fafa7063a 100644 --- a/ports/win32/qs_port.hpp +++ b/ports/win32/qs_port.hpp @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QS/C++ port to POSIX/Win32 - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/qpcpp.qm b/qpcpp.qm deleted file mode 100644 index 9e7f4e5f7..000000000 --- a/qpcpp.qm +++ /dev/null @@ -1,6731 +0,0 @@ - - - QP/C++ Real-Time Embedded Framework (RTEF) -This model is used to generate the whole QP/C++ source code. - -Copyright (c) 2005 Quantum Leaps, LLC. All rights reserved. - - 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 - -The QP/C++ software is dual-licensed under the terms of the open-source GNU -General Public License (GPL) or under the terms of one of the closed- -source Quantum Leaps commercial licenses. - -Redistributions in source code must retain this top-level comment block. -Plagiarizing this software to sidestep the license obligations is illegal. - -NOTE: -The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the -incorporation of the QP/C++ software into proprietary programs. Please -contact Quantum Leaps for commercial licensing options, which expressly -supersede the GPL and are designed explicitly for licensees interested -in using QP/C++ in closed-source proprietary applications. - -Quantum Leaps contact information: -<www.state-machine.com/licensing> -<info@state-machine.com> - - - public -qpcpp -2025-12-31 -Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. - - 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 - -The QP/C++ software is dual-licensed under the terms of the open-source -GNU General Public License (GPL) or under the terms of one of the closed- -source Quantum Leaps commercial licenses. - -Redistributions in source code must retain this top-level comment block. -Plagiarizing this software to sidestep the license obligations is illegal. - -NOTE: -The GPL does NOT permit the incorporation of this code into proprietary -programs. Please contact Quantum Leaps for commercial licensing options, -which expressly supersede the GPL and are designed explicitly for -closed-source distribution. - -Quantum Leaps contact information: -<www.state-machine.com/licensing> -<info@state-machine.com> -#48B37CF39D4FD9DE279250B31FD388AFD0BE9B40 - - - - - - = int; - - - - = int; - - - - = float; - - - - = double; - - - - - - - //! the current QP version number string in ROM, based on #QP_VERSION_STR - {QP_VERSION_STR}; - - - - = std::uint8_t; - - - - = std::uint16_t; - - - - = std::uint32_t; - - - - - - - - - - - - : std::uint8_t { DYNAMIC }; - - - - noexcept - - - : sig(s), - evtTag_(0x01U), - refCtr_(0x0EU) - - - - = delete - - - - noexcept - // no event parameters to initialize - - - - noexcept - - - static_cast<void>(dummy); -// no event parameters to initialize - - - - const noexcept - std::uint8_t rc = refCtr_; -return (rc <= 2U*QF_MAX_ACTIVE) - && (((evtTag_ ^ rc) & 0x0FU) == 0x0FU); - - - - const noexcept - return static_cast<std::uint8_t>(evtTag_ >> 4U); - - - - - = std::uint_fast8_t; - - - - = QState (*)(void * const me, QEvt const * const e); - - - - = QState (*)(void * const me); - - - - // forward declaration - - - - = void (*)(QXThread * const me); - - - - { - QMState const *superstate; - QStateHandler const stateHandler; - QActionHandler const entryAction; - QActionHandler const exitAction; - QActionHandler const initAction; -}; - - - - { - QMState const *target; - QActionHandler const act[1]; -}; - - - - { - QStateHandler fun; - QActionHandler act; - QXThreadHandler thr; - QMState const *obj; - QMTranActTable const *tatbl; -#ifndef Q_UNSAFE - std::uintptr_t uint; -#endif - constexpr QAsmAttr() : fun(nullptr) {} -}; - - - - {4}; - - - - Abstract State Machine - - - - - - - //! All possible return values from state-handlers -//! @note -//! The order is important for algorithmic correctness. - : QState { - // unhandled and need to "bubble up" - Q_RET_SUPER, //!< event passed to superstate to handle - Q_RET_UNHANDLED, //!< event unhandled due to a guard - - // handled and do not need to "bubble up" - Q_RET_HANDLED, //!< event handled (internal transition) - Q_RET_IGNORED, //!< event silently ignored (bubbled up to top) - - // entry/exit - Q_RET_ENTRY, //!< state entry action executed - Q_RET_EXIT, //!< state exit action executed - - // no side effects - Q_RET_NULL, //!< return value without any effect - - // transitions need to execute transition-action table in QP::QMsm - Q_RET_TRAN, //!< regular transition - Q_RET_TRAN_INIT, //!< initial transition in a state - - // transitions that additionally clobber QHsm.m_state - Q_RET_TRAN_HIST, //!< transition to history of a given state - }; - - - - //! Reserved signals by the QP-framework. - : QSignal { - Q_EMPTY_SIG, //!< signal to execute the default case - Q_ENTRY_SIG, //!< signal for entry actions - Q_EXIT_SIG, //!< signal for exit actions - Q_INIT_SIG //!< signal for nested initial transitions - }; - - - - noexcept - : m_state(), - m_temp () - - - - noexcept - // empty - - - - = 0 - - - - - - - - - - this->init(nullptr, qsId); - - - - = 0 - - - - - - - - noexcept - - - static_cast<void>(state); -return false; - - - - const noexcept - return m_state.fun; - - - - const noexcept - return m_state.obj; - - - - noexcept - return m_state.fun; - - - - noexcept - - - - - static_cast<void>(me); -static_cast<void>(e); -return Q_RET_IGNORED; // the top state ignores all events - - - - noexcept - - - m_temp.fun = target; -return Q_RET_TRAN; - - - - noexcept - - - m_temp.fun = hist; -return Q_RET_TRAN_HIST; - - - - noexcept - - - m_temp.fun = superstate; -return Q_RET_SUPER; - - - - noexcept - - - m_temp.tatbl = static_cast<QP::QMTranActTable const *>(tatbl); -return Q_RET_TRAN; - - - - noexcept - - - m_temp.tatbl = static_cast<QP::QMTranActTable const *>(tatbl); -return Q_RET_TRAN_INIT; - - - - noexcept - - - - - m_state.obj = hist; -m_temp.tatbl = static_cast<QP::QMTranActTable const *>(tatbl); -return Q_RET_TRAN_HIST; - - - - noexcept - - - m_temp.obj = s; -return Q_RET_ENTRY; - - - - noexcept - - - static_cast<void>(s); // unused parameter -return Q_RET_ENTRY; - - - - noexcept - - - m_temp.obj = s; -return Q_RET_EXIT; - - - - noexcept - - - static_cast<void>(s); // unused parameter -return Q_RET_EXIT; - - - - - Human-generated State Machine - - - noexcept - - - : QAsm() - -m_state.fun = Q_STATE_CAST(&top); -m_temp.fun = initial; - - - - override - - - - - QF_CRIT_STAT - -QState r; - -// produce QS dictionary for QP::QHsm::top() -#ifdef Q_SPY -QS_CRIT_ENTRY(); -QS_MEM_SYS(); -if ((QS::priv_.flags & 0x01U) == 0U) { - QS::priv_.flags |= 0x01U; - r = Q_RET_HANDLED; -} -else { - r = Q_RET_IGNORED; -} -QS_MEM_APP(); -QS_CRIT_EXIT(); -if (r == Q_RET_HANDLED) { - QS_FUN_DICTIONARY(&QP::QHsm::top); -} -#else -Q_UNUSED_PAR(qsId); -#endif // def Q_SPY - -QStateHandler t = m_state.fun; - -QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(200, (m_temp.fun != nullptr) - && (t == Q_STATE_CAST(&top))); -QF_CRIT_EXIT(); - -// execute the top-most initial tran. -r = (*m_temp.fun)(this, Q_EVT_CAST(QEvt)); - -QF_CRIT_ENTRY(); -// the top-most initial tran. must be taken -Q_ASSERT_INCRIT(210, r == Q_RET_TRAN); - -QS_MEM_SYS(); -QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(t); // the source state - QS_FUN_PRE(m_temp.fun); // the target of the initial tran. -QS_END_PRE() -QS_MEM_APP(); - -QF_CRIT_EXIT(); - -// drill down into the state hierarchy with initial transitions... -do { - QStateHandler path[QHSM_MAX_NEST_DEPTH_]; // tran. entry path array - std::int_fast8_t ip = 0; // tran. entry path index - - path[0] = m_temp.fun; - static_cast<void>(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); - // note: ip is here the fixed upper loop bound - while ((m_temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) { - ++ip; - path[ip] = m_temp.fun; - static_cast<void>(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); - } - QF_CRIT_ENTRY(); - // too many state nesting levels or "malformed" HSM - Q_ENSURE_INCRIT(220, ip < QHSM_MAX_NEST_DEPTH_); - QF_CRIT_EXIT(); - - m_temp.fun = path[0]; - - // retrace the entry path in reverse (desired) order... - // note: ip is the fixed upper loop bound - do { - // enter path[ip] - if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) - == Q_RET_HANDLED) - { - QS_STATE_ENTRY_(path[ip], qsId); - } - --ip; - } while (ip >= 0); - - t = path[0]; // current state becomes the new source - - r = QHSM_RESERVED_EVT_(t, Q_INIT_SIG); // execute initial tran. - -#ifdef Q_SPY - if (r == Q_RET_TRAN) { - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(t); // the source state - QS_FUN_PRE(m_temp.fun); // the target of the initial tran. - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); - } -#endif // Q_SPY -} while (r == Q_RET_TRAN); - -QF_CRIT_ENTRY(); - -QS_MEM_SYS(); -QS_BEGIN_PRE(QS_QEP_INIT_TRAN, qsId) - QS_TIME_PRE(); // time stamp - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(t); // the new active state -QS_END_PRE() -QS_MEM_APP(); - -QF_CRIT_EXIT(); - -m_state.fun = t; // change the current active state -#ifndef Q_UNSAFE -m_temp.uint = ~m_state.uint; -#endif - - - - override - - - this->init(nullptr, qsId); - - - - override - - - - - #ifndef Q_SPY -Q_UNUSED_PAR(qsId); -#endif - -QStateHandler s = m_state.fun; -QStateHandler t = s; -QF_CRIT_STAT - -QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(300, (e != nullptr) && (s != nullptr)); -Q_INVARIANT_INCRIT(301, - e->verify_() - && (m_state.uint == static_cast<std::uintptr_t>(~m_temp.uint))); - -QS_MEM_SYS(); -QS_BEGIN_PRE(QS_QEP_DISPATCH, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s); // the current state -QS_END_PRE() -QS_MEM_APP(); - -QF_CRIT_EXIT(); - -// process the event hierarchically... -QState r; -m_temp.fun = s; -std::int_fast8_t ip = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound -do { - s = m_temp.fun; - r = (*s)(this, e); // invoke state handler s - - if (r == Q_RET_UNHANDLED) { // unhandled due to a guard? - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_UNHANDLED, qsId) - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s); // the current state - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); - - r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); // superstate of s - } - - --ip; -} while ((r == Q_RET_SUPER) && (ip > 0)); - -QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(310, ip > 0); -QF_CRIT_EXIT(); - -if (r >= Q_RET_TRAN) { // tran. (regular or history) taken? -#ifdef Q_SPY - if (r == Q_RET_TRAN_HIST) { // tran. to history? - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_TRAN_HIST, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s); // tran. to history source - QS_FUN_PRE(m_temp.fun); // tran. to history target - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); - } -#endif // Q_SPY - - QStateHandler path[QHSM_MAX_NEST_DEPTH_]; - path[0] = m_temp.fun; // tran. target - path[1] = t; // current state - path[2] = s; // tran. source - - // exit current state to tran. source s... - ip = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound - for (; (t != s) && (ip > 0); t = m_temp.fun) { - // exit from t - if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) == Q_RET_HANDLED) { - QS_STATE_EXIT_(t, qsId); - // find superstate of t - static_cast<void>(QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG)); - } - --ip; - } - QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(320, ip > 0); - QF_CRIT_EXIT(); - - ip = hsm_tran(&path[0], qsId); // take the tran. - - // execute state entry actions in the desired order... - // note: ip is the fixed upper loop bound - for (; ip >= 0; --ip) { - // enter path[ip] - if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) - == Q_RET_HANDLED) - { - QS_STATE_ENTRY_(path[ip], qsId); - } - } - t = path[0]; // stick the target into register - m_temp.fun = t; // update the next state - - // drill into the target hierarchy... - while (QHSM_RESERVED_EVT_(t, Q_INIT_SIG) == Q_RET_TRAN) { - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(t); // the source (pseudo)state - QS_FUN_PRE(m_temp.fun); // the target of the tran. - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); - - ip = 0; - path[0] = m_temp.fun; - - // find superstate - static_cast<void>(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); - - // note: ip is the fixed upper loop bound - while ((m_temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) { - ++ip; - path[ip] = m_temp.fun; - // find superstate - static_cast<void>( - QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); - } - QF_CRIT_ENTRY(); - // too many state nesting levels or "malformed" HSM - Q_ENSURE_INCRIT(330, ip < QHSM_MAX_NEST_DEPTH_); - QF_CRIT_EXIT(); - - m_temp.fun = path[0]; - - // retrace the entry path in reverse (correct) order... - // note: ip is the fixed upper loop bound - do { - // enter path[ip] - if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) - == Q_RET_HANDLED) - { - QS_STATE_ENTRY_(path[ip], qsId); - } - --ip; - } while (ip >= 0); - - t = path[0]; // current state becomes the new source - } - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_TRAN, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s); // the source of the tran. - QS_FUN_PRE(t); // the new active state - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); -} - -#ifdef Q_SPY -else if (r == Q_RET_HANDLED) { - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_INTERN_TRAN, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s); // the source state - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); -} -else { - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_IGNORED, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(m_state.fun); // the current state - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); -} -#endif // Q_SPY - -m_state.fun = t; // change the current active state -#ifndef Q_UNSAFE -m_temp.uint = ~m_state.uint; -#endif - - - - noexcept override - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -Q_INVARIANT_INCRIT(602, - m_state.uint == static_cast<std::uintptr_t>(~m_temp.uint)); -QF_CRIT_EXIT(); - -bool inState = false; // assume that this HSM is not in 'state' - -// scan the state hierarchy bottom-up -QStateHandler s = m_state.fun; -std::int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_ + 1; // fixed upper loop bound -QState r = Q_RET_SUPER; -for (; (r != Q_RET_IGNORED) && (lbound > 0); --lbound) { - if (s == state) { // do the states match? - inState = true; // 'true' means that match found - break; // break out of the for-loop - } - else { - r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); - s = m_temp.fun; - } -} - -QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(690, lbound > 0); -QF_CRIT_EXIT(); - -#ifndef Q_UNSAFE -m_temp.uint = ~m_state.uint; -#endif - -return inState; // return the status - - - - noexcept - - - QStateHandler child = m_state.fun; // start with current state -bool isFound = false; // start with the child not found - -// establish stable state configuration -m_temp.fun = child; -QState r; -std::int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound -do { - // is this the parent of the current child? - if (m_temp.fun == parent) { - isFound = true; // child is found - r = Q_RET_IGNORED; // break out of the loop - } - else { - child = m_temp.fun; - r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG); - } - --lbound; -} while ((r != Q_RET_IGNORED) // the top state not reached - && (lbound > 0)); - -#ifndef Q_UNSAFE -m_temp.uint = ~m_state.uint; -#else -Q_UNUSED_PAR(isFound); -#endif - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -// NOTE: the following postcondition can only succeed when -// (lbound > 0), so no extra check is necessary. -Q_ENSURE_INCRIT(890, isFound); -QF_CRIT_EXIT(); - -return child; - - - - noexcept override - return m_state.fun; - - - - - - - - #ifndef Q_SPY -Q_UNUSED_PAR(qsId); -#endif - -std::int_fast8_t ip = -1; // tran. entry path index -QStateHandler t = path[0]; -QStateHandler const s = path[2]; -QF_CRIT_STAT - -// (a) check source==target (tran. to self)... -if (s == t) { - // exit source s - if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) { - QS_STATE_EXIT_(s, qsId); - } - ip = 0; // enter the target -} -else { - // find superstate of target - static_cast<void>(QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG)); - - t = m_temp.fun; - - // (b) check source==target->super... - if (s == t) { - ip = 0; // enter the target - } - else { - // find superstate of src - static_cast<void>(QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG)); - - // (c) check source->super==target->super... - if (m_temp.fun == t) { - // exit source s - if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) { - QS_STATE_EXIT_(s, qsId); - } - ip = 0; // enter the target - } - else { - // (d) check source->super==target... - if (m_temp.fun == path[0]) { - // exit source s - if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) { - QS_STATE_EXIT_(s, qsId); - } - } - else { - // (e) check rest of source==target->super->super.. - // and store the entry path along the way - std::int_fast8_t iq = 0; // indicate that LCA was found - ip = 1; // enter target and its superstate - path[1] = t; // save the superstate of target - t = m_temp.fun; // save source->super - - // find target->super->super... - // note: ip is the fixed upper loop bound - QState r = QHSM_RESERVED_EVT_(path[1], Q_EMPTY_SIG); - while ((r == Q_RET_SUPER) - && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) - { - ++ip; - path[ip] = m_temp.fun; // store the entry path - if (m_temp.fun == s) { // is it the source? - iq = 1; // indicate that the LCA found - --ip; // do not enter the source - r = Q_RET_HANDLED; // terminate the loop - } - else { // it is not the source, keep going up - r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG); - } - } - QF_CRIT_ENTRY(); - // NOTE: The following postcondition succeeds only when - // ip < QHSM_MAX_NEST_DEPTH, so no additional check is necessary - // too many state nesting levels or "malformed" HSM. - Q_ENSURE_INCRIT(510, r != Q_RET_SUPER); - QF_CRIT_EXIT(); - - // the LCA not found yet? - if (iq == 0) { - // exit source s - if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) - == Q_RET_HANDLED) - { - QS_STATE_EXIT_(s, qsId); - } - - // (f) check the rest of source->super - // == target->super->super... - iq = ip; - r = Q_RET_IGNORED; // indicate that the LCA NOT found - // note: iq is the fixed upper loop bound - do { - if (t == path[iq]) { // is this the LCA? - r = Q_RET_HANDLED; // indicate the LCA found - ip = iq - 1; // do not enter the LCA - iq = -1; // cause termination of the loop - } - else { - --iq; // try lower superstate of target - } - } while (iq >= 0); - - // the LCA not found yet? - if (r != Q_RET_HANDLED) { - // (g) check each source->super->... - // for each target->super... - r = Q_RET_IGNORED; // keep looping - std::int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_; - do { - // exit from t - if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) - == Q_RET_HANDLED) - { - QS_STATE_EXIT_(t, qsId); - // find superstate of t - static_cast<void>( - QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG)); - } - t = m_temp.fun; // set to super of t - iq = ip; - do { - // is this the LCA? - if (t == path[iq]) { - ip = iq - 1; // do not enter the LCA - iq = -1; // break out of inner loop - r = Q_RET_HANDLED; // break outer loop - } - else { - --iq; - } - } while (iq >= 0); - - --lbound; - } while ((r != Q_RET_HANDLED) && (lbound > 0)); - QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(530, lbound > 0); - QF_CRIT_EXIT(); - } - } - } - } - } -} -QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(590, ip < QHSM_MAX_NEST_DEPTH_); -QF_CRIT_EXIT(); -return ip; - - - - - Machine-generated State Machine - - - noexcept - - - : QAsm() - -m_state.obj = &l_msm_top_s; // the current state (top) -m_temp.fun = initial; // the initial tran. handler - - - - override - - - - - #ifndef Q_SPY -Q_UNUSED_PAR(qsId); -#endif - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(200, (m_temp.fun != nullptr) - && (m_state.obj == &l_msm_top_s)); -QF_CRIT_EXIT(); - -// execute the top-most initial tran. -QState r = (*m_temp.fun)(this, Q_EVT_CAST(QEvt)); - -QF_CRIT_ENTRY(); -// the top-most initial tran. must be taken -Q_ASSERT_INCRIT(210, r == Q_RET_TRAN_INIT); - -QS_MEM_SYS(); -QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(m_state.obj->stateHandler); // source state - QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target state -QS_END_PRE() -QS_MEM_APP(); - -QF_CRIT_EXIT(); - -// set state to the last tran. target -m_state.obj = m_temp.tatbl->target; - -// drill down into the state hierarchy with initial transitions... -std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound -do { - // execute the tran. table - r = execTatbl_(m_temp.tatbl, qsId); - --lbound; -} while ((r >= Q_RET_TRAN_INIT) && (lbound > 0)); - -QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(290, lbound > 0); - -QS_MEM_SYS(); -QS_BEGIN_PRE(QS_QEP_INIT_TRAN, qsId) - QS_TIME_PRE(); // time stamp - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(m_state.obj->stateHandler); // the new current state -QS_END_PRE() -QS_MEM_APP(); - -QF_CRIT_EXIT(); - -#ifndef Q_UNSAFE -m_temp.uint = ~m_state.uint; -#endif - - - - override - - - this->init(nullptr, qsId); - - - - override - - - - - #ifndef Q_SPY -Q_UNUSED_PAR(qsId); -#endif - -QMState const *s = m_state.obj; // store the current state -QMState const *t = s; - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(300, (e != nullptr) && (s != nullptr)); -Q_INVARIANT_INCRIT(301, - e->verify_() - && (m_state.uint == static_cast<std::uintptr_t>(~m_temp.uint))); - -QS_MEM_SYS(); -QS_BEGIN_PRE(QS_QEP_DISPATCH, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s->stateHandler); // the current state handler -QS_END_PRE() -QS_MEM_APP(); - -QF_CRIT_EXIT(); - -// scan the state hierarchy up to the top state... -QState r; -std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound -do { - r = (*t->stateHandler)(this, e); // call state handler function - - // event handled? (the most frequent case) - if (r >= Q_RET_HANDLED) { - break; // done scanning the state hierarchy - } - // event unhandled and passed to the superstate? - else if (r == Q_RET_SUPER) { - t = t->superstate; // advance to the superstate - } - else { // event unhandled due to a guard - QF_CRIT_ENTRY(); - // event must be unhandled due to a guard evaluating to 'false' - Q_ASSERT_INCRIT(310, r == Q_RET_UNHANDLED); - - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_UNHANDLED, qsId) - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(t->stateHandler); // the current state - QS_END_PRE() - QS_MEM_APP(); - - QF_CRIT_EXIT(); - - t = t->superstate; // advance to the superstate - } - --lbound; -} while ((t != nullptr) && (lbound > 0)); -QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(320, lbound > 0); -QF_CRIT_EXIT(); - -if (r >= Q_RET_TRAN) { // any kind of tran. taken? - QF_CRIT_ENTRY(); - // the tran. source state must not be nullptr - Q_ASSERT_INCRIT(330, t != nullptr); - QF_CRIT_EXIT(); - -#ifdef Q_SPY - QMState const * const ts = t; // for saving tran. table -#endif // Q_SPY - QMTranActTable const *tatbl; - - if (r == Q_RET_TRAN_HIST) { // was it tran. to history? - QMState const * const hist = m_state.obj; // save history - m_state.obj = s; // restore the original state - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_TRAN_HIST, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(t->stateHandler); // source state handler - QS_FUN_PRE(hist->stateHandler); // target state handler - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); - - // save the tran-action table before it gets clobbered - tatbl = m_temp.tatbl; - exitToTranSource_(s, t, qsId); - static_cast<void>(execTatbl_(tatbl, qsId)); - r = enterHistory_(hist, qsId); - s = m_state.obj; - t = s; // set target to the current state - } - - lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound - while ((r >= Q_RET_TRAN) && (lbound > 0)) { - // save the tran-action table before it gets clobbered - tatbl = m_temp.tatbl; - m_temp.obj = nullptr; // clear - exitToTranSource_(s, t, qsId); - r = execTatbl_(tatbl, qsId); - s = m_state.obj; - t = s; // set target to the current state - --lbound; - } - - QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(360, lbound > 0); - - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_TRAN, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(ts->stateHandler); // the tran. source - QS_FUN_PRE(s->stateHandler); // the new active state - QS_END_PRE() - QS_MEM_APP(); - - QF_CRIT_EXIT(); -} - -#ifdef Q_SPY -// was the event handled? -else if (r == Q_RET_HANDLED) { - QF_CRIT_ENTRY(); - // internal tran. source can't be nullptr - Q_ASSERT_INCRIT(380, t != nullptr); - - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_INTERN_TRAN, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(t->stateHandler); // the source state - QS_END_PRE() - QS_MEM_APP(); - - QF_CRIT_EXIT(); -} -// event bubbled to the 'top' state? -else if (t == nullptr) { - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_IGNORED, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s->stateHandler); // the current state - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); -} -#endif // Q_SPY -else { - // empty -} - -#ifndef Q_UNSAFE -m_temp.uint = ~m_state.uint; -#endif - - - - noexcept override - return m_state.obj->stateHandler; - - - - noexcept override - - - bool inState = false; // assume that this SM is not in 'state' - -QMState const *s = m_state.obj; -std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound -for (; (s != nullptr) && (lbound > 0); --lbound) { - if (s->stateHandler == state) { // match found? - inState = true; - break; - } - else { - s = s->superstate; // advance to the superstate - } -} - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(490, lbound > 0); -QF_CRIT_EXIT(); - -return inState; - - - - const noexcept - - - QMState const *child = m_state.obj; -bool isFound = false; // start with the child not found -QMState const *s; - -std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound -for (s = m_state.obj; - (s != nullptr) && (lbound > 0); - s = s->superstate) -{ - if (s == parent) { - isFound = true; // child is found - break; - } - else { - child = s; - } - --lbound; -} -QF_CRIT_STAT -QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(680, lbound > 0); -QF_CRIT_EXIT(); - -if (!isFound) { // still not found? - lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound - for (s = m_temp.obj; - (s != nullptr) && (lbound > 0); - s = s->superstate) - { - if (s == parent) { - isFound = true; // child is found - break; - } - else { - child = s; - } - --lbound; - } -} - -QF_CRIT_ENTRY(); -// NOTE: the following postcondition can only succeed when -// (lbound > 0), so no extra check is necessary. -Q_ENSURE_INCRIT(690, isFound); -QF_CRIT_EXIT(); - -return child; // return the child - - - - - - - - #ifndef Q_SPY -Q_UNUSED_PAR(qsId); -#endif - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -// precondition: -// - the tran-action table pointer must not be NULL -Q_REQUIRE_INCRIT(700, tatbl != nullptr); -QF_CRIT_EXIT(); - -QState r = Q_RET_NULL; -std::int_fast8_t lbound = QMSM_MAX_TRAN_LENGTH_; // fixed upper loop bound -QActionHandler const *a = &tatbl->act[0]; -for (; (*a != nullptr) && (lbound > 0); ++a) { - r = (*(*a))(this); // call the action through the 'a' pointer - --lbound; -#ifdef Q_SPY - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - if (r == Q_RET_ENTRY) { - QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(m_temp.obj->stateHandler); // entered state - QS_END_PRE() - } - else if (r == Q_RET_EXIT) { - QS_BEGIN_PRE(QS_QEP_STATE_EXIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(m_temp.obj->stateHandler); // exited state - QS_END_PRE() - } - else if (r == Q_RET_TRAN_INIT) { - QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(tatbl->target->stateHandler); // source - QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target - QS_END_PRE() - } - else { - // empty - } - QS_MEM_APP(); - QS_CRIT_EXIT(); -#endif // Q_SPY -} -QF_CRIT_ENTRY(); -// NOTE: the following postcondition can only succeed when -// (lbound > 0), so no extra check is necessary. -Q_ENSURE_INCRIT(790, *a == nullptr); -QF_CRIT_EXIT(); - -m_state.obj = (r >= Q_RET_TRAN) - ? m_temp.tatbl->target - : tatbl->target; -return r; - - - - - - - - - - #ifndef Q_SPY -Q_UNUSED_PAR(qsId); -#endif - -QF_CRIT_STAT - -// exit states from the current state to the tran. source state -QMState const *s = cs; -std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound -for (; (s != ts) && (lbound > 0); --lbound) { - // exit action provided in state 's'? - if (s->exitAction != nullptr) { - // execute the exit action - static_cast<void>((*s->exitAction)(this)); - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_STATE_EXIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s->stateHandler); // the exited state handler - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); - } - - s = s->superstate; // advance to the superstate -} -QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(890, lbound > 0); -QF_CRIT_EXIT(); - - - - - - - - #ifndef Q_SPY -Q_UNUSED_PAR(qsId); -#endif - -// record the entry path from current state to history -QMState const *epath[QMSM_MAX_ENTRY_DEPTH_]; -QMState const *s = hist; -std::int_fast8_t i = 0; // tran. entry path index -while ((s != m_state.obj) && (i < (QMSM_MAX_ENTRY_DEPTH_ - 1))) { - if (s->entryAction != nullptr) { - epath[i] = s; - ++i; - } - s = s->superstate; -} -QF_CRIT_STAT -QF_CRIT_ENTRY(); -Q_ASSERT_INCRIT(910, s == m_state.obj); -QF_CRIT_EXIT(); - -// retrace the entry path in reverse (desired) order... -while (i > 0) { - --i; - (*epath[i]->entryAction)(this); // run entry action in epath[i] - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, qsId) - QS_OBJ_PRE(this); - QS_FUN_PRE(epath[i]->stateHandler); // entered state handler - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); -} - -m_state.obj = hist; // set current state to the tran. target - -// initial tran. present? -QState r; -if (hist->initAction != nullptr) { - r = (*hist->initAction)(this); // execute the tran. action - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(hist->stateHandler); // source - QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); -} -else { - r = Q_RET_NULL; -} - -return r; - - - - const noexcept - return &l_msm_top_s; - - - - - - - - - - \ - QP::QState state_ ## _h(QP::QEvt const * const e); \ - static QP::QState state_(void * const me, QP::QEvt const * const e) - - - - - - - - \ - QP::QState subclass_::state_(void * const me, QP::QEvt const * const e) { \ - return static_cast<subclass_ *>(me)->state_ ## _h(e); } \ - QP::QState subclass_::state_ ## _h(QP::QEvt const * const e) - - - - (Q_RET_HANDLED) - - - - (Q_RET_UNHANDLED) - - - - - - (static_cast<subclass_ const *>(e)) - - - - - - \ - (reinterpret_cast<QP::QStateHandler>(handler_)) - - - - - - \ - QP::QState state_ ## _h(QP::QEvt const * const e); \ - static QP::QState state_(void * const me, QP::QEvt const * const e); \ - static QP::QMState const state_ ## _s - - - - - - \ - QP::QState action_ ## _h(); \ - static QP::QState action_(void * const me) - - - - - - - - \ - QP::QState subclass_::state_(void * const me, QP::QEvt const * const e) {\ - return static_cast<subclass_ *>(me)->state_ ## _h(e); } \ - QP::QState subclass_::state_ ## _h(QP::QEvt const * const e) - - - - - - - - \ - QP::QState subclass_::action_(void * const me) { \ - return static_cast<subclass_ *>(me)->action_ ## _h(); } \ - QP::QState subclass_::action_ ## _h() - - - - (Q_RET_HANDLED) - - - - (Q_RET_HANDLED) - - - - (Q_RET_SUPER) - - - - (nullptr) - - - - (nullptr) - - - - - - (static_cast<void>(par_)) - - - - - - (sizeof(array_) / sizeof((array_)[0U])) - - - - - - - - (reinterpret_cast<type_ *>(uint_)) - - - - - - init((qsId_)) - - - - - - init(0U) - - - - - - - - dispatch((e_), (qsId_)) - - - - - - - - dispatch((e_), 0U) - - - - - - - - - = std::uint16_t; - - - - = QEvt const *; - - - - = std::uint8_t; - - - - = std::uint16_t; - - - - = std::uint32_t; - - - - = std::uint8_t; - - - - = std::uint16_t; - - - - = std::uint32_t; - - - - noexcept - - - static std::uint8_t const log2LUT[16] = { - 0U, 1U, 2U, 2U, 3U, 3U, 3U, 3U, - 4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U -}; -std::uint_fast8_t n = 0U; -QP::QPSetBits t; - -#if (QF_MAX_ACTIVE > 16U) -t = static_cast<QP::QPSetBits>(x >> 16U); -if (t != 0U) { - n += 16U; - x = t; -} -#endif -#if (QF_MAX_ACTIVE > 8U) -t = (x >> 8U); -if (t != 0U) { - n += 8U; - x = t; -} -#endif -t = (x >> 4U); -if (t != 0U) { - n += 4U; - x = t; -} -return n + log2LUT[x]; - - - - - - - - noexcept - m_bits[0] = 0U; -#if (QF_MAX_ACTIVE > 32) -m_bits[1] = 0U; -#endif - - - - const noexcept - #if (QF_MAX_ACTIVE <= 32U) -return (m_bits[0] == 0U); -#else -return (m_bits[0] == 0U) ? (m_bits[1] == 0U) : false; -#endif - - - - const noexcept - #if (QF_MAX_ACTIVE <= 32U) -return (m_bits[0] != 0U); -#else -return (m_bits[0] != 0U) ? true : (m_bits[1] != 0U); -#endif - - - - const noexcept - - - #if (QF_MAX_ACTIVE <= 32U) -return (m_bits[0] & (static_cast<QPSetBits>(1U) << (n - 1U))) != 0U; -#else -return (n <= 32U) - ? ((m_bits[0] & (static_cast<QPSetBits>(1U) << (n - 1U))) != 0U) - : ((m_bits[1] & (static_cast<QPSetBits>(1U) << (n - 33U))) != 0U); -#endif - - - - noexcept - - - #if (QF_MAX_ACTIVE <= 32U) -m_bits[0] = (m_bits[0] | (static_cast<QPSetBits>(1U) << (n - 1U))); -#else -if (n <= 32U) { - m_bits[0] = (m_bits[0] | (static_cast<QPSetBits>(1U) << (n - 1U))); -} -else { - m_bits[1] = (m_bits[1] | (static_cast<QPSetBits>(1U) << (n - 33U))); -} -#endif - - - - noexcept - - - #if (QF_MAX_ACTIVE <= 32U) -m_bits[0] = (m_bits[0] & static_cast<QPSetBits>(~(1U << (n - 1U)))); -#else -if (n <= 32U) { - (m_bits[0] = (m_bits[0] & ~(static_cast<QPSetBits>(1U) << (n - 1U)))); -} -else { - (m_bits[1] = (m_bits[1] & ~(static_cast<QPSetBits>(1U) << (n - 33U)))); -} -#endif - - - - const noexcept - #if (QF_MAX_ACTIVE <= 32U) -return QF_LOG2(m_bits[0]); -#else -return (m_bits[1] != 0U) - ? (QF_LOG2(m_bits[1]) + 32U) - : (QF_LOG2(m_bits[0])); -#endif - - - - const noexcept - - - dis->m_bits[0] = ~m_bits[0]; -#if (QF_MAX_ACTIVE > 32U) -dis->m_bits[1] = ~m_bits[1]; -#endif - - - - const noexcept - - - #if (QF_MAX_ACTIVE <= 32U) -return m_bits[0] == static_cast<QPSetBits>(~dis->m_bits[0]); -#else -return (m_bits[0] == static_cast<QPSetBits>(~dis->m_bits[0])) - && (m_bits[1] == static_cast<QPSetBits>(~dis->m_bits[1])); -#endif - - - - - - - - - - - // friends... - - - - - - - - - // friends... - - - - // friends... - - - - noexcept - - - : m_ptr_dis(static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(ptr))) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // friends... - - - - - - - - - - - - - - - - - - - - noexcept - - - : QAsm(), - m_prio(0U), - m_pthre(0U) - -m_state.fun = Q_STATE_CAST(&top); -m_temp.fun = initial; - -#ifndef Q_UNSAFE -m_prio_dis = static_cast<std::uint8_t>(~m_prio); -m_pthre_dis = static_cast<std::uint8_t>(~m_pthre); -#endif - - - - override - - - - - reinterpret_cast<QHsm *>(this)->QHsm::init(e, qsId); - - - - override - - - this->init(nullptr, qsId); - - - - override - - - - - reinterpret_cast<QHsm *>(this)->QHsm::dispatch(e, qsId); - - - - noexcept override - - - return reinterpret_cast<QHsm *>(this)->QHsm::isIn(state); - - - - noexcept - - - return reinterpret_cast<QHsm *>(this)->QHsm::childState(parent); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - this->start(prioSpec, qSto, qLen, stkSto, stkSize, nullptr); - - - - - - noexcept - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -if (m_pthre == 0U) { // preemption-threshold not defined? - m_pthre = m_prio; // apply the default -} - -#ifndef Q_UNSAFE - -Q_REQUIRE_INCRIT(100, (0U < m_prio) && (m_prio <= QF_MAX_ACTIVE) - && (registry_[m_prio] == nullptr) - && (m_prio <= m_pthre)); - -std::uint8_t prev_thre = m_pthre; -std::uint8_t next_thre = m_pthre; - -std::uint_fast8_t p; -for (p = static_cast<std::uint_fast8_t>(m_prio) - 1U; p > 0U; --p) { - if (registry_[p] != nullptr) { - prev_thre = registry_[p]->m_pthre; - break; - } -} -for (p = static_cast<std::uint_fast8_t>(m_prio) + 1U; - p <= QF_MAX_ACTIVE; ++p) -{ - if (registry_[p] != nullptr) { - next_thre = registry_[p]->m_pthre; - break; - } -} - -Q_ASSERT_INCRIT(190, (prev_thre <= m_pthre) - && (m_pthre <= next_thre)); - -m_prio_dis = static_cast<std::uint8_t>(~m_prio); -m_pthre_dis = static_cast<std::uint8_t>(~m_pthre); - -#endif // Q_UNSAFE - -// register the AO at the QF-prio. -registry_[m_prio] = this; - -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - noexcept - std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio); - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(200, (0U < p) && (p <= QF_MAX_ACTIVE) - && (registry_[p] == this)); -registry_[p] = nullptr; // free-up the priority level -m_state.fun = nullptr; // invalidate the state - -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - noexcept - - - - - - - #ifndef Q_SPY -Q_UNUSED_PAR(sender); -#endif - -#ifdef Q_UTEST // test? -#if (Q_UTEST != 0) // testing QP-stub? -if (m_temp.fun == Q_STATE_CAST(0)) { // QActiveDummy? - return static_cast<QActiveDummy *>(this)->fakePost(e, margin, sender); -} -#endif // (Q_UTEST != 0) -#endif // def Q_UTEST - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(200, e != nullptr); - -QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary -#ifndef Q_UNSAFE -QEQueueCtr dis = static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis); -Q_INVARIANT_INCRIT(201, e->verify_() && (tmp == dis)); -#endif // ndef Q_UNSAFE - -// test-probe#1 for faking queue overflow -QS_TEST_PROBE_DEF(&QActive::post_) -QS_TEST_PROBE_ID(1, - tmp = 0U; // fake no free events -) - -// required margin available? -bool status; -if (margin == QF::NO_MARGIN) { - if (tmp > 0U) { // free entries available in the queue? - status = true; // can post - } - else { // no free entries available - status = false; // cannot post - - // The queue overflows, but QF_NO_MARGIN indicates that - // the "event delivery guarantee" is required. - Q_ERROR_INCRIT(210); // must be able to post the event - } -} -else if (tmp > static_cast<QEQueueCtr>(margin)) { - status = true; // can post -} -else { // the # free entries below the requested margin - status = false; // cannot post, but don't assert -} - -// is it a mutable event? -if (e->getPoolNum_() != 0U) { - QEvt_refCtr_inc_(e); // increment the reference counter -} - -if (status) { // can post the event? - --tmp; // one free entry just used up - - m_eQueue.m_nFree = tmp; // update the original -#ifndef Q_UNSAFE - m_eQueue.m_nFree_dis = static_cast<QEQueueCtr>(~tmp); -#endif // ndef Q_UNSAFE - - if (m_eQueue.m_nMin > tmp) { - m_eQueue.m_nMin = tmp; // update minimum so far - } - - 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 - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); - QS_EQC_PRE(tmp); // # free entries - QS_EQC_PRE(m_eQueue.m_nMin); // min # free entries - QS_END_PRE() - -#ifdef Q_UTEST - // callback to examine the posted event under the same conditions - // as producing the #QS_QF_ACTIVE_POST trace record, which are: - // the local filter for this AO ('m_prio') is set - if (QS_LOC_CHECK_(m_prio)) { - QF_MEM_APP(); - QF_CRIT_EXIT(); - - QS::onTestPost(sender, this, e, status); - - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - } -#endif // def Q_UTEST - - if (m_eQueue.m_frontEvt == nullptr) { // is the queue empty? - m_eQueue.m_frontEvt = e; // deliver event directly -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(211, m_eQueue.m_frontEvt_dis - == static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr))); - m_eQueue.m_frontEvt_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(e)); -#endif // ndef Q_UNSAFE - -#ifdef QXK_HPP_ - if (m_state.act == nullptr) { // eXtended thread? - QXTHREAD_EQUEUE_SIGNAL_(this); // signal eXtended Thread - } - else { - QACTIVE_EQUEUE_SIGNAL_(this); // signal the Active Object - } -#else - QACTIVE_EQUEUE_SIGNAL_(this); // signal the Active Object -#endif // def QXK_HPP_ - } - else { // queue was not empty, insert event into the ring-buffer - tmp = m_eQueue.m_head; // get volatile into temporary -#ifndef Q_UNSAFE - dis = static_cast<QEQueueCtr>(~m_eQueue.m_head_dis); - Q_INVARIANT_INCRIT(212, tmp == dis); -#endif // ndef Q_UNSAFE - m_eQueue.m_ring[tmp] = e; // insert e into buffer - - if (tmp == 0U) { // need to wrap the head? - tmp = m_eQueue.m_end; - } - --tmp; // advance the head (counter-clockwise) - - m_eQueue.m_head = tmp; // update the original -#ifndef Q_UNSAFE - m_eQueue.m_head_dis = static_cast<QEQueueCtr>(~tmp); -#endif // ndef Q_UNSAFE - } - - QF_MEM_APP(); - QF_CRIT_EXIT(); -} -else { // event cannot be posted - - 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 - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); - QS_EQC_PRE(tmp); // # free entries - QS_EQC_PRE(margin); // margin requested - QS_END_PRE() - -#ifdef Q_UTEST - // callback to examine the posted event under the same conditions - // as producing the #QS_QF_ACTIVE_POST trace record, which are: - // the local filter for this AO ('m_prio') is set - if (QS_LOC_CHECK_(m_prio)) { - QF_MEM_APP(); - QF_CRIT_EXIT(); - - QS::onTestPost(sender, this, e, status); - - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - } -#endif // def Q_USTEST - - QF_MEM_APP(); - QF_CRIT_EXIT(); - -#if (QF_MAX_EPOOL > 0U) - QF::gc(e); // recycle the event to avoid a leak -#endif // (QF_MAX_EPOOL > 0U) -} - -return status; - - - - noexcept - - - #ifdef Q_UTEST // test? -#if (Q_UTEST != 0) // testing QP-stub? -if (m_temp.fun == Q_STATE_CAST(0)) { // QActiveDummy? - static_cast<QActiveDummy *>(this)->QActiveDummy::fakePostLIFO(e); - return; -} -#endif // (Q_UTEST != 0) -#endif // def Q_UTEST - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(300, e != nullptr); - -QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary -#ifndef Q_UNSAFE -QEQueueCtr dis = static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis); -Q_INVARIANT_INCRIT(301, e->verify_() && (tmp == dis)); -#endif // ndef Q_UNSAFE - -// test-probe#1 for faking queue overflow -QS_TEST_PROBE_DEF(&QActive::postLIFO) -QS_TEST_PROBE_ID(1, - tmp = 0U; // fake no free events -) - -// The queue must NOT overflow for the LIFO posting policy. -Q_REQUIRE_INCRIT(310, tmp != 0U); - -if (e->getPoolNum_() != 0U) { - QEvt_refCtr_inc_(e); // increment the reference counter -} - ---tmp; // one free entry just used up - -m_eQueue.m_nFree = tmp; // update the original -#ifndef Q_UNSAFE -m_eQueue.m_nFree_dis = static_cast<QEQueueCtr>(~tmp); -#endif // ndef Q_UNSAFE - -if (m_eQueue.m_nMin > tmp) { - m_eQueue.m_nMin = tmp; // update minimum so far -} - -QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(e->sig); // the signal of this event - QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); - QS_EQC_PRE(tmp); // # free entries - QS_EQC_PRE(m_eQueue.m_nMin); // min # free entries -QS_END_PRE() - -#ifdef Q_UTEST -// callback to examine the posted event under the same conditions -// as producing the #QS_QF_ACTIVE_POST trace record, which are: -// the local filter for this AO ('m_prio') is set -if (QS_LOC_CHECK_(m_prio)) { - QF_MEM_APP(); - QF_CRIT_EXIT(); - - QS::onTestPost(nullptr, this, e, true); - - QF_CRIT_ENTRY(); - QF_MEM_SYS(); -} -#endif // def Q_UTEST - -QEvt const * const frontEvt = m_eQueue.m_frontEvt; -m_eQueue.m_frontEvt = e; // deliver the event directly to the front -#ifndef Q_UNSAFE -m_eQueue.m_frontEvt_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(e)); -#endif // ndef Q_UNSAFE - -if (frontEvt != nullptr) { // was the queue NOT empty? - tmp = m_eQueue.m_tail; // get volatile into temporary; -#ifndef Q_UNSAFE - dis = static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis); - Q_INVARIANT_INCRIT(311, tmp == dis); -#endif // ndef Q_UNSAFE - ++tmp; - if (tmp == m_eQueue.m_end) { // need to wrap the tail? - tmp = 0U; // wrap around - } - m_eQueue.m_tail = tmp; -#ifndef Q_UNSAFE - m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~tmp); -#endif // ndef Q_UNSAFE - m_eQueue.m_ring[tmp] = frontEvt; -} -else { // queue was empty - QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue -} - -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - noexcept - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -// wait for event to arrive directly (depends on QP port) -// NOTE: might use assertion-IDs 400-409 -QACTIVE_EQUEUE_WAIT_(this); // wait for event to arrive directly - -// always remove evt from the front -QEvt const * const e = m_eQueue.m_frontEvt; -QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into tmp - -#ifndef Q_UNSAFE -Q_INVARIANT_INCRIT(410, e != nullptr); // queue must NOT be empty -Q_INVARIANT_INCRIT(411, Q_PTR2UINT_CAST_(e) - == static_cast<std::uintptr_t>(~m_eQueue.m_frontEvt_dis)); -QEQueueCtr dis = static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis); -Q_INVARIANT_INCRIT(412, tmp == dis); -#endif // ndef Q_UNSAFE - -++tmp; // one more free event in the queue - -m_eQueue.m_nFree = tmp; // update the # free -#ifndef Q_UNSAFE -m_eQueue.m_nFree_dis = static_cast<QEQueueCtr>(~tmp); -#endif // ndef Q_UNSAFE - -if (tmp <= m_eQueue.m_end) { // any events in the ring buffer? - QS_BEGIN_PRE(QS_QF_ACTIVE_GET, m_prio) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(e->sig); // the signal of this event - QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); - QS_EQC_PRE(tmp); // # free entries - QS_END_PRE() - - // remove event from the tail - tmp = m_eQueue.m_tail; // get volatile into temporary -#ifndef Q_UNSAFE - dis = static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis); - Q_INVARIANT_INCRIT(420, tmp == dis); -#endif // ndef Q_UNSAFE - QEvt const * const frontEvt = m_eQueue.m_ring[tmp]; -#ifndef Q_UNSAFE - Q_ASSERT_INCRIT(421, frontEvt != nullptr); - m_eQueue.m_frontEvt_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(frontEvt)); -#endif // ndef Q_UNSAFE - m_eQueue.m_frontEvt = frontEvt; // update the original - - if (tmp == 0U) { // need to wrap the tail? - tmp = m_eQueue.m_end; - } - --tmp; // advance the tail (counter-clockwise) - - m_eQueue.m_tail = tmp; // update the original -#ifndef Q_UNSAFE - m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~tmp); -#endif // ndef Q_UNSAFE -} -else { - m_eQueue.m_frontEvt = nullptr; // the queue becomes empty -#ifndef Q_UNSAFE - m_eQueue.m_frontEvt_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr)); -#endif // ndef Q_UNSAFE - - // all entries in the queue must be free (+1 for fronEvt) - Q_ASSERT_INCRIT(310, tmp == (m_eQueue.m_end + 1U)); - - QS_BEGIN_PRE(QS_QF_ACTIVE_GET_LAST, m_prio) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(e->sig); // the signal of this event - QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); - QS_END_PRE() -} - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -return e; - - - - noexcept - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(400, (prio <= QF_MAX_ACTIVE) - && (QActive::registry_[prio] != nullptr)); -std::uint_fast16_t const min = static_cast<std::uint_fast16_t>( - QActive::registry_[prio]->m_eQueue.getNMin()); -QF_CRIT_EXIT(); - -return min; - - - - noexcept - - - - - subscrList_ = subscrSto; -maxPubSignal_ = maxSignal; - -// initialize the subscriber list -for (enum_t sig = 0; sig < maxSignal; ++sig) { - subscrSto[sig].m_set.setEmpty(); -#ifndef Q_UNSAFE - subscrSto[sig].m_set.update_(&subscrSto[sig].m_set_dis); -#endif -} - - - - noexcept - - - - - - - #ifndef Q_SPY -Q_UNUSED_PAR(sender); -Q_UNUSED_PAR(qsId); -#endif - -QSignal const sig = e->sig; - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(200, sig < static_cast<QSignal>(maxPubSignal_)); -Q_INVARIANT_INCRIT(202, - subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis)); - -QS_BEGIN_PRE(QS_QF_PUBLISH, qsId) - QS_TIME_PRE(); // the timestamp - QS_OBJ_PRE(sender); // the sender object - QS_SIG_PRE(e->sig); // the signal of the event - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); -QS_END_PRE() - -// is it a mutable event? -if (e->getPoolNum_() != 0U) { - // NOTE: The reference counter of a mutable event is incremented to - // prevent premature recycling of the event while the multicasting - // is still in progress. At the end of the function, the garbage - // collector step (QF::gc()) decrements the reference counter and - // recycles the event if the counter drops to zero. This covers the - // case when the event was published without any subscribers. - QEvt_refCtr_inc_(e); -} - -// make a local, modifiable copy of the subscriber set -QPSet subscrSet = subscrList_[sig].m_set; - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -if (subscrSet.notEmpty()) { // any subscribers? - // highest-prio subscriber - std::uint_fast8_t p = subscrSet.findMax(); - - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - QActive *a = registry_[p]; - // the AO must be registered with the framework - Q_ASSERT_INCRIT(210, a != nullptr); - - QF_MEM_APP(); - QF_CRIT_EXIT(); - - QF_SCHED_STAT_ - QF_SCHED_LOCK_(p); // lock the scheduler up to AO's prio - std::uint_fast8_t lbound = QF_MAX_ACTIVE + 1U; - do { // loop over all subscribers - --lbound; - - // POST() asserts internally if the queue overflows - a->POST(e, sender); - - subscrSet.remove(p); // remove the handled subscriber - if (subscrSet.notEmpty()) { // still more subscribers? - p = subscrSet.findMax(); // highest-prio subscriber - - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - a = registry_[p]; - // the AO must be registered with the framework - Q_ASSERT_INCRIT(220, a != nullptr); - - QF_MEM_APP(); - QF_CRIT_EXIT(); - } - else { - p = 0U; // no more subscribers - } - } while ((p != 0U) && (lbound > 0U)); - - QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(290, p == 0U); - QF_CRIT_EXIT(); - - QF_SCHED_UNLOCK_(); // unlock the scheduler -} - -// The following garbage collection step decrements the reference counter -// and recycles the event if the counter drops to zero. This covers both -// cases when the event was published with or without any subscribers. -#if (QF_MAX_EPOOL > 0U) -QF::gc(e); -#endif - - - - const noexcept - - - std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio); - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(300, (Q_USER_SIG <= sig) - && (sig < maxPubSignal_) - && (0U < p) && (p <= QF_MAX_ACTIVE) - && (registry_[p] == this)); -Q_INVARIANT_INCRIT(302, - subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis)); - -QS_BEGIN_PRE(QS_QF_ACTIVE_SUBSCRIBE, m_prio) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(sig); // the signal of this event - QS_OBJ_PRE(this); // this active object -QS_END_PRE() - -// insert the prio. into the subscriber set -subscrList_[sig].m_set.insert(p); -#ifndef Q_UNSAFE -subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis); -#endif - -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - const noexcept - - - std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio); - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(400, (Q_USER_SIG <= sig) - && (sig < maxPubSignal_) - && (0U < p) && (p <= QF_MAX_ACTIVE) - && (registry_[p] == this)); -Q_INVARIANT_INCRIT(402, - subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis)); - -QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(sig); // the signal of this event - QS_OBJ_PRE(this); // this active object -QS_END_PRE() - -// remove the prio. from the subscriber set -subscrList_[sig].m_set.remove(p); -#ifndef Q_UNSAFE -subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis); -#endif - -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - const noexcept - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio); - -Q_REQUIRE_INCRIT(500, (0U < p) && (p <= QF_MAX_ACTIVE) - && (registry_[p] == this)); -enum_t const maxPubSig = maxPubSignal_; - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -for (enum_t sig = Q_USER_SIG; sig < maxPubSig; ++sig) { - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - if (subscrList_[sig].m_set.hasElement(p)) { - subscrList_[sig].m_set.remove(p); -#ifndef Q_UNSAFE - subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis); -#endif - QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(sig); // the signal of this event - QS_OBJ_PRE(this); // this active object - QS_END_PRE() - } - QF_MEM_APP(); - QF_CRIT_EXIT(); - - QF_CRIT_EXIT_NOP(); // prevent merging critical sections -} - - - - const noexcept - - - - - bool const status = eq->post(e, 0U, m_prio); - -QS_CRIT_STAT -QS_CRIT_ENTRY(); -QS_MEM_SYS(); -QS_BEGIN_PRE(QS_QF_ACTIVE_DEFER, m_prio) - QS_TIME_PRE(); // time stamp - QS_OBJ_PRE(this); // this active object - QS_OBJ_PRE(eq); // the deferred queue - QS_SIG_PRE(e->sig); // the signal of the event - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); -QS_END_PRE() -QS_MEM_APP(); -QS_CRIT_EXIT(); - -return status; - - - - noexcept - - - QEvt const * const e = eq->get(m_prio); // get evt from deferred queue -QF_CRIT_STAT - -bool recalled; -if (e != nullptr) { // event available? - postLIFO(e); // post it to the _front_ of the AO's queue - - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - if (e->getPoolNum_() != 0U) { // is it a mutable event? - - // after posting to the AO's queue the event must be referenced - // at least twice: once in the deferred event queue (eq->get() - // did NOT decrement the reference counter) and once in the - // AO's event queue. - Q_ASSERT_INCRIT(210, e->refCtr_ >= 2U); - - // we need to decrement the reference counter once, to account - // for removing the event from the deferred event queue. - QEvt_refCtr_dec_(e); // decrement the reference counter - } - - QS_BEGIN_PRE(QS_QF_ACTIVE_RECALL, m_prio) - QS_TIME_PRE(); // time stamp - QS_OBJ_PRE(this); // this active object - QS_OBJ_PRE(eq); // the deferred queue - QS_SIG_PRE(e->sig); // the signal of the event - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); - QS_END_PRE() - - QF_MEM_APP(); - QF_CRIT_EXIT(); - - recalled = true; -} -else { - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - QS_BEGIN_PRE(QS_QF_ACTIVE_RECALL_ATTEMPT, m_prio) - QS_TIME_PRE(); // time stamp - QS_OBJ_PRE(this); // this active object - QS_OBJ_PRE(eq); // the deferred queue - QS_END_PRE() - - QS_MEM_APP(); - QS_CRIT_EXIT(); - - recalled = false; -} -return recalled; - - - - const noexcept - - - - - std::uint_fast16_t n = 0U; -while (n < num) { - QEvt const * const e = eq->get(m_prio); - if (e != nullptr) { - ++n; // count one more flushed event -#if (QF_MAX_EPOOL > 0U) - QF::gc(e); // garbage collect -#endif - } - else { - break; - } -} - -return n; - - - - const noexcept - return static_cast<std::uint_fast8_t>(m_prio); - - - - noexcept - - - m_prio = static_cast<std::uint8_t>(prio & 0xFFU); -m_pthre = static_cast<std::uint8_t>(prio >> 8U); - - - - const noexcept - return static_cast<std::uint_fast8_t>(m_pthre); - - - - const noexcept - return m_eQueue; - - - - const noexcept - return m_osObject; - - - - const noexcept - return m_thread; - - - - - - m_thread = thr; - - - - - - - - - noexcept - - - - - - - - - - - - noexcept - - - - - - - - - - - - - noexcept - - - : QActive(initial) - -m_state.obj = reinterpret_cast<QMsm *>(this)->topQMState(); -m_temp.fun = initial; - - - - override - - - - - reinterpret_cast<QMsm *>(this)->QMsm::init(e, qsId); - - - - override - - - this->init(nullptr, qsId); - - - - override - - - - - reinterpret_cast<QMsm *>(this)->QMsm::dispatch(e, qsId); - - - - noexcept override - - - return reinterpret_cast<QMsm *>(this)->QMsm::isIn(state); - - - - noexcept override - return reinterpret_cast<QMsm *>(this)->QMsm::getStateHandler(); - - - - const noexcept - - - return reinterpret_cast<QMsm const *>(this) - ->QMsm::childStateObj(parent); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - noexcept - - - - - - - : QEvt(sig), - m_next(nullptr), -#ifndef Q_UNSAFE - m_next_dis(static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr))), -#endif - m_act(act), - m_ctr(0U), -#ifndef Q_UNSAFE - m_ctr_dis(static_cast<QTimeEvtCtr>(~static_cast<QTimeEvtCtr>(0U))), -#endif - m_interval(0U), - m_tickRate(0U), - m_flags(0U) - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(300, (sig != 0U) - && (tickRate < QF_MAX_TICK_RATE)); -QF_CRIT_EXIT(); - -// adjust the settings from the QEvt(sig) ctor -evtTag_ = 0x0FU; -refCtr_ = 0U; - - - - noexcept - - - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -// dynamic range checks -#if (QF_TIMEEVT_CTR_SIZE == 1U) -Q_REQUIRE_INCRIT(400, (nTicks < 0xFFU) && (interval < 0xFFU)); -#elif (QF_TIMEEVT_CTR_SIZE == 2U) -Q_REQUIRE_INCRIT(400, (nTicks < 0xFFFFU) && (interval < 0xFFFFU)); -#endif - -Q_REQUIRE_INCRIT(401, verify_() && (nTicks != 0U)); - -QTimeEvtCtr const ctr = m_ctr; -std::uint8_t const tickRate = m_tickRate; -#ifdef Q_SPY -std::uint_fast8_t const qsId = - static_cast<QActive const *>(m_act)->m_prio; -#endif // def Q_SPY - -Q_REQUIRE_INCRIT(410, (ctr == 0U) - && (m_act != nullptr) - && (tickRate < QF_MAX_TICK_RATE)); - -#ifndef Q_UNSAFE -Q_INVARIANT_INCRIT(411, ctr == static_cast<QTimeEvtCtr>(~m_ctr_dis)); -#else -Q_UNUSED_PAR(ctr); -#endif // ndef Q_UNSAFE - -m_ctr = static_cast<QTimeEvtCtr>(nTicks); -m_interval = static_cast<QTimeEvtCtr>(interval); -#ifndef Q_UNSAFE -m_ctr_dis = static_cast<QTimeEvtCtr>(~nTicks); -#endif // ndef Q_UNSAFE - -// is the time event unlinked? -// NOTE: For the duration of a single clock tick of the specified tick -// rate a time event can be disarmed and yet still linked into the list -// because un-linking is performed exclusively in the QF_tickX() function. -if ((m_flags & QTE_FLAG_IS_LINKED) == 0U) { - m_flags |= QTE_FLAG_IS_LINKED; // mark as linked - - // The time event is initially inserted into the separate - // "freshly armed" list based on timeEvtHead_[tickRate].act. - // Only later, inside QTimeEvt::tick(), the "freshly armed" - // list is appended to the main list of armed time events based on - // timeEvtHead_[tickRate].next. Again, this is to keep any - // changes to the main list exclusively inside QTimeEvt::tick(). -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(420, - Q_PTR2UINT_CAST_(m_next) == - static_cast<std::uintptr_t>(~m_next_dis)); - Q_INVARIANT_INCRIT(411, - Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) == - static_cast<std::uintptr_t>(~timeEvtHead_dis_[tickRate].m_ptr_dis)); -#endif - m_next = timeEvtHead_[tickRate].toTimeEvt(); - timeEvtHead_[tickRate].m_act = this; -#ifndef Q_UNSAFE - m_next_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(m_next)); - timeEvtHead_dis_[tickRate].m_ptr_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(this)); -#endif // ndef Q_UNSAFE -} - -QS_BEGIN_PRE(QS_QF_TIMEEVT_ARM, qsId) - QS_TIME_PRE(); // timestamp - QS_OBJ_PRE(this); // this time event object - QS_OBJ_PRE(m_act); // the active object - QS_TEC_PRE(nTicks); // the # ticks - QS_TEC_PRE(interval); // the interval - QS_U8_PRE(tickRate); // tick rate -QS_END_PRE() - -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - noexcept - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(500, verify_()); - -QTimeEvtCtr const ctr = m_ctr; -#ifndef Q_UNSAFE -Q_INVARIANT_INCRIT(501, ctr == static_cast<QTimeEvtCtr>(~m_ctr_dis)); -#endif // ndef Q_UNSAFE - -#ifdef Q_SPY -std::uint_fast8_t const qsId = static_cast<QActive *>(m_act)->m_prio; -#endif - -// was the time event actually armed? -bool wasArmed; -if (ctr != 0U) { - wasArmed = true; - m_flags |= QTE_FLAG_WAS_DISARMED; - m_ctr = 0U; // schedule removal from the list -#ifndef Q_UNSAFE - m_ctr_dis = static_cast<QTimeEvtCtr>(~static_cast<QTimeEvtCtr>(0U)); -#endif // ndef Q_UNSAFE - - QS_BEGIN_PRE(QS_QF_TIMEEVT_DISARM, qsId) - QS_TIME_PRE(); // timestamp - QS_OBJ_PRE(this); // this time event object - QS_OBJ_PRE(m_act); // the target AO - QS_TEC_PRE(ctr); // the # ticks - QS_TEC_PRE(m_interval); // the interval - QS_U8_PRE(m_tickRate); // tick rate - QS_END_PRE() -} -else { // the time event was already disarmed automatically - wasArmed = false; - m_flags &= static_cast<std::uint8_t>(~QTE_FLAG_WAS_DISARMED); - - QS_BEGIN_PRE(QS_QF_TIMEEVT_DISARM_ATTEMPT, qsId) - QS_TIME_PRE(); // timestamp - QS_OBJ_PRE(this); // this time event object - QS_OBJ_PRE(m_act); // the target AO - QS_U8_PRE(m_tickRate); // tick rate - QS_END_PRE() -} - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -return wasArmed; - - - - noexcept - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -// dynamic range checks -#if (QF_TIMEEVT_CTR_SIZE == 1U) -Q_REQUIRE_INCRIT(600, nTicks < 0xFFU); -#elif (QF_TIMEEVT_CTR_SIZE == 2U) -Q_REQUIRE_INCRIT(600, nTicks < 0xFFFFU); -#endif - -Q_REQUIRE_INCRIT(601, verify_() && (nTicks != 0U)); - -QTimeEvtCtr const ctr = m_ctr; -std::uint8_t const tickRate = m_tickRate; -#ifdef Q_SPY -std::uint_fast8_t const qsId = static_cast<QActive *>(m_act)->m_prio; -#endif - -Q_REQUIRE_INCRIT(610, (m_act != nullptr) - && (tickRate < QF_MAX_TICK_RATE)); - -#ifndef Q_UNSAFE -Q_INVARIANT_INCRIT(602, ctr == static_cast<QTimeEvtCtr>(~m_ctr_dis)); -#endif // ndef Q_UNSAFE -m_ctr = static_cast<QTimeEvtCtr>(nTicks); -#ifndef Q_UNSAFE -m_ctr_dis = static_cast<QTimeEvtCtr>(~nTicks); -#endif // ndef Q_UNSAFE - -// is the time evt not running? -bool wasArmed; -if (ctr == 0U) { - wasArmed = false; - - // NOTE: For a duration of a single clock tick of the specified - // tick rate a time event can be disarmed and yet still linked into - // the list, because unlinking is performed exclusively in the - // QTimeEvt::tick() function. - - // was the time event unlinked? - if ((m_flags & QTE_FLAG_IS_LINKED) == 0U) { - m_flags |= QTE_FLAG_IS_LINKED; // mark as linked - - // The time event is initially inserted into the separate - // "freshly armed" list based on timeEvtHead_[tickRate].act. - // Only later, inside QTimeEvt::tick(), the "freshly armed" - // list is appended to the main list of armed time events based on - // timeEvtHead_[tickRate].next. Again, this is to keep any - // changes to the main list exclusively inside QTimeEvt::tick(). -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(620, - Q_PTR2UINT_CAST_(m_next) == - static_cast<std::uintptr_t>(~m_next_dis)); - Q_INVARIANT_INCRIT(611, - Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) == - static_cast<std::uintptr_t>(~timeEvtHead_dis_[tickRate].m_ptr_dis)); -#endif - m_next = timeEvtHead_[tickRate].toTimeEvt(); - timeEvtHead_[tickRate].m_act = this; -#ifndef Q_UNSAFE - m_next_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(m_next)); - timeEvtHead_dis_[tickRate].m_ptr_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(this)); -#endif // ndef Q_UNSAFE - } -} -else { // the time event was armed - wasArmed = true; -} - -QS_BEGIN_PRE(QS_QF_TIMEEVT_REARM, qsId) - QS_TIME_PRE(); // timestamp - QS_OBJ_PRE(this); // this time event object - QS_OBJ_PRE(m_act); // the target AO - QS_TEC_PRE(nTicks); // the # ticks - QS_TEC_PRE(m_interval); // the interval - QS_2U8_PRE(tickRate, (wasArmed ? 1U : 0U)); -QS_END_PRE() - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -return wasArmed; - - - - noexcept - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -bool const wasDisarmed = (m_flags & QTE_FLAG_WAS_DISARMED) != 0U; -m_flags |= QTE_FLAG_WAS_DISARMED; - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -return wasDisarmed; - - - - const noexcept - return m_act; - - - - const noexcept - return m_ctr; - - - - const noexcept - return m_interval; - - - - const noexcept - return m_tickRate; - - - - noexcept - - - - - #ifndef Q_SPY -Q_UNUSED_PAR(sender); -#endif - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(800, tickRate < Q_DIM(timeEvtHead_)); - -QTimeEvt *prev = &timeEvtHead_[tickRate]; - -QS_BEGIN_PRE(QS_QF_TICK, 0U) - prev->m_ctr = (prev->m_ctr + 1U); - QS_TEC_PRE(prev->m_ctr); // tick ctr - QS_U8_PRE(tickRate); // tick rate -QS_END_PRE() - -// scan the linked-list of time events at this rate... -std::uint_fast8_t lbound = 2U*QF_MAX_ACTIVE; // fixed upper loop bound -for (; lbound > 0U; --lbound) { - Q_ASSERT_INCRIT(810, prev != nullptr); // sanity check - - QTimeEvt *te = prev->m_next; // advance down the time evt. list -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(811, - Q_PTR2UINT_CAST_(te) == - static_cast<std::uintptr_t>(~prev->m_next_dis)); -#endif // ndef Q_UNSAFE - - if (te == nullptr) { // end of the list? - - // any new time events armed since the last QTimeEvt_tick_()? - if (timeEvtHead_[tickRate].m_act != nullptr) { -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(812, - Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) == - static_cast<std::uintptr_t>( - ~timeEvtHead_dis_[tickRate].m_ptr_dis)); -#endif // ndef Q_UNSAFE - prev->m_next = timeEvtHead_[tickRate].toTimeEvt(); - timeEvtHead_[tickRate].m_act = nullptr; -#ifndef Q_UNSAFE - prev->m_next_dis = - static_cast<std::uintptr_t>( - ~Q_PTR2UINT_CAST_(prev->m_next)); - timeEvtHead_dis_[tickRate].m_ptr_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr)); -#endif // ndef Q_UNSAFE - - te = prev->m_next; // switch to the new list - } - else { // all currently armed time events are processed - break; // terminate the for-loop - } - } - - // the time event 'te' must be valid - Q_ASSERT_INCRIT(820, te != nullptr); - Q_INVARIANT_INCRIT(821, te->verify_()); - - QTimeEvtCtr ctr = te->m_ctr; -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(822, ctr == - static_cast<QTimeEvtCtr>(~te->m_ctr_dis)); -#endif // ndef Q_UNSAFE - - if (ctr == 0U) { // time event scheduled for removal? - prev->m_next = te->m_next; -#ifndef Q_UNSAFE - prev->m_next_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(te->m_next)); -#endif // ndef Q_UNSAFE - - // mark time event 'te' as NOT linked - te->m_flags &= static_cast<std::uint8_t>(~QTE_FLAG_IS_LINKED); - - // do NOT advance the prev pointer - QF_MEM_APP(); - QF_CRIT_EXIT(); // exit crit. section to reduce latency - - // NOTE: prevent merging critical sections - // In some QF ports the critical section exit takes effect only - // on the next machine instruction. If the next instruction is - // another entry to a critical section, the critical section - // might not be really exited, but rather the two adjacent - // critical sections would be MERGED. The QF_CRIT_EXIT_NOP() - // macro contains minimal code required to prevent such merging - // of critical sections in QF ports, in which it can occur. - QF_CRIT_EXIT_NOP(); - } - else if (ctr == 1U) { // is time evt about to expire? - QActive * const act = te->toActive(); - if (te->m_interval != 0U) { // periodic time evt? - te->m_ctr = te->m_interval; // rearm the time event -#ifndef Q_UNSAFE - te->m_ctr_dis = static_cast<QTimeEvtCtr>(~te->m_interval); -#endif // ndef Q_UNSAFE - prev = te; // advance to this time event - } - else { // one-shot time event: automatically disarm - te->m_ctr = 0U; - prev->m_next = te->m_next; -#ifndef Q_UNSAFE - te->m_ctr_dis = - static_cast<QTimeEvtCtr>(~static_cast<QTimeEvtCtr>(0U)); - prev->m_next_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(te->m_next)); -#endif // ndef Q_UNSAFE - - // mark time event 'te' as NOT linked - te->m_flags &= - static_cast<std::uint8_t>(~QTE_FLAG_IS_LINKED); - // do NOT advance the prev pointer - - QS_BEGIN_PRE(QS_QF_TIMEEVT_AUTO_DISARM, act->m_prio) - QS_OBJ_PRE(te); // this time event object - QS_OBJ_PRE(act); // the target AO - QS_U8_PRE(tickRate); // tick rate - QS_END_PRE() - } - - QS_BEGIN_PRE(QS_QF_TIMEEVT_POST, act->m_prio) - QS_TIME_PRE(); // timestamp - QS_OBJ_PRE(te); // the time event object - QS_SIG_PRE(te->sig); // signal of this time event - QS_OBJ_PRE(act); // the target AO - QS_U8_PRE(tickRate); // tick rate - QS_END_PRE() - -#ifdef QXK_HPP_ - if (te->sig < Q_USER_SIG) { - QXThread::timeout_(act); - QF_MEM_APP(); - QF_CRIT_EXIT(); - } - else { - QF_MEM_APP(); - QF_CRIT_EXIT(); // exit crit. section before posting - - // act->POST() asserts if the queue overflows - act->POST(te, sender); - } -#else - QF_MEM_APP(); - QF_CRIT_EXIT(); // exit crit. section before posting - - // act->POST() asserts if the queue overflows - act->POST(te, sender); -#endif - } - else { // time event keeps timing out - --ctr; // decrement the tick counter - te->m_ctr = ctr; // update the original -#ifndef Q_UNSAFE - te->m_ctr_dis = static_cast<QTimeEvtCtr>(~ctr); -#endif // ndef Q_UNSAFE - - prev = te; // advance to this time event - - QF_MEM_APP(); - QF_CRIT_EXIT(); // exit crit. section to reduce latency - - // prevent merging critical sections, see NOTE above - QF_CRIT_EXIT_NOP(); - } - QF_CRIT_ENTRY(); // re-enter crit. section to continue the loop - QF_MEM_SYS(); -} - -Q_ENSURE_INCRIT(890, lbound > 0U); -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - - - - - - - - noexcept - - - - - - - - - - noexcept - - - // NOTE: this function must be called *inside* critical section -Q_REQUIRE_INCRIT(900, tickRate < QF_MAX_TICK_RATE); - -bool inactive; - -QF_MEM_SYS(); -if (timeEvtHead_[tickRate].m_next != nullptr) { - inactive = false; -} -else if (timeEvtHead_[tickRate].m_act != nullptr) { - inactive = false; -} -else { - inactive = true; -} -QF_MEM_APP(); - -return inactive; - - - - noexcept - return static_cast<QActive *>(m_act); - - - - noexcept - return static_cast<QTimeEvt *>(m_act); - - - - noexcept - : QEvt(0U), - m_next(nullptr), -#ifndef Q_UNSAFE - m_next_dis(static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr))), -#endif - m_act(nullptr), - m_ctr(0U), -#ifndef Q_UNSAFE - m_ctr_dis(static_cast<QTimeEvtCtr>(~static_cast<QTimeEvtCtr>(0U))), -#endif - m_interval(0U), - m_tickRate(0U), - m_flags(0U) - - - - = delete - - - - - - = delete - - - - - - - - - noexcept - - - : QActive(nullptr) - -// reuse m_head for tick-rate -m_eQueue.m_head = static_cast<QEQueueCtr>(tickRate); -#ifndef Q_UNSAFE -m_eQueue.m_head_dis = static_cast<QEQueueCtr>(~tickRate); -#endif // ndef Q_UNSAFE - - - - override - - - - - Q_UNUSED_PAR(e); -Q_UNUSED_PAR(qsId); - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -m_eQueue.m_tail = 0U; -#ifndef Q_UNSAFE -m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~0U); -#endif // ndef Q_UNSAFE - -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - override - - - this->init(nullptr, qsId); - - - - override - - - - - Q_UNUSED_PAR(e); -Q_UNUSED_PAR(qsId); - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -// get volatile into temporaries -QEQueueCtr nTicks = m_eQueue.m_tail; -QEQueueCtr const tickRate = m_eQueue.m_head; - -#ifndef Q_UNSAFE -Q_REQUIRE_INCRIT(700, nTicks > 0U); -Q_INVARIANT_INCRIT(701, nTicks - == static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis)); -Q_INVARIANT_INCRIT(702, tickRate - == static_cast<QEQueueCtr>(~m_eQueue.m_head_dis)); -#endif // ndef Q_UNSAFE - -m_eQueue.m_tail = 0U; // clear # ticks -#ifndef Q_UNSAFE -m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~0U); -#endif // ndef Q_UNSAFE - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -for (; nTicks > 0U; --nTicks) { - QTimeEvt::tick(static_cast<std::uint_fast8_t>(tickRate), - this); -} - - - - noexcept - - - #ifndef Q_SPY -Q_UNUSED_PAR(sender); -#endif - -static QEvt const tickEvt(0U); // immutable event - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -QEQueueCtr nTicks = m_eQueue.m_tail; // get volatile into temporary - -if (m_eQueue.m_frontEvt == nullptr) { -#ifndef Q_UNSAFE - Q_REQUIRE_INCRIT(800, nTicks == 0U); - Q_REQUIRE_INCRIT(801, m_eQueue.m_nFree == 1U); - Q_INVARIANT_INCRIT(802, m_eQueue.m_frontEvt_dis - == static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr))); - Q_INVARIANT_INCRIT(803, - 1U == static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis)); - Q_INVARIANT_INCRIT(804, - 0U == static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis)); -#endif // ndef Q_UNSAFE - - m_eQueue.m_frontEvt = &tickEvt; // deliver event directly - m_eQueue.m_nFree = 0U; -#ifndef Q_UNSAFE - m_eQueue.m_frontEvt_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(&tickEvt)); - m_eQueue.m_nFree_dis = static_cast<QEQueueCtr>(~0U); -#endif // ndef Q_UNSAFE - - QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue -} -else { -#ifndef Q_UNSAFE - Q_REQUIRE_INCRIT(810, (nTicks > 0U) && (nTicks < 0xFFU)); - Q_REQUIRE_INCRIT(811, m_eQueue.m_nFree == 0U); - Q_INVARIANT_INCRIT(812, m_eQueue.m_frontEvt_dis - == static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(&tickEvt))); - Q_INVARIANT_INCRIT(813, - 0U == static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis)); - Q_INVARIANT_INCRIT(814, - nTicks == static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis)); -#endif // ndef Q_UNSAFE -} - -++nTicks; // account for one more tick event - -m_eQueue.m_tail = nTicks; // update the original -#ifndef Q_UNSAFE -m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~nTicks); -#endif // ndef Q_UNSAFE - -QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_prio) - QS_TIME_PRE(); // timestamp - QS_OBJ_PRE(sender); // the sender object - QS_SIG_PRE(0U); // the signal of the event - QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(0U, 0U); // poolNum & refCtr - QS_EQC_PRE(0U); // # free entries - QS_EQC_PRE(0U); // min # free entries -QS_END_PRE() - -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // friends... - - - - - - - - - - noexcept - : m_frontEvt(nullptr), - m_ring(nullptr), - m_end(0U), - m_head(0U), - m_tail(0U), - m_nFree(0U), -#ifndef Q_UNSAFE - m_frontEvt_dis(static_cast<std::uintptr_t>(~0U)), - m_head_dis(static_cast<QEQueueCtr>(~0U)), - m_tail_dis(static_cast<QEQueueCtr>(~0U)), - m_nFree_dis(static_cast<QEQueueCtr>(~0U)), -#endif - m_nMin(0U) - - - - noexcept - - - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -#if (QF_EQUEUE_CTR_SIZE == 1U) -Q_REQUIRE_INCRIT(100, qLen < 0xFFU); -#endif - -m_frontEvt = nullptr; // no events in the queue -m_ring = &qSto[0]; -m_end = static_cast<QEQueueCtr>(qLen); -if (qLen > 0U) { - m_head = 0U; - m_tail = 0U; -} -m_nFree = static_cast<QEQueueCtr>(qLen + 1U); //+1 for frontEvt -m_nMin = m_nFree; - -#ifndef Q_UNSAFE -m_frontEvt_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(m_frontEvt)); -m_head_dis = static_cast<QEQueueCtr>(~m_head); -m_tail_dis = static_cast<QEQueueCtr>(~m_tail); -m_nFree_dis = static_cast<QEQueueCtr>(~m_nFree); -#endif - -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - noexcept - - - - - - - #ifndef Q_SPY -Q_UNUSED_PAR(qsId); -#endif - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(200, e != nullptr); -Q_INVARIANT_INCRIT(201, e->verify_()); - -QEQueueCtr tmp = m_nFree; // get volatile into temporary -#ifndef Q_UNSAFE -QEQueueCtr dis = static_cast<QEQueueCtr>(~m_nFree_dis); -Q_INVARIANT_INCRIT(201, tmp == dis); -#endif // ndef Q_UNSAFE - -// test-probe#1 for faking queue overflow -QS_TEST_PROBE_DEF(&QEQueue::post) -QS_TEST_PROBE_ID(1, - tmp = 0U; // fake no free events -) - -// required margin available? -bool status; -if (((margin == QF::NO_MARGIN) && (tmp > 0U)) - || (tmp > static_cast<QEQueueCtr>(margin))) -{ - // is it a mutable event? - if (e->getPoolNum_() != 0U) { - QEvt_refCtr_inc_(e); // increment the reference counter - } - - --tmp; // one free entry just used up - - m_nFree = tmp; // update the original -#ifndef Q_UNSAFE - m_nFree_dis = static_cast<QEQueueCtr>(~tmp); -#endif // ndef Q_UNSAFE - - if (m_nMin > tmp) { - m_nMin = tmp; // update minimum so far - } - - QS_BEGIN_PRE(QS_QF_EQUEUE_POST, qsId) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this queue object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); - QS_EQC_PRE(tmp); // # free entries - QS_EQC_PRE(m_nMin); // min # free entries - QS_END_PRE() - - if (m_frontEvt == nullptr) { // is the queue empty? - m_frontEvt = e; // deliver event directly -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(211, m_frontEvt_dis - == static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr))); - m_frontEvt_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(e)); -#endif // ndef Q_UNSAFE - } - else { // queue was not empty, insert event into the ring-buffer - tmp = m_head; // get volatile into temporary -#ifndef Q_UNSAFE - dis = static_cast<QEQueueCtr>(~m_head_dis); - Q_INVARIANT_INCRIT(212, tmp == dis); -#endif // ndef Q_UNSAFE - m_ring[tmp] = e; // insert e into buffer - - if (tmp == 0U) { // need to wrap the head? - tmp = m_end; - } - --tmp; // advance head (counter-clockwise) - - m_head = tmp; // update the original -#ifndef Q_UNSAFE - m_head_dis = static_cast<QEQueueCtr>(~tmp); -#endif // ndef Q_UNSAFE - } - status = true; // event posted successfully -} -else { // event cannot be posted - // dropping events must be acceptable - Q_ASSERT_INCRIT(210, margin != QF::NO_MARGIN); - - QS_BEGIN_PRE(QS_QF_EQUEUE_POST_ATTEMPT, qsId) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(e->sig); // the signal of this event - QS_OBJ_PRE(this); // this queue object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); - QS_EQC_PRE(tmp); // # free entries - QS_EQC_PRE(margin); // margin requested - QS_END_PRE() - - status = false; // event not posted -} - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -return status; - - - - noexcept - - - - - #ifndef Q_SPY -Q_UNUSED_PAR(qsId); -#endif - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(300, e != nullptr); -Q_INVARIANT_INCRIT(301, e->verify_()); - -QEQueueCtr tmp = m_nFree; // get volatile into temporary -#ifndef Q_UNSAFE -QEQueueCtr dis = static_cast<QEQueueCtr>(~m_nFree_dis); -Q_INVARIANT_INCRIT(301, tmp == dis); -#endif // ndef Q_UNSAFE - -// test-probe#1 for faking queue overflow -QS_TEST_PROBE_DEF(&QEQueue::postLIFO) -QS_TEST_PROBE_ID(1, - tmp = 0U; // fake no free events -) - -// must be able to LIFO-post the event -Q_REQUIRE_INCRIT(310, tmp != 0U); - -if (e->getPoolNum_() != 0U) { // is it a mutable event? - QEvt_refCtr_inc_(e); // increment the reference counter -} - ---tmp; // one free entry just used up - -m_nFree = tmp; // update the original -#ifndef Q_UNSAFE -m_nFree_dis = static_cast<QEQueueCtr>(~tmp); -#endif // ndef Q_UNSAFE - -if (m_nMin > tmp) { - m_nMin = tmp; // update minimum so far -} - -QS_BEGIN_PRE(QS_QF_EQUEUE_POST_LIFO, qsId) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(e->sig); // the signal of this event - QS_OBJ_PRE(this); // this queue object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); - QS_EQC_PRE(tmp); // # free entries - QS_EQC_PRE(m_nMin); // min # free entries -QS_END_PRE() - -QEvt const * const frontEvt = m_frontEvt; // read into temporary -m_frontEvt = e; // deliver the event directly to the front -#ifndef Q_UNSAFE -m_frontEvt_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(e)); -#endif // ndef Q_UNSAFE - -if (frontEvt != nullptr) { // was the queue NOT empty? - tmp = m_tail; // get volatile into temporary; -#ifndef Q_UNSAFE - dis = static_cast<QEQueueCtr>(~m_tail_dis); - Q_INVARIANT_INCRIT(311, tmp == dis); -#endif // ndef Q_UNSAFE - ++tmp; - if (tmp == m_end) { // need to wrap the tail? - tmp = 0U; // wrap around - } - m_tail = tmp; -#ifndef Q_UNSAFE - m_tail_dis = static_cast<QEQueueCtr>(~tmp); -#endif - m_ring[tmp] = frontEvt; -} - -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - noexcept - - - #ifndef Q_SPY -Q_UNUSED_PAR(qsId); -#endif - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -QEvt const * const e = m_frontEvt; // always remove evt from the front -#ifndef Q_UNSAFE -Q_INVARIANT_INCRIT(411, Q_PTR2UINT_CAST_(e) - == static_cast<std::uintptr_t>(~m_frontEvt_dis)); -#endif // ndef Q_UNSAFE - -if (e != nullptr) { // was the queue not empty? - QEQueueCtr tmp = m_nFree; // get volatile into temporary -#ifndef Q_UNSAFE - QEQueueCtr const dis = static_cast<QEQueueCtr>(~m_nFree_dis); - Q_INVARIANT_INCRIT(412, tmp == dis); -#endif // ndef Q_UNSAFE - - ++tmp; // one more free event in the queue - - m_nFree = tmp; // update the # free -#ifndef Q_UNSAFE - m_nFree_dis = static_cast<QEQueueCtr>(~tmp); -#endif // ndef Q_UNSAFE - - // any events in the ring buffer? - if (tmp <= m_end) { - - QS_BEGIN_PRE(QS_QF_EQUEUE_GET, qsId) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(e->sig); // the signal of this event - QS_OBJ_PRE(this); // this queue object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); - QS_EQC_PRE(tmp); // # free entries - QS_END_PRE() - - tmp = m_tail; // get volatile into temporary - QEvt const * const frontEvt = m_ring[tmp]; -#ifndef Q_UNSAFE - Q_ASSERT_INCRIT(421, frontEvt != nullptr); - m_frontEvt_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(frontEvt)); -#endif // ndef Q_UNSAFE - m_frontEvt = frontEvt; // update the original - - if (tmp == 0U) { // need to wrap the tail? - tmp = m_end; - } - --tmp; // advance the tail (counter-clockwise) - m_tail = tmp; // update the original -#ifndef Q_UNSAFE - m_tail_dis = static_cast<QEQueueCtr>(~tmp); -#endif // ndef Q_UNSAFE - } - else { - m_frontEvt = nullptr; // queue becomes empty -#ifndef Q_UNSAFE - m_frontEvt_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr)); -#endif // ndef Q_UNSAFE - - // all entries in the queue must be free (+1 for frontEvt) - Q_INVARIANT_INCRIT(440, tmp == (m_end + 1U)); - - QS_BEGIN_PRE(QS_QF_EQUEUE_GET_LAST, qsId) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(e->sig); // the signal of this event - QS_OBJ_PRE(this); // this queue object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); - QS_END_PRE() - } -} - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -return e; - - - - const noexcept - return m_nFree; - - - - const noexcept - #ifndef Q_UNSAFE -return m_nMin; -#else -return 0U; -#endif - - - - const noexcept - return m_frontEvt == nullptr; - - - - = delete - - - - - - = delete - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - : m_start(nullptr), - m_end(nullptr), - m_free_head(nullptr), - m_blockSize(0U), - m_nTot(0U), - m_nFree(0U) -#ifndef Q_UNSAFE - ,m_nMin(0U), - m_free_head_dis(static_cast<std::uintptr_t>(~0U)), - m_nFree_dis(static_cast<QEQueueCtr>(~0U)) -#endif - - - - noexcept - - - - - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(100, poolSto != nullptr); -Q_REQUIRE_INCRIT(101, - poolSize >= static_cast<std::uint_fast32_t>(sizeof(QFreeBlock))); -Q_REQUIRE_INCRIT(102, - static_cast<std::uint_fast16_t>(blockSize + sizeof(QFreeBlock)) - > blockSize); - -m_free_head = static_cast<QFreeBlock *>(poolSto); - -// find # free blocks in a memory block, NO DIVISION -m_blockSize = static_cast<QMPoolSize>(2U * sizeof(void *)); -std::uint_fast16_t nblocks = 1U; -while (m_blockSize < static_cast<QMPoolSize>(blockSize)) { - m_blockSize += static_cast<QMPoolSize>(sizeof(QFreeBlock)); - ++nblocks; -} - -// the pool buffer must fit at least one rounded-up block -Q_ASSERT_INCRIT(110, poolSize >= m_blockSize); - -// start at the head of the free list -QFreeBlock *fb = m_free_head; -std::uint32_t nTot = 1U; // the last block already in the list - -// chain all blocks together in a free-list... -for (std::uint_fast32_t size = poolSize - m_blockSize; - size >= static_cast<std::uint_fast32_t>(m_blockSize); - size -= static_cast<std::uint_fast32_t>(m_blockSize)) -{ - fb->m_next = &fb[nblocks]; // point next link to next block -#ifndef Q_UNSAFE - fb->m_next_dis = ~Q_PTR2UINT_CAST_(fb->m_next); -#endif - fb = fb->m_next; // advance to the next block - ++nTot; // one more free block in the pool -} - -// dynamic range check -#if (QF_MPOOL_CTR_SIZE == 1U) -Q_ENSURE_INCRIT(190, nTot < 0xFFU); -#elif (QF_MPOOL_CTR_SIZE == 2U) -Q_ENSURE_INCRIT(190, nTot < 0xFFFFU); -#endif - -fb->m_next = nullptr; // the last link points to NULL - -m_nTot = static_cast<QMPoolCtr>(nTot); -m_nFree = m_nTot; // all blocks are free -m_start = static_cast<QFreeBlock *>(poolSto); // original start -m_end = fb; // the last block in this pool - -#ifndef Q_UNSAFE -m_free_head_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(m_free_head)); -m_nFree_dis = static_cast<QMPoolCtr>(~m_nFree); -m_nMin = m_nTot; // the minimum # free blocks -fb->m_next_dis = ~Q_PTR2UINT_CAST_(fb->m_next); -#endif - -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - noexcept - - - - - #ifndef Q_SPY -Q_UNUSED_PAR(qsId); -#endif - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -// get volatile into temporaries -QFreeBlock *fb = m_free_head; -QMPoolCtr nFree = m_nFree; - -#ifndef Q_UNSAFE -Q_INVARIANT_INCRIT(301, Q_PTR2UINT_CAST_(fb) - == static_cast<std::uintptr_t>(~m_free_head_dis)); -Q_INVARIANT_INCRIT(302, nFree == static_cast<QMPoolCtr>(~m_nFree_dis)); -#endif // ndef Q_UNSAFE - -// have more free blocks than the requested margin? -if (nFree > static_cast<QMPoolCtr>(margin)) { - Q_ASSERT_INCRIT(310, fb != nullptr); - - QFreeBlock * const fb_next = fb->m_next; - -#ifndef Q_UNSAFE - // the free block must have integrity (duplicate inverse storage) - Q_INVARIANT_INCRIT(311, Q_PTR2UINT_CAST_(fb_next) - == static_cast<std::uintptr_t>(~fb->m_next_dis)); -#endif // ndef Q_UNSAFE - - --nFree; // one less free block - if (nFree == 0U) { // is the pool becoming empty? - // pool is becoming empty, so the next free block must be NULL - Q_ASSERT_INCRIT(320, fb_next == nullptr); - - m_nFree = 0U; -#ifndef Q_UNSAFE - m_nFree_dis = static_cast<QMPoolCtr>(~m_nFree); - m_nMin = 0U; // remember that the pool got empty -#endif // ndef Q_UNSAFE - } - else { - m_nFree = nFree; // update the original -#ifndef Q_UNSAFE - m_nFree_dis = static_cast<QMPoolCtr>(~nFree); - - // The pool is not empty, so the next free-block pointer - // must be in range. - Q_INVARIANT_INCRIT(330, - QF_PTR_RANGE_(fb_next, m_start, m_end)); - - // is the # free blocks the new minimum so far? - if (m_nMin > nFree) { - m_nMin = nFree; // remember the minimum so far - } -#endif // ndef Q_UNSAFE - } - - m_free_head = fb_next; // set the head to the next free block -#ifndef Q_UNSAFE - m_free_head_dis = - static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(fb_next)); -#endif // ndef Q_UNSAFE - - QS_BEGIN_PRE(QS_QF_MPOOL_GET, qsId) - QS_TIME_PRE(); // timestamp - QS_OBJ_PRE(this); // this memory pool - QS_MPC_PRE(nFree); // # of free blocks in the pool -#ifndef Q_UNSAFE - QS_MPC_PRE(m_nMin); // min # free blocks ever in the pool -#else - QS_MPC_PRE(0U); // min # free blocks (not available) -#endif // ndef Q_UNSAFE - QS_END_PRE() -} -else { // don't have enough free blocks at this point - fb = nullptr; - - QS_BEGIN_PRE(QS_QF_MPOOL_GET_ATTEMPT, qsId) - QS_TIME_PRE(); // timestamp - QS_OBJ_PRE(this); // this memory pool - QS_MPC_PRE(nFree); // # of free blocks in the pool - QS_MPC_PRE(margin); // the requested margin - QS_END_PRE() -} - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -return fb; // return the block or nullptr to the caller - - - - noexcept - - - - - #ifndef Q_SPY -Q_UNUSED_PAR(qsId); -#endif - -QFreeBlock * const fb = static_cast<QFreeBlock *>(block); - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -// get volatile into temporaries -QFreeBlock * const free_head = m_free_head; -QMPoolCtr nFree = m_nFree; - -#ifndef Q_UNSAFE -Q_INVARIANT_INCRIT(401, Q_PTR2UINT_CAST_(free_head) - == static_cast<std::uintptr_t>(~m_free_head_dis)); -Q_INVARIANT_INCRIT(402, nFree == static_cast<QMPoolCtr>(~m_nFree_dis)); - -Q_REQUIRE_INCRIT(410, nFree < m_nTot); -Q_REQUIRE_INCRIT(411, QF_PTR_RANGE_(fb, m_start, m_end)); - -// the block must not be in the pool already -Q_REQUIRE_INCRIT(412, Q_PTR2UINT_CAST_(fb->m_next) - != static_cast<std::uintptr_t>(~fb->m_next_dis)); -#endif // ndef Q_UNSAFE - -++nFree; // one more free block in this pool - -m_free_head = fb; // set as new head of the free list -m_nFree = nFree; -fb->m_next = free_head; // link into the list -#ifndef Q_UNSAFE -m_free_head_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(fb)); -m_nFree_dis = static_cast<QMPoolCtr>(~nFree); -fb->m_next_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(free_head)); -#endif - -QS_BEGIN_PRE(QS_QF_MPOOL_PUT, qsId) - QS_TIME_PRE(); // timestamp - QS_OBJ_PRE(this); // this memory pool - QS_MPC_PRE(nFree); // the # free blocks in the pool -QS_END_PRE() - -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - const noexcept - return m_blockSize; - - - - const noexcept - #ifndef Q_UNSAFE -return m_nMin; -#else -return 0U; -#endif - - - - const noexcept - return m_nFree; - - - - = delete - - - - - - = delete - - - - - - noexcept - - - - - - - - noexcept - - - - - - - - - - - - - - - - - - - - - - noexcept - - - - - std::uint8_t *ptr = static_cast<std::uint8_t *>(start); -for (std::uint_fast16_t n = len; n > 0U; --n) { - *ptr = 0U; - ++ptr; -} - - - - - - - - - - - - - - - - - noexcept - //! @deprecated - - - - - QActive::psInit(subscrSto, maxSignal); - - - - noexcept - //! @deprecated - - - - - - - QActive::publish_(e, sender, qsId); - - - - noexcept - //! @deprecated - - - - - QTimeEvt::tick(tickRate, sender); - - - - noexcept - //! @deprecated - - - return QActive::getQueueMin(prio); - - - - {0xFFFFU}; - - - - - - - noexcept - - - - - - - std::uint_fast8_t const poolNum = priv_.maxPool_; - -// see precondition{qf_dyn,200} and precondition{qf_dyn,201} -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(200, poolNum < QF_MAX_EPOOL); -if (poolNum > 0U) { - Q_REQUIRE_INCRIT(201, - QF_EPOOL_EVENT_SIZE_(priv_.ePool_[poolNum - 1U]) < evtSize); -} -priv_.maxPool_ = poolNum + 1U; // one more pool - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -// perform the port-dependent initialization of the event-pool -QF_EPOOL_INIT_(priv_.ePool_[poolNum], poolSto, poolSize, evtSize); - -#ifdef Q_SPY -// generate the object-dictionary entry for the initialized pool -{ - std::uint8_t obj_name[9] = "EvtPool?"; - obj_name[7] = static_cast<std::uint8_t>( - static_cast<std::uint8_t>('0') - + static_cast<std::uint8_t>(poolNum + 1U)); - QS::obj_dict_pre_(&priv_.ePool_[poolNum], - reinterpret_cast<char *>(&obj_name[0])); -} -#endif // Q_SPY - - - - noexcept - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); -std::uint_fast16_t const max_size = - QF_EPOOL_EVENT_SIZE_(priv_.ePool_[priv_.maxPool_ - 1U]); -QF_MEM_APP(); -QF_CRIT_EXIT(); - -return max_size; - - - - noexcept - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(400, (poolNum <= QF_MAX_EPOOL) - && (0U < poolNum) && (poolNum <= priv_.maxPool_)); - -std::uint_fast16_t const min = static_cast<std::uint_fast16_t>( - priv_.ePool_[poolNum - 1U].getNMin()); - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -return min; - - - - noexcept - - - - - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -// find the pool id that fits the requested event size... -std::uint_fast8_t poolNum = 0U; // zero-based poolNum initially -for (; poolNum < priv_.maxPool_; ++poolNum) { - if (evtSize <= QF_EPOOL_EVENT_SIZE_(priv_.ePool_[poolNum])) { - break; - } -} - -// precondition: -// - cannot run out of registered pools -Q_REQUIRE_INCRIT(300, poolNum < priv_.maxPool_); - -++poolNum; // convert to 1-based poolNum - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -// get event e (port-dependent)... -QEvt *e; -#ifdef Q_SPY -QF_EPOOL_GET_(priv_.ePool_[poolNum - 1U], e, - ((margin != NO_MARGIN) ? margin : 0U), - static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum); -#else -QF_EPOOL_GET_(priv_.ePool_[poolNum - 1U], e, - ((margin != NO_MARGIN) ? margin : 0U), 0U); -#endif - -if (e != nullptr) { // was e allocated correctly? - e->sig = static_cast<QSignal>(sig); // set the signal - e->evtTag_ = static_cast<std::uint8_t>((poolNum << 4U) | 0x0FU); - e->refCtr_ = 0U; // initialize the reference counter to 0 - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QF_NEW, - static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum) - QS_TIME_PRE(); // timestamp - QS_EVS_PRE(evtSize); // the size of the event - QS_SIG_PRE(sig); // the signal of the event - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); -} -else { // event was not allocated - - QF_CRIT_ENTRY(); - // This assertion means that the event allocation failed, - // and this failure cannot be tolerated. The most frequent - // reason is an event leak in the application. - Q_ASSERT_INCRIT(320, margin != NO_MARGIN); - - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QF_NEW_ATTEMPT, - static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum) - QS_TIME_PRE(); // timestamp - QS_EVS_PRE(evtSize); // the size of the event - QS_SIG_PRE(sig); // the signal of the event - QS_END_PRE() - QS_MEM_APP(); - - QF_CRIT_EXIT(); -} - -// the returned event e is guaranteed to be valid (not NULL) -// if we can't tolerate failed allocation -return e; - - - - noexcept - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(400, e != nullptr); -Q_INVARIANT_INCRIT(401, e->verify_()); - -std::uint_fast8_t const poolNum = e->getPoolNum_(); - -if (poolNum != 0U) { // is it a pool event (mutable)? - QF_MEM_SYS(); - - if (e->refCtr_ > 1U) { // isn't this the last reference? - - QS_BEGIN_PRE(QS_QF_GC_ATTEMPT, - static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_2U8_PRE(poolNum, e->refCtr_); - QS_END_PRE() - - QEvt_refCtr_dec_(e); // decrement the ref counter - - QF_MEM_APP(); - QF_CRIT_EXIT(); - } - else { // this is the last reference to this event, recycle it - - QS_BEGIN_PRE(QS_QF_GC, - static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_2U8_PRE(poolNum, e->refCtr_); - QS_END_PRE() - - // pool number must be in range - Q_ASSERT_INCRIT(410, (poolNum <= priv_.maxPool_) - && (poolNum <= QF_MAX_EPOOL)); - QF_MEM_APP(); - QF_CRIT_EXIT(); - - // NOTE: casting 'const' away is legit because it's a pool event -#ifdef Q_SPY - QF_EPOOL_PUT_(priv_.ePool_[poolNum - 1U], - QF_CONST_CAST_(QEvt*, e), - static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum); -#else - QF_EPOOL_PUT_(priv_.ePool_[poolNum - 1U], - QF_CONST_CAST_(QEvt*, e), 0U); -#endif - } -} -else { - QF_CRIT_EXIT(); -} - - - - noexcept - - - - - #ifdef Q_UNSAFE -Q_UNUSED_PAR(evtRef); -#endif - -QF_CRIT_STAT -QF_CRIT_ENTRY(); - -Q_REQUIRE_INCRIT(500, e != nullptr); -Q_INVARIANT_INCRIT(501, e->verify_()); - -std::uint_fast8_t const poolNum = e->getPoolNum_(); -Q_UNUSED_PAR(poolNum); // might be unused - -Q_REQUIRE_INCRIT(501, (poolNum != 0U) - && (evtRef == nullptr)); - -QEvt_refCtr_inc_(e); // increments the ref counter - -QS_MEM_SYS(); -QS_BEGIN_PRE(QS_QF_NEW_REF, - static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_2U8_PRE(poolNum, e->refCtr_); -QS_END_PRE() -QS_MEM_APP(); - -QF_CRIT_EXIT(); - -return e; - - - - noexcept - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); - -QEvt const * const e = evtRef; -Q_REQUIRE_INCRIT(600, e != nullptr); -Q_INVARIANT_INCRIT(601, e->verify_()); - -#ifdef Q_SPY -std::uint_fast8_t const poolNum = e->getPoolNum_(); -#endif - -QS_MEM_SYS(); -QS_BEGIN_PRE(QS_QF_DELETE_REF, - static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum) - QS_TIME_PRE(); // timestamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_2U8_PRE(poolNum, e->refCtr_); -QS_END_PRE() -QS_MEM_APP(); - -QF_CRIT_EXIT(); - -#if (QF_MAX_EPOOL > 0U) -gc(e); // recycle the referenced event -#endif - - - - - - return static_cast<evtT_*>( - QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, sig)); - - - - - - - - evtT_ *e = static_cast<evtT_*>( - QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, sig)); -e->init(args...); // e cannot be nullptr -return e; - - - - - - - - return static_cast<evtT_*>(QP::QF::newX_(sizeof(evtT_), margin, sig)); - - - - - - - - - - evtT_ *e = static_cast<evtT_*>(QP::QF::newX_(sizeof(evtT_), margin, sig)); -if (e != nullptr) { - e->init(args...); -} -return e; - - - - - - - - evtRef = static_cast<evtT_ const *>(QP::QF::newRef_(e, evtRef)); - - - - - - QP::QF::deleteRef_(evtRef); -evtRef = nullptr; - - - - noexcept - - - - - - - - - - noexcept - - - - - - - - - - - - - - - - - - - - - - - - \ - (static_cast<QP::QPrioSpec>((prio_) | (pthre_) << 8U)) - - - - - - - - (QP::QF::q_new<evtT_>((sig_))) - - - - - - - - - - (QP::QF::q_new<evtT_>((sig_), __VA_ARGS__)) - - - - - - - - - - (QP::QF::q_new_x<evtT_>((margin_), (sig_))) - - - - - - - - - - - - (QP::QF::q_new_x<evtT_>((margin_), (sig_), __VA_ARGS__)) - - - - - - - - (QP::QF::q_new_ref<evtT_>(e, (evtRef_))) - - - - - - do { \ - QP::QF::deleteRef_((evtRef_)); \ - (evtRef_) = nullptr; \ -} while (false) - - - - - - - - \ - publish_((e_), (sender_), (sender_)->getPrio()) - - - - - - - - publish_((e_), nullptr, 0U) - - - - - - - - post_((e_), QP::QF::NO_MARGIN, (sender_)) - - - - - - - - post_((e_), QP::QF::NO_MARGIN, nullptr) - - - - - - - - - - \ - post_((e_), (margin_), (sender_)) - - - - - - - - - - post_((e_), (margin_), nullptr) - - - - - - - - tick((tickRate_), (sender_)) - - - - - - - - tick((tickRate_), nullptr) - - - - - - TICK_X(0U, (sender_)) - - - - - - trig_((sender_)) - - - - - - trig_(nullptr) - - - - (static_cast<void>(0)) - - - - (static_cast<void>(0)) - - - - (static_cast<void>(0)) - - - - - - - Native QF event pool - QMPool - - - - Native QF event pool initialization - - - - - - - - - \ - (p_).init((poolSto_), (poolSize_), (evtSize_)) - - - - Native QF event pool event-size getter - - - ((p_).getBlockSize()) - - - - Native QF event pool get-event - - - - - - - - - \ - ((e_) = static_cast<QEvt *>((p_).get((m_), (qsId_)))) - - - - Native QF event pool put-event - - - - - - - ((p_).put((e_), (qsId_))) - - - - - - - - - - - - - - - - - - - - - - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_INVARIANT_INCRIT(102, priv_.schedCeil - == static_cast<std::uint_fast8_t>(~priv_.schedCeil_dis)); - -if (ceiling > priv_.schedCeil) { // raising the scheduler ceiling? - - QS_BEGIN_PRE(QS_SCHED_LOCK, 0U) - QS_TIME_PRE(); // timestamp - // the previous sched ceiling & new sched ceiling - QS_2U8_PRE(static_cast<std::uint8_t>(priv_.schedCeil), - static_cast<std::uint8_t>(ceiling)); - QS_END_PRE() - - priv_.schedCeil = ceiling; -#ifndef Q_UNSAFE - priv_.schedCeil_dis = static_cast<std::uint_fast8_t>(~ceiling); -#endif -} -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_INVARIANT_INCRIT(202, priv_.schedCeil - == static_cast<std::uint_fast8_t>(~priv_.schedCeil_dis)); - -if (priv_.schedCeil != 0U) { // actually enabling the scheduler? - - QS_BEGIN_PRE(QS_SCHED_UNLOCK, 0U) - QS_TIME_PRE(); // timestamp - // current sched ceiling (old), previous sched ceiling (new) - QS_2U8_PRE(static_cast<std::uint8_t>(priv_.schedCeil), 0U); - QS_END_PRE() - - priv_.schedCeil = 0U; -#ifndef Q_UNSAFE - priv_.schedCeil_dis = ~static_cast<std::uint_fast8_t>(0U); -#endif -} -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - - - - - - bzero_(&QF::priv_, sizeof(QF::priv_)); -bzero_(&QV::priv_, sizeof(QV::priv_)); -bzero_(&QActive::registry_[0], sizeof(QActive::registry_)); - -#ifndef Q_UNSAFE -QV::priv_.readySet.update_(&QV::priv_.readySet_dis); -QV::priv_.schedCeil_dis = ~static_cast<std::uint_fast8_t>(0U); -#endif - -#ifdef QV_INIT -QV_INIT(); // port-specific initialization of the QV kernel -#endif - - - - onCleanup(); // cleanup callback -// nothing else to do for the QV kernel - - - - #ifdef Q_SPY -// produce the QS_QF_RUN trace record -QF_INT_DISABLE(); -QF_MEM_SYS(); -QS::beginRec_(QS_REC_NUM_(QS_QF_RUN)); -QS::endRec_(); -QF_MEM_APP(); -QF_INT_ENABLE(); -#endif // Q_SPY - -onStartup(); // application-specific startup callback - -QF_INT_DISABLE(); -QF_MEM_SYS(); - -#ifdef QV_START -QV_START(); // port-specific startup of the QV kernel -#endif - -#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) -std::uint_fast8_t pprev = 0U; // previous prio. - -#ifdef QF_ON_CONTEXT_SW -// officially switch to the idle cotext -QF_onContextSw(nullptr, nullptr); -#endif // def QF_ON_CONTEXT_SW - -#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - -for (;;) { // QV event loop... - - // check internal integrity (duplicate inverse storage) - Q_INVARIANT_INCRIT(302, - QV::priv_.readySet.verify_(&QV::priv_.readySet_dis)); - // check internal integrity (duplicate inverse storage) - Q_INVARIANT_INCRIT(303, QV::priv_.schedCeil - == static_cast<std::uint_fast8_t>(~QV::priv_.schedCeil_dis)); - - // find the maximum prio. AO ready to run - std::uint_fast8_t const p = (QV::priv_.readySet.notEmpty() - ? QV::priv_.readySet.findMax() - : 0U); - - if (p > QV::priv_.schedCeil) { // is it above the sched ceiling? - QActive * const a = QActive::registry_[p]; - -#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - QS_BEGIN_PRE(QS_SCHED_NEXT, p) - QS_TIME_PRE(); // timestamp - QS_2U8_PRE(static_cast<std::uint8_t>(p), - static_cast<std::uint8_t>(pprev)); - QS_END_PRE() - -#ifdef QF_ON_CONTEXT_SW - QF_onContextSw(((pprev != 0U) - ? QActive::registry_[pprev] - : nullptr), a); -#endif // QF_ON_CONTEXT_SW - - pprev = p; // update previous prio. -#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - - QF_MEM_APP(); - QF_INT_ENABLE(); - - QEvt const * const e = a->get_(); - // NOTE QActive::get_() performs QF_MEM_APP() before return - - // dispatch event (virtual call) - a->dispatch(e, a->getPrio()); -#if (QF_MAX_EPOOL > 0U) - gc(e); -#endif - QF_INT_DISABLE(); - QF_MEM_SYS(); - - if (a->getEQueue().isEmpty()) { // empty queue? - QV::priv_.readySet.remove(p); -#ifndef Q_UNSAFE - QV::priv_.readySet.update_(&QV::priv_.readySet_dis); -#endif - } - } - else { // no AO ready to run --> idle -#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - if (pprev != 0U) { - QS_BEGIN_PRE(QS_SCHED_IDLE, pprev) - QS_TIME_PRE(); // timestamp - QS_U8_PRE(static_cast<std::uint8_t>(pprev)); - QS_END_PRE() - -#ifdef QF_ON_CONTEXT_SW - QF_onContextSw(QActive::registry_[pprev], nullptr); -#endif // QF_ON_CONTEXT_SW - - pprev = 0U; // update previous prio - } -#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - - QF_MEM_APP(); - - // QV::onIdle() must be called with interrupts DISABLED - // because the determination of the idle condition (all event - // queues empty) can change at any time by an interrupt posting - // events to a queue. - // - // NOTE: QV::onIdle() MUST enable interrupts internally, - // ideally at the same time as putting the CPU into a power- - // saving mode. - QV::onIdle(); - - QF_INT_DISABLE(); - QF_MEM_SYS(); - } -} -#ifdef __GNUC__ // GNU compiler? -return 0; -#endif - - - - - - - - - - - - - - - - - - - Q_UNUSED_PAR(stkSto); // not needed in QV -Q_UNUSED_PAR(stkSize); // not needed in QV - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(300, stkSto == nullptr); -QF_CRIT_EXIT(); - -m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU); // QF-prio. -m_pthre = 0U; // not used -register_(); // make QF aware of this AO - -m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO - -this->init(par, m_prio); // take the top-most initial tran. (virtual) -QS_FLUSH(); // flush the trace buffer to the host - - - - - - - - - - - - (static_cast<void>(0)) - - - - (static_cast<void>(0)) - - - - - - (static_cast<void>(0)) - - - - - - \ - QV::priv_.readySet.insert((me_)->m_prio); \ - QV::priv_.readySet.update_(&QV::priv_.readySet_dis) - - - - - - \ - (QV::priv_.readySet.insert((me_)->m_prio)) - - - - - - - = std::uint_fast8_t; - - - - - - noexcept - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(100, !QK_ISR_CONTEXT_()); -Q_INVARIANT_INCRIT(102, QK_priv_.lockCeil - == static_cast<std::uint_fast8_t>(~QK_priv_.lockCeil_dis)); - -// first store the previous lock prio -QSchedStatus stat; -if (ceiling > QK_priv_.lockCeil) { // raising the lock ceiling? - QS_BEGIN_PRE(QS_SCHED_LOCK, QK_priv_.actPrio) - QS_TIME_PRE(); // timestamp - // the previous lock ceiling & new lock ceiling - QS_2U8_PRE(static_cast<std::uint8_t>(QK_priv_.lockCeil), - static_cast<std::uint8_t>(ceiling)); - QS_END_PRE() - - // previous status of the lock - stat = static_cast<QSchedStatus>(QK_priv_.lockCeil); - - // new status of the lock - QK_priv_.lockCeil = ceiling; -#ifndef Q_UNSAFE - QK_priv_.lockCeil_dis = static_cast<std::uint_fast8_t>(~ceiling); -#endif -} -else { - stat = 0xFFU; // scheduler not locked -} - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -return stat; // return the status to be saved in a stack variable - - - - noexcept - - - // has the scheduler been actually locked by the last QK::schedLock()? -if (prevCeil != 0xFFU) { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - Q_INVARIANT_INCRIT(202, QK_priv_.lockCeil - == static_cast<std::uint_fast8_t>(~QK_priv_.lockCeil_dis)); - Q_REQUIRE_INCRIT(210, (!QK_ISR_CONTEXT_()) - && (QK_priv_.lockCeil > prevCeil)); - - QS_BEGIN_PRE(QS_SCHED_UNLOCK, QK_priv_.actPrio) - QS_TIME_PRE(); // timestamp - // current lock ceiling (old), previous lock ceiling (new) - QS_2U8_PRE(static_cast<std::uint8_t>(QK_priv_.lockCeil), - static_cast<std::uint8_t>(prevCeil)); - QS_END_PRE() - - // restore the previous lock ceiling - QK_priv_.lockCeil = prevCeil; -#ifndef Q_UNSAFE - QK_priv_.lockCeil_dis = static_cast<std::uint_fast8_t>(~prevCeil); -#endif - - // find if any AOs should be run after unlocking the scheduler - if (QK_sched_() != 0U) { // preemption needed? - QK_activate_(); // activate any unlocked AOs - } - - QF_MEM_APP(); - QF_CRIT_EXIT(); -} - - - - - - - - - bzero_(&QF::priv_, sizeof(QF::priv_)); -bzero_(&QK_priv_, sizeof(QK_priv_)); -bzero_(&QActive::registry_[0], sizeof(QActive::registry_)); - -// setup the QK scheduler as initially locked and not running -QK_priv_.lockCeil = (QF_MAX_ACTIVE + 1U); // scheduler locked - -#ifndef Q_UNSAFE -QK_priv_.readySet.update_(&QK_priv_.readySet_dis); -QK_priv_.actPrio_dis = static_cast<std::uint_fast8_t>(~QK_priv_.actPrio); -QK_priv_.nextPrio_dis = static_cast<std::uint_fast8_t>(~QK_priv_.nextPrio); -QK_priv_.actThre_dis = static_cast<std::uint_fast8_t>(~QK_priv_.actThre); -QK_priv_.lockCeil_dis = static_cast<std::uint_fast8_t>(~QK_priv_.lockCeil); -#endif - -#ifdef QK_INIT -QK_INIT(); // port-specific initialization of the QK kernel -#endif - - - - onCleanup(); // cleanup callback -// nothing else to do for the QK preemptive kernel - - - - #ifdef Q_SPY -// produce the QS_QF_RUN trace record -QF_INT_DISABLE(); -QF_MEM_SYS(); -QS::beginRec_(QS_REC_NUM_(QS_QF_RUN)); -QS::endRec_(); -QF_MEM_APP(); -QF_INT_ENABLE(); -#endif // Q_SPY - -onStartup(); // application-specific startup callback - -QF_INT_DISABLE(); -QF_MEM_SYS(); - -#ifdef QK_START -QK_START(); // port-specific startup of the QK kernel -#endif - -QK_priv_.lockCeil = 0U; // unlock the QK scheduler -#ifndef Q_UNSAFE -QK_priv_.lockCeil_dis = static_cast<std::uint_fast8_t>(~QK_priv_.lockCeil); -#endif - -#ifdef QF_ON_CONTEXT_SW -// officially switch to the idle context -QF_onContextSw(nullptr, QActive::registry_[QK_priv_.nextPrio]); -#endif - -// activate AOs to process events posted so far -if (QK_sched_() != 0U) { - QK_activate_(); -} - -QF_MEM_APP(); -QF_INT_ENABLE(); - -for (;;) { // QK idle loop... - QK::onIdle(); // application-specific QK on-idle callback -} - -#ifdef __GNUC__ // GNU compiler? -return 0; -#endif - - - - - - - - - - - - - - - - - - - Q_UNUSED_PAR(stkSto); // not needed in QK -Q_UNUSED_PAR(stkSize); // not needed in QK - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(300, (!QK_ISR_CONTEXT_()) - && (stkSto == nullptr)); -QF_MEM_APP(); -QF_CRIT_EXIT(); - -m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU); // QF-prio. -m_pthre = static_cast<std::uint8_t>(prioSpec >> 8U); // preemption-thre. -register_(); // make QF aware of this AO - -m_eQueue.init(qSto, qLen); // init the built-in queue - -// top-most initial tran. (virtual call) -this->init(par, m_prio); -QS_FLUSH(); // flush the trace buffer to the host - -// See if this AO needs to be scheduled if QK is already running -QF_CRIT_ENTRY(); -QF_MEM_SYS(); -if (QK_sched_() != 0U) { // activation needed? - QK_activate_(); -} -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - noexcept - // NOTE: this function is entered with interrupts DISABLED - -Q_INVARIANT_INCRIT(402, - QK_priv_.readySet.verify_(&QK_priv_.readySet_dis)); - -std::uint_fast8_t p; -if (QK_priv_.readySet.isEmpty()) { - p = 0U; // no activation needed -} -else { - // find the highest-prio AO with non-empty event queue - p = QK_priv_.readySet.findMax(); - - Q_INVARIANT_INCRIT(412, QK_priv_.actThre - == static_cast<std::uint_fast8_t>(~QK_priv_.actThre_dis)); - - // is the AO's prio. below the active preemption-threshold? - if (p <= QK_priv_.actThre) { - p = 0U; // no activation needed - } - else { - Q_INVARIANT_INCRIT(422, QK_priv_.lockCeil - == static_cast<std::uint_fast8_t>(~QK_priv_.lockCeil_dis)); - - // is the AO's prio. below the lock-ceiling? - if (p <= QK_priv_.lockCeil) { - p = 0U; // no activation needed - } - else { - Q_INVARIANT_INCRIT(432, QK_priv_.nextPrio - == static_cast<std::uint_fast8_t>(~QK_priv_.nextPrio_dis)); - QK_priv_.nextPrio = p; // next AO to run -#ifndef Q_UNSAFE - QK_priv_.nextPrio_dis - = static_cast<std::uint_fast8_t>(~QK_priv_.nextPrio); -#endif - } - } -} - -return p; - - - - noexcept - // NOTE: this function is entered with interrupts DISABLED - -std::uint_fast8_t const prio_in = QK_priv_.actPrio; // save initial prio. -std::uint_fast8_t p = QK_priv_.nextPrio; // next prio to run - -Q_INVARIANT_INCRIT(502, - (prio_in == static_cast<std::uint_fast8_t>(~QK_priv_.actPrio_dis)) - && (p == static_cast<std::uint_fast8_t>(~QK_priv_.nextPrio_dis))); -Q_REQUIRE_INCRIT(510, (prio_in <= QF_MAX_ACTIVE) - && (0U < p) && (p <= QF_MAX_ACTIVE)); - -#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) -std::uint_fast8_t pprev = prio_in; -#endif // QF_ON_CONTEXT_SW || Q_SPY - -QK_priv_.nextPrio = 0U; // clear for the next time -#ifndef Q_UNSAFE -QK_priv_.nextPrio_dis = static_cast<std::uint_fast8_t>(~QK_priv_.nextPrio); -#endif - -std::uint_fast8_t pthre_in; -QP::QActive *a; -if (prio_in == 0U) { // preempting the idle thread? - pthre_in = 0U; -} -else { - a = QP::QActive::registry_[prio_in]; - Q_ASSERT_INCRIT(510, a != nullptr); - - pthre_in = static_cast<std::uint_fast8_t>(a->getPThre()); - Q_INVARIANT_INCRIT(511, pthre_in == static_cast<std::uint_fast8_t>( - ~static_cast<std::uint_fast8_t>(a->m_pthre_dis) & 0xFFU)); -} - -// loop until no more ready-to-run AOs of higher pthre than the initial -do { - a = QP::QActive::registry_[p]; // obtain the pointer to the AO - Q_ASSERT_INCRIT(520, a != nullptr); // the AO must be registered - std::uint_fast8_t const pthre - = static_cast<std::uint_fast8_t>(a->getPThre()); - Q_INVARIANT_INCRIT(522, pthre == static_cast<std::uint_fast8_t>( - ~static_cast<std::uint_fast8_t>(a->m_pthre_dis) & 0xFFU)); - - // set new active prio. and preemption-threshold - QK_priv_.actPrio = p; - QK_priv_.actThre = pthre; -#ifndef Q_UNSAFE - QK_priv_.actPrio_dis = static_cast<std::uint_fast8_t>(~p); - QK_priv_.actThre_dis = static_cast<std::uint_fast8_t>(~pthre); -#endif - -#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - if (p != pprev) { // changing threads? - - QS_BEGIN_PRE(QP::QS_SCHED_NEXT, p) - QS_TIME_PRE(); // timestamp - QS_2U8_PRE(p, // prio. of the scheduled AO - pprev); // previous prio. - QS_END_PRE() - -#ifdef QF_ON_CONTEXT_SW - QF_onContextSw(QP::QActive::registry_[pprev], a); -#endif // QF_ON_CONTEXT_SW - - pprev = p; // update previous prio. - } -#endif // QF_ON_CONTEXT_SW || Q_SPY - - QF_MEM_APP(); - QF_INT_ENABLE(); // unconditionally enable interrupts - - QP::QEvt const * const e = a->get_(); - // NOTE QActive_get_() performs QF_MEM_APP() before return - - // dispatch event (virtual call) - a->dispatch(e, a->getPrio()); -#if (QF_MAX_EPOOL > 0U) - QP::QF::gc(e); -#endif - - // determine the next highest-prio. AO ready to run... - QF_INT_DISABLE(); // unconditionally disable interrupts - QF_MEM_SYS(); - - // internal integrity check (duplicate inverse storage) - Q_INVARIANT_INCRIT(532, - QK_priv_.readySet.verify_(&QK_priv_.readySet_dis)); - - if (a->getEQueue().isEmpty()) { // empty queue? - QK_priv_.readySet.remove(p); -#ifndef Q_UNSAFE - QK_priv_.readySet.update_(&QK_priv_.readySet_dis); -#endif - } - - if (QK_priv_.readySet.isEmpty()) { - p = 0U; // no activation needed - } - else { - // find new highest-prio AO ready to run... - p = QK_priv_.readySet.findMax(); - - // is the new prio. below the initial preemption-threshold? - if (p <= pthre_in) { - p = 0U; // no activation needed - } - else { - Q_INVARIANT_INCRIT(542, - QK_priv_.lockCeil == ~QK_priv_.lockCeil_dis); - - // is the AO's prio. below the lock preemption-threshold? - if (p <= QK_priv_.lockCeil) { - p = 0U; // no activation needed - } - else { - Q_ASSERT_INCRIT(550, p <= QF_MAX_ACTIVE); - } - } - } -} while (p != 0U); - -// restore the active prio. and preemption-threshold -QK_priv_.actPrio = prio_in; -QK_priv_.actThre = pthre_in; -#ifndef Q_UNSAFE -QK_priv_.actPrio_dis = static_cast<std::uint_fast8_t>(~QK_priv_.actPrio); -QK_priv_.actThre_dis = static_cast<std::uint_fast8_t>(~QK_priv_.actThre); -#endif - -#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) -if (prio_in != 0U) { // resuming an active object? - a = QP::QActive::registry_[prio_in]; // pointer to preempted AO - - QS_BEGIN_PRE(QP::QS_SCHED_NEXT, prio_in) - QS_TIME_PRE(); // timestamp - // prio. of the resumed AO, previous prio. - QS_2U8_PRE(prio_in, pprev); - QS_END_PRE() -} -else { // resuming prio.==0 --> idle - a = nullptr; // QK idle loop - - QS_BEGIN_PRE(QP::QS_SCHED_IDLE, pprev) - QS_TIME_PRE(); // timestamp - QS_U8_PRE(pprev); // previous prio. - QS_END_PRE() -} - -#ifdef QF_ON_CONTEXT_SW -QF_onContextSw(QP::QActive::registry_[pprev], a); -#endif // QF_ON_CONTEXT_SW - -#endif // QF_ON_CONTEXT_SW || Q_SPY - - - - - - - QSchedStatus lockStat_; - - - - - - do { \ - if (QK_ISR_CONTEXT_()) { \ - lockStat_ = 0xFFU; \ - } else { \ - lockStat_ = QK::schedLock((ceil_)); \ - } \ -} while (false) - - - - do { \ - if (lockStat_ != 0xFFU) { \ - QK::schedUnlock(lockStat_); \ - } \ -} while (false) - - - - - - (static_cast<void>(0)) - - - - - - do { \ - QK_priv_.readySet.insert( \ - static_cast<std::uint_fast8_t>((me_)->m_prio)); \ - QK_priv_.readySet.update_(&QK_priv_.readySet_dis); \ - if (!QK_ISR_CONTEXT_()) { \ - if (QK_sched_() != 0U) { \ - QK_activate_(); \ - } \ - } \ -} while (false) - - - - - - do { \ - QK_priv_.readySet.insert( \ - static_cast<std::uint_fast8_t>((me_)->m_prio)); \ - if (!QK_ISR_CONTEXT_()) { \ - if (QK_sched_() != 0U) { \ - QK_activate_(); \ - } \ - } \ -} while (false) - - - - - - - #ifndef QP_HPP_ -#define QP_HPP_ - -//============================================================================ -#define QP_VERSION_STR "8.0.1" -#define QP_VERSION 801U -#define QP_RELEASE 0x703931CEU - -//============================================================================ -//! @cond INTERNAL - -#ifndef Q_SIGNAL_SIZE -#define Q_SIGNAL_SIZE 2U -#endif - -#ifndef QF_MAX_ACTIVE -#define QF_MAX_ACTIVE 32U -#endif - -#if (QF_MAX_ACTIVE > 64U) -#error QF_MAX_ACTIVE exceeds the maximum of 64U; -#endif - -#ifndef QF_MAX_TICK_RATE -#define QF_MAX_TICK_RATE 1U -#endif - -#if (QF_MAX_TICK_RATE > 15U) -#error QF_MAX_TICK_RATE exceeds the maximum of 15U; -#endif - -#ifndef QF_MAX_EPOOL -#define QF_MAX_EPOOL 3U -#endif - -#if (QF_MAX_EPOOL > 15U) -#error QF_MAX_EPOOL exceeds the maximum of 15U; -#endif - -#ifndef QF_TIMEEVT_CTR_SIZE -#define QF_TIMEEVT_CTR_SIZE 4U -#endif - -#if (QF_TIMEEVT_CTR_SIZE > 4U) -#error QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U; -#endif - -#ifndef QF_EVENT_SIZ_SIZE -#define QF_EVENT_SIZ_SIZE 2U -#endif - -#if (QF_EVENT_SIZ_SIZE > 4U) -#error QF_EVENT_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U; -#endif - -//! @endcond -//============================================================================ - -$declare ${glob-types} - -$declare ${QEP} - -$declare ${QEP-macros} - -$declare ${QF::types} - -$declare ${QF::QActive} - -$declare ${QF::QMActive} - -$declare ${QF::QTimeEvt} - -$declare ${QF::QTicker} - -$declare ${QF::QF-base} - -$declare ${QF::QF-dyn} - -extern "C" { -$declare ${QF-extern-C} -} // extern "C" - -$declare ${QF-macros} - -#endif // QP_HPP_ - - - - #ifndef QP_PKG_HPP_ -#define QP_PKG_HPP_ - -$declare ${QF::QF-pkg} - -#define QF_CONST_CAST_(type_, ptr_) const_cast<type_>(ptr_) -#define Q_PTR2UINT_CAST_(ptr_) (reinterpret_cast<std::uintptr_t>(ptr_)) -#define QF_PTR_RANGE_(x_, min_, max_) (((min_) <= (x_)) && ((x_) <= (max_))) - -namespace QP { - -// Bitmasks are for the QTimeEvt::flags attribute -constexpr std::uint8_t QTE_FLAG_IS_LINKED {1U << 7U}; -constexpr std::uint8_t QTE_FLAG_WAS_DISARMED {1U << 6U}; - -inline void QEvt_refCtr_inc_(QEvt const * const e) noexcept { - std::uint8_t rc = e->refCtr_ + 1U; - (QF_CONST_CAST_(QEvt*, e))->refCtr_ = rc; // cast away 'const' -#ifndef Q_UNSAFE - (QF_CONST_CAST_(QEvt*, e))->evtTag_ = (e->evtTag_ & 0xF0U) | ((~rc) & 0x0FU); -#endif -} - -inline void QEvt_refCtr_dec_(QEvt const * const e) noexcept { - std::uint8_t rc = e->refCtr_ - 1U; - (QF_CONST_CAST_(QEvt*, e))->refCtr_ = rc; // cast away 'const' -#ifndef Q_UNSAFE - (QF_CONST_CAST_(QEvt*, e))->evtTag_ = (e->evtTag_ & 0xF0U) | ((~rc) & 0x0FU); -#endif -} - -} // namespace QP - -#endif // QP_PKG_HPP_ - - - - #ifndef QEQUEUE_HPP_ -#define QEQUEUE_HPP_ - -#ifndef QF_EQUEUE_CTR_SIZE - #define QF_EQUEUE_CTR_SIZE 1U -#endif - -namespace QP { - -#if (QF_EQUEUE_CTR_SIZE == 1U) - using QEQueueCtr = std::uint8_t; -#elif (QF_EQUEUE_CTR_SIZE == 2U) - using QEQueueCtr = std::uint16_t; -#else - #error "QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1U or 2U" -#endif - -class QEvt; // forward declaration - -} // namespace QP - -$declare ${QF::QEQueue} - -#endif // QEQUEUE_HPP_ - - - - #ifndef QMPOOL_HPP_ -#define QMPOOL_HPP_ - -#ifndef QF_MPOOL_SIZ_SIZE - #define QF_MPOOL_SIZ_SIZE 2U -#endif -#ifndef QF_MPOOL_CTR_SIZE - #define QF_MPOOL_CTR_SIZE 2U -#endif - -namespace QP { - -#if (QF_MPOOL_SIZ_SIZE == 1U) - using QMPoolSize = std::uint8_t; -#elif (QF_MPOOL_SIZ_SIZE == 2U) - using QMPoolSize = std::uint16_t; -#elif (QF_MPOOL_SIZ_SIZE == 4U) - using QMPoolSize = std::uint32_t; -#else - #error "QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U" -#endif - -#if (QF_MPOOL_CTR_SIZE == 1U) - using QMPoolCtr = std::uint8_t; -#elif (QF_MPOOL_CTR_SIZE == 2U) - using QMPoolCtr = std::uint16_t; -#elif (QF_MPOOL_CTR_SIZE == 4U) - using QMPoolCtr = std::uint32_t; -#else - #error "QF_MPOOL_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U" -#endif - -} // namespace QP - -#define QF_MPOOL_EL(evType_) struct { \ - QP::QFreeBlock sto_[((sizeof(evType_) - 1U) / (2U * sizeof(void *))) + 1U]; \ -} - -$declare ${QF::QFreeBlock} - -$declare ${QF::QMPool} - -#endif // QMPOOL_HPP_ - - - - #ifndef QV_HPP_ -#define QV_HPP_ - -$declare ${QV::QV-base} - -//============================================================================ -// interface used only for internal implementation, but not in applications -#ifdef QP_IMPL - -$declare ${QV-impl} - -$declare ${QF_EPOOL-impl} - -#endif // QP_IMPL - -#endif // QV_HPP_ - - - - #ifndef QK_HPP_ -#define QK_HPP_ - -$declare ${QK::QSchedStatus} - -$declare ${QK::QK-base} - -extern "C" { -$declare ${QK-extern-C} -} // extern "C" - -//============================================================================ -// interface used only for internal implementation, but not in applications -#ifdef QP_IMPL - -$declare ${QK-impl} - -$declare ${QF_EPOOL-impl} - -#endif // QP_IMPL - -#endif // QK_HPP_ - - - - #ifndef QSTAMP_HPP_ -#define QSTAMP_HPP_ - -namespace QP { -extern char const BUILD_DATE[12]; -extern char const BUILD_TIME[9]; -} // namespace QP - -#endif // QSTAMP_HPP_ - - - - #ifndef QPCPP_HPP_ -#define QPCPP_HPP_ - -//============================================================================ -#include "qp_port.hpp" // QP port from the port directory -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // software tracing enabled? - #include "qs_port.hpp" // QS/C++ port from the port directory -#else - #include "qs_dummy.hpp" // QS/C++ dummy (inactive) interface -#endif - -//============================================================================ -#ifndef QP_API_VERSION - #define QP_API_VERSION 0 -#endif // QP_API_VERSION - -// QP API compatibility layer... -//============================================================================ -#if (QP_API_VERSION < 750) - -#define QM_SM_STATE_DECL(subm_, state_) error "submachines no longer supported" -#define qm_super_sub(sm_state_) error "submachines no longer supported" -#define qm_tran_ep(tatbl_) error "submachines no longer supported" -#define qm_tran_xp(xp_, tatbl_) error "submachines no longer supported" -#define qm_sm_exit(sm_state_) error "submachines no longer supported" - -#ifdef QEVT_DYN_CTOR -//! @deprecated #QEVT_DYN_CTOR, please use #QEVT_PAR_INIT -#define QEVT_PAR_INIT -#endif - -//! @deprecated plain 'char' is no longer forbidden in MISRA/AUTOSAR-C++ -using char_t = char; - -//! @deprecated assertion failure handler -//! Use Q_onError() instead. -#define Q_onAssert(module_, id_) Q_onError(module_, id_) - -//! @deprecated #Q_NASSERT preprocessor switch to disable QP assertions -#ifdef Q_NASSERT - - // #Q_UNSAFE now replaces the functionality of Q_NASSERT - #define Q_UNSAFE - - //! @deprecated general purpose assertion with user-specified ID - //! number that **always** evaluates the `expr_` expression. - #define Q_ALLEGE_ID(id_, expr_) (static_cast<void>(expr_)) - -#elif defined Q_UNSAFE - - //! @deprecated general purpose assertion with user-specified ID - //! number that **always** evaluates the `expr_` expression. - #define Q_ALLEGE_ID(id_, expr_) (static_cast<void>(expr_)) - -#else // QP FuSa Subsystem enabled - - //! @deprecated general purpose assertion with user-specified ID - //! number that **always** evaluates the `expr_` expression. - //! @note - //! The use of this macro is no longer recommended. - #define Q_ALLEGE_ID(id_, expr_) if (!(expr_)) { \ - QF_CRIT_STAT \ - QF_CRIT_ENTRY(); \ - Q_onError(&Q_this_module_[0], (id_)); \ - QF_CRIT_EXIT(); \ - } else ((void)0) - -#endif - -//! @deprecated general purpose assertion without ID number -//! that **always** evaluates the `expr_` expression. -//! Instead of ID number, this macro is based on the standard -//! `__LINE__` macro. -//! -//! @note The use of this macro is no longer recommended. -#define Q_ALLEGE(expr_) Q_ALLEGE_ID(__LINE__, (expr_)) - -//! Static (compile-time) assertion. -//! -//! @deprecated -//! Use Q_ASSERT_STATIC() or better yet `static_assert()` instead. -//! -#define Q_ASSERT_COMPILE(expr_) Q_ASSERT_STATIC(expr_) - -//! @deprecated use QP::QF::NO_MARGIN instead -#define QF_NO_MARGIN QP::QF::NO_MARGIN - -//============================================================================ -#if (QP_API_VERSION < 691) - -//! @deprecated enable the QS global filter -#define QS_FILTER_ON(rec_) QS_GLB_FILTER((rec_)) - -//! @deprecated disable the QS global filter -#define QS_FILTER_OFF(rec_) QS_GLB_FILTER(-(rec_)) - -//! @deprecated enable the QS local filter for SM (state machine) object -#define QS_FILTER_SM_OBJ(obj_) (static_cast<void>(0)) - -//! @deprecated enable the QS local filter for AO (active objects) -#define QS_FILTER_AO_OBJ(obj_) (static_cast<void>(0)) - -//! @deprecated enable the QS local filter for MP (memory pool) object -#define QS_FILTER_MP_OBJ(obj_) (static_cast<void>(0)) - -//! @deprecated enable the QS local filter for EQ (event queue) object -#define QS_FILTER_EQ_OBJ(obj_) (static_cast<void>(0)) - -//! @deprecated enable the QS local filter for TE (time event) object -#define QS_FILTER_TE_OBJ(obj_) (static_cast<void>(0)) - -#ifdef Q_SPY - -//! @deprecated local Filter for a generic application object `obj_`. -#define QS_FILTER_AP_OBJ(obj_) \ - (QP::QS::filt_.loc_AP = (obj_)) - -//! @deprecated begin of a user QS record, instead use QS_BEGIN_ID() -#define QS_BEGIN(rec_, obj_) \ - if (QS_GLB_FILTER_(rec_) && \ - ((QP::QS::filt_.loc[QP::QS::AP_OBJ] == nullptr) \ - || (QP::QS::filt_.loc_AP == (obj_)))) \ - { \ - QS_CRIT_STAT \ - QS_CRIT_ENTRY(); \ - QP::QS::beginRec_(static_cast<std::uint_fast8_t>(rec_)); \ - QS_TIME_PRE(); - -//! @deprecated output hex-formatted std::uint32_t to the QS record -#define QS_U32_HEX(width_, data_) \ - (QP::QS::u32_fmt_(static_cast<std::uint8_t>( \ - (static_cast<std::uint8_t>((width_) << 4)) | QS_HEX_FMT), (data_))) - -#else - -#define QS_FILTER_AP_OBJ(obj_) (static_cast<void>(0)) -#define QS_BEGIN(rec_, obj_) if (false) { -#define QS_U32_HEX(width_, data_) (Q_UNUSED_PAR(0)) - -#endif // def Q_SPY - -//============================================================================ -#if (QP_API_VERSION < 680) - -//! @deprecated -//! Macro to specify a tran. in the "me->" impl-strategy. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! you call tran(Q_STATE_CAST(target_)). -#define Q_TRAN(target_) (me->tran(Q_STATE_CAST(target_))) - -//! @deprecated -//! Macro to specify a tran-to-history in the "me->" impl-strategy. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! you call tran_hist(Q_STATE_CAST(hist_)). -#define Q_TRAN_HIST(hist_) (me->tran_hist((hist_))) - -//! @deprecated -//! Macro to specify the superstate in the "me->" impl-strategy. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! you call super(state_)). -#define Q_SUPER(state_) (me->super(Q_STATE_CAST(state_))) - -//! @deprecated -//! Macro to call in a QM state entry-handler. Applicable only to QMSMs. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_entry(Q_STATE_CAST(state_)). -#define QM_ENTRY(state_) (me->qm_entry((state_))) - -//! @deprecated -//! Macro to call in a QM state exit-handler. Applicable only to QMSMs. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_exit(Q_STATE_CAST(state_)). -#define QM_EXIT(state_) (me->qm_exit((state_))) - -//! @deprecated -//! Macro to call in a QM state-handler when it executes a tran. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_tran((tatbl_)). -#define QM_TRAN(tatbl_) (me->qm_tran((tatbl_))) - -//! @deprecated -//! Macro to call in a QM state-handler when it executes an initial tran. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_tran_init((tatbl_)). -#define QM_TRAN_INIT(tatbl_) (me->qm_tran_init((tatbl_))) - -//! @deprecated -//! Macro to call in a QM state-handler when it executes a tran-to-history. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_tran_hist((history_), (tatbl_)). -#define QM_TRAN_HIST(history_, tatbl_) \ - (me->qm_tran_hist((history_), (tatbl_))) - -#endif // QP_API_VERSION < 680 -#endif // QP_API_VERSION < 691 -#endif // QP_API_VERSION < 750 - -#endif // QPCPP_HPP_ - - - - - - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -//============================================================================ -//! @cond INTERNAL - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qep_hsm") - -// immutable events corresponding to the reserved signals. -static QP::QEvt const l_reservedEvt_[4] { - QP::QEvt(static_cast<QP::QSignal>(QP::QHsm::Q_EMPTY_SIG)), - QP::QEvt(static_cast<QP::QSignal>(QP::QHsm::Q_ENTRY_SIG)), - QP::QEvt(static_cast<QP::QSignal>(QP::QHsm::Q_EXIT_SIG)), - QP::QEvt(static_cast<QP::QSignal>(QP::QHsm::Q_INIT_SIG)) -}; - -// maximum depth of state nesting in a QHsm (including the top level) -// must be >= 3 -static constexpr std::int_fast8_t QHSM_MAX_NEST_DEPTH_ {6}; - -} // unnamed namespace - -// helper macro to handle reserved event in an QHsm -#define QHSM_RESERVED_EVT_(state_, sig_) \ - ((*(state_))(this, &l_reservedEvt_[(sig_)])) - -// helper macro to trace state entry -#define QS_STATE_ENTRY_(state_, qsId_) \ - QS_CRIT_ENTRY(); \ - QS_MEM_SYS(); \ - QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, (qsId_)) \ - QS_OBJ_PRE(this); \ - QS_FUN_PRE(state_); \ - QS_END_PRE() \ - QS_MEM_APP(); \ - QS_CRIT_EXIT() - -// helper macro to trace state exit -#define QS_STATE_EXIT_(state_, qsId_) \ - QS_CRIT_ENTRY(); \ - QS_MEM_SYS(); \ - QS_BEGIN_PRE(QS_QEP_STATE_EXIT, (qsId_)) \ - QS_OBJ_PRE(this); \ - QS_FUN_PRE(state_); \ - QS_END_PRE() \ - QS_MEM_APP(); \ - QS_CRIT_EXIT() - -//! @endcond - -//============================================================================ - -$define ${QEP::versionStr[]} - -$define ${QEP::QHsm} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -//============================================================================ -//! @cond INTERNAL - -// unnamed namespace for local definitions with internal linkage -namespace { - -Q_DEFINE_THIS_MODULE("qep_msm") - -// top-state object for QMsm-style state machines -QP::QMState const l_msm_top_s = { - nullptr, - nullptr, - nullptr, - nullptr, - nullptr -}; - -// maximum depth of state nesting in a QMsm (including the top level) -static constexpr std::int_fast8_t QMSM_MAX_NEST_DEPTH_ {8}; - -// maximum length of transition-action array -static constexpr std::int_fast8_t QMSM_MAX_TRAN_LENGTH_ {2*QMSM_MAX_NEST_DEPTH_}; - -// maximum depth of entry levels in a MSM for tran. to history. -static constexpr std::int_fast8_t QMSM_MAX_ENTRY_DEPTH_ {4}; - -} // unnamed namespace - -//! @endcond -//============================================================================ - -$define ${QEP::QMsm} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -//Q_DEFINE_THIS_MODULE("qf_act") -} // unnamed namespace - -$define ${QF::QActive::registry_[QF_MAX_ACTIVE + 1U]} - -$define ${QF::QF-pkg} -$define ${QF::types::QF_LOG2} -#ifndef Q_UNSAFE -$define ${QF::types::QPtrDis} -#endif - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -//============================================================================ -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_actq") -} // unnamed namespace - -$define ${QF::QActive::post_} - -$define ${QF::QActive::postLIFO} - -$define ${QF::QActive::get_} - -$define ${QF::QTicker} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_defer") -} // unnamed namespace - -$define ${QF::QActive::defer} - -$define ${QF::QActive::recall} - -$define ${QF::QActive::flushDeferred} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -#if (QF_MAX_EPOOL > 0U) // mutable events configured? - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_dyn") -} // unnamed namespace - -$define ${QF::QF-dyn} - -#endif // (QF_MAX_EPOOL > 0U) mutable events configured - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_mem") -} // unnamed namespace - -$define ${QF::QMPool} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_qact") -} // unnamed namespace - -$define ${QF::QActive::QActive} - -$define ${QF::QActive::register_} - -$define ${QF::QActive::unregister_} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -//Q_DEFINE_THIS_MODULE("qf_qmact") -} // unnamed namespace - -$define ${QF::QMActive} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_qeq") -} // unnamed namespace - -$define ${QF::QEQueue} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_ps") -} // unnamed namespace - -$define ${QF::QActive::subscrList_} - -$define ${QF::QActive::maxPubSignal_} - -$define ${QF::QActive::psInit} - -$define ${QF::QActive::publish_} - -$define ${QF::QActive::subscribe} - -$define ${QF::QActive::unsubscribe} - -$define ${QF::QActive::unsubscribeAll} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_time") -} // unnamed namespace - -$define ${QF::QTimeEvt} - - - - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// protection against including this source file in a wrong project -#ifndef QV_HPP_ - #error "Source file included in a project NOT based on the QV kernel" -#endif // QV_HPP_ - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qv") -} // unnamed namespace - -$define ${QV::QV-base} - -$define ${QV::QF-cust} - -$define ${QV::QActive} - - - - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// protection against including this source file in a wrong project -#ifndef QK_HPP_ - #error "Source file included in a project NOT based on the QK kernel" -#endif // QK_HPP_ - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qk") -} // unnamed namespace - -$define ${QK::QK-base} - -extern "C" { -$define ${QK-extern-C} -} // extern "C" - -$define ${QK::QF-cust} - -$define ${QK::QActive} - - - - - - - #include "qstamp.hpp" - -namespace QP { -char const BUILD_DATE[12] = __DATE__; -char const BUILD_TIME[9] = __TIME__; -} // namespace QP - - - - diff --git a/qpcpp_8.0.1.sha1 b/qpcpp_8.0.1.sha1 deleted file mode 100644 index 7fe10a299..000000000 --- a/qpcpp_8.0.1.sha1 +++ /dev/null @@ -1,162 +0,0 @@ -bda783a346fb750c7a1fe32dc0a8ca52609cb5f4 *qpcpp.qm -46578fc304c597329289978acee1027c8c533335 *include/qequeue.hpp -1a8e0b05536b89c1cd3806782ae1a21dd4ceca69 *include/qk.hpp -cb1c39aabacb619060924356f7c8e900686538e0 *include/qmpool.hpp -559a9ca895f97f38c5d3bb0511675f321e041911 *include/qp.hpp -bf47a939e525fa575673f89b8106bcee166240a2 *include/qp_pkg.hpp -e5b0d14c9e6994b82a5cd9200bde46bd179bfb20 *include/qpcpp.hpp -d4f14d2ed18ef725ea17d0a97b78ae22a283c96b *include/qs.hpp -88220a7d892fee54053b467b596dc6b536aaf8be *include/qs_dummy.hpp -9694f10e44d53563599410d37dd1c5a19cf1788b *include/qs_pkg.hpp -49d2620b0afa9e74d73680495c3e8a931e5d8f73 *include/qsafe.h -09e9ffe95120ba17a49d7039b5316f2614710dab *include/qstamp.hpp -73749ed396bbc0419971769a47069448c8136960 *include/qv.hpp -05b617dad20f07f07b64dccf84f9b7cd9b8d2bb7 *include/qxk.hpp -0199f3eeb6c02b8cc890ee4c6f6d344569a0858f *include/README.md -71899ce74eeb04f333ed00d53f87719f722a39ab *src/qf/CMakeLists.txt -864d627f2600987a2194c57093e1f210e0de2a7a *src/qf/qep_hsm.cpp -d3242def2b23df5b9704bb3b0411fd01de6c0a67 *src/qf/qep_msm.cpp -62f87a60d04e1c98f40162a166ec14a1f2f1252f *src/qf/qf_act.cpp -07671fb85e9b2492b0ea37b853d7e0eea42bf637 *src/qf/qf_actq.cpp -ed83f5f8b3533cc97ffc2a85aeeb63f29b4f1dd8 *src/qf/qf_defer.cpp -f41d8815460d26f5bbf89e40dcb607b6a3ddeaa8 *src/qf/qf_dyn.cpp -974493184d40e0a2f698c6e63e0bc450343ef591 *src/qf/qf_mem.cpp -ef51e4840107b0ed6ec97e170ac2689e1b1fdb95 *src/qf/qf_ps.cpp -08b490d7505a7ff6fe493058975eb9f0a82daa3d *src/qf/qf_qact.cpp -23892cde4fd7226e899026884e07b01e32d0aef4 *src/qf/qf_qeq.cpp -5fc4874b74779641454e2d8e7960a5bf3d130115 *src/qf/qf_qmact.cpp -04dd9fbddc336f096bd214f8e7368d7a6dce43c8 *src/qf/qf_time.cpp -7cdab433e81612862fd27f0cf792d38e1197d064 *src/qk/CMakeLists.txt -1be4743dc14186779abb96b4bd16ba9a99d3314d *src/qk/qk.cpp -eb28260d471fc752ca54b2c1e2d763f28432c2c1 *src/qs/CMakeLists.txt -66fd2a553c8ae6709dfe286b6ccce002208251f1 *src/qs/qs.cpp -2ca73a0d38dd7b544864d72fd337f29c7dae2a85 *src/qs/qs_64bit.cpp -349c18625bd2cceda297e1c98a85a9fa9538cef9 *src/qs/qs_fp.cpp -ad4e3a9faacc038cb51a7773ffc42903be947a22 *src/qs/qs_rx.cpp -8008d9c24757b2bb02e85123aa89a3a33090921d *src/qs/qstamp.cpp -92338453dc612419b0e16e0560e761312d0f3900 *src/qs/qutest.cpp -b6d93a16f5b176d3da4888a7efb265730337f46d *src/qv/CMakeLists.txt -f530563e062ff7ea84763f6e799bf4ca1cb73054 *src/qv/qv.cpp -2d0c3d3d93e4d4ac8e2218b9ed68e6269b02419e *src/qxk/qxk.cpp -e0e633a980e4c04a85f877e810ce77ad51903e87 *src/qxk/qxk_mutex.cpp -8e15812d14f250866dfa8a96fe5b14638ca2c4ae *src/qxk/qxk_sema.cpp -58e6a9354a1c7c4d53204b7ad2fad05d6eb3117c *src/qxk/qxk_xthr.cpp -81f1a6dbcebd0b5df9e437902ffbe0fecdd03d25 *ports/arm-cm/qk/armclang/qk_port.cpp -7119fc94c0b5560ab8e3197a83917667e311e415 *ports/arm-cm/qk/armclang/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/armclang/qs_port.hpp -5f2353117f9940b0ea891d2e0bd486e0d024b67c *ports/arm-cm/qk/gnu/qk_port.cpp -7119fc94c0b5560ab8e3197a83917667e311e415 *ports/arm-cm/qk/gnu/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/gnu/qs_port.hpp -2b9c1112e3e5be79ce2b1799adfd5e812467765b *ports/arm-cm/qk/iar/qk_port.cpp -f54416674c33ffd19408f02af60f7d69b8613797 *ports/arm-cm/qk/iar/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/iar/qs_port.hpp -9cc71aed12d57408252019035aff449ce028372c *ports/arm-cm/qv/armclang/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/armclang/qs_port.hpp -90b14adcd8f8b29de3358073c39bd4161f5ce2eb *ports/arm-cm/qv/armclang/qv_port.cpp -bed3687b29555f6fa9c721cf34a098218f64e1ad *ports/arm-cm/qv/gnu/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/gnu/qs_port.hpp -b2d5e72b65813bdc37bcab3c8cd9107bda009131 *ports/arm-cm/qv/gnu/qv_port.cpp -424864680661227e4ab418b2af905d4bd92767ad *ports/arm-cm/qv/iar/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/iar/qs_port.hpp -15fb0660dff33295bad38facfc7aacca928133a3 *ports/arm-cm/qv/iar/qv_port.cpp -9e248cb426d8495e5cd677ff79cd3b9ced2a76a5 *ports/arm-cm/qxk/armclang/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qxk/armclang/qs_port.hpp -16423aebab91be16d8c2c7b128d8494709a6a746 *ports/arm-cm/qxk/armclang/qxk_port.cpp -9ec8ed9717f9130b23252d2c381f779617165932 *ports/arm-cm/qxk/gnu/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qxk/gnu/qs_port.hpp -75fc7a6c1b0775832f3e0e0e2bbacc19f56ddc94 *ports/arm-cm/qxk/gnu/qxk_port.cpp -f40b0ea4761d187ac7d4460a161efb9b4f3e6ef6 *ports/arm-cm/qxk/iar/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qxk/iar/qs_port.hpp -44509ff079ba173a28076f3fa1488582a6ef48a1 *ports/arm-cm/qxk/iar/qxk_port.cpp -69256fd1a5b81db3e3174cba9196bf9da925e098 *ports/arm-cm/qutest/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qutest/qs_port.hpp -1194c26fdfc9665a04cc3d01e6de49afe1698376 *ports/arm-cr/qk/gnu/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/gnu/qs_port.hpp -a8f4351725564e449206909176d09bc58cd6f45d *ports/arm-cr/qk/iar/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/iar/qs_port.hpp -7203200deaa5dbb4746434d4a3d79a160d4ccf4b *ports/arm-cr/qk/ti/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/ti/qs_port.hpp -fd3e4b882efb671f2522ae83bfde016ea416d4a7 *ports/arm-cr/qv/gnu/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qv/gnu/qs_port.hpp -fafbe56ae4266a412cb1b6db6e146fbfe5022b4a *ports/arm-cr/qv/iar/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qv/iar/qs_port.hpp -78d39f7479a0ea046e77607740e4211d9e4cb60f *ports/arm-cr/qv/ti/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qv/ti/qs_port.hpp -bc080e68d0edfc28da2df882ed3661cf99f2942c *ports/msp430/qk/qp_port.hpp -197ec45394793b79a29afe5bb31b6de1ad78ad00 *ports/msp430/qk/qs_port.hpp -7b2654746a747c427b5ee1dd7f8b4b82c372a040 *ports/msp430/qv/qp_port.hpp -197ec45394793b79a29afe5bb31b6de1ad78ad00 *ports/msp430/qv/qs_port.hpp -650f628d87a39c559a87c6f849c58fb9a8e777a7 *ports/msp430/qutest/qp_port.hpp -197ec45394793b79a29afe5bb31b6de1ad78ad00 *ports/msp430/qutest/qs_port.hpp -8614593b911e6db6f634d972e79093e964756556 *ports/config/qp_config.hpp -b6b5d23c618976a6fbed51dc5a13e227928e1d4b *ports/embos/CMakeLists.txt -0b5ad806f47800c1481c9af3d88c1bff3cb1d784 *ports/embos/qf_port.cpp -5e28aa0e89239f970e4b5e85be4e5c3b6a34dd69 *ports/embos/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/embos/qs_port.hpp -e4f00894f86806af6d88d38e831a8fc0ad36059e *ports/freertos/CMakeLists.txt -699baf504d4d3df68b0e66196c48516490e795be *ports/freertos/qf_port.cpp -c7efbc2cc8425c0e21d5bd892584b3e2ff7a145b *ports/freertos/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/freertos/qs_port.hpp -18df978f665338c757f1a2a284c2acc779bd59d3 *ports/threadx/CMakeLists.txt -90717daaf983e8425a9939d17f732ce3d4646bb4 *ports/threadx/qf_port.cpp -f0d61f6806b0207e56dd75f8aaac55c4b1393996 *ports/threadx/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/threadx/qs_port.hpp -46699d3c8ad92f9c98ea5e03e72d4190a7794aa4 *ports/threadx/README.md -0ab8b95f50fa767b951c6f56efe86789623b7127 *ports/uc-os2/CMakeLists.txt -3624f6191213536a8be528185d97d1e35b1fa369 *ports/uc-os2/qf_port.cpp -528d3c2c337c639f3879d24da74369facea0bca6 *ports/uc-os2/qp_port.hpp -5597ed8e115824f146a12f18c8142371bfa1852a *ports/uc-os2/qs_port.hpp -227dedab24f1e20440103a0cabc210b4b5adedef *ports/qep-only/CMakeLists.txt -6d75bdbb41cd68d2fcab63d0eb8ff91f96f52c24 *ports/qep-only/qp_port.hpp -7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/qep-only/safe_std.h -12255313ebcf963d29d91bee4c917bb6ab2f9e1d *ports/posix/CMakeLists.txt -9119c0c12ecc34d41cba8da898496c1f99ea47ac *ports/posix/qf_port.cpp -56956443bf38d12075ce2ddc53f8a0e8b86f135b *ports/posix/qp_port.hpp -66922bad40ecb6b213858f935849569713457f71 *ports/posix/qs_port.cpp -f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/posix/qs_port.hpp -e6a5523e16619370638f6305687cd480d1e3744b *ports/posix/README.md -7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix/safe_std.h -493900b9aa5475785c65458332995a184690d43f *ports/posix-qv/CMakeLists.txt -819137bb54242fd0279ed152fe874decb9fd3c16 *ports/posix-qv/qf_port.cpp -f458af1511007d6ba2a4a0a0e40d74e03719ceb1 *ports/posix-qv/qp_port.hpp -66922bad40ecb6b213858f935849569713457f71 *ports/posix-qv/qs_port.cpp -f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/posix-qv/qs_port.hpp -e2e295c371bc14f0089a888b07d98c657dea07bf *ports/posix-qv/README.md -7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix-qv/safe_std.h -c9969a454b540a3b1abd3dd5cc46fb211663310e *ports/posix-qutest/CMakeLists.txt -edfa2baff22735f98a094e315db11c40ed07e5e8 *ports/posix-qutest/qp_port.hpp -f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/posix-qutest/qs_port.hpp -772fdcf6a4ca3e3303016384de92874ec06c11fe *ports/posix-qutest/qutest_port.cpp -7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix-qutest/safe_std.h -06b76c6c30ea880876b47ee27115178ff62ea66b *ports/win32/CMakeLists.txt -48dfd18fce993f237138d5d99f2fb0e385efbe93 *ports/win32/qf_port.cpp -ea88910c991455756433cff5338a62ed3d181bf2 *ports/win32/qp_port.hpp -6e6aef4b105bd807de96922fcb5698b695fce7e2 *ports/win32/qs_port.cpp -f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/win32/qs_port.hpp -40f18295a0013cbba3c6b270d1d70748ec1d325a *ports/win32/qwin_gui.c -ddc62932b46bbc0ad147193d0dd7efa28127c6c4 *ports/win32/qwin_gui.h -ad6de94157c477eacb61f321870b5f8c1a09a5cd *ports/win32/README.md -7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32/safe_std.h -dd5b9a8736e1a1171f7d8565e29e1acb6f7a9691 *ports/win32-qv/CMakeLists.txt -55381dce63d87ddee340d5a153f6054c4fbf5c0e *ports/win32-qv/qf_port.cpp -b2c8d14a04c2bbf3f6f0f3dae097e485a55dc008 *ports/win32-qv/qp_port.hpp -6e6aef4b105bd807de96922fcb5698b695fce7e2 *ports/win32-qv/qs_port.cpp -f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/win32-qv/qs_port.hpp -40f18295a0013cbba3c6b270d1d70748ec1d325a *ports/win32-qv/qwin_gui.c -ddc62932b46bbc0ad147193d0dd7efa28127c6c4 *ports/win32-qv/qwin_gui.h -ddd27415c3d1df6d8c210966e8915c407b15bf58 *ports/win32-qv/README.md -7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32-qv/safe_std.h -3c23c06f425a8d8dbb18d1f191ac6cab483a8e51 *ports/win32-qutest/CMakeLists.txt -edfa2baff22735f98a094e315db11c40ed07e5e8 *ports/win32-qutest/qp_port.hpp -f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/win32-qutest/qs_port.hpp -5bda26c8c82914e6cc16685e4adc02cbc32c5291 *ports/win32-qutest/qutest_port.cpp -7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32-qutest/safe_std.h -76dd9078dc4311d53d3862d44177a8660258da6d *zephyr/CMakeLists.txt -36a0252cf0bfd6be0d345c48c00b2300f8917f05 *zephyr/Kconfig -2eb2a922e18b4760a68151ebee1b6282d20b4692 *zephyr/module.yml -36ceff869a883b6cb0a262755e3bf03d790f3a87 *zephyr/qf_port.cpp -109c291df50110f185adc17bcdf8becc0a79346c *zephyr/qp-zephyr.jpg -76548c9e125899106122946cdba17b7da1a32c91 *zephyr/qp_port.hpp -d414f620c05844bbad1988f0951509856acc63db *zephyr/qs_port.hpp -50863abaf410b184dbe28b36f6e63b74e26af26e *zephyr/qutest_port.cpp -791248d57ce8dfa6497728c7c2d0734c2c581625 *zephyr/README.md diff --git a/qpcpp_8.0.2.sha1 b/qpcpp_8.0.2.sha1 new file mode 100644 index 000000000..212f8cd03 --- /dev/null +++ b/qpcpp_8.0.2.sha1 @@ -0,0 +1,163 @@ +10c35486e20dc82668e4a77ec1a4cc427ba92b21 *include/qequeue.hpp +2af472589274db820aa2a3e7928d7100d2f87cb3 *include/qk.hpp +7394e76571868dfaea3c297e9d00e9f429cbdc3c *include/qmpool.hpp +acc36cf4768e1707256f9891edb39850ad754ab0 *include/qp.hpp +4a28afe5b5fabfa5ce45c2eb07c63388d8cd92b1 *include/qp_pkg.hpp +c8c44d7959d255f98aac76f6040433aaa20956b6 *include/qpcpp.hpp +0b4b406267c65182e40565ce01f510554827f005 *include/qs.hpp +40f446662e01fcd410b0be8f7813dcd86995f22a *include/qs_dummy.hpp +007ade6761260b32bf34ebaaea633977f0cff881 *include/qs_pkg.hpp +cf142966637ce4c4ae831017e8a77fb1fe3a678a *include/qsafe.h +87c77d984d77178533b4e76eb204c4e265b23e9e *include/qstamp.hpp +0e7a9cc9d0511828380e5cd5ee2d7f35ed1bf317 *include/qv.hpp +1cb8c24e0188d17c3c0ca4c12fe88f8c04a9e1e7 *include/qxk.hpp +0199f3eeb6c02b8cc890ee4c6f6d344569a0858f *include/README.md +71899ce74eeb04f333ed00d53f87719f722a39ab *src/qf/CMakeLists.txt +750abbc6caf645de293f5107b10fba3fdbb107c9 *src/qf/qep_hsm.cpp +875f0a15305079a6d5861d66fbcceb8333e9b75b *src/qf/qep_msm.cpp +43eef9ea75c14b1378fc01772bf5e4bdc0621ba2 *src/qf/qf_act.cpp +a8608d5b17afbe82161b01bf0a2edfdc8bbc5a44 *src/qf/qf_actq.cpp +42aa87da9938aea033cda394b2677743d9733149 *src/qf/qf_defer.cpp +19e4d2302186284364543182f6f5af5133516827 *src/qf/qf_dyn.cpp +a06e9252217812cebd30b93fee4c0e4892b7e8e3 *src/qf/qf_mem.cpp +91de7f212c546469f0b7ac9127ccc02860bd6abe *src/qf/qf_ps.cpp +dffd53a967ea218a38c23e71d1aec228a5641b66 *src/qf/qf_qact.cpp +1171eac0c4d4a69a1994e0e9461b785d5ce9803b *src/qf/qf_qeq.cpp +06a3f2fc2b976f7948cac34a434b00ebfbf4a198 *src/qf/qf_qmact.cpp +685aaac6419b8e86e8d6a8029bd2210bb582322c *src/qf/qf_time.cpp +7cdab433e81612862fd27f0cf792d38e1197d064 *src/qk/CMakeLists.txt +5c7393e1bf2f1f336ffda9b4ccfda7849bae6842 *src/qk/qk.cpp +eb28260d471fc752ca54b2c1e2d763f28432c2c1 *src/qs/CMakeLists.txt +450e30ae7919195dc76d934297e3bacd39eed7dc *src/qs/qs.cpp +a49e4cc82d27458d880e3cea5edf7111228b5c83 *src/qs/qs_64bit.cpp +a79389856629896857f68345a0aa908c07d5ac92 *src/qs/qs_fp.cpp +0f206dfea5178ff9d5217b64d112053abb415627 *src/qs/qs_rx.cpp +6e68d4e35a2743c33c45792c922ce065639b8bf5 *src/qs/qstamp.cpp +b4a201fc64467596edadda63dd7f0c8e8344f99d *src/qs/qutest.cpp +b6d93a16f5b176d3da4888a7efb265730337f46d *src/qv/CMakeLists.txt +1588af3ba142febd147eace532cd1993c53a0d11 *src/qv/qv.cpp +2242492063a43fbb9d1725bc243ab30018634bfc *src/qxk/qxk.cpp +97f0a0bd72757e02e422d1a1d7ecb53343295942 *src/qxk/qxk_mutex.cpp +7081b032e0db0675840a6c8b75edf4d47d13c9c7 *src/qxk/qxk_sema.cpp +70982d9277482d775c967aaf745e9c4c442aef19 *src/qxk/qxk_xthr.cpp +99754876405825cd0cd3a6257f27525455288c9d *ports/arm-cm/config/qp_config.hpp +ae09530b01a3ce4f2cdc5dc007c97dcc0e08bae1 *ports/arm-cm/qk/armclang/qk_port.cpp +5e2f09fa46a4a3bfd1c84126c845c9d86849f306 *ports/arm-cm/qk/armclang/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qk/armclang/qs_port.hpp +4e10609efc099d39294cd0713e304b3de812fac6 *ports/arm-cm/qk/gnu/qk_port.cpp +5e2f09fa46a4a3bfd1c84126c845c9d86849f306 *ports/arm-cm/qk/gnu/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qk/gnu/qs_port.hpp +eebf9abd3858d108b12735c308c52725b777a676 *ports/arm-cm/qk/iar/qk_port.cpp +52b074dacb05c7af593a56a375f4462c1de1ed8f *ports/arm-cm/qk/iar/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qk/iar/qs_port.hpp +2c0ec84bc34f1368c8ea5ccde2cdf08eb7aaed5f *ports/arm-cm/qv/armclang/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qv/armclang/qs_port.hpp +fd3556c0d6af1042ecafeefa6d9aff66d1a39244 *ports/arm-cm/qv/armclang/qv_port.cpp +8e732484b6a9742d4e54bfe33c30b01a87ab02a3 *ports/arm-cm/qv/gnu/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qv/gnu/qs_port.hpp +1399bbbce01a1269e41463d35c3431061e8b16a3 *ports/arm-cm/qv/gnu/qv_port.cpp +f26fb7762d713962854dc16b3bc82ebdd03c33c9 *ports/arm-cm/qv/iar/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qv/iar/qs_port.hpp +839ccd47dc6e513c5b850a1a6c9158d4909920e1 *ports/arm-cm/qv/iar/qv_port.cpp +d4edac916a2df8dc2880467d01792f22f5939177 *ports/arm-cm/qxk/armclang/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qxk/armclang/qs_port.hpp +c6804025f48f7ea744db38ad5d7955696c1ccdcf *ports/arm-cm/qxk/armclang/qxk_port.cpp +d4edac916a2df8dc2880467d01792f22f5939177 *ports/arm-cm/qxk/gnu/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qxk/gnu/qs_port.hpp +eec76849164d90d48cfd080dced937b07627e8c4 *ports/arm-cm/qxk/gnu/qxk_port.cpp +2db00521dc7bdca6467f9c7978f4a47daf375688 *ports/arm-cm/qxk/iar/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qxk/iar/qs_port.hpp +c6dbe8a03de76baad665faf5a50c863d38334b58 *ports/arm-cm/qxk/iar/qxk_port.cpp +b83cf186b80decce5fdeb5f66080d7a88d9436e3 *ports/arm-cm/qutest/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qutest/qs_port.hpp +5808649f96e035b70d0d752602883528aacb283a *ports/arm-cr/config/qp_config.hpp +496bf7670fae59aa34ea0a7dfde8bb4d70a6a2a9 *ports/arm-cr/qk/gnu/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cr/qk/gnu/qs_port.hpp +1dd57dbde83ee29ef6a40cd6150aeaa181937957 *ports/arm-cr/qk/iar/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cr/qk/iar/qs_port.hpp +410cfb06e914a9a7efa9d321e8e63e8b132e5567 *ports/arm-cr/qk/ti/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cr/qk/ti/qs_port.hpp +ad5ba7bf199209edb6683128638d596c8056a1a0 *ports/arm-cr/qv/gnu/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cr/qv/gnu/qs_port.hpp +631549a2f7f4aab54d469b4f711e79e499b604be *ports/arm-cr/qv/iar/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cr/qv/iar/qs_port.hpp +75a60334fe636906329001ed18f5c54033ed9d04 *ports/arm-cr/qv/ti/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cr/qv/ti/qs_port.hpp +18596df7b34eb99db5d580d4f1c2b2a43e3ab3a3 *ports/msp430/qk/qp_port.hpp +6577bacc46c9a9f0cc27893506be39b1e69dd240 *ports/msp430/qk/qs_port.hpp +90e2a0391ea79ae8507a06356a06e8c1f942daee *ports/msp430/qv/qp_port.hpp +6577bacc46c9a9f0cc27893506be39b1e69dd240 *ports/msp430/qv/qs_port.hpp +55012fd62bb201af549da0c39d6ef85ea225790a *ports/msp430/qutest/qp_port.hpp +6577bacc46c9a9f0cc27893506be39b1e69dd240 *ports/msp430/qutest/qs_port.hpp +ea650ce477ced748760fdad526ea964be5c5ff95 *ports/config/qp_config.hpp +b6b5d23c618976a6fbed51dc5a13e227928e1d4b *ports/embos/CMakeLists.txt +670c6241eb418c66d46fc024fec33a623a2c2457 *ports/embos/qf_port.cpp +b80f7433aa174c6560ba1fd7f4ae2f2c94938906 *ports/embos/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/embos/qs_port.hpp +e4f00894f86806af6d88d38e831a8fc0ad36059e *ports/freertos/CMakeLists.txt +19acb29335a0244d1838102237aa4b8330df2f6a *ports/freertos/qf_port.cpp +96b4b2111d90b5326bed4de44e05830ada4e8678 *ports/freertos/qp_port.hpp +e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/freertos/qs_port.hpp +18df978f665338c757f1a2a284c2acc779bd59d3 *ports/threadx/CMakeLists.txt +931be3f4d0a2761d69ac8285d128fe1668731604 *ports/threadx/qf_port.cpp +29ab3ac5a56faaaf5d866a43d2e4edff7013a1ae *ports/threadx/qp_port.hpp +0182f7957f25390579a30b7ab56604819f9a3773 *ports/threadx/qs_port.hpp +46699d3c8ad92f9c98ea5e03e72d4190a7794aa4 *ports/threadx/README.md +0ab8b95f50fa767b951c6f56efe86789623b7127 *ports/uc-os2/CMakeLists.txt +989f46b139112b66f31f516266db338971bdef7f *ports/uc-os2/qf_port.cpp +1b511d790891f3f1fb78f6c7272c20205a4eb0dd *ports/uc-os2/qp_port.hpp +0182f7957f25390579a30b7ab56604819f9a3773 *ports/uc-os2/qs_port.hpp +227dedab24f1e20440103a0cabc210b4b5adedef *ports/qep-only/CMakeLists.txt +c96963c82a774605baab1839214e8bd32d173a68 *ports/qep-only/qp_port.hpp +7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/qep-only/safe_std.h +12255313ebcf963d29d91bee4c917bb6ab2f9e1d *ports/posix/CMakeLists.txt +720ff5c7ed5de9f9630ce5b80d34d157f0cb8151 *ports/posix/qf_port.cpp +c735c52b19b7692464902aca05dcd13cb7d2236e *ports/posix/qp_port.hpp +b566671ee550bd9735005b04f474cac6eb3301dd *ports/posix/qs_port.cpp +0242b0613d7133442426f5834f2677e77b32014b *ports/posix/qs_port.hpp +e6a5523e16619370638f6305687cd480d1e3744b *ports/posix/README.md +7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix/safe_std.h +493900b9aa5475785c65458332995a184690d43f *ports/posix-qv/CMakeLists.txt +0e0243f24a521c6c135c548b22854543a5cdf4b1 *ports/posix-qv/qf_port.cpp +2909abe049eff960b4008efaa9c6a12eff5a6517 *ports/posix-qv/qp_port.hpp +b566671ee550bd9735005b04f474cac6eb3301dd *ports/posix-qv/qs_port.cpp +0242b0613d7133442426f5834f2677e77b32014b *ports/posix-qv/qs_port.hpp +e2e295c371bc14f0089a888b07d98c657dea07bf *ports/posix-qv/README.md +7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix-qv/safe_std.h +c9969a454b540a3b1abd3dd5cc46fb211663310e *ports/posix-qutest/CMakeLists.txt +2c96ee69ca3c443a1224c4eacb83bbfb3cb60300 *ports/posix-qutest/qp_port.hpp +0242b0613d7133442426f5834f2677e77b32014b *ports/posix-qutest/qs_port.hpp +24b9c9258b3621ac757439cc7e93b817ffe9fefe *ports/posix-qutest/qutest_port.cpp +7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix-qutest/safe_std.h +06b76c6c30ea880876b47ee27115178ff62ea66b *ports/win32/CMakeLists.txt +0c2a046c664038d547e8dc8ba9573c599c087c60 *ports/win32/qf_port.cpp +6d89a4f5c91649cfff645f13a24cc632522797d4 *ports/win32/qp_port.hpp +a816ee62f507984cdbc37ac190b9f8a23a461bfb *ports/win32/qs_port.cpp +9daff0910db201c165600d3e55458f2ebec2dcc8 *ports/win32/qs_port.hpp +40f18295a0013cbba3c6b270d1d70748ec1d325a *ports/win32/qwin_gui.c +ddc62932b46bbc0ad147193d0dd7efa28127c6c4 *ports/win32/qwin_gui.h +ad6de94157c477eacb61f321870b5f8c1a09a5cd *ports/win32/README.md +7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32/safe_std.h +dd5b9a8736e1a1171f7d8565e29e1acb6f7a9691 *ports/win32-qv/CMakeLists.txt +eebb50308338c99e97d4f99272f37a4e9989d9ea *ports/win32-qv/qf_port.cpp +4b947280e9b569adb81afe7d72abca402bc39e9d *ports/win32-qv/qp_port.hpp +a816ee62f507984cdbc37ac190b9f8a23a461bfb *ports/win32-qv/qs_port.cpp +9daff0910db201c165600d3e55458f2ebec2dcc8 *ports/win32-qv/qs_port.hpp +40f18295a0013cbba3c6b270d1d70748ec1d325a *ports/win32-qv/qwin_gui.c +ddc62932b46bbc0ad147193d0dd7efa28127c6c4 *ports/win32-qv/qwin_gui.h +ddd27415c3d1df6d8c210966e8915c407b15bf58 *ports/win32-qv/README.md +7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32-qv/safe_std.h +3c23c06f425a8d8dbb18d1f191ac6cab483a8e51 *ports/win32-qutest/CMakeLists.txt +2c96ee69ca3c443a1224c4eacb83bbfb3cb60300 *ports/win32-qutest/qp_port.hpp +9daff0910db201c165600d3e55458f2ebec2dcc8 *ports/win32-qutest/qs_port.hpp +2b66a9145abdee9e280c67f78fe892c069bfabea *ports/win32-qutest/qutest_port.cpp +7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32-qutest/safe_std.h +76dd9078dc4311d53d3862d44177a8660258da6d *zephyr/CMakeLists.txt +36a0252cf0bfd6be0d345c48c00b2300f8917f05 *zephyr/Kconfig +2eb2a922e18b4760a68151ebee1b6282d20b4692 *zephyr/module.yml +bab81f1bd3833d059c0e2276380d82ed18aa514e *zephyr/qf_port.cpp +109c291df50110f185adc17bcdf8becc0a79346c *zephyr/qp-zephyr.jpg +b91b2672da8f3108e103f44d649e90afec956e46 *zephyr/qp_port.hpp +e390a0d4bef60bf18fa5ce4527c3d4e5eef0a473 *zephyr/qs_port.hpp +986dbb809e35eace3e8b2b9941df76c7153a8c0c *zephyr/qutest_port.cpp +791248d57ce8dfa6497728c7c2d0734c2c581625 *zephyr/README.md diff --git a/qpcpp_sha1.bat b/qpcpp_sha1.bat index c4282691c..30a92848b 100644 --- a/qpcpp_sha1.bat +++ b/qpcpp_sha1.bat @@ -1,6 +1,6 @@ @setlocal -set VERSION=8.0.1 +set VERSION=8.0.2 :: usage @echo Usage: qppcp_sha1 [gen] @@ -15,14 +15,15 @@ goto end ) @echo generating qpcpp_%VERSION%.sha1... -@sha1sum qpcpp.qm ^ +@sha1sum ^ include/* ^ src/qf/* src/qk/* src/qs/* src/qv/* src/qxk/* ^ - ports/arm-cm/qk/armclang/* ports/arm-cm/qk/config/* ports/arm-cm/qk/gnu/* ports/arm-cm/qk/iar/* ^ - ports/arm-cm/qv/armclang/* ports/arm-cm/qv/config/* ports/arm-cm/qv/gnu/* ports/arm-cm/qv/iar/* ^ - ports/arm-cm/qxk/armclang/* ports/arm-cm/qxk/config/* ports/arm-cm/qxk/gnu/* ports/arm-cm/qxk/iar/* ^ + ports/arm-cm/config/* ^ + ports/arm-cm/qk/armclang/* ports/arm-cm/qk/gnu/* ports/arm-cm/qk/iar/* ^ + ports/arm-cm/qv/armclang/* ports/arm-cm/qv/gnu/* ports/arm-cm/qv/iar/* ^ + ports/arm-cm/qxk/armclang/* ports/arm-cm/qxk/gnu/* ports/arm-cm/qxk/iar/* ^ ports/arm-cm/qutest/* ^ - ports/arm-cr/qk/config/* ^ + ports/arm-cr/config/* ^ ports/arm-cr/qk/gnu/* ports/arm-cr/qk/iar/* ports/arm-cr/qk/ti/* ^ ports/arm-cr/qv/gnu/* ports/arm-cr/qv/iar/* ports/arm-cr/qv/ti/* ^ ports/msp430/qk/* ports/msp430/qv/* ports/msp430/qutest/* ^ diff --git a/src/qf/qep_hsm.cpp b/src/qf/qep_hsm.cpp index e00adb970..3e693eacd 100644 --- a/src/qf/qep_hsm.cpp +++ b/src/qf/qep_hsm.cpp @@ -1,10 +1,6 @@ -//$file${src::qf::qep_hsm.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qf::qep_hsm.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${src::qf::qep_hsm.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -42,13 +37,17 @@ #include "qs_dummy.hpp" // disable the QS software tracing #endif // Q_SPY -//============================================================================ -//! @cond INTERNAL - // unnamed namespace for local definitions with internal linkage namespace { + Q_DEFINE_THIS_MODULE("qep_hsm") +// maximum depth of state nesting in a QHsm (including the top level) +// must be >= 3 +static constexpr std::int_fast8_t QHSM_MAX_NEST_DEPTH_ {6}; + +//! @cond INTERNAL + // immutable events corresponding to the reserved signals. static QP::QEvt const l_reservedEvt_[4] { QP::QEvt(static_cast(QP::QHsm::Q_EMPTY_SIG)), @@ -57,263 +56,218 @@ static QP::QEvt const l_reservedEvt_[4] { QP::QEvt(static_cast(QP::QHsm::Q_INIT_SIG)) }; -// maximum depth of state nesting in a QHsm (including the top level) -// must be >= 3 -static constexpr std::int_fast8_t QHSM_MAX_NEST_DEPTH_ {6}; +//! @endcond } // unnamed namespace -// helper macro to handle reserved event in an QHsm +//============================================================================ +//! @cond INTERNAL + +// internal helper macro to pass a reserved event into the state handler #define QHSM_RESERVED_EVT_(state_, sig_) \ ((*(state_))(this, &l_reservedEvt_[(sig_)])) -// helper macro to trace state entry -#define QS_STATE_ENTRY_(state_, qsId_) \ - QS_CRIT_ENTRY(); \ - QS_MEM_SYS(); \ - QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, (qsId_)) \ - QS_OBJ_PRE(this); \ - QS_FUN_PRE(state_); \ - QS_END_PRE() \ - QS_MEM_APP(); \ +#ifdef Q_SPY +// helper macro to trace state action (entry/exit) +#define QS_STATE_ACT_(rec_, state_) \ + QS_CRIT_ENTRY(); \ + QS_BEGIN_PRE((rec_), qsId) \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(state_); \ + QS_END_PRE() \ QS_CRIT_EXIT() -// helper macro to trace state exit -#define QS_STATE_EXIT_(state_, qsId_) \ - QS_CRIT_ENTRY(); \ - QS_MEM_SYS(); \ - QS_BEGIN_PRE(QS_QEP_STATE_EXIT, (qsId_)) \ - QS_OBJ_PRE(this); \ - QS_FUN_PRE(state_); \ - QS_END_PRE() \ - QS_MEM_APP(); \ +// internal helper macro to top-most init +#define QS_TOP_INIT_(rec_, trg_) \ + QS_CRIT_ENTRY(); \ + QS_BEGIN_PRE((rec_), qsId) \ + QS_TIME_PRE(); \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(trg_); \ + QS_END_PRE() \ QS_CRIT_EXIT() -//! @endcond +// internal helper macro to trace transition segment +#define QS_TRAN_SEG_(rec_, src_, trg_) \ + QS_CRIT_ENTRY(); \ + QS_BEGIN_PRE((rec_), qsId) \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(src_); \ + QS_FUN_PRE(trg_); \ + QS_END_PRE() \ + QS_CRIT_EXIT() -//============================================================================ +// internal helper macro to trace transition action +#define QS_TRAN_ACT_(rec_, state_) \ + QS_CRIT_ENTRY(); \ + QS_BEGIN_PRE((rec_), qsId) \ + QS_SIG_PRE(e->sig); \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(state_); \ + QS_END_PRE() \ + QS_CRIT_EXIT() + +// internal helper macro to trace transition begin/end +#define QS_TRAN0_(rec_, trg_) \ + QS_CRIT_ENTRY(); \ + QS_BEGIN_PRE((rec_), qsId) \ + QS_TIME_PRE(); \ + QS_SIG_PRE(e->sig); \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(trg_); \ + QS_END_PRE() \ + QS_CRIT_EXIT() -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required +// internal helper macro to trace regulsr transition +#define QS_TRAN_END_(rec_, src_, trg_) \ + QS_CRIT_ENTRY(); \ + QS_BEGIN_PRE((rec_), qsId) \ + QS_TIME_PRE(); \ + QS_SIG_PRE(e->sig); \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(src_); \ + QS_FUN_PRE(trg_); \ + QS_END_PRE() \ + QS_CRIT_EXIT() + +#else +#define QS_STATE_ACT_(rec_, state_) (static_cast(0)) +#define QS_TOP_INIT_(rec_, trg_) (static_cast(0)) +#define QS_TRAN_SEG_(rec_, src_, trg_) (static_cast(0)) +#define QS_TRAN_ACT_(rec_, state_) (static_cast(0)) +#define QS_TRAN0_(rec_, trg_) (static_cast(0)) +#define QS_TRAN_END_(rec_, src_, trg_) (static_cast(0)) #endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QEP::versionStr[]} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -} // namespace QP -//$enddef${QEP::versionStr[]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//! @endcond -//$define${QEP::QHsm} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { -//${QEP::QHsm} ............................................................... - -//${QEP::QHsm::QHsm} ......................................................... +//............................................................................ QHsm::QHsm(QStateHandler const initial) noexcept : QAsm() { - m_state.fun = Q_STATE_CAST(&top); + m_state.fun = ⊤ m_temp.fun = initial; } -//${QEP::QHsm::init} ......................................................... +//............................................................................ void QHsm::init( void const * const e, std::uint_fast8_t const qsId) { QF_CRIT_STAT - QState r; - // produce QS dictionary for QP::QHsm::top() - #ifdef Q_SPY +#ifdef Q_SPY QS_CRIT_ENTRY(); - QS_MEM_SYS(); + bool isDone = true; if ((QS::priv_.flags & 0x01U) == 0U) { QS::priv_.flags |= 0x01U; - r = Q_RET_HANDLED; - } - else { - r = Q_RET_IGNORED; + isDone = false; } - QS_MEM_APP(); QS_CRIT_EXIT(); - if (r == Q_RET_HANDLED) { + if (!isDone) { QS_FUN_DICTIONARY(&QP::QHsm::top); } - #else +#else Q_UNUSED_PAR(qsId); - #endif // def Q_SPY +#endif // def Q_SPY QStateHandler t = m_state.fun; QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(200, (m_temp.fun != nullptr) - && (t == Q_STATE_CAST(&top))); + Q_REQUIRE_INCRIT(200, + (m_temp.fun != nullptr) + && (t == Q_STATE_CAST(&top))); QF_CRIT_EXIT(); // execute the top-most initial tran. - r = (*m_temp.fun)(this, Q_EVT_CAST(QEvt)); + QState r = (*m_temp.fun)(this, Q_EVT_CAST(QEvt)); QF_CRIT_ENTRY(); // the top-most initial tran. must be taken Q_ASSERT_INCRIT(210, r == Q_RET_TRAN); - - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(t); // the source state - QS_FUN_PRE(m_temp.fun); // the target of the initial tran. - QS_END_PRE() - QS_MEM_APP(); - QF_CRIT_EXIT(); + QS_TRAN_SEG_(QS_QEP_STATE_INIT, t, m_temp.fun); + // drill down into the state hierarchy with initial transitions... - do { - QStateHandler path[QHSM_MAX_NEST_DEPTH_]; // tran. entry path array - std::int_fast8_t ip = 0; // tran. entry path index + QStateHandler path[QHSM_MAX_NEST_DEPTH_]; // tran. entry path array + path[0] = m_temp.fun; + static_cast(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); - path[0] = m_temp.fun; + std::int_fast8_t ip = 1; // tran. entry path index (also the loop bound) + for (; (m_temp.fun != t) && (ip < QHSM_MAX_NEST_DEPTH_); ++ip) { + path[ip] = m_temp.fun; static_cast(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); - // note: ip is here the fixed upper loop bound - while ((m_temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) { - ++ip; - path[ip] = m_temp.fun; - static_cast(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); - } - QF_CRIT_ENTRY(); - // too many state nesting levels or "malformed" HSM - Q_ENSURE_INCRIT(220, ip < QHSM_MAX_NEST_DEPTH_); - QF_CRIT_EXIT(); - - m_temp.fun = path[0]; - - // retrace the entry path in reverse (desired) order... - // note: ip is the fixed upper loop bound - do { - // enter path[ip] - if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) - == Q_RET_HANDLED) - { - QS_STATE_ENTRY_(path[ip], qsId); - } - --ip; - } while (ip >= 0); - - t = path[0]; // current state becomes the new source - - r = QHSM_RESERVED_EVT_(t, Q_INIT_SIG); // execute initial tran. - - #ifdef Q_SPY - if (r == Q_RET_TRAN) { - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(t); // the source state - QS_FUN_PRE(m_temp.fun); // the target of the initial tran. - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); - } - #endif // Q_SPY - } while (r == Q_RET_TRAN); - + } QF_CRIT_ENTRY(); + // must NOT be too many state nesting levels or "malformed" HSM + Q_ASSERT_INCRIT(220, ip <= QHSM_MAX_NEST_DEPTH_); + QF_CRIT_EXIT(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_INIT_TRAN, qsId) - QS_TIME_PRE(); // time stamp - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(t); // the new active state - QS_END_PRE() - QS_MEM_APP(); + m_temp.fun = path[0]; + enter_target_(&path[0], ip - 1, qsId); + t = path[0]; - QF_CRIT_EXIT(); + QS_TOP_INIT_(QS_QEP_INIT_TRAN, t); - m_state.fun = t; // change the current active state - #ifndef Q_UNSAFE - m_temp.uint = ~m_state.uint; - #endif + m_state.fun = t; // change the current active state +#ifdef Q_UNSAFE + Q_UNUSED_PAR(r); +#endif } -//${QEP::QHsm::dispatch} ..................................................... +//............................................................................ void QHsm::dispatch( QEvt const * const e, std::uint_fast8_t const qsId) { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(qsId); - #endif +#endif QStateHandler s = m_state.fun; QStateHandler t = s; QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(300, (e != nullptr) && (s != nullptr)); - Q_INVARIANT_INCRIT(301, - e->verify_() - && (m_state.uint == static_cast(~m_temp.uint))); - - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_DISPATCH, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s); // the current state - QS_END_PRE() - QS_MEM_APP(); - + Q_REQUIRE_INCRIT(300, + (e != nullptr) + && (s != nullptr)); QF_CRIT_EXIT(); + QS_TRAN0_(QS_QEP_DISPATCH, s); + + QState r = Q_RET_SUPER; + // process the event hierarchically... - QState r; m_temp.fun = s; - std::int_fast8_t ip = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound - do { + std::int_fast8_t ip = QHSM_MAX_NEST_DEPTH_; + // NOTE: ip is the fixed loop upper bound + for (; ip > 0; --ip) { s = m_temp.fun; r = (*s)(this, e); // invoke state handler s if (r == Q_RET_UNHANDLED) { // unhandled due to a guard? - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_UNHANDLED, qsId) - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s); // the current state - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); - + QS_TRAN_ACT_(QS_QEP_UNHANDLED, s); r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); // superstate of s } - - --ip; - } while ((r == Q_RET_SUPER) && (ip > 0)); - + if (r != Q_RET_SUPER) { // event NOT "bubbled up" + break; + } + } QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(310, ip > 0); + Q_ASSERT_INCRIT(310, ip > 0); QF_CRIT_EXIT(); if (r >= Q_RET_TRAN) { // tran. (regular or history) taken? - #ifdef Q_SPY +#ifdef Q_SPY if (r == Q_RET_TRAN_HIST) { // tran. to history? - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_TRAN_HIST, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s); // tran. to history source - QS_FUN_PRE(m_temp.fun); // tran. to history target - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); + QS_TRAN_SEG_(QS_QEP_TRAN_HIST, s, m_temp.fun); } - #endif // Q_SPY +#endif // Q_SPY QStateHandler path[QHSM_MAX_NEST_DEPTH_]; path[0] = m_temp.fun; // tran. target @@ -321,224 +275,104 @@ void QHsm::dispatch( path[2] = s; // tran. source // exit current state to tran. source s... - ip = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound - for (; (t != s) && (ip > 0); t = m_temp.fun) { + while (t != s) { // exit from t if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) == Q_RET_HANDLED) { - QS_STATE_EXIT_(t, qsId); + QS_STATE_ACT_(QS_QEP_STATE_EXIT, t); // find superstate of t static_cast(QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG)); } - --ip; + t = m_temp.fun; } - QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(320, ip > 0); - QF_CRIT_EXIT(); - - ip = hsm_tran(&path[0], qsId); // take the tran. - // execute state entry actions in the desired order... - // note: ip is the fixed upper loop bound - for (; ip >= 0; --ip) { - // enter path[ip] - if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) - == Q_RET_HANDLED) - { - QS_STATE_ENTRY_(path[ip], qsId); - } + // take the tran... + ip = tran_simple_(&path[0], qsId); + if (ip < -1) { // not a simple tran.? + ip = tran_complex_(&path[0], qsId); } - t = path[0]; // stick the target into register - m_temp.fun = t; // update the next state - // drill into the target hierarchy... - while (QHSM_RESERVED_EVT_(t, Q_INIT_SIG) == Q_RET_TRAN) { - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(t); // the source (pseudo)state - QS_FUN_PRE(m_temp.fun); // the target of the tran. - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); - - ip = 0; - path[0] = m_temp.fun; - - // find superstate - static_cast(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); - - // note: ip is the fixed upper loop bound - while ((m_temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) { - ++ip; - path[ip] = m_temp.fun; - // find superstate - static_cast( - QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); - } - QF_CRIT_ENTRY(); - // too many state nesting levels or "malformed" HSM - Q_ENSURE_INCRIT(330, ip < QHSM_MAX_NEST_DEPTH_); - QF_CRIT_EXIT(); - - m_temp.fun = path[0]; - - // retrace the entry path in reverse (correct) order... - // note: ip is the fixed upper loop bound - do { - // enter path[ip] - if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) - == Q_RET_HANDLED) - { - QS_STATE_ENTRY_(path[ip], qsId); - } - --ip; - } while (ip >= 0); - - t = path[0]; // current state becomes the new source - } - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_TRAN, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s); // the source of the tran. - QS_FUN_PRE(t); // the new active state - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); + enter_target_(&path[0], ip, qsId); + t = path[0]; + QS_TRAN_END_(QS_QEP_TRAN, s, t); } - - #ifdef Q_SPY +#ifdef Q_SPY else if (r == Q_RET_HANDLED) { - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_INTERN_TRAN, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s); // the source state - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); + QS_TRAN0_(QS_QEP_INTERN_TRAN, s); } else { - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_IGNORED, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(m_state.fun); // the current state - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); + QS_TRAN0_(QS_QEP_IGNORED, m_state.fun); } - #endif // Q_SPY +#endif // Q_SPY m_state.fun = t; // change the current active state - #ifndef Q_UNSAFE - m_temp.uint = ~m_state.uint; - #endif } -//${QEP::QHsm::isIn} ......................................................... +//............................................................................ bool QHsm::isIn(QStateHandler const state) noexcept { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - Q_INVARIANT_INCRIT(602, - m_state.uint == static_cast(~m_temp.uint)); - QF_CRIT_EXIT(); - bool inState = false; // assume that this HSM is not in 'state' // scan the state hierarchy bottom-up QStateHandler s = m_state.fun; - std::int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_ + 1; // fixed upper loop bound QState r = Q_RET_SUPER; - for (; (r != Q_RET_IGNORED) && (lbound > 0); --lbound) { + while (r != Q_RET_IGNORED) { if (s == state) { // do the states match? inState = true; // 'true' means that match found break; // break out of the for-loop } - else { - r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); - s = m_temp.fun; - } + r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); + s = m_temp.fun; } - - QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(690, lbound > 0); - QF_CRIT_EXIT(); - - #ifndef Q_UNSAFE - m_temp.uint = ~m_state.uint; - #endif - return inState; // return the status } -//${QEP::QHsm::childState} ................................................... +//............................................................................ QStateHandler QHsm::childState(QStateHandler const parent) noexcept { +#ifndef Q_UNSAFE + bool isFound = false; // assume the child state NOT found +#endif + QStateHandler child = m_state.fun; // start with current state - bool isFound = false; // start with the child not found - - // establish stable state configuration - m_temp.fun = child; - QState r; - std::int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound - do { - // is this the parent of the current child? + m_temp.fun = child; // establish stable state configuration + QState r = Q_RET_SUPER; + while (r != Q_RET_IGNORED) { + // have the parent of the current child? if (m_temp.fun == parent) { - isFound = true; // child is found - r = Q_RET_IGNORED; // break out of the loop - } - else { - child = m_temp.fun; - r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG); +#ifndef Q_UNSAFE + isFound = true; // indicate that child state was found +#endif + break; } - --lbound; - } while ((r != Q_RET_IGNORED) // the top state not reached - && (lbound > 0)); - - #ifndef Q_UNSAFE - m_temp.uint = ~m_state.uint; - #else - Q_UNUSED_PAR(isFound); - #endif - + child = m_temp.fun; + r = QHSM_RESERVED_EVT_(child, Q_EMPTY_SIG); + } QF_CRIT_STAT QF_CRIT_ENTRY(); - // NOTE: the following postcondition can only succeed when - // (lbound > 0), so no extra check is necessary. - Q_ENSURE_INCRIT(890, isFound); + Q_ASSERT_INCRIT(590, isFound); QF_CRIT_EXIT(); return child; } -//${QEP::QHsm::hsm_tran} ..................................................... -std::int_fast8_t QHsm::hsm_tran( +//............................................................................ +//! @private @memberof QHsm +std::int_fast8_t QHsm::tran_simple_( QStateHandler * const path, std::uint_fast8_t const qsId) { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(qsId); - #endif +#endif - std::int_fast8_t ip = -1; // tran. entry path index QStateHandler t = path[0]; QStateHandler const s = path[2]; - QF_CRIT_STAT + std::int_fast8_t ip = 0; // tran. entry path index + QS_CRIT_STAT // (a) check source==target (tran. to self)... if (s == t) { // exit source s if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) { - QS_STATE_EXIT_(s, qsId); + QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); } ip = 0; // enter the target } @@ -560,121 +394,184 @@ std::int_fast8_t QHsm::hsm_tran( if (m_temp.fun == t) { // exit source s if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) { - QS_STATE_EXIT_(s, qsId); + QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); } ip = 0; // enter the target } + // (d) check source->super==target... + else if (m_temp.fun == path[0]) { + // exit source s + if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) { + QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); + } + ip = -1; // do not enter the target + } else { - // (d) check source->super==target... - if (m_temp.fun == path[0]) { - // exit source s - if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) { - QS_STATE_EXIT_(s, qsId); - } + path[1] = t; // save the superstate of target + ip = -2; // cause execution of complex tran. + } + } + } + return ip; +} + +//............................................................................ +//! @private @memberof QHsm +std::int_fast8_t QHsm::tran_complex_( + QStateHandler * const path, + std::uint_fast8_t const qsId) +{ +#ifndef Q_SPY + Q_UNUSED_PAR(qsId); +#endif + + // (e) check rest of source==target->super->super.. + // and store the entry path along the way + std::int_fast8_t iq = 0; // indicate that LCA was found + std::int_fast8_t ip = 1; // enter target and its superstate + QStateHandler const s = path[2]; // source state + QStateHandler t = m_temp.fun; // source->super + QF_CRIT_STAT + + // find target->super->super... + // note: ip is the fixed upper loop bound + QState r = QHSM_RESERVED_EVT_(path[1], Q_EMPTY_SIG); + while ((r == Q_RET_SUPER) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) { + ++ip; + path[ip] = m_temp.fun; // store the entry path + if (m_temp.fun == s) { // is it the source? + iq = 1; // indicate that the LCA found + --ip; // do not enter the source + break; // terminate the loop + } + r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG); + } + QF_CRIT_ENTRY(); + Q_INVARIANT_INCRIT(711, ip < (QHSM_MAX_NEST_DEPTH_ - 1)); + QF_CRIT_EXIT(); + + // the LCA not found yet? + if (iq == 0) { + + // exit source s +#ifndef Q_SPY + static_cast(QHSM_RESERVED_EVT_(s, Q_EXIT_SIG)); +#else + if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) { + QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); + } +#endif // def Q_SPY + + // (f) check the rest of + // source->super == target->super->super... + iq = ip; + r = Q_RET_IGNORED; // indicate that the LCA NOT found + // note: iq is the fixed upper loop bound + do { + if (t == path[iq]) { // is this the LCA? + r = Q_RET_HANDLED; // indicate the LCA found + ip = iq - 1; // do not enter the LCA + break; // terminate the loop + } + --iq; // try lower superstate of target + } while (iq >= 0); + + if (r != Q_RET_HANDLED) { // the LCA still not found? + // (g) check each source->super->... + // for each target->super... + r = Q_RET_SUPER; // keep looping + while (r != Q_RET_HANDLED) { + // exit from t + if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) == Q_RET_HANDLED) { + QS_STATE_ACT_(QS_QEP_STATE_EXIT, t); + // find superstate of t + static_cast(QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG)); } - else { - // (e) check rest of source==target->super->super.. - // and store the entry path along the way - std::int_fast8_t iq = 0; // indicate that LCA was found - ip = 1; // enter target and its superstate - path[1] = t; // save the superstate of target - t = m_temp.fun; // save source->super - - // find target->super->super... - // note: ip is the fixed upper loop bound - QState r = QHSM_RESERVED_EVT_(path[1], Q_EMPTY_SIG); - while ((r == Q_RET_SUPER) - && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) - { - ++ip; - path[ip] = m_temp.fun; // store the entry path - if (m_temp.fun == s) { // is it the source? - iq = 1; // indicate that the LCA found - --ip; // do not enter the source - r = Q_RET_HANDLED; // terminate the loop - } - else { // it is not the source, keep going up - r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG); - } + t = m_temp.fun; // set to super of t + iq = ip; + do { + if (t == path[iq]) { // is this the LCA? + ip = iq - 1; // do not enter the LCA + r = Q_RET_HANDLED; // break outer loop + break; // terminate the inner loop } - QF_CRIT_ENTRY(); - // NOTE: The following postcondition succeeds only when - // ip < QHSM_MAX_NEST_DEPTH, so no additional check is necessary - // too many state nesting levels or "malformed" HSM. - Q_ENSURE_INCRIT(510, r != Q_RET_SUPER); - QF_CRIT_EXIT(); - - // the LCA not found yet? - if (iq == 0) { - // exit source s - if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) - == Q_RET_HANDLED) - { - QS_STATE_EXIT_(s, qsId); - } - - // (f) check the rest of source->super - // == target->super->super... - iq = ip; - r = Q_RET_IGNORED; // indicate that the LCA NOT found - // note: iq is the fixed upper loop bound - do { - if (t == path[iq]) { // is this the LCA? - r = Q_RET_HANDLED; // indicate the LCA found - ip = iq - 1; // do not enter the LCA - iq = -1; // cause termination of the loop - } - else { - --iq; // try lower superstate of target - } - } while (iq >= 0); - - // the LCA not found yet? - if (r != Q_RET_HANDLED) { - // (g) check each source->super->... - // for each target->super... - r = Q_RET_IGNORED; // keep looping - std::int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_; - do { - // exit from t - if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) - == Q_RET_HANDLED) - { - QS_STATE_EXIT_(t, qsId); - // find superstate of t - static_cast( - QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG)); - } - t = m_temp.fun; // set to super of t - iq = ip; - do { - // is this the LCA? - if (t == path[iq]) { - ip = iq - 1; // do not enter the LCA - iq = -1; // break out of inner loop - r = Q_RET_HANDLED; // break outer loop - } - else { - --iq; - } - } while (iq >= 0); - - --lbound; - } while ((r != Q_RET_HANDLED) && (lbound > 0)); - QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(530, lbound > 0); - QF_CRIT_EXIT(); - } - } - } + --iq; // try lower superstate of target + } while (iq >= 0); } } } + return ip; +} + +//............................................................................ +//! @private @memberof QHsm +void QHsm::enter_target_( + QStateHandler * const path, + std::int_fast8_t const depth, + std::uint_fast8_t const qsId) +{ +#ifndef Q_SPY + Q_UNUSED_PAR(qsId); +#endif + + QF_CRIT_STAT + QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(590, ip < QHSM_MAX_NEST_DEPTH_); + Q_REQUIRE_INCRIT(800, depth < QHSM_MAX_NEST_DEPTH_); QF_CRIT_EXIT(); - return ip; + + std::int_fast8_t ip = depth; + // execute state entry actions in the desired order... + // note: ip is the fixed upper loop bound + for (; ip >= 0; --ip) { + // enter path[ip] + if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) + == Q_RET_HANDLED) + { + QS_STATE_ACT_(QS_QEP_STATE_ENTRY, path[ip]); + } + } + QStateHandler t = path[0]; + m_temp.fun = t; // update the next state + + // drill into the target hierarchy... + while (QHSM_RESERVED_EVT_(t, Q_INIT_SIG) == Q_RET_TRAN) { + + QS_TRAN_SEG_(QS_QEP_STATE_INIT, t, m_temp.fun); + + ip = 0; + path[0] = m_temp.fun; + + // find superstate + static_cast(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); + + // note: ip is the fixed upper loop bound + while ((m_temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) { + ++ip; + path[ip] = m_temp.fun; + // find superstate + static_cast(QHSM_RESERVED_EVT_( + m_temp.fun, Q_EMPTY_SIG)); + } + QF_CRIT_ENTRY(); + // too many state nesting levels or "malformed" HSM + Q_INVARIANT_INCRIT(891, ip < QHSM_MAX_NEST_DEPTH_); + QF_CRIT_EXIT(); + + m_temp.fun = path[0]; + + // retrace the entry path in reverse (correct) order... + // note: ip is the fixed upper loop bound + do { + // enter path[ip] + if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) == Q_RET_HANDLED) { + QS_STATE_ACT_(QS_QEP_STATE_ENTRY, path[ip]); + } + --ip; + } while (ip >= 0); + + t = path[0]; // current state becomes the new source + } } } // namespace QP -//$enddef${QEP::QHsm} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/qf/qep_msm.cpp b/src/qf/qep_msm.cpp index 160f31960..7c2d259c8 100644 --- a/src/qf/qep_msm.cpp +++ b/src/qf/qep_msm.cpp @@ -1,10 +1,6 @@ -//$file${src::qf::qep_msm.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qf::qep_msm.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${src::qf::qep_msm.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -42,16 +37,18 @@ #include "qs_dummy.hpp" // disable the QS software tracing #endif // Q_SPY -//============================================================================ -//! @cond INTERNAL - // unnamed namespace for local definitions with internal linkage namespace { Q_DEFINE_THIS_MODULE("qep_msm") +// maximum depth of entry levels in a MSM for tran. to history. +static constexpr std::int_fast8_t QMSM_MAX_ENTRY_DEPTH_ {4}; + +//! @cond INTERNAL + // top-state object for QMsm-style state machines -QP::QMState const l_msm_top_s = { +constexpr QP::QMState l_msm_top_s = { nullptr, nullptr, nullptr, @@ -59,32 +56,75 @@ QP::QMState const l_msm_top_s = { nullptr }; -// maximum depth of state nesting in a QMsm (including the top level) -static constexpr std::int_fast8_t QMSM_MAX_NEST_DEPTH_ {8}; - -// maximum length of transition-action array -static constexpr std::int_fast8_t QMSM_MAX_TRAN_LENGTH_ {2*QMSM_MAX_NEST_DEPTH_}; +} // unnamed namespace -// maximum depth of entry levels in a MSM for tran. to history. -static constexpr std::int_fast8_t QMSM_MAX_ENTRY_DEPTH_ {4}; +#ifdef Q_SPY +// helper macro to trace state action (entry/exit) +#define QS_STATE_ACT_(rec_, state_) \ + QS_CRIT_ENTRY(); \ + QS_BEGIN_PRE((rec_), qsId) \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(state_); \ + QS_END_PRE() \ + QS_CRIT_EXIT() + +// internal helper macro to top-most init +#define QS_TOP_INIT_(rec_, trg_) \ + QS_CRIT_ENTRY(); \ + QS_BEGIN_PRE((rec_), qsId) \ + QS_TIME_PRE(); \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(trg_); \ + QS_END_PRE() \ + QS_CRIT_EXIT() + +// internal helper macro to trace transition segment +#define QS_TRAN_SEG_(rec_, src_, trg_) \ + QS_CRIT_ENTRY(); \ + QS_BEGIN_PRE((rec_), qsId) \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(src_); \ + QS_FUN_PRE(trg_); \ + QS_END_PRE() \ + QS_CRIT_EXIT() + +// internal helper macro to trace transition begin/end +#define QS_TRAN0_(rec_, trg_) \ + QS_CRIT_ENTRY(); \ + QS_BEGIN_PRE((rec_), qsId) \ + QS_TIME_PRE(); \ + QS_SIG_PRE(e->sig); \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(trg_); \ + QS_END_PRE() \ + QS_CRIT_EXIT() + +// internal helper macro to trace regulsr transition +#define QS_TRAN_END_(rec_, src_, trg_) \ + QS_CRIT_ENTRY(); \ + QS_BEGIN_PRE((rec_), qsId) \ + QS_TIME_PRE(); \ + QS_SIG_PRE(e->sig); \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(src_); \ + QS_FUN_PRE(trg_); \ + QS_END_PRE() \ + QS_CRIT_EXIT() -} // unnamed namespace +#else +#define QS_STATE_ACT_(rec_, state_) (static_cast(0)) +#define QS_TOP_INIT_(rec_, trg_) (static_cast(0)) +#define QS_TRAN_SEG_(rec_, src_, trg_) (static_cast(0)) +#define QS_TRAN0_(rec_, trg_) (static_cast(0)) +#define QS_TRAN_END_(rec_, src_, trg_) (static_cast(0)) +#endif //! @endcond -//============================================================================ -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QEP::QMsm} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +//============================================================================ namespace QP { -//${QEP::QMsm} ............................................................... - -//${QEP::QMsm::QMsm} ......................................................... +//............................................................................ QMsm::QMsm(QStateHandler const initial) noexcept : QAsm() { @@ -92,19 +132,20 @@ QMsm::QMsm(QStateHandler const initial) noexcept m_temp.fun = initial; // the initial tran. handler } -//${QEP::QMsm::init} ......................................................... +//............................................................................ void QMsm::init( void const * const e, std::uint_fast8_t const qsId) { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(qsId); - #endif +#endif QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(200, (m_temp.fun != nullptr) - && (m_state.obj == &l_msm_top_s)); + Q_REQUIRE_INCRIT(200, + (m_temp.fun != nullptr) + && (m_state.obj == &l_msm_top_s)); QF_CRIT_EXIT(); // execute the top-most initial tran. @@ -113,140 +154,85 @@ void QMsm::init( QF_CRIT_ENTRY(); // the top-most initial tran. must be taken Q_ASSERT_INCRIT(210, r == Q_RET_TRAN_INIT); - - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(m_state.obj->stateHandler); // source state - QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target state - QS_END_PRE() - QS_MEM_APP(); - QF_CRIT_EXIT(); + QS_TRAN_SEG_(QS_QEP_STATE_INIT, + m_state.obj->stateHandler, m_temp.tatbl->target->stateHandler); + // set state to the last tran. target m_state.obj = m_temp.tatbl->target; // drill down into the state hierarchy with initial transitions... - std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound - do { + while (r >= Q_RET_TRAN_INIT) { // execute the tran. table r = execTatbl_(m_temp.tatbl, qsId); - --lbound; - } while ((r >= Q_RET_TRAN_INIT) && (lbound > 0)); - - QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(290, lbound > 0); - - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_INIT_TRAN, qsId) - QS_TIME_PRE(); // time stamp - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(m_state.obj->stateHandler); // the new current state - QS_END_PRE() - QS_MEM_APP(); - - QF_CRIT_EXIT(); + } - #ifndef Q_UNSAFE - m_temp.uint = ~m_state.uint; - #endif + QS_TOP_INIT_(QS_QEP_INIT_TRAN, m_state.obj->stateHandler); } -//${QEP::QMsm::dispatch} ..................................................... +//............................................................................ void QMsm::dispatch( QEvt const * const e, std::uint_fast8_t const qsId) { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(qsId); - #endif +#endif QMState const *s = m_state.obj; // store the current state QMState const *t = s; QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(300, (e != nullptr) && (s != nullptr)); - Q_INVARIANT_INCRIT(301, - e->verify_() - && (m_state.uint == static_cast(~m_temp.uint))); - - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_DISPATCH, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s->stateHandler); // the current state handler - QS_END_PRE() - QS_MEM_APP(); - + Q_REQUIRE_INCRIT(300, + (e != nullptr) + && (s != nullptr)); QF_CRIT_EXIT(); + QS_TRAN0_(QS_QEP_DISPATCH, s->stateHandler); + // scan the state hierarchy up to the top state... - QState r; - std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound - do { + QState r = Q_RET_SUPER; + while (t != nullptr) { r = (*t->stateHandler)(this, e); // call state handler function - // event handled? (the most frequent case) - if (r >= Q_RET_HANDLED) { + if (r >= Q_RET_HANDLED) { // event handled? (the most frequent case) break; // done scanning the state hierarchy } - // event unhandled and passed to the superstate? - else if (r == Q_RET_SUPER) { - t = t->superstate; // advance to the superstate - } - else { // event unhandled due to a guard - QF_CRIT_ENTRY(); - // event must be unhandled due to a guard evaluating to 'false' - Q_ASSERT_INCRIT(310, r == Q_RET_UNHANDLED); - - QS_MEM_SYS(); +#ifdef Q_SPY + if (r == Q_RET_UNHANDLED) { // event unhandled due to a guard? + QS_CRIT_ENTRY(); QS_BEGIN_PRE(QS_QEP_UNHANDLED, qsId) - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(t->stateHandler); // the current state + QS_SIG_PRE(e->sig); + QS_OBJ_PRE(this); + QS_FUN_PRE(t->stateHandler); QS_END_PRE() - QS_MEM_APP(); - - QF_CRIT_EXIT(); - - t = t->superstate; // advance to the superstate + QS_CRIT_EXIT(); } - --lbound; - } while ((t != nullptr) && (lbound > 0)); - QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(320, lbound > 0); - QF_CRIT_EXIT(); +#endif + t = t->superstate; // advance to the superstate + } if (r >= Q_RET_TRAN) { // any kind of tran. taken? QF_CRIT_ENTRY(); - // the tran. source state must not be nullptr + // the tran. source state must not be NULL Q_ASSERT_INCRIT(330, t != nullptr); QF_CRIT_EXIT(); - #ifdef Q_SPY - QMState const * const ts = t; // for saving tran. table - #endif // Q_SPY - QMTranActTable const *tatbl; +#ifdef Q_SPY + QMState const * const ts = t; // tran. source for QS tracing +#endif // Q_SPY if (r == Q_RET_TRAN_HIST) { // was it tran. to history? QMState const * const hist = m_state.obj; // save history m_state.obj = s; // restore the original state - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_TRAN_HIST, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(t->stateHandler); // source state handler - QS_FUN_PRE(hist->stateHandler); // target state handler - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); + QS_TRAN_SEG_(QS_QEP_TRAN_HIST, + t->stateHandler, hist->stateHandler); // save the tran-action table before it gets clobbered - tatbl = m_temp.tatbl; + QMTranActTable const *tatbl = m_temp.tatbl; exitToTranSource_(s, t, qsId); static_cast(execTatbl_(tatbl, qsId)); r = enterHistory_(hist, qsId); @@ -254,205 +240,120 @@ void QMsm::dispatch( t = s; // set target to the current state } - lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound - while ((r >= Q_RET_TRAN) && (lbound > 0)) { + while (r >= Q_RET_TRAN) { // save the tran-action table before it gets clobbered - tatbl = m_temp.tatbl; + QMTranActTable const *tatbl = m_temp.tatbl; m_temp.obj = nullptr; // clear exitToTranSource_(s, t, qsId); r = execTatbl_(tatbl, qsId); s = m_state.obj; t = s; // set target to the current state - --lbound; } - QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(360, lbound > 0); - - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_TRAN, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(ts->stateHandler); // the tran. source - QS_FUN_PRE(s->stateHandler); // the new active state - QS_END_PRE() - QS_MEM_APP(); - - QF_CRIT_EXIT(); + QS_TRAN_END_(QS_QEP_TRAN, ts->stateHandler, s->stateHandler); } - - #ifdef Q_SPY - // was the event handled? - else if (r == Q_RET_HANDLED) { +#ifdef Q_SPY + else if (r == Q_RET_HANDLED) { // was the event handled? QF_CRIT_ENTRY(); - // internal tran. source can't be nullptr + // internal tran. source can't be NULL Q_ASSERT_INCRIT(380, t != nullptr); - - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_INTERN_TRAN, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(t->stateHandler); // the source state - QS_END_PRE() - QS_MEM_APP(); - QF_CRIT_EXIT(); + + QS_TRAN0_(QS_QEP_INTERN_TRAN, t->stateHandler); } - // event bubbled to the 'top' state? - else if (t == nullptr) { - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_IGNORED, qsId) - QS_TIME_PRE(); // time stamp - QS_SIG_PRE(e->sig); // the signal of the event - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s->stateHandler); // the current state - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); + else if (t == nullptr) { // event bubbled to the 'top' state? + QS_TRAN0_(QS_QEP_IGNORED, s->stateHandler); } - #endif // Q_SPY +#endif // Q_SPY else { // empty } - - #ifndef Q_UNSAFE - m_temp.uint = ~m_state.uint; - #endif } -//${QEP::QMsm::isIn} ......................................................... +//............................................................................ bool QMsm::isIn(QStateHandler const state) noexcept { bool inState = false; // assume that this SM is not in 'state' QMState const *s = m_state.obj; - std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound - for (; (s != nullptr) && (lbound > 0); --lbound) { + while (s != nullptr) { if (s->stateHandler == state) { // match found? inState = true; break; } - else { - s = s->superstate; // advance to the superstate - } + s = s->superstate; // advance to the superstate } - QF_CRIT_STAT - QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(490, lbound > 0); - QF_CRIT_EXIT(); - return inState; } -//${QEP::QMsm::childStateObj} ................................................ -QMState const * QMsm::childStateObj(QMState const * const parent) const noexcept { - QMState const *child = m_state.obj; - bool isFound = false; // start with the child not found - QMState const *s; - - std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound - for (s = m_state.obj; - (s != nullptr) && (lbound > 0); - s = s->superstate) - { +//............................................................................ +QMState const * QMsm::childStateObj(QMState const * const parent) + const noexcept +{ + QMState const *s = m_state.obj; // start with current state + QMState const *child = s; + bool isFound = false; // assume the child NOT found + + while (s != nullptr) { if (s == parent) { isFound = true; // child is found break; } - else { - child = s; - } - --lbound; + child = s; + s = s->superstate; } QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(680, lbound > 0); + Q_ASSERT_INCRIT(590, isFound); QF_CRIT_EXIT(); - if (!isFound) { // still not found? - lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound - for (s = m_temp.obj; - (s != nullptr) && (lbound > 0); - s = s->superstate) - { - if (s == parent) { - isFound = true; // child is found - break; - } - else { - child = s; - } - --lbound; - } - } - - QF_CRIT_ENTRY(); - // NOTE: the following postcondition can only succeed when - // (lbound > 0), so no extra check is necessary. - Q_ENSURE_INCRIT(690, isFound); - QF_CRIT_EXIT(); +#ifdef Q_UNSAFE + Q_UNUSED_PAR(isFound); +#endif return child; // return the child } -//${QEP::QMsm::execTatbl_} ................................................... +//............................................................................ QState QMsm::execTatbl_( QMTranActTable const * const tatbl, std::uint_fast8_t const qsId) { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(qsId); - #endif +#endif QF_CRIT_STAT QF_CRIT_ENTRY(); // precondition: // - the tran-action table pointer must not be NULL - Q_REQUIRE_INCRIT(700, tatbl != nullptr); + Q_REQUIRE_INCRIT(600, tatbl != nullptr); QF_CRIT_EXIT(); QState r = Q_RET_NULL; - std::int_fast8_t lbound = QMSM_MAX_TRAN_LENGTH_; // fixed upper loop bound QActionHandler const *a = &tatbl->act[0]; - for (; (*a != nullptr) && (lbound > 0); ++a) { + while (*a != nullptr) { r = (*(*a))(this); // call the action through the 'a' pointer - --lbound; - #ifdef Q_SPY - QS_CRIT_ENTRY(); - QS_MEM_SYS(); + ++a; +#ifdef Q_SPY if (r == Q_RET_ENTRY) { - QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(m_temp.obj->stateHandler); // entered state - QS_END_PRE() + QS_STATE_ACT_(QS_QEP_STATE_ENTRY, m_temp.obj->stateHandler); } else if (r == Q_RET_EXIT) { - QS_BEGIN_PRE(QS_QEP_STATE_EXIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(m_temp.obj->stateHandler); // exited state - QS_END_PRE() + QS_STATE_ACT_(QS_QEP_STATE_EXIT, m_temp.obj->stateHandler); } else if (r == Q_RET_TRAN_INIT) { - QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(tatbl->target->stateHandler); // source - QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target - QS_END_PRE() + QS_TRAN_SEG_(QS_QEP_STATE_INIT, + tatbl->target->stateHandler, + m_temp.tatbl->target->stateHandler); } else { // empty } - QS_MEM_APP(); - QS_CRIT_EXIT(); - #endif // Q_SPY +#endif // Q_SPY } QF_CRIT_ENTRY(); - // NOTE: the following postcondition can only succeed when - // (lbound > 0), so no extra check is necessary. - Q_ENSURE_INCRIT(790, *a == nullptr); + Q_ASSERT_INCRIT(690, *a == nullptr); QF_CRIT_EXIT(); m_state.obj = (r >= Q_RET_TRAN) @@ -461,58 +362,45 @@ QState QMsm::execTatbl_( return r; } -//${QEP::QMsm::exitToTranSource_} ............................................ +//............................................................................ void QMsm::exitToTranSource_( QMState const * const cs, QMState const * const ts, std::uint_fast8_t const qsId) { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(qsId); - #endif - - QF_CRIT_STAT +#endif + QS_CRIT_STAT // exit states from the current state to the tran. source state QMState const *s = cs; - std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound - for (; (s != ts) && (lbound > 0); --lbound) { + while (s != ts) { // exit action provided in state 's'? if (s->exitAction != nullptr) { // execute the exit action static_cast((*s->exitAction)(this)); - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_STATE_EXIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(s->stateHandler); // the exited state handler - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); + QS_STATE_ACT_(QS_QEP_STATE_EXIT, m_temp.obj->stateHandler); } - s = s->superstate; // advance to the superstate } - QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(890, lbound > 0); - QF_CRIT_EXIT(); } -//${QEP::QMsm::enterHistory_} ................................................ +//............................................................................ QState QMsm::enterHistory_( QMState const * const hist, std::uint_fast8_t const qsId) { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(qsId); - #endif +#endif // record the entry path from current state to history QMState const *epath[QMSM_MAX_ENTRY_DEPTH_]; QMState const *s = hist; - std::int_fast8_t i = 0; // tran. entry path index - while ((s != m_state.obj) && (i < (QMSM_MAX_ENTRY_DEPTH_ - 1))) { + std::int_fast8_t i = 0; // tran. entry path index & fixed upper loop bound + while ((s != m_state.obj) && (i < QMSM_MAX_ENTRY_DEPTH_)) { if (s->entryAction != nullptr) { epath[i] = s; ++i; @@ -521,51 +409,34 @@ QState QMsm::enterHistory_( } QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(910, s == m_state.obj); + Q_ASSERT_INCRIT(810, i <= QMSM_MAX_ENTRY_DEPTH_); QF_CRIT_EXIT(); // retrace the entry path in reverse (desired) order... - while (i > 0) { - --i; - (*epath[i]->entryAction)(this); // run entry action in epath[i] - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, qsId) - QS_OBJ_PRE(this); - QS_FUN_PRE(epath[i]->stateHandler); // entered state handler - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); + // NOTE: i the fixed upper loop bound + for (i = i - 1; i >= 0; --i) { + // run entry action in epath[i] + static_cast((*epath[i]->entryAction)(this)); + + QS_STATE_ACT_(QS_QEP_STATE_ENTRY, epath[i]->stateHandler); } m_state.obj = hist; // set current state to the tran. target // initial tran. present? - QState r; + QState r = Q_RET_NULL; if (hist->initAction != nullptr) { r = (*hist->initAction)(this); // execute the tran. action - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE(this); // this state machine object - QS_FUN_PRE(hist->stateHandler); // source - QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target - QS_END_PRE() - QS_MEM_APP(); - QS_CRIT_EXIT(); - } - else { - r = Q_RET_NULL; - } + QS_TRAN_SEG_(QS_QEP_STATE_INIT, + hist->stateHandler, m_temp.tatbl->target->stateHandler); + } return r; } -//${QEP::QMsm::topQMState} ................................................... +//............................................................................ QMState const * QMsm::topQMState() const noexcept { return &l_msm_top_s; } } // namespace QP -//$enddef${QEP::QMsm} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/qf/qf_act.cpp b/src/qf/qf_act.cpp index f0c8de6ef..60e67a56d 100644 --- a/src/qf/qf_act.cpp +++ b/src/qf/qf_act.cpp @@ -1,10 +1,6 @@ -//$file${src::qf::qf_act.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qf::qf_act.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${src::qf::qf_act.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -48,27 +43,17 @@ namespace { //Q_DEFINE_THIS_MODULE("qf_act") } // unnamed namespace -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QF::QActive::registry_[QF_MAX_ACTIVE + 1U]} vvvvvvvvvvvvvvvvvvvvvvv namespace QP { -QActive * QActive::registry_[QF_MAX_ACTIVE + 1U]; -} // namespace QP -//$enddef${QF::QActive::registry_[QF_MAX_ACTIVE + 1U]} ^^^^^^^^^^^^^^^^^^^^^^^ +// QP version string embedded in the binary image +char const versionStr[] = "QP/C++ " QP_VERSION_STR; + +QActive * QActive::registry_[QF_MAX_ACTIVE + 1U]; -//$define${QF::QF-pkg} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { namespace QF { -//${QF::QF-pkg::priv_} ....................................................... QF::Attr priv_; -//${QF::QF-pkg::bzero_} ...................................................... void bzero_( void * const start, std::uint_fast16_t const len) noexcept @@ -81,57 +66,47 @@ void bzero_( } } // namespace QF -} // namespace QP -//$enddef${QF::QF-pkg} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QF::types::QF_LOG2} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -//${QF::types::QF_LOG2} ...................................................... +//............................................................................ #ifndef QF_LOG2 -std::uint_fast8_t QF_LOG2(QP::QPSetBits x) noexcept { - static std::uint8_t const log2LUT[16] = { +std::uint_fast8_t QF_LOG2(QP::QPSetBits const bitmask) noexcept { + static constexpr std::uint8_t log2LUT[16] = { 0U, 1U, 2U, 2U, 3U, 3U, 3U, 3U, 4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U }; std::uint_fast8_t n = 0U; - QP::QPSetBits t; + QP::QPSetBits x = bitmask; + QP::QPSetBits tmp; - #if (QF_MAX_ACTIVE > 16U) - t = static_cast(x >> 16U); - if (t != 0U) { +#if (QF_MAX_ACTIVE > 16U) + tmp = static_cast(x >> 16U); + if (tmp != 0U) { n += 16U; - x = t; + x = tmp; } - #endif - #if (QF_MAX_ACTIVE > 8U) - t = (x >> 8U); - if (t != 0U) { +#endif +#if (QF_MAX_ACTIVE > 8U) + tmp = (x >> 8U); + if (tmp != 0U) { n += 8U; - x = t; + x = tmp; } - #endif - t = (x >> 4U); - if (t != 0U) { +#endif + tmp = (x >> 4U); + if (tmp != 0U) { n += 4U; - x = t; + x = tmp; } return n + log2LUT[x]; } #endif // ndef QF_LOG2 -} // namespace QP -//$enddef${QF::types::QF_LOG2} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//............................................................................ #ifndef Q_UNSAFE -//$define${QF::types::QPtrDis} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QF::types::QPtrDis} ...................................................... - -//${QF::types::QPtrDis::QPtrDis} ............................................. QPtrDis::QPtrDis(void const * const ptr) noexcept : m_ptr_dis(static_cast(~Q_PTR2UINT_CAST_(ptr))) {} +#endif } // namespace QP -//$enddef${QF::types::QPtrDis} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#endif + diff --git a/src/qf/qf_actq.cpp b/src/qf/qf_actq.cpp index a1b49acef..d156011ac 100644 --- a/src/qf/qf_actq.cpp +++ b/src/qf/qf_actq.cpp @@ -1,10 +1,6 @@ -//$file${src::qf::qf_actq.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qf::qf_actq.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${src::qf::qf_actq.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -49,243 +44,122 @@ namespace { Q_DEFINE_THIS_MODULE("qf_actq") } // unnamed namespace -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QF::QActive::post_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { -//${QF::QActive::post_} ...................................................... +//............................................................................ bool QActive::post_( QEvt const * const e, std::uint_fast16_t const margin, void const * const sender) noexcept { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(sender); - #endif +#endif - #ifdef Q_UTEST // test? - #if (Q_UTEST != 0) // testing QP-stub? +#ifdef Q_UTEST // test? +#if (Q_UTEST != 0) // testing QP-stub? if (m_temp.fun == Q_STATE_CAST(0)) { // QActiveDummy? return static_cast(this)->fakePost(e, margin, sender); } - #endif // (Q_UTEST != 0) - #endif // def Q_UTEST +#endif // (Q_UTEST != 0) +#endif // def Q_UTEST QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); Q_REQUIRE_INCRIT(200, e != nullptr); - QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary - #ifndef Q_UNSAFE - QEQueueCtr dis = static_cast(~m_eQueue.m_nFree_dis); - Q_INVARIANT_INCRIT(201, e->verify_() && (tmp == dis)); - #endif // ndef Q_UNSAFE - - // test-probe#1 for faking queue overflow - QS_TEST_PROBE_DEF(&QActive::post_) - QS_TEST_PROBE_ID(1, - tmp = 0U; // fake no free events - ) + QEQueueCtr const nFree = m_eQueue.m_nFree; // get volatile into temporary // required margin available? - bool status; + bool status = false; // assume that event cannot be posted if (margin == QF::NO_MARGIN) { - if (tmp > 0U) { // free entries available in the queue? + if (nFree > 0U) { // free entries available in the queue? status = true; // can post } else { // no free entries available - status = false; // cannot post - // The queue overflows, but QF_NO_MARGIN indicates that // the "event delivery guarantee" is required. Q_ERROR_INCRIT(210); // must be able to post the event } } - else if (tmp > static_cast(margin)) { + else if (nFree > static_cast(margin)) { // enough free? status = true; // can post } - else { // the # free entries below the requested margin - status = false; // cannot post, but don't assert + else { + // empty } - // is it a mutable event? - if (e->getPoolNum_() != 0U) { +#if (QF_MAX_EPOOL > 0U) + if (e->poolNum_ != 0U) { // is it a mutable event? + Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); // increment the reference counter } +#endif // (QF_MAX_EPOOL > 0U) if (status) { // can post the event? - --tmp; // one free entry just used up - - m_eQueue.m_nFree = tmp; // update the original - #ifndef Q_UNSAFE - m_eQueue.m_nFree_dis = static_cast(~tmp); - #endif // ndef Q_UNSAFE - - if (m_eQueue.m_nMin > tmp) { - m_eQueue.m_nMin = tmp; // update minimum so far - } - - 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 - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); - QS_EQC_PRE(tmp); // # free entries - QS_EQC_PRE(m_eQueue.m_nMin); // min # free entries - QS_END_PRE() - - #ifdef Q_UTEST - // callback to examine the posted event under the same conditions - // as producing the #QS_QF_ACTIVE_POST trace record, which are: - // the local filter for this AO ('m_prio') is set - if (QS_LOC_CHECK_(m_prio)) { - QF_MEM_APP(); - QF_CRIT_EXIT(); - - QS::onTestPost(sender, this, e, status); - - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - } - #endif // def Q_UTEST - - if (m_eQueue.m_frontEvt == nullptr) { // is the queue empty? - m_eQueue.m_frontEvt = e; // deliver event directly - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(211, m_eQueue.m_frontEvt_dis - == static_cast(~Q_PTR2UINT_CAST_(nullptr))); - m_eQueue.m_frontEvt_dis = - static_cast(~Q_PTR2UINT_CAST_(e)); - #endif // ndef Q_UNSAFE - - #ifdef QXK_HPP_ - if (m_state.act == nullptr) { // eXtended thread? - QXTHREAD_EQUEUE_SIGNAL_(this); // signal eXtended Thread - } - else { - QACTIVE_EQUEUE_SIGNAL_(this); // signal the Active Object - } - #else - QACTIVE_EQUEUE_SIGNAL_(this); // signal the Active Object - #endif // def QXK_HPP_ - } - else { // queue was not empty, insert event into the ring-buffer - tmp = m_eQueue.m_head; // get volatile into temporary - #ifndef Q_UNSAFE - dis = static_cast(~m_eQueue.m_head_dis); - Q_INVARIANT_INCRIT(212, tmp == dis); - #endif // ndef Q_UNSAFE - m_eQueue.m_ring[tmp] = e; // insert e into buffer - - if (tmp == 0U) { // need to wrap the head? - tmp = m_eQueue.m_end; - } - --tmp; // advance the head (counter-clockwise) - - m_eQueue.m_head = tmp; // update the original - #ifndef Q_UNSAFE - m_eQueue.m_head_dis = static_cast(~tmp); - #endif // ndef Q_UNSAFE - } - - QF_MEM_APP(); + postFIFO_(e, sender); QF_CRIT_EXIT(); } else { // event cannot be posted - 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 - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); - QS_EQC_PRE(tmp); // # free entries + QS_OBJ_PRE(this); // this active object (recipient) + QS_2U8_PRE(e->poolNum_, e->refCtr_); + QS_EQC_PRE(nFree); // # free entries QS_EQC_PRE(margin); // margin requested QS_END_PRE() - #ifdef Q_UTEST - // callback to examine the posted event under the same conditions - // as producing the #QS_QF_ACTIVE_POST trace record, which are: - // the local filter for this AO ('m_prio') is set +#ifdef Q_UTEST if (QS_LOC_CHECK_(m_prio)) { - QF_MEM_APP(); QF_CRIT_EXIT(); - QS::onTestPost(sender, this, e, status); - QF_CRIT_ENTRY(); - QF_MEM_SYS(); } - #endif // def Q_USTEST +#endif // def Q_USTEST - QF_MEM_APP(); QF_CRIT_EXIT(); - #if (QF_MAX_EPOOL > 0U) +#if (QF_MAX_EPOOL > 0U) QF::gc(e); // recycle the event to avoid a leak - #endif // (QF_MAX_EPOOL > 0U) +#endif // (QF_MAX_EPOOL > 0U) } return status; } -} // namespace QP -//$enddef${QF::QActive::post_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QF::QActive::postLIFO} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QF::QActive::postLIFO} ................................................... +//............................................................................ void QActive::postLIFO(QEvt const * const e) noexcept { - #ifdef Q_UTEST // test? - #if (Q_UTEST != 0) // testing QP-stub? +#ifdef Q_UTEST // test? +#if (Q_UTEST != 0) // testing QP-stub? if (m_temp.fun == Q_STATE_CAST(0)) { // QActiveDummy? static_cast(this)->QActiveDummy::fakePostLIFO(e); return; } - #endif // (Q_UTEST != 0) - #endif // def Q_UTEST +#endif // (Q_UTEST != 0) +#endif // def Q_UTEST QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); + // the posted event must be be valid (which includes not NULL) Q_REQUIRE_INCRIT(300, e != nullptr); QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary - #ifndef Q_UNSAFE - QEQueueCtr dis = static_cast(~m_eQueue.m_nFree_dis); - Q_INVARIANT_INCRIT(301, e->verify_() && (tmp == dis)); - #endif // ndef Q_UNSAFE - - // test-probe#1 for faking queue overflow - QS_TEST_PROBE_DEF(&QActive::postLIFO) - QS_TEST_PROBE_ID(1, - tmp = 0U; // fake no free events - ) // The queue must NOT overflow for the LIFO posting policy. Q_REQUIRE_INCRIT(310, tmp != 0U); - if (e->getPoolNum_() != 0U) { + if (e->poolNum_ != 0U) { // is it a mutable event? + Q_ASSERT_INCRIT(305, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); // increment the reference counter } --tmp; // one free entry just used up m_eQueue.m_nFree = tmp; // update the original - #ifndef Q_UNSAFE - m_eQueue.m_nFree_dis = static_cast(~tmp); - #endif // ndef Q_UNSAFE - if (m_eQueue.m_nMin > tmp) { m_eQueue.m_nMin = tmp; // update minimum so far } @@ -294,113 +168,77 @@ void QActive::postLIFO(QEvt const * const e) noexcept { QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(tmp); // # free entries QS_EQC_PRE(m_eQueue.m_nMin); // min # free entries QS_END_PRE() - #ifdef Q_UTEST +#ifdef Q_UTEST // callback to examine the posted event under the same conditions // as producing the #QS_QF_ACTIVE_POST trace record, which are: // the local filter for this AO ('m_prio') is set if (QS_LOC_CHECK_(m_prio)) { - QF_MEM_APP(); QF_CRIT_EXIT(); QS::onTestPost(nullptr, this, e, true); QF_CRIT_ENTRY(); - QF_MEM_SYS(); } - #endif // def Q_UTEST +#endif // def Q_UTEST QEvt const * const frontEvt = m_eQueue.m_frontEvt; m_eQueue.m_frontEvt = e; // deliver the event directly to the front - #ifndef Q_UNSAFE - m_eQueue.m_frontEvt_dis = - static_cast(~Q_PTR2UINT_CAST_(e)); - #endif // ndef Q_UNSAFE if (frontEvt != nullptr) { // was the queue NOT empty? tmp = m_eQueue.m_tail; // get volatile into temporary; - #ifndef Q_UNSAFE - dis = static_cast(~m_eQueue.m_tail_dis); - Q_INVARIANT_INCRIT(311, tmp == dis); - #endif // ndef Q_UNSAFE ++tmp; if (tmp == m_eQueue.m_end) { // need to wrap the tail? tmp = 0U; // wrap around } m_eQueue.m_tail = tmp; - #ifndef Q_UNSAFE - m_eQueue.m_tail_dis = static_cast(~tmp); - #endif // ndef Q_UNSAFE m_eQueue.m_ring[tmp] = frontEvt; } else { // queue was empty QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue } - QF_MEM_APP(); QF_CRIT_EXIT(); } -} // namespace QP -//$enddef${QF::QActive::postLIFO} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QF::QActive::get_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QF::QActive::get_} ....................................................... +//............................................................................ QEvt const * QActive::get_() noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); // wait for event to arrive directly (depends on QP port) // NOTE: might use assertion-IDs 400-409 QACTIVE_EQUEUE_WAIT_(this); // wait for event to arrive directly - // always remove evt from the front + // always remove event from the front QEvt const * const e = m_eQueue.m_frontEvt; - QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into tmp + QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(410, e != nullptr); // queue must NOT be empty - Q_INVARIANT_INCRIT(411, Q_PTR2UINT_CAST_(e) - == static_cast(~m_eQueue.m_frontEvt_dis)); - QEQueueCtr dis = static_cast(~m_eQueue.m_nFree_dis); - Q_INVARIANT_INCRIT(412, tmp == dis); - #endif // ndef Q_UNSAFE + Q_REQUIRE_INCRIT(410, e != nullptr); // queue must NOT be empty ++tmp; // one more free event in the queue m_eQueue.m_nFree = tmp; // update the # free - #ifndef Q_UNSAFE - m_eQueue.m_nFree_dis = static_cast(~tmp); - #endif // ndef Q_UNSAFE if (tmp <= m_eQueue.m_end) { // any events in the ring buffer? + QS_BEGIN_PRE(QS_QF_ACTIVE_GET, m_prio) QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(tmp); // # free entries QS_END_PRE() // remove event from the tail tmp = m_eQueue.m_tail; // get volatile into temporary - #ifndef Q_UNSAFE - dis = static_cast(~m_eQueue.m_tail_dis); - Q_INVARIANT_INCRIT(420, tmp == dis); - #endif // ndef Q_UNSAFE QEvt const * const frontEvt = m_eQueue.m_ring[tmp]; - #ifndef Q_UNSAFE - Q_ASSERT_INCRIT(421, frontEvt != nullptr); - m_eQueue.m_frontEvt_dis = - static_cast(~Q_PTR2UINT_CAST_(frontEvt)); - #endif // ndef Q_UNSAFE + + Q_ASSERT_INCRIT(430, frontEvt != nullptr); m_eQueue.m_frontEvt = frontEvt; // update the original if (tmp == 0U) { // need to wrap the tail? @@ -409,54 +247,100 @@ QEvt const * QActive::get_() noexcept { --tmp; // advance the tail (counter-clockwise) m_eQueue.m_tail = tmp; // update the original - #ifndef Q_UNSAFE - m_eQueue.m_tail_dis = static_cast(~tmp); - #endif // ndef Q_UNSAFE } else { m_eQueue.m_frontEvt = nullptr; // the queue becomes empty - #ifndef Q_UNSAFE - m_eQueue.m_frontEvt_dis = - static_cast(~Q_PTR2UINT_CAST_(nullptr)); - #endif // ndef Q_UNSAFE // all entries in the queue must be free (+1 for fronEvt) - Q_ASSERT_INCRIT(310, tmp == (m_eQueue.m_end + 1U)); + Q_ASSERT_INCRIT(440, tmp == (m_eQueue.m_end + 1U)); QS_BEGIN_PRE(QS_QF_ACTIVE_GET_LAST, m_prio) QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_END_PRE() } - QF_MEM_APP(); QF_CRIT_EXIT(); return e; } -} // namespace QP -//$enddef${QF::QActive::get_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//............................................................................ +void QActive::postFIFO_( + QEvt const * const e, + void const * const sender) +{ + // NOTE: this helper function is called *inside* critical section +#ifndef Q_SPY + Q_UNUSED_PAR(sender); +#endif -//$define${QF::QTicker} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { + QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary + --tmp; // one free entry just used up + + m_eQueue.m_nFree = tmp; // update the original + if (m_eQueue.m_nMin > tmp) { + m_eQueue.m_nMin = tmp; // update minimum so far + } + + 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_); + QS_EQC_PRE(tmp); // # free entries + QS_EQC_PRE(m_eQueue.m_nMin); // min # free entries + QS_END_PRE() + +#ifdef Q_UTEST + if (QS_LOC_CHECK_(m_prio)) { + QF_CRIT_EXIT(); + QS::onTestPost(sender, this, e, true); // QUTEst callback + QF_CRIT_ENTRY(); + } +#endif // def Q_UTEST + + if (m_eQueue.m_frontEvt == nullptr) { // is the queue empty? + m_eQueue.m_frontEvt = e; // deliver event directly + +#ifdef QXK_HPP_ + if (m_state.act == nullptr) { // eXtended thread? + QXTHREAD_EQUEUE_SIGNAL_(this); // signal eXtended Thread + } + else { + QACTIVE_EQUEUE_SIGNAL_(this); // signal the Active Object + } +#else + QACTIVE_EQUEUE_SIGNAL_(this); // signal the Active Object +#endif // def QXK_HPP_ + } + else { // queue was not empty, insert event into the ring-buffer + tmp = m_eQueue.m_head; // get volatile into temporary + m_eQueue.m_ring[tmp] = e; // insert e into buffer -//${QF::QTicker} ............................................................. + if (tmp == 0U) { // need to wrap the head? + tmp = m_eQueue.m_end; + } + --tmp; // advance the head (counter-clockwise) + + m_eQueue.m_head = tmp; // update the original + } +} + + +//============================================================================ -//${QF::QTicker::QTicker} .................................................... QTicker::QTicker(std::uint_fast8_t const tickRate) noexcept : QActive(nullptr) { // reuse m_head for tick-rate m_eQueue.m_head = static_cast(tickRate); - #ifndef Q_UNSAFE - m_eQueue.m_head_dis = static_cast(~tickRate); - #endif // ndef Q_UNSAFE } -//${QF::QTicker::init} ....................................................... +//............................................................................ void QTicker::init( void const * const e, std::uint_fast8_t const qsId) @@ -466,18 +350,11 @@ void QTicker::init( QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); - m_eQueue.m_tail = 0U; - #ifndef Q_UNSAFE - m_eQueue.m_tail_dis = static_cast(~0U); - #endif // ndef Q_UNSAFE - - QF_MEM_APP(); QF_CRIT_EXIT(); } -//${QF::QTicker::dispatch} ................................................... +//............................................................................ void QTicker::dispatch( QEvt const * const e, std::uint_fast8_t const qsId) @@ -487,26 +364,13 @@ void QTicker::dispatch( QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); // get volatile into temporaries QEQueueCtr nTicks = m_eQueue.m_tail; QEQueueCtr const tickRate = m_eQueue.m_head; - #ifndef Q_UNSAFE - Q_REQUIRE_INCRIT(700, nTicks > 0U); - Q_INVARIANT_INCRIT(701, nTicks - == static_cast(~m_eQueue.m_tail_dis)); - Q_INVARIANT_INCRIT(702, tickRate - == static_cast(~m_eQueue.m_head_dis)); - #endif // ndef Q_UNSAFE - + Q_REQUIRE_INCRIT(800, nTicks > 0U); m_eQueue.m_tail = 0U; // clear # ticks - #ifndef Q_UNSAFE - m_eQueue.m_tail_dis = static_cast(~0U); - #endif // ndef Q_UNSAFE - - QF_MEM_APP(); QF_CRIT_EXIT(); for (; nTicks > 0U; --nTicks) { @@ -515,61 +379,37 @@ void QTicker::dispatch( } } -//${QF::QTicker::trig_} ...................................................... +//............................................................................ void QTicker::trig_(void const * const sender) noexcept { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(sender); - #endif +#endif static QEvt const tickEvt(0U); // immutable event QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); QEQueueCtr nTicks = m_eQueue.m_tail; // get volatile into temporary if (m_eQueue.m_frontEvt == nullptr) { - #ifndef Q_UNSAFE - Q_REQUIRE_INCRIT(800, nTicks == 0U); - Q_REQUIRE_INCRIT(801, m_eQueue.m_nFree == 1U); - Q_INVARIANT_INCRIT(802, m_eQueue.m_frontEvt_dis - == static_cast(~Q_PTR2UINT_CAST_(nullptr))); - Q_INVARIANT_INCRIT(803, - 1U == static_cast(~m_eQueue.m_nFree_dis)); - Q_INVARIANT_INCRIT(804, - 0U == static_cast(~m_eQueue.m_tail_dis)); - #endif // ndef Q_UNSAFE + Q_REQUIRE_INCRIT(900, + (m_eQueue.m_nFree == 1U) + && (nTicks == 0U)); m_eQueue.m_frontEvt = &tickEvt; // deliver event directly m_eQueue.m_nFree = 0U; - #ifndef Q_UNSAFE - m_eQueue.m_frontEvt_dis = - static_cast(~Q_PTR2UINT_CAST_(&tickEvt)); - m_eQueue.m_nFree_dis = static_cast(~0U); - #endif // ndef Q_UNSAFE QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue } else { - #ifndef Q_UNSAFE - Q_REQUIRE_INCRIT(810, (nTicks > 0U) && (nTicks < 0xFFU)); - Q_REQUIRE_INCRIT(811, m_eQueue.m_nFree == 0U); - Q_INVARIANT_INCRIT(812, m_eQueue.m_frontEvt_dis - == static_cast(~Q_PTR2UINT_CAST_(&tickEvt))); - Q_INVARIANT_INCRIT(813, - 0U == static_cast(~m_eQueue.m_nFree_dis)); - Q_INVARIANT_INCRIT(814, - nTicks == static_cast(~m_eQueue.m_tail_dis)); - #endif // ndef Q_UNSAFE + Q_REQUIRE_INCRIT(910, (nTicks > 0U) && (nTicks < 0xFFU)); + Q_REQUIRE_INCRIT(920, m_eQueue.m_nFree == 0U); } ++nTicks; // account for one more tick event m_eQueue.m_tail = nTicks; // update the original - #ifndef Q_UNSAFE - m_eQueue.m_tail_dis = static_cast(~nTicks); - #endif // ndef Q_UNSAFE QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_prio) QS_TIME_PRE(); // timestamp @@ -581,9 +421,7 @@ void QTicker::trig_(void const * const sender) noexcept { QS_EQC_PRE(0U); // min # free entries QS_END_PRE() - QF_MEM_APP(); QF_CRIT_EXIT(); } } // namespace QP -//$enddef${QF::QTicker} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/qf/qf_defer.cpp b/src/qf/qf_defer.cpp index 5cfdcc411..75eae08dd 100644 --- a/src/qf/qf_defer.cpp +++ b/src/qf/qf_defer.cpp @@ -1,10 +1,6 @@ -//$file${src::qf::qf_defer.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qf::qf_defer.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${src::qf::qf_defer.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -48,16 +43,9 @@ namespace { Q_DEFINE_THIS_MODULE("qf_defer") } // unnamed namespace -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QF::QActive::defer} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { -//${QF::QActive::defer} ...................................................... +//............................................................................ bool QActive::defer( QEQueue * const eq, QEvt const * const e) const noexcept @@ -66,27 +54,19 @@ bool QActive::defer( QS_CRIT_STAT QS_CRIT_ENTRY(); - QS_MEM_SYS(); QS_BEGIN_PRE(QS_QF_ACTIVE_DEFER, m_prio) QS_TIME_PRE(); // time stamp QS_OBJ_PRE(this); // this active object QS_OBJ_PRE(eq); // the deferred queue QS_SIG_PRE(e->sig); // the signal of the event - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_END_PRE() - QS_MEM_APP(); QS_CRIT_EXIT(); return status; } -} // namespace QP -//$enddef${QF::QActive::defer} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QF::QActive::recall} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QF::QActive::recall} ..................................................... +//............................................................................ bool QActive::recall(QEQueue * const eq) noexcept { QEvt const * const e = eq->get(m_prio); // get evt from deferred queue QF_CRIT_STAT @@ -96,15 +76,14 @@ bool QActive::recall(QEQueue * const eq) noexcept { postLIFO(e); // post it to the _front_ of the AO's queue QF_CRIT_ENTRY(); - QF_MEM_SYS(); - if (e->getPoolNum_() != 0U) { // is it a mutable event? + if (e->poolNum_ != 0U) { // is it a mutable event? // after posting to the AO's queue the event must be referenced // at least twice: once in the deferred event queue (eq->get() // did NOT decrement the reference counter) and once in the // AO's event queue. - Q_ASSERT_INCRIT(210, e->refCtr_ >= 2U); + Q_ASSERT_INCRIT(205, e->refCtr_ >= 2U); // we need to decrement the reference counter once, to account // for removing the event from the deferred event queue. @@ -116,17 +95,15 @@ bool QActive::recall(QEQueue * const eq) noexcept { QS_OBJ_PRE(this); // this active object QS_OBJ_PRE(eq); // the deferred queue QS_SIG_PRE(e->sig); // the signal of the event - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_END_PRE() - QF_MEM_APP(); QF_CRIT_EXIT(); recalled = true; } else { QS_CRIT_ENTRY(); - QS_MEM_SYS(); QS_BEGIN_PRE(QS_QF_ACTIVE_RECALL_ATTEMPT, m_prio) QS_TIME_PRE(); // time stamp @@ -134,7 +111,6 @@ bool QActive::recall(QEQueue * const eq) noexcept { QS_OBJ_PRE(eq); // the deferred queue QS_END_PRE() - QS_MEM_APP(); QS_CRIT_EXIT(); recalled = false; @@ -142,13 +118,7 @@ bool QActive::recall(QEQueue * const eq) noexcept { return recalled; } -} // namespace QP -//$enddef${QF::QActive::recall} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QF::QActive::flushDeferred} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QF::QActive::flushDeferred} .............................................. +//............................................................................ std::uint_fast16_t QActive::flushDeferred( QEQueue * const eq, std::uint_fast16_t const num) const noexcept @@ -158,9 +128,9 @@ std::uint_fast16_t QActive::flushDeferred( QEvt const * const e = eq->get(m_prio); if (e != nullptr) { ++n; // count one more flushed event - #if (QF_MAX_EPOOL > 0U) +#if (QF_MAX_EPOOL > 0U) QF::gc(e); // garbage collect - #endif +#endif } else { break; @@ -171,4 +141,3 @@ std::uint_fast16_t QActive::flushDeferred( } } // namespace QP -//$enddef${QF::QActive::flushDeferred} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/qf/qf_dyn.cpp b/src/qf/qf_dyn.cpp index 22facab54..b064ebb45 100644 --- a/src/qf/qf_dyn.cpp +++ b/src/qf/qf_dyn.cpp @@ -1,10 +1,6 @@ -//$file${src::qf::qf_dyn.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qf::qf_dyn.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${src::qf::qf_dyn.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -50,17 +45,10 @@ namespace { Q_DEFINE_THIS_MODULE("qf_dyn") } // unnamed namespace -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QF::QF-dyn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { namespace QF { -//${QF::QF-dyn::poolInit} .................................................... +//............................................................................ void poolInit( void * const poolSto, std::uint_fast32_t const poolSize, @@ -71,22 +59,20 @@ void poolInit( // see precondition{qf_dyn,200} and precondition{qf_dyn,201} QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); - Q_REQUIRE_INCRIT(200, poolNum < QF_MAX_EPOOL); + Q_REQUIRE_INCRIT(100, poolNum < QF_MAX_EPOOL); if (poolNum > 0U) { - Q_REQUIRE_INCRIT(201, + Q_REQUIRE_INCRIT(110, QF_EPOOL_EVENT_SIZE_(priv_.ePool_[poolNum - 1U]) < evtSize); } priv_.maxPool_ = poolNum + 1U; // one more pool - QF_MEM_APP(); QF_CRIT_EXIT(); // perform the port-dependent initialization of the event-pool QF_EPOOL_INIT_(priv_.ePool_[poolNum], poolSto, poolSize, evtSize); - #ifdef Q_SPY +#ifdef Q_SPY // generate the object-dictionary entry for the initialized pool { std::uint8_t obj_name[9] = "EvtPool?"; @@ -96,41 +82,37 @@ void poolInit( QS::obj_dict_pre_(&priv_.ePool_[poolNum], reinterpret_cast(&obj_name[0])); } - #endif // Q_SPY +#endif // Q_SPY } -//${QF::QF-dyn::poolGetMaxBlockSize} ......................................... +//............................................................................ std::uint_fast16_t poolGetMaxBlockSize() noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); std::uint_fast16_t const max_size = QF_EPOOL_EVENT_SIZE_(priv_.ePool_[priv_.maxPool_ - 1U]); - QF_MEM_APP(); QF_CRIT_EXIT(); return max_size; } -//${QF::QF-dyn::getPoolMin} .................................................. +//............................................................................ std::uint_fast16_t getPoolMin(std::uint_fast8_t const poolNum) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); - Q_REQUIRE_INCRIT(400, (poolNum <= QF_MAX_EPOOL) + Q_REQUIRE_INCRIT(300, (poolNum <= QF_MAX_EPOOL) && (0U < poolNum) && (poolNum <= priv_.maxPool_)); std::uint_fast16_t const min = static_cast( priv_.ePool_[poolNum - 1U].getNMin()); - QF_MEM_APP(); QF_CRIT_EXIT(); return min; } -//${QF::QF-dyn::newX_} ....................................................... +//............................................................................ QEvt * newX_( std::uint_fast16_t const evtSize, std::uint_fast16_t const margin, @@ -138,10 +120,9 @@ QEvt * newX_( { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); // find the pool id that fits the requested event size... - std::uint_fast8_t poolNum = 0U; // zero-based poolNum initially + std::uint8_t poolNum = 0U; // zero-based poolNum initially for (; poolNum < priv_.maxPool_; ++poolNum) { if (evtSize <= QF_EPOOL_EVENT_SIZE_(priv_.ePool_[poolNum])) { break; @@ -150,38 +131,35 @@ QEvt * newX_( // precondition: // - cannot run out of registered pools - Q_REQUIRE_INCRIT(300, poolNum < priv_.maxPool_); + Q_REQUIRE_INCRIT(400, poolNum < priv_.maxPool_); ++poolNum; // convert to 1-based poolNum - QF_MEM_APP(); QF_CRIT_EXIT(); - // get event e (port-dependent)... - QEvt *e; - #ifdef Q_SPY + // get event `e` out of the event pool (port-dependent)... + QEvt *e = nullptr; +#ifdef Q_SPY QF_EPOOL_GET_(priv_.ePool_[poolNum - 1U], e, ((margin != NO_MARGIN) ? margin : 0U), static_cast(QS_EP_ID) + poolNum); - #else +#else QF_EPOOL_GET_(priv_.ePool_[poolNum - 1U], e, ((margin != NO_MARGIN) ? margin : 0U), 0U); - #endif +#endif if (e != nullptr) { // was e allocated correctly? - e->sig = static_cast(sig); // set the signal - e->evtTag_ = static_cast((poolNum << 4U) | 0x0FU); - e->refCtr_ = 0U; // initialize the reference counter to 0 + e->sig = static_cast(sig); // set the signal + e->poolNum_ = poolNum; + e->refCtr_ = 0U; // initialize the reference counter to 0 QS_CRIT_ENTRY(); - QS_MEM_SYS(); QS_BEGIN_PRE(QS_QF_NEW, static_cast(QS_EP_ID) + poolNum) QS_TIME_PRE(); // timestamp QS_EVS_PRE(evtSize); // the size of the event QS_SIG_PRE(sig); // the signal of the event QS_END_PRE() - QS_MEM_APP(); QS_CRIT_EXIT(); } else { // event was not allocated @@ -190,16 +168,14 @@ QEvt * newX_( // This assertion means that the event allocation failed, // and this failure cannot be tolerated. The most frequent // reason is an event leak in the application. - Q_ASSERT_INCRIT(320, margin != NO_MARGIN); + Q_ASSERT_INCRIT(420, margin != NO_MARGIN); - QS_MEM_SYS(); QS_BEGIN_PRE(QS_QF_NEW_ATTEMPT, static_cast(QS_EP_ID) + poolNum) QS_TIME_PRE(); // timestamp QS_EVS_PRE(evtSize); // the size of the event QS_SIG_PRE(sig); // the signal of the event QS_END_PRE() - QS_MEM_APP(); QF_CRIT_EXIT(); } @@ -209,17 +185,16 @@ QEvt * newX_( return e; } -//${QF::QF-dyn::gc} .......................................................... +//............................................................................ void gc(QEvt const * const e) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(400, e != nullptr); - Q_INVARIANT_INCRIT(401, e->verify_()); - std::uint_fast8_t const poolNum = e->getPoolNum_(); + Q_REQUIRE_INCRIT(500, e != nullptr); + + std::uint_fast8_t const poolNum = e->poolNum_; if (poolNum != 0U) { // is it a pool event (mutable)? - QF_MEM_SYS(); if (e->refCtr_ > 1U) { // isn't this the last reference? @@ -230,9 +205,9 @@ void gc(QEvt const * const e) noexcept { QS_2U8_PRE(poolNum, e->refCtr_); QS_END_PRE() + Q_ASSERT_INCRIT(505, e->refCtr_ > 0U); QEvt_refCtr_dec_(e); // decrement the ref counter - QF_MEM_APP(); QF_CRIT_EXIT(); } else { // this is the last reference to this event, recycle it @@ -245,20 +220,19 @@ void gc(QEvt const * const e) noexcept { QS_END_PRE() // pool number must be in range - Q_ASSERT_INCRIT(410, (poolNum <= priv_.maxPool_) + Q_ASSERT_INCRIT(510, (poolNum <= priv_.maxPool_) && (poolNum <= QF_MAX_EPOOL)); - QF_MEM_APP(); QF_CRIT_EXIT(); // NOTE: casting 'const' away is legit because it's a pool event - #ifdef Q_SPY +#ifdef Q_SPY QF_EPOOL_PUT_(priv_.ePool_[poolNum - 1U], QF_CONST_CAST_(QEvt*, e), static_cast(QS_EP_ID) + poolNum); - #else +#else QF_EPOOL_PUT_(priv_.ePool_[poolNum - 1U], QF_CONST_CAST_(QEvt*, e), 0U); - #endif +#endif } } else { @@ -266,74 +240,68 @@ void gc(QEvt const * const e) noexcept { } } -//${QF::QF-dyn::newRef_} ..................................................... +//............................................................................ QEvt const * newRef_( QEvt const * const e, QEvt const * const evtRef) noexcept { - #ifdef Q_UNSAFE +#ifdef Q_UNSAFE Q_UNUSED_PAR(evtRef); - #endif +#endif QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(500, e != nullptr); - Q_INVARIANT_INCRIT(501, e->verify_()); + Q_REQUIRE_INCRIT(600, e != nullptr); - std::uint_fast8_t const poolNum = e->getPoolNum_(); + std::uint_fast8_t const poolNum = e->poolNum_; Q_UNUSED_PAR(poolNum); // might be unused - Q_REQUIRE_INCRIT(501, (poolNum != 0U) + Q_REQUIRE_INCRIT(610, (poolNum != 0U) && (evtRef == nullptr)); + Q_ASSERT_INCRIT(605, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); // increments the ref counter - QS_MEM_SYS(); QS_BEGIN_PRE(QS_QF_NEW_REF, static_cast(QS_EP_ID) + poolNum) QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of the event QS_2U8_PRE(poolNum, e->refCtr_); QS_END_PRE() - QS_MEM_APP(); QF_CRIT_EXIT(); return e; } -//${QF::QF-dyn::deleteRef_} .................................................. +//............................................................................ void deleteRef_(QEvt const * const evtRef) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); QEvt const * const e = evtRef; - Q_REQUIRE_INCRIT(600, e != nullptr); - Q_INVARIANT_INCRIT(601, e->verify_()); + Q_REQUIRE_INCRIT(700, e != nullptr); - #ifdef Q_SPY - std::uint_fast8_t const poolNum = e->getPoolNum_(); - #endif +#ifdef Q_SPY + std::uint_fast8_t const poolNum = e->poolNum_; - QS_MEM_SYS(); QS_BEGIN_PRE(QS_QF_DELETE_REF, static_cast(QS_EP_ID) + poolNum) QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of the event QS_2U8_PRE(poolNum, e->refCtr_); QS_END_PRE() - QS_MEM_APP(); +#endif // def Q_SPY QF_CRIT_EXIT(); - #if (QF_MAX_EPOOL > 0U) +#if (QF_MAX_EPOOL > 0U) gc(e); // recycle the referenced event - #endif +#endif } } // namespace QF } // namespace QP -//$enddef${QF::QF-dyn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #endif // (QF_MAX_EPOOL > 0U) mutable events configured diff --git a/src/qf/qf_mem.cpp b/src/qf/qf_mem.cpp index 8c56db061..ef9f28261 100644 --- a/src/qf/qf_mem.cpp +++ b/src/qf/qf_mem.cpp @@ -1,10 +1,6 @@ -//$file${src::qf::qf_mem.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qf::qf_mem.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,15 +26,14 @@ // Quantum Leaps contact information: // // -// -//$endhead${src::qf::qf_mem.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem #ifdef Q_SPY // QS software tracing enabled? #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records + #include "qs_pkg.hpp" // QS package-scope internal interface #else #include "qs_dummy.hpp" // disable the QS software tracing #endif // Q_SPY @@ -48,18 +43,9 @@ namespace { Q_DEFINE_THIS_MODULE("qf_mem") } // unnamed namespace -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QF::QMPool} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { -//${QF::QMPool} .............................................................. - -//${QF::QMPool::init} ........................................................ +//............................................................................ void QMPool::init( void * const poolSto, std::uint_fast32_t const poolSize, @@ -67,30 +53,24 @@ void QMPool::init( { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); Q_REQUIRE_INCRIT(100, poolSto != nullptr); - Q_REQUIRE_INCRIT(101, - poolSize >= static_cast(sizeof(QFreeBlock))); - Q_REQUIRE_INCRIT(102, - static_cast(blockSize + sizeof(QFreeBlock)) - > blockSize); - m_free_head = static_cast(poolSto); + m_freeHead = static_cast(poolSto); - // find # free blocks in a memory block, NO DIVISION + // find # free links in a memory block, see NOTE1 m_blockSize = static_cast(2U * sizeof(void *)); - std::uint_fast16_t nblocks = 1U; + std::uint_fast16_t inext = 2U; while (m_blockSize < static_cast(blockSize)) { - m_blockSize += static_cast(sizeof(QFreeBlock)); - ++nblocks; + m_blockSize += static_cast(sizeof(void *)); + ++inext; } // the pool buffer must fit at least one rounded-up block Q_ASSERT_INCRIT(110, poolSize >= m_blockSize); // start at the head of the free list - QFreeBlock *fb = m_free_head; + void * *pfb = m_freeHead; // pointer to free block std::uint32_t nTot = 1U; // the last block already in the list // chain all blocks together in a free-list... @@ -98,179 +78,125 @@ void QMPool::init( size >= static_cast(m_blockSize); size -= static_cast(m_blockSize)) { - fb->m_next = &fb[nblocks]; // point next link to next block - #ifndef Q_UNSAFE - fb->m_next_dis = ~Q_PTR2UINT_CAST_(fb->m_next); - #endif - fb = fb->m_next; // advance to the next block - ++nTot; // one more free block in the pool + pfb[0] = &pfb[inext]; // set the next link to next free block + pfb = static_cast(pfb[0]); // advance to the next block + ++nTot; // one more free block in the pool } + pfb[0] = nullptr; // the last link points to NULL // dynamic range check - #if (QF_MPOOL_CTR_SIZE == 1U) - Q_ENSURE_INCRIT(190, nTot < 0xFFU); - #elif (QF_MPOOL_CTR_SIZE == 2U) - Q_ENSURE_INCRIT(190, nTot < 0xFFFFU); - #endif - - fb->m_next = nullptr; // the last link points to NULL +#if (QF_MPOOL_CTR_SIZE == 1U) + Q_ASSERT_INCRIT(190, nTot < 0xFFU); +#elif (QF_MPOOL_CTR_SIZE == 2U) + Q_ASSERT_INCRIT(190, nTot < 0xFFFFU); +#endif m_nTot = static_cast(nTot); - m_nFree = m_nTot; // all blocks are free - m_start = static_cast(poolSto); // original start - m_end = fb; // the last block in this pool - - #ifndef Q_UNSAFE - m_free_head_dis = - static_cast(~Q_PTR2UINT_CAST_(m_free_head)); - m_nFree_dis = static_cast(~m_nFree); - m_nMin = m_nTot; // the minimum # free blocks - fb->m_next_dis = ~Q_PTR2UINT_CAST_(fb->m_next); - #endif - - QF_MEM_APP(); + m_nFree = m_nTot; // all blocks are free + m_start = static_cast(poolSto); // original start + m_end = pfb; // the last block in this pool + m_nMin = m_nTot; // the minimum # free blocks + QF_CRIT_EXIT(); } -//${QF::QMPool::get} ......................................................... +//............................................................................ void * QMPool::get( std::uint_fast16_t const margin, std::uint_fast8_t const qsId) noexcept { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(qsId); - #endif +#endif QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); // get volatile into temporaries - QFreeBlock *fb = m_free_head; + void * *pfb = m_freeHead; // pointer to free block QMPoolCtr nFree = m_nFree; - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(301, Q_PTR2UINT_CAST_(fb) - == static_cast(~m_free_head_dis)); - Q_INVARIANT_INCRIT(302, nFree == static_cast(~m_nFree_dis)); - #endif // ndef Q_UNSAFE - // have more free blocks than the requested margin? if (nFree > static_cast(margin)) { - Q_ASSERT_INCRIT(310, fb != nullptr); + Q_ASSERT_INCRIT(310, pfb != nullptr); - QFreeBlock * const fb_next = fb->m_next; - - #ifndef Q_UNSAFE - // the free block must have integrity (duplicate inverse storage) - Q_INVARIANT_INCRIT(311, Q_PTR2UINT_CAST_(fb_next) - == static_cast(~fb->m_next_dis)); - #endif // ndef Q_UNSAFE + // fast temporary + void * * const pfb_next = static_cast(pfb[0]); --nFree; // one less free block if (nFree == 0U) { // is the pool becoming empty? // pool is becoming empty, so the next free block must be NULL - Q_ASSERT_INCRIT(320, fb_next == nullptr); + Q_ASSERT_INCRIT(320, pfb_next == nullptr); - m_nFree = 0U; - #ifndef Q_UNSAFE - m_nFree_dis = static_cast(~m_nFree); - m_nMin = 0U; // remember that the pool got empty - #endif // ndef Q_UNSAFE + m_nFree = 0U; // no more free blocks + m_nMin = 0U; // remember that the pool got empty } - else { - m_nFree = nFree; // update the original - #ifndef Q_UNSAFE - m_nFree_dis = static_cast(~nFree); + else { // the pool is NOT empty - // The pool is not empty, so the next free-block pointer - // must be in range. - Q_INVARIANT_INCRIT(330, - QF_PTR_RANGE_(fb_next, m_start, m_end)); + // the next free-block pointer must be in range + Q_ASSERT_INCRIT(330, QF_PTR_RANGE_(pfb_next, m_start, m_end)); - // is the # free blocks the new minimum so far? - if (m_nMin > nFree) { + m_nFree = nFree; // update the original + if (m_nMin > nFree) { // is this the new minimum? m_nMin = nFree; // remember the minimum so far } - #endif // ndef Q_UNSAFE } - m_free_head = fb_next; // set the head to the next free block - #ifndef Q_UNSAFE - m_free_head_dis = - static_cast(~Q_PTR2UINT_CAST_(fb_next)); - #endif // ndef Q_UNSAFE + m_freeHead = pfb_next; // set the head to the next free block + + // change the allocated block contents so that it is different + // than a free block inside the pool. + pfb[0] = &m_end[1]; // invalid location beyond the end QS_BEGIN_PRE(QS_QF_MPOOL_GET, qsId) QS_TIME_PRE(); // timestamp QS_OBJ_PRE(this); // this memory pool - QS_MPC_PRE(nFree); // # of free blocks in the pool - #ifndef Q_UNSAFE + QS_MPC_PRE(nFree); // # free blocks in the pool QS_MPC_PRE(m_nMin); // min # free blocks ever in the pool - #else - QS_MPC_PRE(0U); // min # free blocks (not available) - #endif // ndef Q_UNSAFE QS_END_PRE() } else { // don't have enough free blocks at this point - fb = nullptr; + pfb = nullptr; QS_BEGIN_PRE(QS_QF_MPOOL_GET_ATTEMPT, qsId) QS_TIME_PRE(); // timestamp QS_OBJ_PRE(this); // this memory pool - QS_MPC_PRE(nFree); // # of free blocks in the pool + QS_MPC_PRE(nFree); // # free blocks in the pool QS_MPC_PRE(margin); // the requested margin QS_END_PRE() } - QF_MEM_APP(); QF_CRIT_EXIT(); - return fb; // return the block or nullptr to the caller + return pfb; // return the block or nullptr to the caller } -//${QF::QMPool::put} ......................................................... +//............................................................................ void QMPool::put( void * const block, std::uint_fast8_t const qsId) noexcept { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(qsId); - #endif +#endif - QFreeBlock * const fb = static_cast(block); + void * * const pfb = static_cast(block); // pointer to free block QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); // get volatile into temporaries - QFreeBlock * const free_head = m_free_head; + void * * const freeHead = m_freeHead; QMPoolCtr nFree = m_nFree; - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(401, Q_PTR2UINT_CAST_(free_head) - == static_cast(~m_free_head_dis)); - Q_INVARIANT_INCRIT(402, nFree == static_cast(~m_nFree_dis)); - - Q_REQUIRE_INCRIT(410, nFree < m_nTot); - Q_REQUIRE_INCRIT(411, QF_PTR_RANGE_(fb, m_start, m_end)); - - // the block must not be in the pool already - Q_REQUIRE_INCRIT(412, Q_PTR2UINT_CAST_(fb->m_next) - != static_cast(~fb->m_next_dis)); - #endif // ndef Q_UNSAFE + Q_REQUIRE_INCRIT(400, nFree < m_nTot); + Q_REQUIRE_INCRIT(410, QF_PTR_RANGE_(pfb, m_start, m_end)); ++nFree; // one more free block in this pool - m_free_head = fb; // set as new head of the free list - m_nFree = nFree; - fb->m_next = free_head; // link into the list - #ifndef Q_UNSAFE - m_free_head_dis = static_cast(~Q_PTR2UINT_CAST_(fb)); - m_nFree_dis = static_cast(~nFree); - fb->m_next_dis = static_cast(~Q_PTR2UINT_CAST_(free_head)); - #endif + m_freeHead = pfb; // set as new head of the free list + m_nFree = nFree; + pfb[0] = freeHead; // link into the list QS_BEGIN_PRE(QS_QF_MPOOL_PUT, qsId) QS_TIME_PRE(); // timestamp @@ -278,14 +204,18 @@ void QMPool::put( QS_MPC_PRE(nFree); // the # free blocks in the pool QS_END_PRE() - QF_MEM_APP(); QF_CRIT_EXIT(); } -//${QF::QMPool::getBlockSize} ................................................ -QMPoolSize QMPool::getBlockSize() const noexcept { - return m_blockSize; -} - } // namespace QP -//$enddef${QF::QMPool} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +//============================================================================ +// NOTE1: +// The memory buffer for the pool is organized as an array of void* pointers +// (see void * data type). These pointers are used to form a linked-list +// of free blocks in the pool. The first location pfb[0] is the actual link. +// The second location pfb[1] is used in SafeQP as the redundant "duplicate +// storage" for the link at pfb[0]. Even though the "duplicate storage" is NOT +// used in this QP edition, the minimum number of number of void* pointers +// (void * data type) inside a memory block is still kept at 2 to maintain +// the same policy for sizing the memory blocks. diff --git a/src/qf/qf_ps.cpp b/src/qf/qf_ps.cpp index 6cb579cca..d55d83f78 100644 --- a/src/qf/qf_ps.cpp +++ b/src/qf/qf_ps.cpp @@ -1,10 +1,6 @@ -//$file${src::qf::qf_ps.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qf::qf_ps.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${src::qf::qf_ps.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -48,30 +43,12 @@ namespace { Q_DEFINE_THIS_MODULE("qf_ps") } // unnamed namespace -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QF::QActive::subscrList_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { QSubscrList * QActive::subscrList_; -} // namespace QP -//$enddef${QF::QActive::subscrList_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QF::QActive::maxPubSignal_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { enum_t QActive::maxPubSignal_; -} // namespace QP -//$enddef${QF::QActive::maxPubSignal_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QF::QActive::psInit} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QF::QActive::psInit} ..................................................... +//............................................................................ void QActive::psInit( QSubscrList * const subscrSto, enum_t const maxSignal) noexcept @@ -82,61 +59,49 @@ void QActive::psInit( // initialize the subscriber list for (enum_t sig = 0; sig < maxSignal; ++sig) { subscrSto[sig].m_set.setEmpty(); - #ifndef Q_UNSAFE - subscrSto[sig].m_set.update_(&subscrSto[sig].m_set_dis); - #endif } } -} // namespace QP -//$enddef${QF::QActive::psInit} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QF::QActive::publish_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QF::QActive::publish_} ................................................... +//............................................................................ void QActive::publish_( QEvt const * const e, void const * const sender, std::uint_fast8_t const qsId) noexcept { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(sender); Q_UNUSED_PAR(qsId); - #endif +#endif QSignal const sig = e->sig; QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); Q_REQUIRE_INCRIT(200, sig < static_cast(maxPubSignal_)); - Q_INVARIANT_INCRIT(202, - subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis)); QS_BEGIN_PRE(QS_QF_PUBLISH, qsId) QS_TIME_PRE(); // the timestamp QS_OBJ_PRE(sender); // the sender object QS_SIG_PRE(e->sig); // the signal of the event - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_END_PRE() // is it a mutable event? - if (e->getPoolNum_() != 0U) { + if (e->poolNum_ != 0U) { // NOTE: The reference counter of a mutable event is incremented to // prevent premature recycling of the event while the multicasting // is still in progress. At the end of the function, the garbage // collector step (QF::gc()) decrements the reference counter and // recycles the event if the counter drops to zero. This covers the // case when the event was published without any subscribers. + Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); } // make a local, modifiable copy of the subscriber set QPSet subscrSet = subscrList_[sig].m_set; - QF_MEM_APP(); QF_CRIT_EXIT(); if (subscrSet.notEmpty()) { // any subscribers? @@ -144,21 +109,16 @@ void QActive::publish_( std::uint_fast8_t p = subscrSet.findMax(); QF_CRIT_ENTRY(); - QF_MEM_SYS(); QActive *a = registry_[p]; // the AO must be registered with the framework Q_ASSERT_INCRIT(210, a != nullptr); - QF_MEM_APP(); QF_CRIT_EXIT(); QF_SCHED_STAT_ QF_SCHED_LOCK_(p); // lock the scheduler up to AO's prio - std::uint_fast8_t lbound = QF_MAX_ACTIVE + 1U; do { // loop over all subscribers - --lbound; - // POST() asserts internally if the queue overflows a->POST(e, sender); @@ -167,22 +127,20 @@ void QActive::publish_( p = subscrSet.findMax(); // highest-prio subscriber QF_CRIT_ENTRY(); - QF_MEM_SYS(); a = registry_[p]; // the AO must be registered with the framework Q_ASSERT_INCRIT(220, a != nullptr); - QF_MEM_APP(); QF_CRIT_EXIT(); } else { p = 0U; // no more subscribers } - } while ((p != 0U) && (lbound > 0U)); + } while (p != 0U); QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(290, p == 0U); + Q_ASSERT_INCRIT(290, p == 0U); // all subscribers processed QF_CRIT_EXIT(); QF_SCHED_UNLOCK_(); // unlock the scheduler @@ -191,31 +149,22 @@ void QActive::publish_( // The following garbage collection step decrements the reference counter // and recycles the event if the counter drops to zero. This covers both // cases when the event was published with or without any subscribers. - #if (QF_MAX_EPOOL > 0U) - QF::gc(e); - #endif +#if (QF_MAX_EPOOL > 0U) + QF::gc(e); // recycle the event to avoid a leak +#endif } -} // namespace QP -//$enddef${QF::QActive::publish_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QF::QActive::subscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QF::QActive::subscribe} .................................................. +//............................................................................ void QActive::subscribe(enum_t const sig) const noexcept { std::uint_fast8_t const p = static_cast(m_prio); QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); Q_REQUIRE_INCRIT(300, (Q_USER_SIG <= sig) && (sig < maxPubSignal_) && (0U < p) && (p <= QF_MAX_ACTIVE) && (registry_[p] == this)); - Q_INVARIANT_INCRIT(302, - subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis)); QS_BEGIN_PRE(QS_QF_ACTIVE_SUBSCRIBE, m_prio) QS_TIME_PRE(); // timestamp @@ -225,36 +174,23 @@ void QActive::subscribe(enum_t const sig) const noexcept { // insert the prio. into the subscriber set subscrList_[sig].m_set.insert(p); - #ifndef Q_UNSAFE - subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis); - #endif - QF_MEM_APP(); QF_CRIT_EXIT(); } -} // namespace QP -//$enddef${QF::QActive::subscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QF::QActive::unsubscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QF::QActive::unsubscribe} ................................................ +//............................................................................ void QActive::unsubscribe(enum_t const sig) const noexcept { std::uint_fast8_t const p = static_cast(m_prio); QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); Q_REQUIRE_INCRIT(400, (Q_USER_SIG <= sig) && (sig < maxPubSignal_) && (0U < p) && (p <= QF_MAX_ACTIVE) && (registry_[p] == this)); - Q_INVARIANT_INCRIT(402, - subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis)); - QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio) + QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, p) QS_TIME_PRE(); // timestamp QS_SIG_PRE(sig); // the signal of this event QS_OBJ_PRE(this); // this active object @@ -262,25 +198,14 @@ void QActive::unsubscribe(enum_t const sig) const noexcept { // remove the prio. from the subscriber set subscrList_[sig].m_set.remove(p); - #ifndef Q_UNSAFE - subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis); - #endif - QF_MEM_APP(); QF_CRIT_EXIT(); } -} // namespace QP -//$enddef${QF::QActive::unsubscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QF::QActive::unsubscribeAll} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QF::QActive::unsubscribeAll} ............................................. +//............................................................................ void QActive::unsubscribeAll() const noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); std::uint_fast8_t const p = static_cast(m_prio); @@ -288,25 +213,19 @@ void QActive::unsubscribeAll() const noexcept { && (registry_[p] == this)); enum_t const maxPubSig = maxPubSignal_; - QF_MEM_APP(); QF_CRIT_EXIT(); for (enum_t sig = Q_USER_SIG; sig < maxPubSig; ++sig) { QF_CRIT_ENTRY(); - QF_MEM_SYS(); if (subscrList_[sig].m_set.hasElement(p)) { subscrList_[sig].m_set.remove(p); - #ifndef Q_UNSAFE - subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis); - #endif QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio) QS_TIME_PRE(); // timestamp QS_SIG_PRE(sig); // the signal of this event QS_OBJ_PRE(this); // this active object QS_END_PRE() } - QF_MEM_APP(); QF_CRIT_EXIT(); QF_CRIT_EXIT_NOP(); // prevent merging critical sections @@ -314,4 +233,3 @@ void QActive::unsubscribeAll() const noexcept { } } // namespace QP -//$enddef${QF::QActive::unsubscribeAll} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/qf/qf_qact.cpp b/src/qf/qf_qact.cpp index 43bdd2141..0f99e0807 100644 --- a/src/qf/qf_qact.cpp +++ b/src/qf/qf_qact.cpp @@ -1,10 +1,6 @@ -//$file${src::qf::qf_qact.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qf::qf_qact.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${src::qf::qf_qact.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -48,36 +43,22 @@ namespace { Q_DEFINE_THIS_MODULE("qf_qact") } // unnamed namespace -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QF::QActive::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -} // namespace QP -//$enddef${QF::QActive::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QF::QActive::register_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { -//${QF::QActive::register_} .................................................. +//............................................................................ void QActive::register_() noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); if (m_pthre == 0U) { // preemption-threshold not defined? m_pthre = m_prio; // apply the default } - #ifndef Q_UNSAFE - - Q_REQUIRE_INCRIT(100, (0U < m_prio) && (m_prio <= QF_MAX_ACTIVE) - && (registry_[m_prio] == nullptr) - && (m_prio <= m_pthre)); +#ifndef Q_UNSAFE + Q_REQUIRE_INCRIT(100, + (0U < m_prio) && (m_prio <= QF_MAX_ACTIVE) + && (registry_[m_prio] == nullptr) + && (m_prio <= m_pthre)); std::uint8_t prev_thre = m_pthre; std::uint8_t next_thre = m_pthre; @@ -98,43 +79,30 @@ void QActive::register_() noexcept { } } - Q_ASSERT_INCRIT(190, (prev_thre <= m_pthre) - && (m_pthre <= next_thre)); - - m_prio_dis = static_cast(~m_prio); - m_pthre_dis = static_cast(~m_pthre); - - #endif // Q_UNSAFE + Q_ASSERT_INCRIT(190, + (prev_thre <= m_pthre) + && (m_pthre <= next_thre)); +#endif // Q_UNSAFE // register the AO at the QF-prio. registry_[m_prio] = this; - QF_MEM_APP(); QF_CRIT_EXIT(); } -} // namespace QP -//$enddef${QF::QActive::register_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QF::QActive::unregister_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QF::QActive::unregister_} ................................................ +//............................................................................ void QActive::unregister_() noexcept { std::uint_fast8_t const p = static_cast(m_prio); QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); Q_REQUIRE_INCRIT(200, (0U < p) && (p <= QF_MAX_ACTIVE) && (registry_[p] == this)); registry_[p] = nullptr; // free-up the priority level m_state.fun = nullptr; // invalidate the state - QF_MEM_APP(); QF_CRIT_EXIT(); } } // namespace QP -//$enddef${QF::QActive::unregister_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/qf/qf_qeq.cpp b/src/qf/qf_qeq.cpp index 4fb160d0e..8160adc72 100644 --- a/src/qf/qf_qeq.cpp +++ b/src/qf/qf_qeq.cpp @@ -1,10 +1,6 @@ -//$file${src::qf::qf_qeq.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qf::qf_qeq.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${src::qf::qf_qeq.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -48,124 +43,83 @@ namespace { Q_DEFINE_THIS_MODULE("qf_qeq") } // unnamed namespace -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QF::QEQueue} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { -//${QF::QEQueue} ............................................................. - -//${QF::QEQueue::init} ....................................................... +//............................................................................ void QEQueue::init( - QEvt const * qSto[], + QEvt const * * const qSto, std::uint_fast16_t const qLen) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); - #if (QF_EQUEUE_CTR_SIZE == 1U) +#if (QF_EQUEUE_CTR_SIZE == 1U) Q_REQUIRE_INCRIT(100, qLen < 0xFFU); - #endif +#endif m_frontEvt = nullptr; // no events in the queue - m_ring = &qSto[0]; + m_ring = qSto; m_end = static_cast(qLen); if (qLen > 0U) { m_head = 0U; m_tail = 0U; } - m_nFree = static_cast(qLen + 1U); //+1 for frontEvt - m_nMin = m_nFree; - - #ifndef Q_UNSAFE - m_frontEvt_dis = static_cast(~Q_PTR2UINT_CAST_(m_frontEvt)); - m_head_dis = static_cast(~m_head); - m_tail_dis = static_cast(~m_tail); - m_nFree_dis = static_cast(~m_nFree); - #endif + m_nFree = static_cast(qLen + 1U); //+1 for frontEvt + m_nMin = m_nFree; - QF_MEM_APP(); QF_CRIT_EXIT(); } -//${QF::QEQueue::post} ....................................................... +//............................................................................ bool QEQueue::post( QEvt const * const e, std::uint_fast16_t const margin, std::uint_fast8_t const qsId) noexcept { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(qsId); - #endif +#endif QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); Q_REQUIRE_INCRIT(200, e != nullptr); - Q_INVARIANT_INCRIT(201, e->verify_()); QEQueueCtr tmp = m_nFree; // get volatile into temporary - #ifndef Q_UNSAFE - QEQueueCtr dis = static_cast(~m_nFree_dis); - Q_INVARIANT_INCRIT(201, tmp == dis); - #endif // ndef Q_UNSAFE - - // test-probe#1 for faking queue overflow - QS_TEST_PROBE_DEF(&QEQueue::post) - QS_TEST_PROBE_ID(1, - tmp = 0U; // fake no free events - ) - - // required margin available? - bool status; - if (((margin == QF::NO_MARGIN) && (tmp > 0U)) - || (tmp > static_cast(margin))) - { + + // can the queue accept the event? + bool status = ((margin == QF::NO_MARGIN) && (tmp > 0U)) + || (tmp > static_cast(margin)); + if (status) { // is it a mutable event? - if (e->getPoolNum_() != 0U) { + if (e->poolNum_ != 0U) { + Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); // increment the reference counter } --tmp; // one free entry just used up m_nFree = tmp; // update the original - #ifndef Q_UNSAFE - m_nFree_dis = static_cast(~tmp); - #endif // ndef Q_UNSAFE - - if (m_nMin > tmp) { + if (m_nMin > tmp) { // is this the new minimum? m_nMin = tmp; // update minimum so far } +#ifdef Q_SPY QS_BEGIN_PRE(QS_QF_EQUEUE_POST, qsId) QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of the event QS_OBJ_PRE(this); // this queue object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(tmp); // # free entries QS_EQC_PRE(m_nMin); // min # free entries QS_END_PRE() +#endif // def Q_SPY if (m_frontEvt == nullptr) { // is the queue empty? m_frontEvt = e; // deliver event directly - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(211, m_frontEvt_dis - == static_cast(~Q_PTR2UINT_CAST_(nullptr))); - m_frontEvt_dis = static_cast(~Q_PTR2UINT_CAST_(e)); - #endif // ndef Q_UNSAFE } else { // queue was not empty, insert event into the ring-buffer tmp = m_head; // get volatile into temporary - #ifndef Q_UNSAFE - dis = static_cast(~m_head_dis); - Q_INVARIANT_INCRIT(212, tmp == dis); - #endif // ndef Q_UNSAFE m_ring[tmp] = e; // insert e into buffer if (tmp == 0U) { // need to wrap the head? @@ -174,77 +128,57 @@ bool QEQueue::post( --tmp; // advance head (counter-clockwise) m_head = tmp; // update the original - #ifndef Q_UNSAFE - m_head_dis = static_cast(~tmp); - #endif // ndef Q_UNSAFE } - status = true; // event posted successfully } else { // event cannot be posted // dropping events must be acceptable - Q_ASSERT_INCRIT(210, margin != QF::NO_MARGIN); + Q_ASSERT_INCRIT(230, margin != QF::NO_MARGIN); +#ifdef Q_SPY QS_BEGIN_PRE(QS_QF_EQUEUE_POST_ATTEMPT, qsId) QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this queue object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(tmp); // # free entries QS_EQC_PRE(margin); // margin requested QS_END_PRE() - - status = false; // event not posted +#endif // def Q_SPY } - QF_MEM_APP(); QF_CRIT_EXIT(); return status; } -//${QF::QEQueue::postLIFO} ................................................... +//............................................................................ void QEQueue::postLIFO( QEvt const * const e, std::uint_fast8_t const qsId) noexcept { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(qsId); - #endif +#endif QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); Q_REQUIRE_INCRIT(300, e != nullptr); - Q_INVARIANT_INCRIT(301, e->verify_()); QEQueueCtr tmp = m_nFree; // get volatile into temporary - #ifndef Q_UNSAFE - QEQueueCtr dis = static_cast(~m_nFree_dis); - Q_INVARIANT_INCRIT(301, tmp == dis); - #endif // ndef Q_UNSAFE - - // test-probe#1 for faking queue overflow - QS_TEST_PROBE_DEF(&QEQueue::postLIFO) - QS_TEST_PROBE_ID(1, - tmp = 0U; // fake no free events - ) // must be able to LIFO-post the event Q_REQUIRE_INCRIT(310, tmp != 0U); - if (e->getPoolNum_() != 0U) { // is it a mutable event? + if (e->poolNum_ != 0U) { // is it a mutable event? + Q_ASSERT_INCRIT(305, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); // increment the reference counter } --tmp; // one free entry just used up m_nFree = tmp; // update the original - #ifndef Q_UNSAFE - m_nFree_dis = static_cast(~tmp); - #endif // ndef Q_UNSAFE - - if (m_nMin > tmp) { + if (m_nMin > tmp) { // is this the new minimum? m_nMin = tmp; // update minimum so far } @@ -252,67 +186,44 @@ void QEQueue::postLIFO( QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this queue object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(tmp); // # free entries QS_EQC_PRE(m_nMin); // min # free entries QS_END_PRE() QEvt const * const frontEvt = m_frontEvt; // read into temporary m_frontEvt = e; // deliver the event directly to the front - #ifndef Q_UNSAFE - m_frontEvt_dis = static_cast(~Q_PTR2UINT_CAST_(e)); - #endif // ndef Q_UNSAFE if (frontEvt != nullptr) { // was the queue NOT empty? tmp = m_tail; // get volatile into temporary; - #ifndef Q_UNSAFE - dis = static_cast(~m_tail_dis); - Q_INVARIANT_INCRIT(311, tmp == dis); - #endif // ndef Q_UNSAFE ++tmp; if (tmp == m_end) { // need to wrap the tail? tmp = 0U; // wrap around } m_tail = tmp; - #ifndef Q_UNSAFE - m_tail_dis = static_cast(~tmp); - #endif m_ring[tmp] = frontEvt; } - QF_MEM_APP(); QF_CRIT_EXIT(); } -//${QF::QEQueue::get} ........................................................ +//............................................................................ QEvt const * QEQueue::get(std::uint_fast8_t const qsId) noexcept { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(qsId); - #endif +#endif QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); QEvt const * const e = m_frontEvt; // always remove evt from the front - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(411, Q_PTR2UINT_CAST_(e) - == static_cast(~m_frontEvt_dis)); - #endif // ndef Q_UNSAFE if (e != nullptr) { // was the queue not empty? QEQueueCtr tmp = m_nFree; // get volatile into temporary - #ifndef Q_UNSAFE - QEQueueCtr const dis = static_cast(~m_nFree_dis); - Q_INVARIANT_INCRIT(412, tmp == dis); - #endif // ndef Q_UNSAFE ++tmp; // one more free event in the queue m_nFree = tmp; // update the # free - #ifndef Q_UNSAFE - m_nFree_dis = static_cast(~tmp); - #endif // ndef Q_UNSAFE // any events in the ring buffer? if (tmp <= m_end) { @@ -321,17 +232,15 @@ QEvt const * QEQueue::get(std::uint_fast8_t const qsId) noexcept { QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this queue object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(tmp); // # free entries QS_END_PRE() tmp = m_tail; // get volatile into temporary QEvt const * const frontEvt = m_ring[tmp]; - #ifndef Q_UNSAFE - Q_ASSERT_INCRIT(421, frontEvt != nullptr); - m_frontEvt_dis = - static_cast(~Q_PTR2UINT_CAST_(frontEvt)); - #endif // ndef Q_UNSAFE + + Q_ASSERT_INCRIT(420, frontEvt != nullptr); + m_frontEvt = frontEvt; // update the original if (tmp == 0U) { // need to wrap the tail? @@ -339,16 +248,9 @@ QEvt const * QEQueue::get(std::uint_fast8_t const qsId) noexcept { } --tmp; // advance the tail (counter-clockwise) m_tail = tmp; // update the original - #ifndef Q_UNSAFE - m_tail_dis = static_cast(~tmp); - #endif // ndef Q_UNSAFE } else { m_frontEvt = nullptr; // queue becomes empty - #ifndef Q_UNSAFE - m_frontEvt_dis = - static_cast(~Q_PTR2UINT_CAST_(nullptr)); - #endif // ndef Q_UNSAFE // all entries in the queue must be free (+1 for frontEvt) Q_INVARIANT_INCRIT(440, tmp == (m_end + 1U)); @@ -357,16 +259,14 @@ QEvt const * QEQueue::get(std::uint_fast8_t const qsId) noexcept { QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this queue object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_END_PRE() } } - QF_MEM_APP(); QF_CRIT_EXIT(); return e; } } // namespace QP -//$enddef${QF::QEQueue} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/qf/qf_qmact.cpp b/src/qf/qf_qmact.cpp index 535251ad8..3029e3a4b 100644 --- a/src/qf/qf_qmact.cpp +++ b/src/qf/qf_qmact.cpp @@ -1,10 +1,6 @@ -//$file${src::qf::qf_qmact.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qf::qf_qmact.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${src::qf::qf_qmact.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -48,18 +43,9 @@ namespace { //Q_DEFINE_THIS_MODULE("qf_qmact") } // unnamed namespace -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QF::QMActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { -//${QF::QMActive} ............................................................ - -//${QF::QMActive::QMActive} .................................................. +//............................................................................ QMActive::QMActive(QStateHandler const initial) noexcept : QActive(initial) { @@ -68,4 +54,3 @@ QMActive::QMActive(QStateHandler const initial) noexcept } } // namespace QP -//$enddef${QF::QMActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/qf/qf_time.cpp b/src/qf/qf_time.cpp index c2c49e759..1c5fd60cd 100644 --- a/src/qf/qf_time.cpp +++ b/src/qf/qf_time.cpp @@ -1,10 +1,6 @@ -//$file${src::qf::qf_time.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qf::qf_time.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// SafeQP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -12,26 +8,24 @@ // ------------------------ // Modern Embedded Software // -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// SPDX-License-Identifier: LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- -// source Quantum Leaps commercial licenses. +// This software is licensed under the terms of the Quantum Leaps commercial +// licenses. Please contact Quantum Leaps for more information about the +// available licensing options. // -// Redistributions in source code must retain this top-level comment block. -// Plagiarizing this software to sidestep the license obligations is illegal. -// -// NOTE: -// The GPL does NOT permit the incorporation of this code into proprietary -// programs. Please contact Quantum Leaps for commercial licensing options, -// which expressly supersede the GPL and are designed explicitly for -// closed-source distribution. +// RESTRICTIONS +// You may NOT : +// (a) redistribute, encumber, sell, rent, lease, sublicense, or otherwise +// transfer rights in this software, +// (b) remove or alter any trademark, logo, copyright or other proprietary +// notices, legends, symbols or labels present in this software, +// (c) plagiarize this software to sidestep the licensing obligations. // // Quantum Leaps contact information: // // -// -//$endhead${src::qf::qf_time.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -48,37 +42,20 @@ namespace { Q_DEFINE_THIS_MODULE("qf_time") } // unnamed namespace -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QF::QTimeEvt} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { //${QF::QTimeEvt} ............................................................ QTimeEvt QTimeEvt::timeEvtHead_[QF_MAX_TICK_RATE]; -#ifndef Q_UNSAFE -QPtrDis QTimeEvt::timeEvtHead_dis_[QF_MAX_TICK_RATE]; -#endif // ndef Q_UNSAFE - -//${QF::QTimeEvt::QTimeEvt} .................................................. +//............................................................................ QTimeEvt::QTimeEvt( QActive * const act, QSignal const sig, std::uint_fast8_t const tickRate) noexcept : QEvt(sig), m_next(nullptr), -#ifndef Q_UNSAFE - m_next_dis(static_cast(~Q_PTR2UINT_CAST_(nullptr))), -#endif m_act(act), m_ctr(0U), -#ifndef Q_UNSAFE - m_ctr_dis(static_cast(~static_cast(0U))), -#endif m_interval(0U), m_tickRate(0U), m_flags(0U) @@ -89,56 +66,48 @@ QTimeEvt::QTimeEvt( && (tickRate < QF_MAX_TICK_RATE)); QF_CRIT_EXIT(); - // adjust the settings from the QEvt(sig) ctor - evtTag_ = 0x0FU; - refCtr_ = 0U; + refCtr_ = 0U; // adjust from the QEvt(sig) ctor } -//${QF::QTimeEvt::armX} ...................................................... +//............................................................................ void QTimeEvt::armX( std::uint32_t const nTicks, std::uint32_t const interval) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); // dynamic range checks - #if (QF_TIMEEVT_CTR_SIZE == 1U) +#if (QF_TIMEEVT_CTR_SIZE == 1U) Q_REQUIRE_INCRIT(400, (nTicks < 0xFFU) && (interval < 0xFFU)); - #elif (QF_TIMEEVT_CTR_SIZE == 2U) +#elif (QF_TIMEEVT_CTR_SIZE == 2U) Q_REQUIRE_INCRIT(400, (nTicks < 0xFFFFU) && (interval < 0xFFFFU)); - #endif - - Q_REQUIRE_INCRIT(401, verify_() && (nTicks != 0U)); +#endif QTimeEvtCtr const ctr = m_ctr; std::uint8_t const tickRate = m_tickRate; - #ifdef Q_SPY +#ifdef Q_SPY std::uint_fast8_t const qsId = static_cast(m_act)->m_prio; - #endif // def Q_SPY +#endif // def Q_SPY - Q_REQUIRE_INCRIT(410, (ctr == 0U) + Q_REQUIRE_INCRIT(410, + (nTicks != 0U) + && (ctr == 0U) && (m_act != nullptr) && (tickRate < QF_MAX_TICK_RATE)); - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(411, ctr == static_cast(~m_ctr_dis)); - #else +#ifdef Q_UNSAFE Q_UNUSED_PAR(ctr); - #endif // ndef Q_UNSAFE +#endif // ndef Q_UNSAFE m_ctr = static_cast(nTicks); m_interval = static_cast(interval); - #ifndef Q_UNSAFE - m_ctr_dis = static_cast(~nTicks); - #endif // ndef Q_UNSAFE // is the time event unlinked? // NOTE: For the duration of a single clock tick of the specified tick // rate a time event can be disarmed and yet still linked into the list - // because un-linking is performed exclusively in the QF_tickX() function. + // because un-linking is performed exclusively in the QTimeEvt::tick(). if ((m_flags & QTE_FLAG_IS_LINKED) == 0U) { m_flags |= QTE_FLAG_IS_LINKED; // mark as linked @@ -148,22 +117,8 @@ void QTimeEvt::armX( // list is appended to the main list of armed time events based on // timeEvtHead_[tickRate].next. Again, this is to keep any // changes to the main list exclusively inside QTimeEvt::tick(). - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(420, - Q_PTR2UINT_CAST_(m_next) == - static_cast(~m_next_dis)); - Q_INVARIANT_INCRIT(411, - Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) == - static_cast(~timeEvtHead_dis_[tickRate].m_ptr_dis)); - #endif m_next = timeEvtHead_[tickRate].toTimeEvt(); timeEvtHead_[tickRate].m_act = this; - #ifndef Q_UNSAFE - m_next_dis = - static_cast(~Q_PTR2UINT_CAST_(m_next)); - timeEvtHead_dis_[tickRate].m_ptr_dis = - static_cast(~Q_PTR2UINT_CAST_(this)); - #endif // ndef Q_UNSAFE } QS_BEGIN_PRE(QS_QF_TIMEEVT_ARM, qsId) @@ -175,36 +130,26 @@ void QTimeEvt::armX( QS_U8_PRE(tickRate); // tick rate QS_END_PRE() - QF_MEM_APP(); QF_CRIT_EXIT(); } -//${QF::QTimeEvt::disarm} .................................................... +//............................................................................ bool QTimeEvt::disarm() noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - Q_REQUIRE_INCRIT(500, verify_()); QTimeEvtCtr const ctr = m_ctr; - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(501, ctr == static_cast(~m_ctr_dis)); - #endif // ndef Q_UNSAFE - #ifdef Q_SPY +#ifdef Q_SPY std::uint_fast8_t const qsId = static_cast(m_act)->m_prio; - #endif +#endif // was the time event actually armed? - bool wasArmed; + bool wasArmed = false; if (ctr != 0U) { wasArmed = true; m_flags |= QTE_FLAG_WAS_DISARMED; m_ctr = 0U; // schedule removal from the list - #ifndef Q_UNSAFE - m_ctr_dis = static_cast(~static_cast(0U)); - #endif // ndef Q_UNSAFE QS_BEGIN_PRE(QS_QF_TIMEEVT_DISARM, qsId) QS_TIME_PRE(); // timestamp @@ -216,7 +161,6 @@ bool QTimeEvt::disarm() noexcept { QS_END_PRE() } else { // the time event was already disarmed automatically - wasArmed = false; m_flags &= static_cast(~QTE_FLAG_WAS_DISARMED); QS_BEGIN_PRE(QS_QF_TIMEEVT_DISARM_ATTEMPT, qsId) @@ -227,55 +171,46 @@ bool QTimeEvt::disarm() noexcept { QS_END_PRE() } - QF_MEM_APP(); QF_CRIT_EXIT(); return wasArmed; } -//${QF::QTimeEvt::rearm} ..................................................... +//............................................................................ bool QTimeEvt::rearm(std::uint32_t const nTicks) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); // dynamic range checks - #if (QF_TIMEEVT_CTR_SIZE == 1U) +#if (QF_TIMEEVT_CTR_SIZE == 1U) Q_REQUIRE_INCRIT(600, nTicks < 0xFFU); - #elif (QF_TIMEEVT_CTR_SIZE == 2U) +#elif (QF_TIMEEVT_CTR_SIZE == 2U) Q_REQUIRE_INCRIT(600, nTicks < 0xFFFFU); - #endif - - Q_REQUIRE_INCRIT(601, verify_() && (nTicks != 0U)); +#endif - QTimeEvtCtr const ctr = m_ctr; std::uint8_t const tickRate = m_tickRate; - #ifdef Q_SPY - std::uint_fast8_t const qsId = static_cast(m_act)->m_prio; - #endif + QTimeEvtCtr const ctr = m_ctr; - Q_REQUIRE_INCRIT(610, (m_act != nullptr) + Q_REQUIRE_INCRIT(610, + (nTicks != 0U) + && (m_act != nullptr) && (tickRate < QF_MAX_TICK_RATE)); - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(602, ctr == static_cast(~m_ctr_dis)); - #endif // ndef Q_UNSAFE +#ifdef Q_SPY + std::uint_fast8_t const qsId = static_cast(m_act)->m_prio; +#endif + m_ctr = static_cast(nTicks); - #ifndef Q_UNSAFE - m_ctr_dis = static_cast(~nTicks); - #endif // ndef Q_UNSAFE - // is the time evt not running? - bool wasArmed; + // was the time evt not running? + bool wasArmed = false; if (ctr == 0U) { - wasArmed = false; - - // NOTE: For a duration of a single clock tick of the specified + // NOTE: For the duration of a single clock tick of the specified // tick rate a time event can be disarmed and yet still linked into // the list, because unlinking is performed exclusively in the // QTimeEvt::tick() function. - // was the time event unlinked? + // is the time event unlinked? if ((m_flags & QTE_FLAG_IS_LINKED) == 0U) { m_flags |= QTE_FLAG_IS_LINKED; // mark as linked @@ -285,22 +220,8 @@ bool QTimeEvt::rearm(std::uint32_t const nTicks) noexcept { // list is appended to the main list of armed time events based on // timeEvtHead_[tickRate].next. Again, this is to keep any // changes to the main list exclusively inside QTimeEvt::tick(). - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(620, - Q_PTR2UINT_CAST_(m_next) == - static_cast(~m_next_dis)); - Q_INVARIANT_INCRIT(611, - Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) == - static_cast(~timeEvtHead_dis_[tickRate].m_ptr_dis)); - #endif m_next = timeEvtHead_[tickRate].toTimeEvt(); timeEvtHead_[tickRate].m_act = this; - #ifndef Q_UNSAFE - m_next_dis = - static_cast(~Q_PTR2UINT_CAST_(m_next)); - timeEvtHead_dis_[tickRate].m_ptr_dis = - static_cast(~Q_PTR2UINT_CAST_(this)); - #endif // ndef Q_UNSAFE } } else { // the time event was armed @@ -316,245 +237,186 @@ bool QTimeEvt::rearm(std::uint32_t const nTicks) noexcept { QS_2U8_PRE(tickRate, (wasArmed ? 1U : 0U)); QS_END_PRE() - QF_MEM_APP(); QF_CRIT_EXIT(); return wasArmed; } -//${QF::QTimeEvt::wasDisarmed} ............................................... +//............................................................................ bool QTimeEvt::wasDisarmed() noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); bool const wasDisarmed = (m_flags & QTE_FLAG_WAS_DISARMED) != 0U; m_flags |= QTE_FLAG_WAS_DISARMED; - QF_MEM_APP(); QF_CRIT_EXIT(); return wasDisarmed; } -//${QF::QTimeEvt::tick} ...................................................... +//............................................................................ void QTimeEvt::tick( std::uint_fast8_t const tickRate, void const * const sender) noexcept { - #ifndef Q_SPY +#ifndef Q_SPY Q_UNUSED_PAR(sender); - #endif +#endif QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); Q_REQUIRE_INCRIT(800, tickRate < Q_DIM(timeEvtHead_)); QTimeEvt *prev = &timeEvtHead_[tickRate]; +#ifdef Q_SPY QS_BEGIN_PRE(QS_QF_TICK, 0U) prev->m_ctr = (prev->m_ctr + 1U); QS_TEC_PRE(prev->m_ctr); // tick ctr QS_U8_PRE(tickRate); // tick rate QS_END_PRE() +#endif // def Q_SPY // scan the linked-list of time events at this rate... - std::uint_fast8_t lbound = 2U*QF_MAX_ACTIVE; // fixed upper loop bound - for (; lbound > 0U; --lbound) { + while (true) { Q_ASSERT_INCRIT(810, prev != nullptr); // sanity check QTimeEvt *te = prev->m_next; // advance down the time evt. list - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(811, - Q_PTR2UINT_CAST_(te) == - static_cast(~prev->m_next_dis)); - #endif // ndef Q_UNSAFE if (te == nullptr) { // end of the list? - - // any new time events armed since the last QTimeEvt_tick_()? - if (timeEvtHead_[tickRate].m_act != nullptr) { - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(812, - Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) == - static_cast( - ~timeEvtHead_dis_[tickRate].m_ptr_dis)); - #endif // ndef Q_UNSAFE - prev->m_next = timeEvtHead_[tickRate].toTimeEvt(); - timeEvtHead_[tickRate].m_act = nullptr; - #ifndef Q_UNSAFE - prev->m_next_dis = - static_cast( - ~Q_PTR2UINT_CAST_(prev->m_next)); - timeEvtHead_dis_[tickRate].m_ptr_dis = - static_cast(~Q_PTR2UINT_CAST_(nullptr)); - #endif // ndef Q_UNSAFE - - te = prev->m_next; // switch to the new list - } - else { // all currently armed time events are processed - break; // terminate the for-loop + // NO any new time events armed since the last QTimeEvt_tick_()? + if (timeEvtHead_[tickRate].m_act == nullptr) { + break; // terminate the while-loop } + + prev->m_next = timeEvtHead_[tickRate].toTimeEvt(); + timeEvtHead_[tickRate].m_act = nullptr; + + te = prev->m_next; // switch to the new list } // the time event 'te' must be valid - Q_ASSERT_INCRIT(820, te != nullptr); - Q_INVARIANT_INCRIT(821, te->verify_()); + Q_ASSERT_INCRIT(840, te != nullptr); QTimeEvtCtr ctr = te->m_ctr; - #ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(822, ctr == - static_cast(~te->m_ctr_dis)); - #endif // ndef Q_UNSAFE if (ctr == 0U) { // time event scheduled for removal? prev->m_next = te->m_next; - #ifndef Q_UNSAFE - prev->m_next_dis = - static_cast(~Q_PTR2UINT_CAST_(te->m_next)); - #endif // ndef Q_UNSAFE // mark time event 'te' as NOT linked te->m_flags &= static_cast(~QTE_FLAG_IS_LINKED); - // do NOT advance the prev pointer - QF_MEM_APP(); QF_CRIT_EXIT(); // exit crit. section to reduce latency - - // NOTE: prevent merging critical sections - // In some QF ports the critical section exit takes effect only - // on the next machine instruction. If the next instruction is - // another entry to a critical section, the critical section - // might not be really exited, but rather the two adjacent - // critical sections would be MERGED. The QF_CRIT_EXIT_NOP() - // macro contains minimal code required to prevent such merging - // of critical sections in QF ports, in which it can occur. - QF_CRIT_EXIT_NOP(); } - else if (ctr == 1U) { // is time evt about to expire? + else if (ctr == 1U) { // is time event about to expire? QActive * const act = te->toActive(); - if (te->m_interval != 0U) { // periodic time evt? - te->m_ctr = te->m_interval; // rearm the time event - #ifndef Q_UNSAFE - te->m_ctr_dis = static_cast(~te->m_interval); - #endif // ndef Q_UNSAFE - prev = te; // advance to this time event - } - else { // one-shot time event: automatically disarm - te->m_ctr = 0U; - prev->m_next = te->m_next; - #ifndef Q_UNSAFE - te->m_ctr_dis = - static_cast(~static_cast(0U)); - prev->m_next_dis = - static_cast(~Q_PTR2UINT_CAST_(te->m_next)); - #endif // ndef Q_UNSAFE - - // mark time event 'te' as NOT linked - te->m_flags &= - static_cast(~QTE_FLAG_IS_LINKED); - // do NOT advance the prev pointer - - QS_BEGIN_PRE(QS_QF_TIMEEVT_AUTO_DISARM, act->m_prio) - QS_OBJ_PRE(te); // this time event object - QS_OBJ_PRE(act); // the target AO - QS_U8_PRE(tickRate); // tick rate - QS_END_PRE() - } - - QS_BEGIN_PRE(QS_QF_TIMEEVT_POST, act->m_prio) - QS_TIME_PRE(); // timestamp - QS_OBJ_PRE(te); // the time event object - QS_SIG_PRE(te->sig); // signal of this time event - QS_OBJ_PRE(act); // the target AO - QS_U8_PRE(tickRate); // tick rate - QS_END_PRE() + prev = te->expire_(prev, act, tickRate); - #ifdef QXK_HPP_ +#ifdef QXK_HPP_ if (te->sig < Q_USER_SIG) { QXThread::timeout_(act); - QF_MEM_APP(); QF_CRIT_EXIT(); } else { - QF_MEM_APP(); QF_CRIT_EXIT(); // exit crit. section before posting // act->POST() asserts if the queue overflows act->POST(te, sender); } - #else - QF_MEM_APP(); +#else // not QXK QF_CRIT_EXIT(); // exit crit. section before posting // act->POST() asserts if the queue overflows act->POST(te, sender); - #endif +#endif } else { // time event keeps timing out --ctr; // decrement the tick counter te->m_ctr = ctr; // update the original - #ifndef Q_UNSAFE - te->m_ctr_dis = static_cast(~ctr); - #endif // ndef Q_UNSAFE prev = te; // advance to this time event - - QF_MEM_APP(); QF_CRIT_EXIT(); // exit crit. section to reduce latency - - // prevent merging critical sections, see NOTE above - QF_CRIT_EXIT_NOP(); } QF_CRIT_ENTRY(); // re-enter crit. section to continue the loop - QF_MEM_SYS(); } - - Q_ENSURE_INCRIT(890, lbound > 0U); - QF_MEM_APP(); QF_CRIT_EXIT(); } -//${QF::QTimeEvt::noActive} .................................................. +//............................................................................ bool QTimeEvt::noActive(std::uint_fast8_t const tickRate) noexcept { // NOTE: this function must be called *inside* critical section Q_REQUIRE_INCRIT(900, tickRate < QF_MAX_TICK_RATE); - bool inactive; + bool inactive = false; - QF_MEM_SYS(); if (timeEvtHead_[tickRate].m_next != nullptr) { - inactive = false; + // empty } else if (timeEvtHead_[tickRate].m_act != nullptr) { - inactive = false; + // empty } else { inactive = true; } - QF_MEM_APP(); return inactive; } -//${QF::QTimeEvt::QTimeEvt} .................................................. +//............................................................................ QTimeEvt::QTimeEvt() noexcept : QEvt(0U), m_next(nullptr), -#ifndef Q_UNSAFE - m_next_dis(static_cast(~Q_PTR2UINT_CAST_(nullptr))), -#endif m_act(nullptr), m_ctr(0U), -#ifndef Q_UNSAFE - m_ctr_dis(static_cast(~static_cast(0U))), -#endif m_interval(0U), m_tickRate(0U), m_flags(0U) {} +//............................................................................ +QTimeEvt *QTimeEvt::expire_( + QTimeEvt * const prev_link, + QActive const * const act, + std::uint_fast8_t const tickRate) noexcept +{ + // NOTE: this helper function is called *inside* critical section +#ifndef Q_SPY + Q_UNUSED_PAR(act); + Q_UNUSED_PAR(tickRate); +#endif + + QTimeEvt *prev = prev_link; + if (m_interval != 0U) { // periodic time evt? + m_ctr = m_interval; // rearm the time event + prev = this; // advance to this time event + } + else { // one-shot time event: automatically disarm + m_ctr = 0U; + prev->m_next = m_next; + + // mark this time event as NOT linked + m_flags &= + static_cast(~QTE_FLAG_IS_LINKED); + // do NOT advance the prev pointer + + QS_BEGIN_PRE(QS_QF_TIMEEVT_AUTO_DISARM, act->m_prio) + QS_OBJ_PRE(this); // this time event object + QS_OBJ_PRE(act); // the target AO + QS_U8_PRE(tickRate); // tick rate + QS_END_PRE() + } + + QS_BEGIN_PRE(QS_QF_TIMEEVT_POST, act->m_prio) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // the time event object + QS_SIG_PRE(sig); // signal of this time event + QS_OBJ_PRE(act); // the target AO + QS_U8_PRE(tickRate); // tick rate + QS_END_PRE() + + return prev; +} + } // namespace QP -//$enddef${QF::QTimeEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/qk/qk.cpp b/src/qk/qk.cpp index 8d9a74186..0b1013771 100644 --- a/src/qk/qk.cpp +++ b/src/qk/qk.cpp @@ -1,10 +1,6 @@ -//$file${src::qk::qk.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qk::qk.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${src::qk::qk.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -45,7 +40,7 @@ // protection against including this source file in a wrong project #ifndef QK_HPP_ - #error "Source file included in a project NOT based on the QK kernel" + #error Source file included in a project NOT based on the QK kernel #endif // QK_HPP_ // unnamed namespace for local definitions with internal linkage @@ -53,28 +48,18 @@ namespace { Q_DEFINE_THIS_MODULE("qk") } // unnamed namespace -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QK::QK-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { namespace QK { -//${QK::QK-base::schedLock} .................................................. +//............................................................................ QSchedStatus schedLock(std::uint_fast8_t const ceiling) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); Q_REQUIRE_INCRIT(100, !QK_ISR_CONTEXT_()); - Q_INVARIANT_INCRIT(102, QK_priv_.lockCeil - == static_cast(~QK_priv_.lockCeil_dis)); // first store the previous lock prio - QSchedStatus stat; + QSchedStatus stat = 0xFFU; // assume scheduler NOT locked if (ceiling > QK_priv_.lockCeil) { // raising the lock ceiling? QS_BEGIN_PRE(QS_SCHED_LOCK, QK_priv_.actPrio) QS_TIME_PRE(); // timestamp @@ -88,33 +73,21 @@ QSchedStatus schedLock(std::uint_fast8_t const ceiling) noexcept { // new status of the lock QK_priv_.lockCeil = ceiling; - #ifndef Q_UNSAFE - QK_priv_.lockCeil_dis = static_cast(~ceiling); - #endif } - else { - stat = 0xFFU; // scheduler not locked - } - - QF_MEM_APP(); QF_CRIT_EXIT(); return stat; // return the status to be saved in a stack variable } -//${QK::QK-base::schedUnlock} ................................................ +//............................................................................ void schedUnlock(QSchedStatus const prevCeil) noexcept { // has the scheduler been actually locked by the last QK::schedLock()? if (prevCeil != 0xFFU) { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); - Q_INVARIANT_INCRIT(202, QK_priv_.lockCeil - == static_cast(~QK_priv_.lockCeil_dis)); - Q_REQUIRE_INCRIT(210, (!QK_ISR_CONTEXT_()) + Q_REQUIRE_INCRIT(200, (!QK_ISR_CONTEXT_()) && (QK_priv_.lockCeil > prevCeil)); - QS_BEGIN_PRE(QS_SCHED_UNLOCK, QK_priv_.actPrio) QS_TIME_PRE(); // timestamp // current lock ceiling (old), previous lock ceiling (new) @@ -124,68 +97,44 @@ void schedUnlock(QSchedStatus const prevCeil) noexcept { // restore the previous lock ceiling QK_priv_.lockCeil = prevCeil; - #ifndef Q_UNSAFE - QK_priv_.lockCeil_dis = static_cast(~prevCeil); - #endif // find if any AOs should be run after unlocking the scheduler if (QK_sched_() != 0U) { // preemption needed? QK_activate_(); // activate any unlocked AOs } - QF_MEM_APP(); QF_CRIT_EXIT(); } } } // namespace QK } // namespace QP -//$enddef${QK::QK-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ extern "C" { -//$define${QK-extern-C} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -//${QK-extern-C::QK_priv_} ................................................... QK_Attr QK_priv_; -//${QK-extern-C::QK_sched_} .................................................. +//............................................................................ std::uint_fast8_t QK_sched_() noexcept { // NOTE: this function is entered with interrupts DISABLED - Q_INVARIANT_INCRIT(402, - QK_priv_.readySet.verify_(&QK_priv_.readySet_dis)); - - std::uint_fast8_t p; - if (QK_priv_.readySet.isEmpty()) { - p = 0U; // no activation needed - } - else { + std::uint_fast8_t p = 0U; // assume NO activation needed + if (QK_priv_.readySet.notEmpty()) { // find the highest-prio AO with non-empty event queue p = QK_priv_.readySet.findMax(); - Q_INVARIANT_INCRIT(412, QK_priv_.actThre - == static_cast(~QK_priv_.actThre_dis)); - // is the AO's prio. below the active preemption-threshold? if (p <= QK_priv_.actThre) { p = 0U; // no activation needed } else { - Q_INVARIANT_INCRIT(422, QK_priv_.lockCeil - == static_cast(~QK_priv_.lockCeil_dis)); - // is the AO's prio. below the lock-ceiling? if (p <= QK_priv_.lockCeil) { p = 0U; // no activation needed } else { - Q_INVARIANT_INCRIT(432, QK_priv_.nextPrio - == static_cast(~QK_priv_.nextPrio_dis)); QK_priv_.nextPrio = p; // next AO to run - #ifndef Q_UNSAFE - QK_priv_.nextPrio_dis - = static_cast(~QK_priv_.nextPrio); - #endif } } } @@ -193,60 +142,77 @@ std::uint_fast8_t QK_sched_() noexcept { return p; } -//${QK-extern-C::QK_activate_} ............................................... +//............................................................................ +std::uint_fast8_t QK_sched_act_( + QP::QActive const * const act, + std::uint_fast8_t const pthre_in) noexcept +{ + // NOTE: this function is entered with interrupts DISABLED + + std::uint_fast8_t p = act->getPrio(); + if (act->getEQueue().isEmpty()) { // empty queue? + QK_priv_.readySet.remove(p); + } + + if (QK_priv_.readySet.isEmpty()) { + p = 0U; // no activation needed + } + else { + // find new highest-prio AO ready to run... + p = QK_priv_.readySet.findMax(); + // NOTE: p is guaranteed to be <= QF_MAX_ACTIVE + + // is the new prio. below the initial preemption-threshold? + if (p <= pthre_in) { + p = 0U; // no activation needed + } + else { + // is the AO's prio. below the lock preemption-threshold? + if (p <= QK_priv_.lockCeil) { + p = 0U; // no activation needed + } + } + } + + return p; +} + +//............................................................................ void QK_activate_() noexcept { // NOTE: this function is entered with interrupts DISABLED std::uint_fast8_t const prio_in = QK_priv_.actPrio; // save initial prio. std::uint_fast8_t p = QK_priv_.nextPrio; // next prio to run - Q_INVARIANT_INCRIT(502, - (prio_in == static_cast(~QK_priv_.actPrio_dis)) - && (p == static_cast(~QK_priv_.nextPrio_dis))); - Q_REQUIRE_INCRIT(510, (prio_in <= QF_MAX_ACTIVE) + Q_REQUIRE_INCRIT(500, (prio_in <= QF_MAX_ACTIVE) && (0U < p) && (p <= QF_MAX_ACTIVE)); - #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) +#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) std::uint_fast8_t pprev = prio_in; - #endif // QF_ON_CONTEXT_SW || Q_SPY +#endif // QF_ON_CONTEXT_SW || Q_SPY QK_priv_.nextPrio = 0U; // clear for the next time - #ifndef Q_UNSAFE - QK_priv_.nextPrio_dis = static_cast(~QK_priv_.nextPrio); - #endif - - std::uint_fast8_t pthre_in; - QP::QActive *a; - if (prio_in == 0U) { // preempting the idle thread? - pthre_in = 0U; - } - else { - a = QP::QActive::registry_[prio_in]; + + std::uint_fast8_t pthre_in = 0U; // assume preempting the idle thread + if (prio_in != 0U) { // preempting NOT the idle thread + QP::QActive const * const a = QP::QActive::registry_[prio_in]; Q_ASSERT_INCRIT(510, a != nullptr); pthre_in = static_cast(a->getPThre()); - Q_INVARIANT_INCRIT(511, pthre_in == static_cast( - ~static_cast(a->m_pthre_dis) & 0xFFU)); } // loop until no more ready-to-run AOs of higher pthre than the initial do { - a = QP::QActive::registry_[p]; // obtain the pointer to the AO + QP::QActive * const a = QP::QActive::registry_[p]; Q_ASSERT_INCRIT(520, a != nullptr); // the AO must be registered std::uint_fast8_t const pthre = static_cast(a->getPThre()); - Q_INVARIANT_INCRIT(522, pthre == static_cast( - ~static_cast(a->m_pthre_dis) & 0xFFU)); // set new active prio. and preemption-threshold QK_priv_.actPrio = p; QK_priv_.actThre = pthre; - #ifndef Q_UNSAFE - QK_priv_.actPrio_dis = static_cast(~p); - QK_priv_.actThre_dis = static_cast(~pthre); - #endif - #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) +#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) if (p != pprev) { // changing threads? QS_BEGIN_PRE(QP::QS_SCHED_NEXT, p) @@ -255,108 +221,68 @@ void QK_activate_() noexcept { pprev); // previous prio. QS_END_PRE() - #ifdef QF_ON_CONTEXT_SW +#ifdef QF_ON_CONTEXT_SW QF_onContextSw(QP::QActive::registry_[pprev], a); - #endif // QF_ON_CONTEXT_SW +#endif // QF_ON_CONTEXT_SW pprev = p; // update previous prio. } - #endif // QF_ON_CONTEXT_SW || Q_SPY +#endif // QF_ON_CONTEXT_SW || Q_SPY - QF_MEM_APP(); QF_INT_ENABLE(); // unconditionally enable interrupts QP::QEvt const * const e = a->get_(); - // NOTE QActive_get_() performs QF_MEM_APP() before return // dispatch event (virtual call) a->dispatch(e, a->getPrio()); - #if (QF_MAX_EPOOL > 0U) +#if (QF_MAX_EPOOL > 0U) QP::QF::gc(e); - #endif +#endif // determine the next highest-prio. AO ready to run... QF_INT_DISABLE(); // unconditionally disable interrupts - QF_MEM_SYS(); - - // internal integrity check (duplicate inverse storage) - Q_INVARIANT_INCRIT(532, - QK_priv_.readySet.verify_(&QK_priv_.readySet_dis)); + p = QK_sched_act_(a, pthre_in); // schedule next AO - if (a->getEQueue().isEmpty()) { // empty queue? - QK_priv_.readySet.remove(p); - #ifndef Q_UNSAFE - QK_priv_.readySet.update_(&QK_priv_.readySet_dis); - #endif - } - - if (QK_priv_.readySet.isEmpty()) { - p = 0U; // no activation needed - } - else { - // find new highest-prio AO ready to run... - p = QK_priv_.readySet.findMax(); - - // is the new prio. below the initial preemption-threshold? - if (p <= pthre_in) { - p = 0U; // no activation needed - } - else { - Q_INVARIANT_INCRIT(542, - QK_priv_.lockCeil == ~QK_priv_.lockCeil_dis); - - // is the AO's prio. below the lock preemption-threshold? - if (p <= QK_priv_.lockCeil) { - p = 0U; // no activation needed - } - else { - Q_ASSERT_INCRIT(550, p <= QF_MAX_ACTIVE); - } - } - } } while (p != 0U); // restore the active prio. and preemption-threshold QK_priv_.actPrio = prio_in; QK_priv_.actThre = pthre_in; - #ifndef Q_UNSAFE - QK_priv_.actPrio_dis = static_cast(~QK_priv_.actPrio); - QK_priv_.actThre_dis = static_cast(~QK_priv_.actThre); - #endif - #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) +#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) if (prio_in != 0U) { // resuming an active object? - a = QP::QActive::registry_[prio_in]; // pointer to preempted AO - QS_BEGIN_PRE(QP::QS_SCHED_NEXT, prio_in) QS_TIME_PRE(); // timestamp // prio. of the resumed AO, previous prio. QS_2U8_PRE(prio_in, pprev); QS_END_PRE() + +#ifdef QF_ON_CONTEXT_SW + QF_onContextSw(QP::QActive::registry_[pprev], + QP::QActive::registry_[prio_in]); +#endif // QF_ON_CONTEXT_SW } else { // resuming prio.==0 --> idle - a = nullptr; // QK idle loop - QS_BEGIN_PRE(QP::QS_SCHED_IDLE, pprev) QS_TIME_PRE(); // timestamp QS_U8_PRE(pprev); // previous prio. QS_END_PRE() + +#ifdef QF_ON_CONTEXT_SW + QF_onContextSw(QP::QActive::registry_[pprev], nullptr); +#endif // QF_ON_CONTEXT_SW } - #ifdef QF_ON_CONTEXT_SW - QF_onContextSw(QP::QActive::registry_[pprev], a); - #endif // QF_ON_CONTEXT_SW - #endif // QF_ON_CONTEXT_SW || Q_SPY +#endif // QF_ON_CONTEXT_SW || Q_SPY } -//$enddef${QK-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } // extern "C" -//$define${QK::QF-cust} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +//............................................................................ namespace QP { namespace QF { -//${QK::QF-cust::init} ....................................................... +//............................................................................ void init() { bzero_(&QF::priv_, sizeof(QF::priv_)); bzero_(&QK_priv_, sizeof(QK_priv_)); @@ -365,83 +291,61 @@ void init() { // setup the QK scheduler as initially locked and not running QK_priv_.lockCeil = (QF_MAX_ACTIVE + 1U); // scheduler locked - #ifndef Q_UNSAFE - QK_priv_.readySet.update_(&QK_priv_.readySet_dis); - QK_priv_.actPrio_dis = static_cast(~QK_priv_.actPrio); - QK_priv_.nextPrio_dis = static_cast(~QK_priv_.nextPrio); - QK_priv_.actThre_dis = static_cast(~QK_priv_.actThre); - QK_priv_.lockCeil_dis = static_cast(~QK_priv_.lockCeil); - #endif - - #ifdef QK_INIT +#ifdef QK_INIT QK_INIT(); // port-specific initialization of the QK kernel - #endif +#endif } -//${QK::QF-cust::stop} ....................................................... +//............................................................................ void stop() { - onCleanup(); // cleanup callback - // nothing else to do for the QK preemptive kernel + onCleanup(); // application-specific cleanup callback + // nothing else to do for the preemptive QK kernel } -//${QK::QF-cust::run} ........................................................ +//............................................................................ int_t run() { - #ifdef Q_SPY +#ifdef Q_SPY // produce the QS_QF_RUN trace record QF_INT_DISABLE(); - QF_MEM_SYS(); QS::beginRec_(QS_REC_NUM_(QS_QF_RUN)); QS::endRec_(); - QF_MEM_APP(); QF_INT_ENABLE(); - #endif // Q_SPY +#endif // Q_SPY onStartup(); // application-specific startup callback QF_INT_DISABLE(); - QF_MEM_SYS(); - #ifdef QK_START +#ifdef QK_START QK_START(); // port-specific startup of the QK kernel - #endif +#endif QK_priv_.lockCeil = 0U; // unlock the QK scheduler - #ifndef Q_UNSAFE - QK_priv_.lockCeil_dis = static_cast(~QK_priv_.lockCeil); - #endif - #ifdef QF_ON_CONTEXT_SW +#ifdef QF_ON_CONTEXT_SW // officially switch to the idle context QF_onContextSw(nullptr, QActive::registry_[QK_priv_.nextPrio]); - #endif +#endif // activate AOs to process events posted so far if (QK_sched_() != 0U) { QK_activate_(); } - QF_MEM_APP(); QF_INT_ENABLE(); for (;;) { // QK idle loop... QK::onIdle(); // application-specific QK on-idle callback } - #ifdef __GNUC__ // GNU compiler? +#ifdef __GNUC__ // GNU compiler? return 0; - #endif +#endif } } // namespace QF -} // namespace QP -//$enddef${QK::QF-cust} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QK::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QK::QActive} ............................................................. -//${QK::QActive::start} ...................................................... +//............................................................................ void QActive::start( QPrioSpec const prioSpec, QEvtPtr * const qSto, @@ -455,15 +359,13 @@ void QActive::start( QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); - Q_REQUIRE_INCRIT(300, (!QK_ISR_CONTEXT_()) - && (stkSto == nullptr)); - QF_MEM_APP(); + Q_REQUIRE_INCRIT(300, + (stkSto == nullptr)); QF_CRIT_EXIT(); m_prio = static_cast(prioSpec & 0xFFU); // QF-prio. - m_pthre = static_cast(prioSpec >> 8U); // preemption-thre. + m_pthre = static_cast(prioSpec >> 8U); // preemption-thre. register_(); // make QF aware of this AO m_eQueue.init(qSto, qLen); // init the built-in queue @@ -474,13 +376,10 @@ void QActive::start( // See if this AO needs to be scheduled if QK is already running QF_CRIT_ENTRY(); - QF_MEM_SYS(); if (QK_sched_() != 0U) { // activation needed? QK_activate_(); } - QF_MEM_APP(); QF_CRIT_EXIT(); } } // namespace QP -//$enddef${QK::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/qs/qstamp.cpp b/src/qs/qstamp.cpp index dea2155b8..91f43c2d2 100644 --- a/src/qs/qstamp.cpp +++ b/src/qs/qstamp.cpp @@ -1,10 +1,6 @@ -//$file${src::qs::qstamp.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qs::qstamp.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -12,26 +8,24 @@ // ------------------------ // Modern Embedded Software // -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// SPDX-License-Identifier: LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- -// source Quantum Leaps commercial licenses. +// This software is licensed under the terms of the Quantum Leaps commercial +// licenses. Please contact Quantum Leaps for more information about the +// available licensing options. // -// Redistributions in source code must retain this top-level comment block. -// Plagiarizing this software to sidestep the license obligations is illegal. -// -// NOTE: -// The GPL does NOT permit the incorporation of this code into proprietary -// programs. Please contact Quantum Leaps for commercial licensing options, -// which expressly supersede the GPL and are designed explicitly for -// closed-source distribution. +// RESTRICTIONS +// You may NOT : +// (a) redistribute, encumber, sell, rent, lease, sublicense, or otherwise +// transfer rights in this software, +// (b) remove or alter any trademark, logo, copyright or other proprietary +// notices, legends, symbols or labels present in this software, +// (c) plagiarize this software to sidestep the licensing obligations. // // Quantum Leaps contact information: // // -// -//$endhead${src::qs::qstamp.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #include "qstamp.hpp" namespace QP { diff --git a/src/qv/qv.cpp b/src/qv/qv.cpp index c8efcba49..78b96ccdd 100644 --- a/src/qv/qv.cpp +++ b/src/qv/qv.cpp @@ -1,10 +1,6 @@ -//$file${src::qv::qv.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qv::qv.cpp} -// -// This code has been generated by QM 7.0.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +//============================================================================ +// QP/C++ Real-Time Embedded Framework (RTEF) +// Version 8.0.2 // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -14,8 +10,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C++ software is dual-licensed under the terms of the open-source -// GNU General Public License (GPL) or under the terms of one of the closed- +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. @@ -30,8 +26,7 @@ // Quantum Leaps contact information: // // -// -//$endhead${src::qv::qv.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -45,7 +40,7 @@ // protection against including this source file in a wrong project #ifndef QV_HPP_ - #error "Source file included in a project NOT based on the QV kernel" + #error Source file included in a project NOT based on the QV kernel #endif // QV_HPP_ // unnamed namespace for local definitions with internal linkage @@ -53,27 +48,15 @@ namespace { Q_DEFINE_THIS_MODULE("qv") } // unnamed namespace -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QV::QV-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { namespace QV { -//${QV::QV-base::priv_} ...................................................... QV::Attr priv_; -//${QV::QV-base::schedDisable} ............................................... +//............................................................................ void schedDisable(std::uint_fast8_t const ceiling) { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - Q_INVARIANT_INCRIT(102, priv_.schedCeil - == static_cast(~priv_.schedCeil_dis)); if (ceiling > priv_.schedCeil) { // raising the scheduler ceiling? @@ -85,22 +68,14 @@ void schedDisable(std::uint_fast8_t const ceiling) { QS_END_PRE() priv_.schedCeil = ceiling; - #ifndef Q_UNSAFE - priv_.schedCeil_dis = static_cast(~ceiling); - #endif } - QF_MEM_APP(); QF_CRIT_EXIT(); } -//${QV::QV-base::schedEnable} ................................................ +//............................................................................ void schedEnable() { QF_CRIT_STAT QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - Q_INVARIANT_INCRIT(202, priv_.schedCeil - == static_cast(~priv_.schedCeil_dis)); if (priv_.schedCeil != 0U) { // actually enabling the scheduler? @@ -111,39 +86,26 @@ void schedEnable() { QS_END_PRE() priv_.schedCeil = 0U; - #ifndef Q_UNSAFE - priv_.schedCeil_dis = ~static_cast(0U); - #endif } - QF_MEM_APP(); QF_CRIT_EXIT(); } } // namespace QV -} // namespace QP -//$enddef${QV::QV-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QV::QF-cust} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { namespace QF { -//${QV::QF-cust::init} ....................................................... +//............................................................................ void init() { bzero_(&QF::priv_, sizeof(QF::priv_)); bzero_(&QV::priv_, sizeof(QV::priv_)); bzero_(&QActive::registry_[0], sizeof(QActive::registry_)); - #ifndef Q_UNSAFE - QV::priv_.readySet.update_(&QV::priv_.readySet_dis); - QV::priv_.schedCeil_dis = ~static_cast(0U); - #endif - - #ifdef QV_INIT +#ifdef QV_INIT QV_INIT(); // port-specific initialization of the QV kernel - #endif +#endif } -//${QV::QF-cust::stop} ....................................................... +//............................................................................ void stop() { onCleanup(); // cleanup callback // nothing else to do for the QV kernel @@ -151,44 +113,33 @@ void stop() { //${QV::QF-cust::run} ........................................................ int_t run() { - #ifdef Q_SPY +#ifdef Q_SPY // produce the QS_QF_RUN trace record QF_INT_DISABLE(); - QF_MEM_SYS(); QS::beginRec_(QS_REC_NUM_(QS_QF_RUN)); QS::endRec_(); - QF_MEM_APP(); QF_INT_ENABLE(); - #endif // Q_SPY +#endif // Q_SPY onStartup(); // application-specific startup callback QF_INT_DISABLE(); - QF_MEM_SYS(); - #ifdef QV_START +#ifdef QV_START QV_START(); // port-specific startup of the QV kernel - #endif +#endif - #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) +#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) std::uint_fast8_t pprev = 0U; // previous prio. - #ifdef QF_ON_CONTEXT_SW +#ifdef QF_ON_CONTEXT_SW // officially switch to the idle cotext QF_onContextSw(nullptr, nullptr); - #endif // def QF_ON_CONTEXT_SW +#endif // def QF_ON_CONTEXT_SW - #endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) +#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) for (;;) { // QV event loop... - - // check internal integrity (duplicate inverse storage) - Q_INVARIANT_INCRIT(302, - QV::priv_.readySet.verify_(&QV::priv_.readySet_dis)); - // check internal integrity (duplicate inverse storage) - Q_INVARIANT_INCRIT(303, QV::priv_.schedCeil - == static_cast(~QV::priv_.schedCeil_dis)); - // find the maximum prio. AO ready to run std::uint_fast8_t const p = (QV::priv_.readySet.notEmpty() ? QV::priv_.readySet.findMax() @@ -197,90 +148,72 @@ int_t run() { if (p > QV::priv_.schedCeil) { // is it above the sched ceiling? QActive * const a = QActive::registry_[p]; - #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) +#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) QS_BEGIN_PRE(QS_SCHED_NEXT, p) QS_TIME_PRE(); // timestamp QS_2U8_PRE(static_cast(p), static_cast(pprev)); QS_END_PRE() - #ifdef QF_ON_CONTEXT_SW +#ifdef QF_ON_CONTEXT_SW QF_onContextSw(((pprev != 0U) ? QActive::registry_[pprev] : nullptr), a); - #endif // QF_ON_CONTEXT_SW +#endif // QF_ON_CONTEXT_SW pprev = p; // update previous prio. - #endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) +#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - QF_MEM_APP(); QF_INT_ENABLE(); QEvt const * const e = a->get_(); - // NOTE QActive::get_() performs QF_MEM_APP() before return // dispatch event (virtual call) a->dispatch(e, a->getPrio()); - #if (QF_MAX_EPOOL > 0U) +#if (QF_MAX_EPOOL > 0U) gc(e); - #endif +#endif QF_INT_DISABLE(); - QF_MEM_SYS(); if (a->getEQueue().isEmpty()) { // empty queue? QV::priv_.readySet.remove(p); - #ifndef Q_UNSAFE - QV::priv_.readySet.update_(&QV::priv_.readySet_dis); - #endif } } else { // no AO ready to run --> idle - #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) +#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) if (pprev != 0U) { QS_BEGIN_PRE(QS_SCHED_IDLE, pprev) QS_TIME_PRE(); // timestamp QS_U8_PRE(static_cast(pprev)); QS_END_PRE() - #ifdef QF_ON_CONTEXT_SW +#ifdef QF_ON_CONTEXT_SW QF_onContextSw(QActive::registry_[pprev], nullptr); - #endif // QF_ON_CONTEXT_SW +#endif // QF_ON_CONTEXT_SW pprev = 0U; // update previous prio } - #endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - - QF_MEM_APP(); +#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - // QV::onIdle() must be called with interrupts DISABLED - // because the determination of the idle condition (all event - // queues empty) can change at any time by an interrupt posting - // events to a queue. + // QV::onIdle() must be called with interrupts DISABLED because + // the determination of the idle condition can change at any time + // by an interrupt posting events to a queue. // - // NOTE: QV::onIdle() MUST enable interrupts internally, - // ideally at the same time as putting the CPU into a power- - // saving mode. + // NOTE: QV::onIdle() MUST enable interrupts internally, ideally + // atomically with putting the CPU into a power-saving mode. QV::onIdle(); QF_INT_DISABLE(); - QF_MEM_SYS(); } } - #ifdef __GNUC__ // GNU compiler? +#ifdef __GNUC__ // GNU compiler? return 0; - #endif +#endif } } // namespace QF -} // namespace QP -//$enddef${QV::QF-cust} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QV::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QV::QActive} ............................................................. -//${QV::QActive::start} ...................................................... +//............................................................................ void QActive::start( QPrioSpec const prioSpec, QEvtPtr * const qSto, @@ -294,7 +227,8 @@ void QActive::start( QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(300, stkSto == nullptr); + Q_REQUIRE_INCRIT(300, + stkSto == nullptr); QF_CRIT_EXIT(); m_prio = static_cast(prioSpec & 0xFFU); // QF-prio. @@ -308,4 +242,3 @@ void QActive::start( } } // namespace QP -//$enddef${QV::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/zephyr/qf_port.cpp b/zephyr/qf_port.cpp index d88ca83e6..f55eeb7c2 100644 --- a/zephyr/qf_port.cpp +++ b/zephyr/qf_port.cpp @@ -7,7 +7,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -25,12 +25,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-26 -//! @version Last updated for: @ref qpc_8_0_0 -//! -//! @file -//! @brief QF/C++ port to Zephyr RTOS kernel, all supported compilers - #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface @@ -204,9 +198,6 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, QF_CRIT_ENTRY(); Q_REQUIRE_INCRIT(200, e != nullptr); -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(201, e->verify_()); -#endif // ndef Q_UNSAFE // NOTE: k_msgq_num_free_get() can be safely called from crit-section std::uint_fast16_t nFree = @@ -236,12 +227,13 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, 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->getPoolNum_(), e->refCtr_);// pool-Id & ref-Count + QS_2U8_PRE(e->poolNum_, e->refCtr_);// pool-Id & ref-Count QS_EQC_PRE(nFree); // # free entries available QS_EQC_PRE(0U); // min # free entries (unknown) QS_END_PRE() - if (e->getPoolNum_() != 0U) { // is it a pool event? + if (e->poolNum_ != 0U) { // is it a pool event? + Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); // increment the reference counter } @@ -262,7 +254,7 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, 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->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(nFree); // # free entries available QS_EQC_PRE(0U); // min # free entries (unknown) QS_END_PRE() @@ -277,20 +269,18 @@ void QActive::postLIFO(QEvt const * const e) noexcept { QF_CRIT_ENTRY(); Q_REQUIRE_INCRIT(300, e != nullptr); -#ifndef Q_UNSAFE - Q_INVARIANT_INCRIT(301, e->verify_()); -#endif // ndef Q_UNSAFE QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio) QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_2U8_PRE(e->poolNum_, e->refCtr_); QS_EQC_PRE(k_msgq_num_free_get(&m_eQueue)); // # free entries QS_EQC_PRE(0U); // min # free entries (unknown) QS_END_PRE() - if (e->getPoolNum_() != 0U) { // is it a pool event? + if (e->poolNum_ != 0U) { // is it a pool event? + Q_ASSERT_INCRIT(305, e->refCtr_ < (2U * QF_MAX_ACTIVE)); QEvt_refCtr_inc_(e); // increment the reference counter } @@ -326,7 +316,7 @@ QEvt const *QActive::get_(void) noexcept { QS_TIME_PRE(); // timestamp QS_SIG_PRE(e->sig); // the signal of this event QS_OBJ_PRE(this); // this active object - QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); // pool-Id & ref-Count + QS_2U8_PRE(e->poolNum_, e->refCtr_); // pool-Id & ref-Count QS_EQC_PRE(k_msgq_num_free_get(&m_eQueue)); // # free entries QS_END_PRE() diff --git a/zephyr/qp_port.hpp b/zephyr/qp_port.hpp index f29a20cc3..0465509d2 100644 --- a/zephyr/qp_port.hpp +++ b/zephyr/qp_port.hpp @@ -7,7 +7,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The QP/C software is dual-licensed under the terms of the open-source GNU +// This software is dual-licensed under the terms of the open-source GNU // General Public License (GPL) or under the terms of one of the closed- // source Quantum Leaps commercial licenses. // @@ -25,12 +25,6 @@ // // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 -//! -//! @file -//! @brief QP/C++ port to Zephyr RTOS 3.4 - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ diff --git a/zephyr/qs_port.hpp b/zephyr/qs_port.hpp index 40d6b9a07..42eee9948 100644 --- a/zephyr/qs_port.hpp +++ b/zephyr/qs_port.hpp @@ -1,33 +1,30 @@ //============================================================================ -// QP/C++ Real-Time Embedded Framework (RTEF) // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // -// 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. +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software // -// The terms of the open source GNU General Public License version 3 -// can be found at: +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-08-16 -//! @version Last updated for: @ref qpcpp_7_3_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++ compiler - #ifndef QS_PORT_HPP_ #define QS_PORT_HPP_ diff --git a/zephyr/qutest_port.cpp b/zephyr/qutest_port.cpp index 1d8bd4ae9..822d36fc0 100644 --- a/zephyr/qutest_port.cpp +++ b/zephyr/qutest_port.cpp @@ -1,36 +1,32 @@ //============================================================================ -// Product: QUTEST port for Zephyr RTOS -// Last updated for version 8.0.0 -// Last updated on 2024-06-11 +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC. -// // 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: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// This software is dual-licensed under the terms of the open-source GNU +// General Public License (GPL) or under the terms of one of the closed- +// source Quantum Leaps commercial licenses. // // Redistributions in source code must retain this top-level comment block. // Plagiarizing this software to sidestep the license obligations is illegal. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ #ifndef Q_SPY - #error "Q_SPY must be defined to compile qutest_cpp.cpp" + #error Q_SPY must be defined to compile qutest_cpp.cpp #endif // Q_SPY #define QP_IMPL // this is QP implementation