7.3.5-rc.1

Semantic versioning
This commit is contained in:
MMS 2024-04-24 09:13:46 -04:00
parent 10441f7a03
commit 4028ad2dd6
41 changed files with 1952 additions and 618 deletions

@ -1 +1 @@
Subproject commit db8b6155e6931d2c55315dfd55b0e1fac0f96e33
Subproject commit 054cd1abe4b4abef5e45f36b1ce8f2aff4575494

130
README.md
View File

@ -4,26 +4,25 @@
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/QuantumLeaps/qpcpp)](https://github.com/QuantumLeaps/qpcpp/releases/latest)
View QP/C++ Revision History at: https://www.state-machine.com/qpcpp/history.html
> **NOTE:** If you're interested in the latest QP/C++ version from GitHub,
it is highly recommended that you clone this repo like that:
it is recommended that you clone this repo like that:
```
git clone https://github.com/QuantumLeaps/qpcpp --recurse-submodules --depth 1
```
Alternatively, you can also download the latest
[QP/C++ Release](https://github.com/QuantumLeaps/qpcpp/releases).
Alternatively, you can also download one of the stable
[QP/C++ Releases][QP-Rel].
# Getting Started with QP/C++
The most recommended way of obtaining QP/C++ is by downloading the
[QP-bundle](https://www.state-machine.com/#Downloads), which includes QP/C++
as well as the QM modeling tool and the QTools collection. The main advantage of
obtaining QP/C++ bundled together like that is that you get all components,
tools and examples ready to go.
as well as the [QM modeling tool][QM] and the [QTools collection][QTools].
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]
@ -35,82 +34,96 @@ provides instructions on how to download, install, and get started with QP.
- [AppNote: "Getting Started with QP Real-Time Embedded Frameworks"][AN]
contains also a tutorial, in which you build a simple "Blinky" application.
## Licensing
The QP frameworks (QP/C and QP/C++) are licensed under the
[dual licensing model](https://www.state-machine.com/licensing), with
the following licensing options:
1. [Open-source licensing](https://www.state-machine.com/licensing#Open) under the
[GNU General Public License (GPLv3)](https://www.gnu.org/licenses/gpl-3.0.en.html).
> NOTE: GPL requires that all modifications to the original code
as well as your application code (Derivative Works as defined in the
Copyright Law) must also be released under the terms of the GPL
open source license.
2. [Closed-source licensing](https://www.state-machine.com/licensing#Closed) under one of
[Quantum Leaps commercial licenses](https://www.state-machine.com/licensing#Commercial),
which are specifically designed for users interested in retaining the
proprietary status of their code.
> NOTE: If your company has a policy forbidding open source in your product,
all QP frameworks can be licensed commercially, in which case you don't use
any open source license and you do not violate your policy.
# 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]
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 is based on the [Active Object][Active] (**actor**)
design pattern, which inherently supports and automatically enforces the
following best practices of concurrent programming:
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
- 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. Using asynchronous events keeps the threads running truly
- 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
- 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.
within an Active Object thread itself.
This architecture is generally **safer**, more responsive and easier to
understand and maintain than the shared-state concurrency of a conventional
RTOS. It also provides higher level of abstraction and the *correct*
abstractions to effectively apply **modeling** and **code generation** to
deeply embedded real-time systems.
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
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 bare-metal single-chip microcontrollers,
completely replacing a traditional RTOS. The framework contains a selection
of **built-in real-time kernels**, such as the cooperative QV kernel, the
preemptive non-blocking QK kernel, and the preemptive, blocking QXK kernel
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).
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/M85).
## Traditional RTOS/OS
QP/C++ can also work with a traditional RTOS, such as ThreadX, FreeRTOS, embOS,
uC/OS-II and TI-RTOS, as well as with (embedded) Linux (POSIX) and Windows.
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, over [350 commercial licensees][Cust],
and many times more open source users worldwide, the QP<EFBFBD> frameworks are the
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++ Licensing
QP/C++ is licensed under the sustainable [dual licensing model][Lic],
in which both the open source software distribution mechanism and
traditional closed source software distribution models are combined.
> **NOTE:** If your company has a policy forbidding open source in your
product, all QP frameworks can be [licensed commercially][Lic], in which case
you don't use any open source license and you do not violate your policy.
# QP/C++ Documentation
The online HTML documentation for the **latest** version of QP/C++ is located
at: https://www.state-machine.com/qpcpp
The offline HTML documentation for **this** particular version of QP/C++
is located in the sub-folder [html](html). To view the offline documentation,
open the file [html/index.html](html/index.html) in your web browser.
is located in the sub-folder [html](html) (included in the [QP/C++ releases][QP-Rel]).
To view the offline documentation, open the file [html/index.html](html/index.html)
in your web browser.
# How to Get Help?
@ -127,16 +140,19 @@ If you like this project, please give it a star (in the upper-right corner of yo
![GitHub star](https://www.state-machine.com/img/github-star.jpg)
[RTEF]: <https://www.state-machine.com/rtef>
[QP]: <https://www.state-machine.com/products/qp>
[QP/C]: <https://www.state-machine.com/qpc>
[QP/C++]: <https://www.state-machine.com/qpcpp>
[QM]: <https://www.state-machine.com/products/qm>
[Active]: <https://www.state-machine.com/active-object>
[HSM]: <https://www.state-machine.com/fsm#HSM>
[Lic]: <https://www.state-machine.com/licensing>
[Cust]: <https://www.state-machine.com/customers>
[AN]: <https://www.state-machine.com/doc/AN_Getting_Started_with_QP.pdf>
[RTEF]: <https://www.state-machine.com/rtef>
[QP]: <https://www.state-machine.com/products/qp>
[QP/C]: <https://github.com/QuantumLeaps/qpc>
[QP/C++]: <https://github.com/QuantumLeaps/qpcpp>
[QM]: <https://github.com/QuantumLeaps/qm>
[QTools]: <https://github.com/QuantumLeaps/qtools>
[QP-Rel]: <https://github.com/QuantumLeaps/qpcpp/releases>
[Active]: <https://www.state-machine.com/qpcpp/srs-qp_ao.html>
[AO_model]: <https://www.state-machine.com/qpcpp/srs-qp_ao.html#srs-qp_ao-model>
[Event]: <https://www.state-machine.com/qpcpp/srs-qp_evt.html>
[HSM]: <https://www.state-machine.com/qpcpp/srs-qp_sm.html>
[Lic]: <https://www.state-machine.com/licensing>
[Cust]: <https://www.state-machine.com/customers>
[AN]: <https://www.state-machine.com/doc/AN_Getting_Started_with_QP.pdf>
[Tutorial]: <https://www.state-machine.com/qpcpp/gs_tut.html>
[Video]: <https://youtu.be/O7ER6_VqIH0>
[Video]: <https://youtu.be/O7ER6_VqIH0>

@ -1 +1 @@
Subproject commit a4becf08ed700750fce0bfea22a8968349330e55
Subproject commit 4c76095e91087b69c97ce5e602690210a97893af

View File

@ -93,10 +93,6 @@ public:
m_nFree(0U),
m_nMin(0U)
{}
#ifdef Q_XTOR
~QEQueue();
#endif // def Q_XTOR
void init(
QEvt const * qSto[],
std::uint_fast16_t const qLen) noexcept;

View File

@ -118,10 +118,6 @@ public:
m_nFree(0U),
m_nMin(0U)
{}
#ifdef Q_XTOR
~QMPool();
#endif // def Q_XTOR
void init(
void * const poolSto,
std::uint_fast32_t const poolSize,

View File

@ -44,11 +44,9 @@
#define QP_HPP_
//============================================================================
#define QP_VERSION 733U
#define QP_VERSION_STR "7.3.3"
//! Encrypted current QP release (7.3.3) and date (2024-03-01)
#define QP_RELEASE 0x70C4F752U
#define QP_VERSION_STR "7.3.5-rc.1"
#define QP_VERSION 735U
#define QP_RELEASE 0x70A1DEF0U
//============================================================================
//! @cond INTERNAL
@ -970,10 +968,6 @@ public:
QActive * const act,
QSignal const sig,
std::uint_fast8_t const tickRate = 0U) noexcept;
#ifdef Q_XTOR
~QTimeEvt();
#endif // def Q_XTOR
void armX(
QTimeEvtCtr const nTicks,
QTimeEvtCtr const interval = 0U) noexcept;

View File

@ -3,7 +3,7 @@
// Model: qpc.qm
// File: ${include::qsafe.h}
//
// This code has been generated by QM 5.3.0 <www.state-machine.com/qm>.
// This code has been generated by QM 6.1.1 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//
// This code is covered by the following QP license:
@ -150,6 +150,9 @@ extern "C" {
//${QP-FuSa::Q_INVARIANT} ....................................................
#define Q_INVARIANT(expr_) Q_ASSERT(expr_)
//${QP-FuSa::Q_INVARIANT_INCRIT} .............................................
#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]

View File

@ -27,8 +27,8 @@
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2023-12-04
//! @version Last updated for: @ref qpcpp_7_3_1
//! @date Last updated on: 2024-05-28
//! @version Last updated for: @ref qpcpp_7_3_5
//!
//! @file
//! @brief QXK/C++ port to ARM Cortex-M, ARM-CLANG
@ -385,10 +385,10 @@ __asm volatile (
" MOVS r1,#1 \n"
" LSLS r1,r1,#27 \n" // r1 := (1 << 27) (UNPENDSVSET bit)
" LDR r2,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State
" STR r1,[r2] \n" // ICSR[27] := 1 (unpend PendSV)
" STR r1,[r2] \n" // ICSR[27] := 1 (un-pend PendSV)
// Check QXK_priv_.next, which contains the pointer to the next thread
// to run, which is set in QXK_ISR_EXIT(). This pointer must not be NULL.
// to run, which is set in QXK_ISR_EXIT(). Return if QXK_priv_.next == 0
" LDR r3,=QXK_priv_ \n"
" LDR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // r1 := QXK_priv_.next
" CMP r0,#0 \n" // is (QXK_priv_.next == 0)?
@ -498,7 +498,7 @@ __asm volatile (
" MOV lr,r2 \n" // make sure MSP is used
#else // ARMv7-M or higher
#ifdef __ARM_FP //--------- if VFP available...
" POP {r0,lr} \n" // restore alighner and EXC_RETURN into lr
" POP {r0,lr} \n" // restore aligner and EXC_RETURN into lr
" DSB \n" // ARM Erratum 838869
" TST lr,#(1 << 4) \n" // is it return to the VFP exception frame?
" IT EQ \n" // if EXC_RETURN[4] is zero...
@ -517,19 +517,18 @@ __asm volatile (
" BCC PendSV_activate \n" // if (next->prio > actPrio) activate the next AO
// otherwise no activation needed...
" MOVS r0,#0 \n"
" STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0
" STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0
" MOVS r2,#0 \n"
" STR r2,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0
" STR r2,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0
" PUSH {r0,lr} \n" // save the aligner + EXC_RETURN
#if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW)
// r0 is still 0 (parameter next) for QXK_contextSw_()
" CMP r0,#0 \n" // r0 == QXK_priv_.next->prio
" BEQ PendSV_idle \n" // if (QXK_priv_.next->prio != 0)
" MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_()
"PendSV_idle: \n"
" LDR r3,=QXK_contextSw_ \n"
" BLX r3 \n" // call QXK_contextSw_()
#ifdef QF_MEM_ISOLATE
" LDR r3,=QF_onMemApp \n"
" BLX r3 \n" // call QF_onMemApp()
#endif
#endif // defined(Q_SPY) || defined(QF_ON_CONTEXT_SW)
" B PendSV_return1 \n" // skip over saving aligner + EXC_RETURN
@ -538,6 +537,10 @@ __asm volatile (
" PUSH {r0,lr} \n" // save the aligner + EXC_RETURN
"PendSV_return1: \n"
#ifdef QF_MEM_ISOLATE
" LDR r3,=QF_onMemApp \n"
" BLX r3 \n" // call QF_onMemApp()
#endif
" LDR r0,=QF_int_enable_ \n"
" BLX r0 \n" // call QF_int_enable_()
//>>>>>>>>>>>>>>>>>>>>>>>> CRITICAL SECTION END >>>>>>>>>>>>>>>>>>>>>>>>>
@ -600,7 +603,7 @@ __asm volatile (
" PUSH {r0-r2,lr} \n" // save next, osObject, EXC_RETURN
#if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW)
" MOV r0,r12 \n" // parameter next
" MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_()
" LDR r3,=QXK_contextSw_ \n"
" BLX r3 \n" // call QXK_contextSw_()
#ifdef QF_MEM_ISOLATE
@ -753,7 +756,7 @@ __asm volatile (
" ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame
#ifdef __ARM_FP //--------- if VFP available...
" POP {r0,lr} \n" // restore alighner and EXC_RETURN into lr
" POP {r0,lr} \n" // restore aligher and EXC_RETURN into lr
" DSB \n" // ARM Erratum 838869
" TST lr,#(1 << 4) \n" // is it return to the VFP exception frame?
" IT EQ \n" // if EXC_RETURN[4] is zero...

View File

@ -27,8 +27,8 @@
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-01-30
//! @version Last updated for: @ref qpcpp_7_3_3
//! @date Last updated on: 2024-05-28
//! @version Last updated for: @ref qpcpp_7_3_5
//!
//! @file
//! @brief QXK/C++ port to ARM Cortex-M, GNU-ARM
@ -390,10 +390,10 @@ __asm volatile (
" MOV r1,#1 \n"
" LSL r1,r1,#27 \n" // r1 := (1 << 27) (UNPENDSVSET bit)
" LDR r2,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State
" STR r1,[r2] \n" // ICSR[27] := 1 (unpend PendSV)
" STR r1,[r2] \n" // ICSR[27] := 1 (un-pend PendSV)
// Check QXK_priv_.next, which contains the pointer to the next thread
// to run, which is set in QXK_ISR_EXIT(). This pointer must not be NULL.
// to run, which is set in QXK_ISR_EXIT(). Return if QXK_priv_.next == 0
" LDR r3,=QXK_priv_ \n"
" LDR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // r1 := QXK_priv_.next
" CMP r0,#0 \n" // is (QXK_priv_.next == 0)?
@ -503,7 +503,7 @@ __asm volatile (
" MOV lr,r2 \n" // make sure MSP is used
#else // ARMv7-M or higher
#ifdef __ARM_FP //--------- if VFP available...
" POP {r0,lr} \n" // restore alighner and EXC_RETURN into lr
" POP {r0,lr} \n" // restore aligner and EXC_RETURN into lr
" DSB \n" // ARM Erratum 838869
" TST lr,#(1 << 4) \n" // is it return to the VFP exception frame?
" IT EQ \n" // if EXC_RETURN[4] is zero...
@ -522,19 +522,18 @@ __asm volatile (
" BCC PendSV_activate \n" // if (next->prio > actPrio) activate the next AO
// otherwise no activation needed...
" MOV r0,#0 \n"
" STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0
" STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0
" MOV r2,#0 \n"
" STR r2,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0
" STR r2,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0
" PUSH {r0,lr} \n" // save the aligner + EXC_RETURN
#if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW)
// r0 is still 0 (parameter next) for QXK_contextSw_()
" CMP r0,#0 \n" // r0 == QXK_priv_.next->prio
" BEQ PendSV_idle \n" // if (QXK_priv_.next->prio != 0)
" MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_()
"PendSV_idle: \n"
" LDR r3,=QXK_contextSw_ \n"
" BLX r3 \n" // call QXK_contextSw_()
#ifdef QF_MEM_ISOLATE
" LDR r3,=QF_onMemApp \n"
" BLX r3 \n" // call QF_onMemApp()
#endif
#endif // defined(Q_SPY) || defined(QF_ON_CONTEXT_SW)
" B PendSV_return1 \n" // skip over saving aligner + EXC_RETURN
@ -543,6 +542,10 @@ __asm volatile (
" PUSH {r0,lr} \n" // save the aligner + EXC_RETURN
"PendSV_return1: \n"
#ifdef QF_MEM_ISOLATE
" LDR r3,=QF_onMemApp \n"
" BLX r3 \n" // call QF_onMemApp()
#endif
" LDR r0,=QF_int_enable_ \n"
" BLX r0 \n" // call QF_int_enable_()
//>>>>>>>>>>>>>>>>>>>>>>>> CRITICAL SECTION END >>>>>>>>>>>>>>>>>>>>>>>>>
@ -605,7 +608,7 @@ __asm volatile (
" PUSH {r0-r2,lr} \n" // save next, osObject, EXC_RETURN
#if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW)
" MOV r0,r12 \n" // parameter next
" MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_()
" LDR r3,=QXK_contextSw_ \n"
" BLX r3 \n" // call QXK_contextSw_()
#ifdef QF_MEM_ISOLATE
@ -758,7 +761,7 @@ __asm volatile (
" ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame
#ifdef __ARM_FP //--------- if VFP available...
" POP {r0,lr} \n" // restore alighner and EXC_RETURN into lr
" POP {r0,lr} \n" // restore aligher and EXC_RETURN into lr
" DSB \n" // ARM Erratum 838869
" TST lr,#(1 << 4) \n" // is it return to the VFP exception frame?
" IT EQ \n" // if EXC_RETURN[4] is zero...

View File

@ -27,8 +27,8 @@
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2023-12-10
//! @version Last updated for: @ref qpcpp_7_3_1
//! @date Last updated on: 2024-05-28
//! @version Last updated for: @ref qpcpp_7_3_5
//!
//! @file
//! @brief QXK/C++ port to ARM Cortex-M, IAR-ARM
@ -389,10 +389,10 @@ __asm volatile (
" MOVS r1,#1 \n"
" LSLS r1,r1,#27 \n" // r1 := (1 << 27) (UNPENDSVSET bit)
" LDR r2,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State
" STR r1,[r2] \n" // ICSR[27] := 1 (unpend PendSV)
" STR r1,[r2] \n" // ICSR[27] := 1 (un-pend PendSV)
// Check QXK_priv_.next, which contains the pointer to the next thread
// to run, which is set in QXK_ISR_EXIT(). This pointer must not be NULL.
// to run, which is set in QXK_ISR_EXIT(). Return if QXK_priv_.next == 0
" LDR r3,=QXK_priv_ \n"
" LDR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // r1 := QXK_priv_.next
" CMP r0,#0 \n" // is (QXK_priv_.next == 0)?
@ -502,7 +502,7 @@ __asm volatile (
" MOV lr,r2 \n" // make sure MSP is used
#else // ARMv7-M or higher
#ifdef __ARM_FP //--------- if VFP available...
" POP {r0,lr} \n" // restore alighner and EXC_RETURN into lr
" POP {r0,lr} \n" // restore aligner and EXC_RETURN into lr
" DSB \n" // ARM Erratum 838869
" TST lr,#(1 << 4) \n" // is it return to the VFP exception frame?
" IT EQ \n" // if EXC_RETURN[4] is zero...
@ -521,19 +521,18 @@ __asm volatile (
" BCC PendSV_activate \n" // if (next->prio > actPrio) activate the next AO
// otherwise no activation needed...
" MOVS r0,#0 \n"
" STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0
" STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0
" MOVS r2,#0 \n"
" STR r2,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0
" STR r2,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0
" PUSH {r0,lr} \n" // save the aligner + EXC_RETURN
#if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW)
// r0 is still 0 (parameter next) for QXK_contextSw_()
" CMP r0,#0 \n" // r0 == QXK_priv_.next->prio
" BEQ PendSV_idle \n" // if (QXK_priv_.next->prio != 0)
" MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_()
"PendSV_idle: \n"
" LDR r3,=QXK_contextSw_ \n"
" BLX r3 \n" // call QXK_contextSw_()
#ifdef QF_MEM_ISOLATE
" LDR r3,=QF_onMemApp \n"
" BLX r3 \n" // call QF_onMemApp()
#endif
#endif // defined(Q_SPY) || defined(QF_ON_CONTEXT_SW)
" B PendSV_return1 \n" // skip over saving aligner + EXC_RETURN
@ -542,6 +541,10 @@ __asm volatile (
" PUSH {r0,lr} \n" // save the aligner + EXC_RETURN
"PendSV_return1: \n"
#ifdef QF_MEM_ISOLATE
" LDR r3,=QF_onMemApp \n"
" BLX r3 \n" // call QF_onMemApp()
#endif
" LDR r0,=QF_int_enable_ \n"
" BLX r0 \n" // call QF_int_enable_()
//>>>>>>>>>>>>>>>>>>>>>>>> CRITICAL SECTION END >>>>>>>>>>>>>>>>>>>>>>>>>
@ -604,7 +607,7 @@ __asm volatile (
" PUSH {r0-r2,lr} \n" // save next, osObject, EXC_RETURN
#if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW)
" MOV r0,r12 \n" // parameter next
" MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_()
" LDR r3,=QXK_contextSw_ \n"
" BLX r3 \n" // call QXK_contextSw_()
#ifdef QF_MEM_ISOLATE
@ -757,7 +760,7 @@ __asm volatile (
" ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame
#ifdef __ARM_FP //--------- if VFP available...
" POP {r0,lr} \n" // restore alighner and EXC_RETURN into lr
" POP {r0,lr} \n" // restore aligher and EXC_RETURN into lr
" DSB \n" // ARM Erratum 838869
" TST lr,#(1 << 4) \n" // is it return to the VFP exception frame?
" IT EQ \n" // if EXC_RETURN[4] is zero...

View File

@ -22,17 +22,18 @@
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-02-19
//! @version Last updated for: @ref qpcpp_7_3_0
//! @date Last updated on: 2024-05-01
//! @version Last updated for version: 7.3.4
//!
//! @file
//! @brief PC-Lint-Plus option file for linting QP/C++ source code
//============================================================================
// general options
-unit_check // perform only subset check (suppresses Global Wrapup)
-max_threads=1 // suppress message "no '-max_threads=N' option"
//-vf // print names of all source files (for debugging linting)
-unit_check // perform only subset check (suppresses Global Wrapup)
-max_threads=1 // suppress message "no '-max_threads=N' option"
++efreeze(686) // never suppress (see PC-Lint-Plus in Safety-Critical)
//-vf // print names of all source files (for debugging linting)
// include directories
-i. // QP/C++ port includes (see also qk/ and qv/)
@ -40,12 +41,8 @@
// standards
au-autosar.lnt // AUTOSAR:C++14
au-ds.lnt // Dan Saks recommendations
au-ql-cpp11.lnt // Quantum Leaps coding standard for C++11
// size/alignment options
cpu.lnt // for the chosen CPU
au-ds.lnt // Dan Saks recommendations
cpu.lnt // size/alignment options for the chosen CPU
// defined macros (might be undefined on command-line with -u<macro>)
-dQ_SPY
@ -83,6 +80,7 @@ qpcpp.lnt // QP/C++ options
Q_ASSERT_INCRIT,
Q_REQUIRE_INCRIT,
Q_ENSURE_INCRIT,
Q_INVARIANT_INCRIT,
Q_ERROR_INCRIT)
//! M4-D4.9(A) function-like macro

View File

@ -0,0 +1,6 @@
// Size Options for 16bit CPU (e.g., MSP430)
-si2 -sl4 -sll8 -ss2 -sw2 -sp2 -sf4 -sd8 -sld8
// Alignment options for 16bit CPU
-ai2 -al2 -all2 -as2 -af4 -ad8 -ald8

View File

@ -0,0 +1,39 @@
/// @file cstdint
/// This is an emulation of a Standard C++ Library header for 16bit CPUs,
/// like MSP430.
#ifndef _GLIBCXX_CSTDINT
#define _GLIBCXX_CSTDINT
//lint -save
//lint -e9093 AUTOSAR:M17-0-2 the name ... is reserved to the compiler
//lint -e9145 AUTOSAR:M7-3-6 9145: using declaration in header
namespace std {
using int8_t = signed char; //!< exact-width 8-bit signed int
using int16_t = signed int; //!< exact-width 16-bit signed int
using int32_t = signed long int; //!< exact-width 32-bit signed int
using int64_t = signed long long; //!< exact-width 64-bit signed int
using uint8_t = unsigned char; //!< exact-width 8-bit unsigned int
using uint16_t = unsigned int; //!< exact-width 16-bit unsigned int
using uint32_t = unsigned long int; //!< exact-width 32-bit unsigned int
using uint64_t = unsigned long long; //!< exact-width 64-bit unsigned int
// Fastest minimum-width types. WG14/N843 C99 Standard, Section 7.18.1.3
using int_fast8_t = signed int; //!< fast at-least 8-bit signed int
using uint_fast8_t = unsigned int; //!< fast at-least 8-bit unsigned int
using int_fast16_t = signed int; //!< fast at-least 16-bit signed int
using uint_fast16_t = unsigned int; //!< fast at-least 16-bit unsigned int
using int_fast32_t = signed long; //!< fast at-least 32-bit signed int
using uint_fast32_t = unsigned long; //!< fast at-least 32-bit unsigned int
// unsigned integer type capable of holding a pointer to void.
using uintptr_t = unsigned; //!< unsigned int capable of holding void*
} // namespace std
//lint -restore
#endif // _GLIBCXX_CSTDINT

View File

@ -0,0 +1,58 @@
//============================================================================
// 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.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <www.gnu.org/licenses/gpl-3.0>
//
// The terms of the closed source Quantum Leaps commercial licenses
// can be found at: <www.state-machine.com/licensing>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2023-08-17
//! @version Last updated for: @ref qpcpp_7_3_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++ compiler
//! @description
//! This is an example QP/C++ port with the documentation for the main
//! items, such as configuration macros, functions, and includes.
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_
// QS time-stamp size in bytes
#define QS_TIME_SIZE 4U
// object pointer size in bytes
#define QS_OBJ_PTR_SIZE 2U
// function pointer size in bytes
#define QS_FUN_PTR_SIZE 2U
//============================================================================
// NOTE: QS might be used with or without other QP components, in which case
// the separate definitions of the macros QF_CRIT_STAT, QF_CRIT_ENTRY(),
// and QF_CRIT_EXIT() are needed. In this port QS is configured to be used with
// the other QP component, by simply including "qp_port.hpp" *before* "qs.hpp".
//
#ifndef QP_PORT_HPP_
#include "qp_port.hpp" // use QS with QP
#endif
#include "qs.hpp" // QS platform-independent public interface
#endif // QS_PORT_HPP_

View File

@ -0,0 +1,3 @@
// Size Options for 32bit CPU (e.g., ARM Cortex-M)
-si4 -sl4 -sll8 -ss2 -sw4 -sp4 -sf4 -sd8 -sld8

View File

@ -0,0 +1,39 @@
/// @file cstdint
/// This is an emulation of a Standard C++ Library header for 32bit CPUs,
/// like ARM Cortex-M.
#ifndef _GLIBCXX_CSTDINT
#define _GLIBCXX_CSTDINT
//lint -save
//lint -e9093 AUTOSAR:M17-0-2 the name ... is reserved to the compiler
//lint -e9145 AUTOSAR:M7-3-6 9145: using declaration in header
namespace std {
using int8_t = signed char; //!< exact-width 8-bit signed int
using int16_t = signed short; //!< exact-width 16-bit signed int
using int32_t = signed long; //!< exact-width 32-bit signed int
using int64_t = signed long long; //!< exact-width 64-bit signed int
using uint8_t = unsigned char; //!< exact-width 8-bit unsigned int
using uint16_t = unsigned short; //!< exact-width 16-bit unsigned int
using uint32_t = unsigned long; //!< exact-width 32-bit unsigned int
using uint64_t = unsigned long long; //!< exact-width 64-bit unsigned int
// Fastest minimum-width types. WG14/N843 C99 Standard, Section 7.18.1.3
using int_fast8_t = signed int; //!< fast at-least 8-bit signed int
using uint_fast8_t = unsigned int; //!< fast at-least 8-bit unsigned int
using int_fast16_t = signed int; //!< fast at-least 16-bit signed int
using uint_fast16_t = unsigned int; //!< fast at-least 16-bit unsigned int
using int_fast32_t = signed long; //!< fast at-least 32-bit signed int
using uint_fast32_t = unsigned long; //!< fast at-least 32-bit unsigned int
// unsigned integer type capable of holding a pointer to void.
using uintptr_t = unsigned; //!< unsigned int capable of holding void*
} // namespace std
//lint -restore
#endif // _GLIBCXX_CSTDINT

View File

@ -0,0 +1,61 @@
//============================================================================
// 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.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <www.gnu.org/licenses/gpl-3.0>
//
// The terms of the closed source Quantum Leaps commercial licenses
// can be found at: <www.state-machine.com/licensing>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2023-08-17
//! @version Last updated for: @ref qpcpp_7_3_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++ compiler
//! @description
//! This is an example QP/C++ port with the documentation for the main
//! items, such as configuration macros, functions, and includes.
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_
//! QS buffer counter size in bytes
#define QS_CTR_SIZE 2U
//! QS time-stamp size in bytes
#define QS_TIME_SIZE 4U
//! object pointer size in bytes
#define QS_OBJ_PTR_SIZE 4U
//! function pointer size in bytes
#define QS_FUN_PTR_SIZE 4U
//============================================================================
// NOTE: QS might be used with or without other QP components, in which case
// the separate definitions of the macros QF_CRIT_STAT, QF_CRIT_ENTRY(),
// and QF_CRIT_EXIT() are needed. In this port QS is configured to be used with
// the other QP component, by simply including "qp_port.hpp" *before* "qs.hpp".
//
#ifndef QP_PORT_HPP_
#include "qp_port.hpp" // use QS with QP
#endif
#include "qs.hpp" // QS platform-independent public interface
#endif // QS_PORT_HPP_

View File

@ -0,0 +1,21 @@
// au-ds.lnt -- Author options - Dan Saks
/*
This options file can be used to explicitly activate those
checks advocated by Dan Saks in his series of presentations on
"C++ Gotchas".
You can use this file directly when linting your programs as in:
lin au-ds files
*/
+fsc // consider string constants as const char *
+e1933 // turn on "virtual call from member detection"
// The rationale for the following two options are fully described
// in Dan Saks' article "const T vs. T const". Visit his web site
// at www.dansaks.com and click "Published Articles".
//
-fqb +e963 // require T const rather than const T

42
ports/lint-plus2/cstddef Normal file
View File

@ -0,0 +1,42 @@
#ifndef _CSTDDEF_
#define _CSTDDEF_
//lint -save
//lint -e9093 the name is reserved to the compiler
//lint -e9141 global declaration of symbol 'operator new'
//lint -e9215 unnamed parameter for 'non-virtual' function 'operator new'
namespace std {
using ptrdiff_t = unsigned int;
using size_t = unsigned int;
using max_align_t = unsigned int;
using nullptr_t = decltype(nullptr);
enum class byte : unsigned char {};
// byte type operations
template<class IntType>
constexpr byte& operator<<=(byte& b, IntType shift) noexcept;
template<class IntType>
constexpr byte operator<<(byte b, IntType shift) noexcept;
template<class IntType>
constexpr byte& operator>>=(byte& b, IntType shift) noexcept;
template<class IntType>
constexpr byte operator>>(byte b, IntType shift) noexcept;
constexpr byte& operator|=(byte& l, byte r) noexcept;
constexpr byte operator|(byte l, byte r) noexcept;
constexpr byte& operator&=(byte& l, byte r) noexcept;
constexpr byte operator&(byte l, byte r) noexcept;
constexpr byte& operator^=(byte& l, byte r) noexcept;
constexpr byte operator^(byte l, byte r) noexcept;
constexpr byte operator~(byte b) noexcept;
template<class IntType>
constexpr IntType to_integer(byte b) noexcept;
}
#define NULL nullptr
//#define offsetof(type, member) ...
//lint -restore
#endif // _CSTDDEF_

70
ports/lint-plus2/make.bat Normal file
View File

@ -0,0 +1,70 @@
@echo off
:: ===========================================================================
:: Batch script for linting QP/C with PC-Lint-Plus2
:: 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: <www.gnu.org/licenses/gpl-3.0>
::
:: The terms of the closed source Quantum Leaps commercial licenses
:: can be found at: <www.state-machine.com/licensing>
::
:: Redistributions in source code must retain this top-level comment block.
:: Plagiarizing this software to sidestep the license obligations is illegal.
::
:: Contact information:
:: <www.state-machine.com>
:: <info@state-machine.com>
:: ===========================================================================
@setlocal
:: usage of make.bat
@echo Usage: make [16bit] [-u...] files
@echo examples:
@echo make -uQ_SPY -uQ_UTEST : use 32bit CPU (default) and undefine Q_SPY/Q_UTEST
@echo make 16bit -uQ_SPY : use 16bit CPU includes and undefine Q_SPY
@echo.
:: NOTE: adjust to for your installation directory of PC-Lint-Plus
@set PCLP=C:\tools\lint-plus2.2-beta\windows
@set PCLP_EXE=%PCLP%\pclp64.exe
if NOT exist "%PCLP%" (
@echo The PC-Lint-Plus toolset not found. Please adjust make.bat
@goto end
)
:: set the QP/C++ directory
set QPCPP=..\..
if "%1"=="16bit" (
set LINTFLAGS=-i16bit options.lnt %1 %2 %3 %4
@echo 16bit CPU
) else (
set LINTFLAGS=-i32bit options.lnt %1 %2 %3 %4
@echo 32bit CPU default
)
:: cleanup
@del *.log
:: linting -------------------------------------------------------------------
%PCLP_EXE% -os(lint_qf.log) std.lnt %LINTFLAGS% -iqv ..\..\src\qf\*.cpp
%PCLP_EXE% -os(lint_qv.log) std.lnt %LINTFLAGS% -iqv ..\..\src\qv\*.cpp
%PCLP_EXE% -os(lint_qk.log) std.lnt %LINTFLAGS% -iqk ..\..\src\qk\*.cpp
%PCLP_EXE% -os(lint_qxk.log) std.lnt %LINTFLAGS% -iqxk ..\..\src\qxk\*.cpp
%PCLP_EXE% -os(lint_qs.log) std.lnt %LINTFLAGS% -iqv ..\..\src\qs\*.cpp
:end
@endlocal

View File

@ -0,0 +1,406 @@
//============================================================================
// 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.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <www.gnu.org/licenses/gpl-3.0>
//
// The terms of the closed source Quantum Leaps commercial licenses
// can be found at: <www.state-machine.com/licensing>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-05-01
//! @version Last updated for version: 7.3.4
//!
//! @file
//! @brief PC-Lint-Plus option file for linting QP/C++ source code
//============================================================================
// general options
-unit_check // perform only subset check (suppresses Global Wrapup)
-max_threads=1 // suppress message "no '-max_threads=N' option"
++efreeze(686) // never suppress (see PC-Lint-Plus in Safety-Critical)
//-vf // print names of all source files (for debugging linting)
// include directories
-i%PCLP%/lnt // PC-Lint-Plus standard .lnt files
-i. // QP/C++ port includes (see also qk/ and qv/)
-i%QPCPP%/include // QP/C++ public includes
// standards
au-autosar.lnt // AUTOSAR:C++14
au-ds.lnt // Dan Saks recommendations
cpu.lnt // size/alignment options for the chosen CPU
// defined macros (might be undefined on command-line with -u<macro>)
-dQ_SPY
-dQ_UTEST
//============================================================================
// QP/C++ options for clients
qpcpp.lnt // QP/C++ options
//============================================================================
// additional suppression rules for building QP/C source code...
// general suppression for now...
// preprocessor directive ... is deprecated. [AUTOSAR Rule A16-0-1]
-e586
// preprocessor directive encountered in conditionally excluded region
// [AUTOSAR Rule A16-0-1], [AUTOSAR Rule A16-6-1]
-e886
// friend ... in class
-e9435
// symbol ... has array type
-e9436
// enum ... is not a scoped enumeration [AUTOSAR Rule A7-2-3]
-e9419
// QEP -----------------------------------------------------------------------
//! MC++R16-0-4 function-like macro ???
-esym(9026,
Q_ASSERT_INCRIT,
Q_REQUIRE_INCRIT,
Q_ENSURE_INCRIT,
Q_INVARIANT_INCRIT,
Q_ERROR_INCRIT)
//! M4-D4.9(A) function-like macro
//! @tr{DVP-QP-MC4-D04_09B}
-esym(9026,
QHSM_RESERVED_EVT_,
QS_STATE_ENTRY_,
QS_STATE_EXIT_)
// implicit conversion of enum 'QP::QAsm::QStateRet' to integral type
-esym(641,
QP::QAsm::QStateRet)
// MC++R7-1-2 parameter of function could be pointer to const
-esym(818,
QP::QHsm::top)
// QF ------------------------------------------------------------------------
// MC++R16-0-4 function-like macro
-esym(9026,
QF_CRIT_ENTRY,
QF_CRIT_EXIT,
QF_MEM_SYS,
QF_MEM_APP,
QF_CONST_CAST_,
QF_SCHED_LOCK_,
QF_SCHED_UNLOCK_,
QF_PTR_RANGE_,
QF_MPOOL_EL,
Q_ACTION_CAST,
QTICKER_CAST_)
// MC++R16-0-4 function-like macro
-esym(9026,
QACTIVE_EQUEUE_WAIT_,
QACTIVE_EQUEUE_SIGNAL_,
QF_EPOOL_INIT_,
QF_EPOOL_EVENT_SIZE_,
QF_EPOOL_GET_,
QF_EPOOL_PUT_)
// MC++R10-0-6 unparenthesized macro parameter in definition of macro
-esym(9022,
QF_CONST_CAST_)
// [AUTOSAR Rule A5-2-3] cast drops const qualifier
-emacro(9005,
QF_CONST_CAST_)
// M3-R11.3(r) cast from pointer to object type
-emacro(9087,
QTICKER_CAST_)
// suspicious pointer-to-pointer conversion (area too small)
-emacro(826,
QTICKER_CAST_)
// AC++M5-2-9 casting from pointer type to integer type
-emacro(9091,
Q_UINTPTR_CAST_)
// [AC++M12-1-1] non-static data member not initialized by ctor
-esym(1401,
QP::QEvt::*,
QP::QActive::*)
// definition of macro ends in semi-colon
-esym(823,
QF_SCHED_STAT_)
// MC++5-2-8 conversion from integer type (0) to pointer type
-emacro(9010,
Q_ACTION_CAST)
// M3-R11.8(r) cast drops const qualifier
-emacro(9005,
QF_EPOOL_PUT_)
// M3-D11.5(a) conversion from pointer to void to other pointer type
-efunc(9079,
QF_bzero)
// M3-R17.8(a) function parameter modified
-efunc(9044,
QF_LOG2,
QMPool_init)
// M3-R18.1(r) potential out of bounds pointer access
-emacro(661,
QF_EPOOL_EVENT_SIZE_)
// AR-M5-2-8 conversion from pointer to void to other pointer type
-emacro(9079,
QF_EPOOL_GET_)
// M3-R18.3(r) relational operator <= applied to pointers
-emacro(946,
QF_PTR_RANGE_)
// M3-R8.13(a) parameter of function could be pointer to const
-efunc(818,
QP::QActive::start,
QP::QTicker::postLIFO)
// MC++R0-1-1 statement is unreachable due to unconditional transfer
// of control (assertion)
//-efunc(527,
// QP::QMActive::isIn,
// QP::QMActive::state,
// QP::QMActive::childState)
// MC++R7-1-1 parameter of function could be declared const
-esym(952,
QP::QEQueue::init)
// AC++M5-2-3: downcast of polymorphic type
-efunc(9171,
QP::QActive::post_,
QP::QActive::postLIFO)
// BARR-C:2018 R 6.2c return statement before end of function
-efunc(904,
QP::QActive::post_,
QP::QActive::postLIFO)
// [AC++M5-2-2]: casting from base class to derived class (QP::QActiveDummy)
-efunc(1939,
QP::QActive::post_,
QP::QActive::postLIFO)
// PCLP-1731: public virtual function (in a class without virtual destructor)
-esym(1731,
QP::QTicker::*)
// PCLP-1933: call to unqualified virtual function from non-static member function
-efunc(1933,
QP::QActive::start)
// PCLP-9079:
-efunc(9079,
QP::QF::bzero_,
QP::QTimeEvt::armX,
QP::QTimeEvt::disarm,
QP::QTimeEvt::rearm,
QP::QMPool::init,
QP::QMPool::get,
QP::QMPool::put)
// QV ------------------------------------------------------------------------
// MC++R16-0-4 function-like macro
-esym(9026,
QV_CPU_SLEEP)
// QK ------------------------------------------------------------------------
// MC++R16-0-4 function-like macro
-esym(9026,
QK_ISR_CONTEXT_,
QK_ISR_ENTRY,
QK_ISR_EXIT)
// QXK -----------------------------------------------------------------------
// MC++R16-0-4 function-like macro
-esym(9026,
QXK_ISR_CONTEXT_,
QXK_CONTEXT_SWITCH_,
QXK_PTR_CAST_,
QXTHREAD_CAST_,
QXTHREAD_EQUEUE_SIGNAL_)
// MC++R10-0-6 unparenthesized macro parameter in definition of macro
-esym(9022,
QXK_PTR_CAST_)
// MC++R5-2-7 pointer type converted to unrelated pointer
-emacro(9176,
Q_STATE_CAST)
// M3-R11.3(r) cast to pointer to different object type
//-emacro(9087,
// QXK_PTR_CAST_,
// QXTHREAD_CAST_)
// MC++R5-2-7 pointer type converted to unrelated pointer type
-emacro(9176,
QXK_PTR_CAST_)
// MC++R5-2-3 downcast of polymorphic type ... to type ...
-emacro(9171,
QXK_PTR_CAST_)
// casting from base class 'QP::QActive' to derived class
-emacro(1939,
QXK_PTR_CAST_)
// suspicious pointer-to-pointer conversion (area too small)
-emacro(826,
QXK_PTR_CAST_,
QXTHREAD_CAST_)
// QS ------------------------------------------------------------------------
// the following options are needed only when Q_SPY is defined
// MC++R16-0-4 function-like macro
-esym(9026,
QS_CRIT_ENTRY,
QS_CRIT_EXIT,
QS_MEM_SYS,
QS_MEM_APP,
QS_PTR_AT_,
QS_PTR_INC_,
QS_INSERT_BYTE_,
QS_INSERT_ESC_BYTE_,
QS_REC_NUM_)
// M3-R14.3(r) boolean condition for 'if' always evaluates to 'false'
-emacro(774,,
QS_INSERT_BYTE_,
QS_INSERT_ESC_BYTE_,
QS_BEGIN_PRE_,
QS_BEGIN_PRE_)
// the right operand to << always evaluates to 0
-emacro(845,
QS_BEGIN_PRE_,
QS_BEGIN_PRE_)
// excessive shift value (precision 3 shifted right by 3)
-emacro(572,
QS_BEGIN_PRE_,
QS_BEGIN_PRE_)
// constant expression evaluates to 0 in 'binary' operation '>>'
-emacro(778,
QS_BEGIN_PRE_,
QS_BEGIN_PRE_)
// constant value used in Boolean context
-emacro(506,
QS_BEGIN_PRE_,
QS_BEGIN_PRE_)
// bitwise operator '>>' applied to signed underlying type [AS-M5-0-21]
-emacro(9130,
QS_BEGIN_PRE_,
QS_BEGIN_PRE_)
// use of c-style cast to void [AS-A5-2-2]
-emacro(1954,
QS_END_PRE_)
// MC++R0-1-9 operator == always evaluates to true
-emacro(948,
QS_BEGIN_PRE_)
// MC++R0-1-1, MC++R0-1-2, MC++R0-1-9
// left operand to '||' always evaluates to 'true'
-emacro(944,
QS_BEGIN_PRE_)
// MC++R5-2-9 casting from pointer type to integer type
-emacro(9091,
QS_OBJ_PRE_,
QS_FUN_PRE_)
// M3-R11.6(r) explicit cast from 'void *volatile' to 'uint32_t'
//-emacro(923,
// QS_OBJ_PRE_,
// QS_FUN_PRE_)
// M3-R11.1(4) conversion between pointer to function and differing type
//-emacro(9074,
// QS_FUN_PRE_)
// definition of macro ends in semi-colon
-esym(823,
QS_CRIT_STAT,
QS_BEGIN_PRE_)
// union initialization
-efunc(708,
QS_f64_fmt_)
// M3-R19.2(a) union declared
-efunc(9018,
QS_f32_fmt_,
QS_f64_fmt_)
// MC++R10-0-6 unparenthesized macro parameter in definition of macro
-esym(9022,
QS_TEST_PROBE,
QS_TEST_PROBE_ID)
// AR M5-0-10 the result of the ~ operator applied to an object with an
// underlying type of 'unsigned char' must be cast to 'unsigned char'
// in this context
-efunc(9126,
QP::QS::glbFilter_,
QP::QS::locFilter_)
// don't report problems within QS_target_info_() function
-efunc(9130,
QP::QS_target_info_)
-efunc(9114,
QP::QS_target_info_)
-efunc(9117,
QP::QS_target_info_)
-efunc(9125,
QP::QS_target_info_)
-efunc(9112,
QP::QS_target_info_)
-efunc(9128,
QP::QS_target_info_)
-efunc(737,
QP::QS_target_info_)

View File

@ -0,0 +1,101 @@
//============================================================================
// 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.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <www.gnu.org/licenses/gpl-3.0>
//
// The terms of the closed source Quantum Leaps commercial licenses
// can be found at: <www.state-machine.com/licensing>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2023-09-07
//! @version Last updated for: @ref qpcpp_7_3_0
//!
//! @file
//! @brief QP/C++ port for QK kernel, Generic C++11
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
#include <cstdint> // Exact-width types. C++11 Standard
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
// no-return function specifier (C++11 Standard)
#define Q_NORETURN [[ noreturn ]] void
// QF configuration for QK -- data members of the QActive class...
// QK event-queue used for AOs
#define QACTIVE_EQUEUE_TYPE QEQueue
// QF "thread" type used to store the MPU settings in the AO
#define QACTIVE_THREAD_TYPE void const *
// interrupt disabling mechanism
#define QF_INT_DISABLE() intDisable()
#define QF_INT_ENABLE() intEnable()
// QF critical section mechanism
#define QF_CRIT_STAT std::uint32_t crit_stat_;
#define QF_CRIT_ENTRY() (crit_stat_ = critEntry())
#define QF_CRIT_EXIT() critExit(crit_stat_)
// Check if the code executes in the ISR context
#define QK_ISR_CONTEXT_() (QK_get_IPSR() != 0U)
// Define the ISR entry sequence
#define QK_ISR_ENTRY() (static_cast<void>(0))
// Define the ISR exit sequence
#define QK_ISR_EXIT() \
do { \
QF_INT_DISABLE(); \
--QK_priv_.intNest; \
if (QK_priv_.intNest == 0U) { \
if (QK_sched_() != 0U) { \
QK_activate_(); \
} \
} \
QF_INT_ENABLE(); \
} while (false)
extern "C" {
void intDisable(void);
void intEnable(void);
std::uint32_t critEntry(void);
void critExit(std::uint32_t stat);
std::uint32_t QK_get_IPSR(void);
} // extern "C"
// include files -------------------------------------------------------------
#include "qequeue.hpp" // QK kernel uses the native QP event queue
#include "qmpool.hpp" // QK kernel uses the native QP memory pool
#include "qp.hpp" // QP framework
#include "qk.hpp" // QK kernel
#endif // QP_PORT_HPP_

459
ports/lint-plus2/qpcpp.lnt Normal file
View File

@ -0,0 +1,459 @@
//============================================================================
// 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.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <www.gnu.org/licenses/gpl-3.0>
//
// The terms of the closed source Quantum Leaps commercial licenses
// can be found at: <www.state-machine.com/licensing>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-02-18
//! @version Last updated for version: 7.3.3
//!
//! @file
//! @brief PC-Lint-Plus option file for linting QP/C++ __Applications__
//----------------------------------------------------------------------------
// globally suppress the following warnings:
-e546 // explicitly taking address of function
-e717 // monocarpic do-while used to group statements
-e1756 // variable has 'static' storage duration and non-POD type
-e3412 // class has virtual functions but non-virtual destructor
// Assertions ----------------------------------------------------------------
// give Q_onError() the semantics of "exit"
-function(exit,
Q_onError)
// C-style array type [AUTOSAR Rule A18-1-1]
-esym(9436,
QP::versionStr)
// AC++M16-3-2 function-like macro
-esym(9026,
Q_DEFINE_THIS_MODULE,
Q_ASSERT_STATIC,
Q_ASSERT,
Q_ASSERT_ID,
Q_ERROR,
Q_ERROR_ID,
Q_REQUIRE,
Q_REQUIRE_ID,
Q_ENSURE,
Q_ENSURE_ID,
Q_INVARIANT,
Q_INVARIANT_ID,
Q_DIM)
// use of c-style cast to void [AS-A5-2-2]
-emacro(1954,
Q_ASSERT,
Q_ASSERT_ID,
Q_ERROR,
Q_ERROR_ID,
Q_REQUIRE,
Q_REQUIRE_ID,
Q_ENSURE,
Q_ENSURE_ID,
Q_INVARIANT,
Q_INVARIANT_ID,
Q_ASSERT_INCRIT)
// MC++R10-0-6 unparenthesized macro parameter in definition of macro
-esym(9022,
Q_DEFINE_THIS_FILE,
Q_DEFINE_THIS_MODULE)
// definition of macro ends in semi-colon
-esym(823,
Q_DEFINE_THIS_FILE,
Q_DEFINE_THIS_MODULE)
// AC++M16-3-2 function-like macro
-esym(9026,
Q_UNUSED_PAR,
Q_DIM,
Q_UINT2PTR_CAST,
Q_UINTPTR_CAST_)
// MC++R5-2-4 use of c-style cast
-emacro(1924,
Q_ASSERT,
Q_ASSERT_ID,
Q_ERROR,
Q_ERROR_ID)
// QEP -----------------------------------------------------------------------
// MC++R7-3-1 global declaration of symbol
-esym(9141,
char_t,
int_t,
enum_t,
float32_t,
float64_t)
// AUTOSAR Rule A3-3-2 non-private data member within a non-POD structure
// NOTE: public access needed for extern "C" functions
-esym(9150,
QP::QAsmAttr::*,
QP::QAsm::*)
// AC++M16-3-2 function-like macro
-esym(9026,
INIT,
DISPATCH,
Q_STATE_DECL,
Q_STATE_DEF,
QM_STATE_DECL,
QM_STATE_DEF,
QM_SM_STATE_DECL,
QM_ACTION_DECL,
QM_ACTION_DEF,
QHSM_INIT,
QHSM_DISPATCH,
Q_TRAN,
Q_TRAN_HIST,
Q_SUPER,
Q_HANDLED,
Q_UNHANDLED,
QM_ENTRY,
QM_EXIT,
QM_SM_EXIT,
QM_TRAN,
QM_TRAN_INIT,
QM_TRAN_HIST,
QM_TRAN_EP,
QM_TRAN_XP,
QM_SUPER,
QM_SUPER_SUB,
QM_HANDLED,
QM_UNHANDLED,
Q_HSM_UPCAST,
Q_EVT_CAST,
Q_STATE_CAST,
Q_UINT2PTR_CAST)
// MC++R5-2-8 conversion from pointer to other pointer type
-emacro(9079,
Q_EVT_CAST)
// MC++R5-2-2 casting from base class 'QP::QEvt' to derived class
-emacro(1939,
Q_EVT_CAST)
// MC++R10-0-6 unparenthesized macro parameter 'class_' in definition of macro
-esym(9022,
Q_EVT_CAST,
Q_UINT2PTR_CAST,
Q_STATE_DECL,
Q_STATE_DEF,
QM_STATE_DECL,
QM_STATE_DEF,
QM_SM_STATE_DECL,
QM_ACTION_DECL,
QM_ACTION_DEF,
QEP_TRIG_,
QEP_ENTER_,
QEP_EXIT_)
// MC++16-3-1 multiple use of stringize/pasting operators in definition of macro
-esym(9023,
Q_STATE_DECL,
Q_STATE_DEF,
QM_STATE_DECL,
QM_STATE_DEF,
QM_SM_STATE_DECL,
QM_ACTION_DEF)
// AC++M16-3-2 stringize operator used in definition of function-like macro
-esym(9024,
Q_STATE_DECL,
Q_STATE_DEF,
QM_STATE_DECL,
QM_STATE_DEF,
QM_SM_STATE_DECL,
QM_ACTION_DECL,
QM_ACTION_DEF)
// MC++R5-2-8 conversion from pointer to void to other pointer type
-emacro(9079,
Q_STATE_DEF,
QM_STATE_DEF,
QM_ACTION_DEF)
// MC++R9-3-3 member function could be made const
-emacro(1762,
Q_STATE_DEF,
QM_STATE_DEF)
// MC++9-5-1 union declared
-esym(9018,
QP::QAsmAttr)
// MC++5-2-8 conversion from integer type (0) to pointer type
-emacro(9010,
Q_STATE_CAST)
// public virtual function 'QP::QHsm::...'
-esym(1731,
QP::QHsm::*,
QP::QMsm::*)
// QF ------------------------------------------------------------------------
// AUTOSAR Rule A3-3-2 non-private data member within a non-POD structure
// NOTE: public access needed for extern "C" functions
-esym(9150,
QP::QF::QF_Attr::*)
// AC++M16-3-2 function-like macro
-esym(9026,
POST,
POST_X,
PUBLISH,
TICK_X,
TICK,
TRIG,
QF_INT_DISABLE,
QF_INT_ENABLE,
QF_CRIT_EXIT_NOP,
QF_LOG2,
Q_PRIO,
Q_NEW,
Q_NEW_X,
Q_NEW_REF,
Q_DELETE_REF,
QF_INT_DISABLE,
QF_INT_ENABLE,
QF_MPOOL_EL)
// MC++R0-3-2 ignoring return value of function
-emacro(534,
POST)
// [AUTOSAR Rule M17-0-2] the name xxx is reserved to the compiler
-esym(9093,
remove) // QPrioSet::remove()
// MC++R5-2-7 pointer type converted to unrelated pointer type
-emacro(9176,
QF_QMACTIVE_TO_QMSM_CAST_,
QF_QMACTIVE_TO_QMSM_CONST_CAST_)
// MC++R5-2-2 casting from base class 'QP::QEvt' to derived class
-emacro(1939,
Q_NEW,
Q_NEW_X)
// MC++R10-0-6 unparenthesized macro parameter in definition of macro
-esym(9022,
Q_NEW,
Q_NEW_X,
Q_NEW_REF)
// QK ------------------------------------------------------------------------
// AC++M16-3-2 function-like macro
-esym(9026,
QK_ISR_ENTRY,
QK_ISR_EXIT)
// AC++M7-3-1 global declaration of symbol
-esym(9141,
QK_Attr)
// MC++R11-0-1 non-private data member within a non-POD structure
// NOTE: public access needed for extern "C" functions
-esym(9150,
QK_Attr::*)
// QXK -----------------------------------------------------------------------
// MC++R16-0-4 function-like macro
-esym(9026,
QXK_ISR_ENTRY,
QXK_ISR_EXIT,
QXK_TLS)
// MC++R7-3-1 global declaration of symbol
-esym(9141,
QXK_Attr)
// MC++R10-0-6 unparenthesized macro parameter in definition of macro
-esym(9022,
QXK_TLS)
// MC++R5-2-8 conversion from pointer to void to other pointer type
-emacro(9079,
QXK_PTR_CAST_)
// MC++R5-2-2 casting from base class to derived class
-emacro(1939,
QXTHREAD_CAST_)
// MC++R5-2-3 downcast of polymorphic type
-emacro(9171,
QXTHREAD_CAST_)
// [AUTOSAR Rule M17-0-2] the name 'signal' is reserved to the compiler
-esym(9093,
signal)
// public virtual function 'QP::QXThread::...'
-esym(1731,
QP::QXThread::*)
// [AUTOSAR Rule M8-4-2] parameter of function has different name than
// overridden function
-esym(9272,
QP::QXMutex::init*)
// function xxx matches the name of a standard library function
-esym(8502,
signal) // QXSemaphore::signal()
// QS ------------------------------------------------------------------------
// AC++M16-3-2 function-like macro
-esym(9026,
QS_INIT,
QS_EXIT,
QS_DUMP,
QS_RESET,
QS_GLB_FILTER,
QS_LOC_FILTER,
QS_FILTER_AP_OBJ,
QS_GET_BYTE,
QS_GET_BLOCK,
QS_BEGIN_ID,
QS_END,
QS_BEGIN_INCRIT,
QS_END_INCRIT,
QS_QF_CRIT_ENTRY,
QS_QF_CRIT_EXIT,
QS_QF_ISR_ENTRY,
QS_QF_ISR_EXIT,
QS_ONLY,
QS_I8,
QS_U8,
QS_I16,
QS_U16,
QS_I32,
QS_I64,
QS_U32,
QS_F32,
QS_F64,
QS_U64,
QS_U32_HEX,
QS_STR,
QS_OBJ,
QS_FUN,
QS_SIG_DICTIONARY,
QS_OBJ_DICTIONARY,
QS_OBJ_ARR_DICTIONARY,
QS_FUN_DICTIONARY,
QS_USR_DICTIONARY,
QS_ENUM_DICTIONARY,
QS_ASSERTION,
QS_FLUSH,
QS_MEM,
QS_ENUM,
QS_SIG,
QS_PTR_AT_,
QS_RX_PUT,
QS_OUTPUT,
QS_RX_INPUT,
QS_TEST_PAUSE,
QS_TEST_PROBE_DEF,
QS_TEST_PROBE,
QS_TEST_PROBE_ID)
// AC++M16-3-2 function-like macro
-esym(9026,
QS_GLB_CHECK_,
QS_LOC_CHECK_,
QS_BEGIN_PRE_,
QS_END_PRE_,
QS_BEGIN_PRE_,
QS_END_PRE_,
QS_U8_PRE_,
QS_2U8_PRE_,
QS_U16_PRE_,
QS_U32_PRE_,
QS_STR_PRE_,
QS_TIME_PRE_,
QS_SIG_PRE_,
QS_EVS_PRE_,
QS_OBJ_PRE_,
QS_FUN_PRE_,
QS_EQC_PRE_,
QS_MPC_PRE_,
QS_MPS_PRE_,
QS_TEC_PRE_)
// AC++M16-3-2 function-like macro
-esym(9026,
QS_REC_DONE)
// definition of macro ends in semi-colon
-esym(823,
QS_TEST_PROBE_DEF)
// M3-R11.1(r) conversion between pointer to function type
-emacro(9074,
QS_FUN_DICTIONARY,
QS_TEST_PROBE_DEF)
// AC++M16-3-2 stringize operator used in definition of function-like macro
-esym(9024,
QS_OBJ_DICTIONARY,
QS_OBJ_ARR_DICTIONARY,
QS_FUN_DICTIONARY,
QS_SIG_DICTIONARY,
QS_USR_DICTIONARY,
QS_ENUM_DICTIONARY)
// M3-R10.3(r) cannot assign enum to different essential type
-emacro(9034,
QS_SIG_DICTIONARY)
// implicit conversion of enum to integral type 'int'
-emacro(641,
QS_SIG_DICTIONARY)
// MC++R11-0-1 non-private data member within a non-POD structure
-esym(9150,
QP::QEvt::*,
QP::QActive::*,
QP::QF::Attr::*,
QP::QS::QSrxPriv::*)
// MC++9-5-1 union declared
-esym(9018,
F32Rep,
F64Rep,
U32Rep,
TCast,
QP::QS::RxAttr::Variant)

View File

@ -0,0 +1,89 @@
//============================================================================
// 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.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <www.gnu.org/licenses/gpl-3.0>
//
// The terms of the closed source Quantum Leaps commercial licenses
// can be found at: <www.state-machine.com/licensing>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2023-09-07
//! @version Last updated for: @ref qpcpp_7_3_0
//!
//! @file
//! @brief QP/C++ port for QV kernel, Generic C++
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
#include <cstdint> // Exact-width types. C++11 Standard
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
// no-return function specifier (C++11 Standard)
#define Q_NORETURN [[ noreturn ]] void
// QF configuration for QV -- data members of the QActive class...
// QV event-queue used for AOs
#define QACTIVE_EQUEUE_TYPE QEQueue
// QF "thread" type used to store the MPU settings in the AO
#define QACTIVE_THREAD_TYPE void const *
// interrupt disabling mechanism
#define QF_INT_DISABLE() intDisable()
#define QF_INT_ENABLE() intEnable()
// QF critical section mechanism
#define QF_CRIT_STAT std::uint32_t crit_stat_;
#define QF_CRIT_ENTRY() (crit_stat_ = critEntry())
#define QF_CRIT_EXIT() critExit(crit_stat_)
#define QV_CPU_SLEEP() \
do { \
__disable_interrupt(); \
QF_INT_ENABLE(); \
__WFI(); \
__enable_interrupt(); \
} while (false)
extern "C" {
void intDisable(void);
void intEnable(void);
std::uint32_t critEntry(void);
void critExit(std::uint32_t stat);
} // extern "C"
// include files -------------------------------------------------------------
#include "qequeue.hpp" // QV kernel uses the native QP event queue
#include "qmpool.hpp" // QV kernel uses the native QP memory pool
#include "qp.hpp" // QP framework
#include "qv.hpp" // QV kernel
#endif // QP_PORT_HPP_

View File

@ -0,0 +1,104 @@
//============================================================================
// 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.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <www.gnu.org/licenses/gpl-3.0>
//
// The terms of the closed source Quantum Leaps commercial licenses
// can be found at: <www.state-machine.com/licensing>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2023-09-07
//! @version Last updated for: @ref qpcpp_7_3_0
//!
//! @file
//! @brief QP/C++ port for QXK kernel, Generic C++
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
#include <cstdint> // Exact-width types. C++11 Standard
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
// no-return function specifier (C++11 Standard)
#define Q_NORETURN [[ noreturn ]] void
// QF configuration for QXK -- data members of the QActive class...
// QXK event-queue type used for AOs and eXtended threads.
#define QACTIVE_EQUEUE_TYPE QEQueue
// QXK OS-Object type used for the private stack pointer for eXtended threads.
// (The private stack pointer is NULL for basic-threads).
#define QACTIVE_OS_OBJ_TYPE void*
// QF "thread" type used to store the MPU settings in the AO
#define QACTIVE_THREAD_TYPE void const *
// interrupt disabling mechanism
#define QF_INT_DISABLE() intDisable()
#define QF_INT_ENABLE() intEnable()
// QF critical section mechanism
#define QF_CRIT_STAT std::uint32_t crit_stat_;
#define QF_CRIT_ENTRY() (crit_stat_ = critEntry())
#define QF_CRIT_EXIT() critExit(crit_stat_)
// Check if the code executes in the ISR context
#define QXK_ISR_CONTEXT_() (QXK_get_IPSR() != 0U)
// Define the ISR entry sequence
#define QXK_ISR_ENTRY() (static_cast<void>(0))
// Define the ISR exit sequence
#define QXK_ISR_EXIT() do { \
QF_INT_DISABLE(); \
if (QXK_sched_() != 0U) { \
*Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U);\
} \
QF_INT_ENABLE(); \
} while (false)
#define QXK_CONTEXT_SWITCH_() (QXK_trigPendSV())
extern "C" {
void intDisable(void);
void intEnable(void);
std::uint32_t critEntry(void);
void critExit(std::uint32_t stat);
std::uint32_t QXK_get_IPSR(void);
void QXK_trigPendSV(void);
} // extern "C"
// include files -------------------------------------------------------------
#include "qequeue.hpp" // QK kernel uses the native QP event queue
#include "qmpool.hpp" // QK kernel uses the native QP memory pool
#include "qp.hpp" // QP framework
#include "qxk.hpp" // QXK kernel
#endif // QP_PORT_HPP_

45
ports/lint-plus2/std.lnt Normal file
View File

@ -0,0 +1,45 @@
//============================================================================
// 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.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <www.gnu.org/licenses/gpl-3.0>
//
// The terms of the closed source Quantum Leaps commercial licenses
// can be found at: <www.state-machine.com/licensing>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2023-08-08
//! @version Last updated for version: 7.3.0
//!
//! @file
//! @brief PC-Lint-Plus standard option file
// message formatting options...
-hF1 // output: a single line
+ffn // use full path names
//-"format=%(\q%f\q %l %C%) %t %n: %m"
//-width(0,0) // do not break lines
-width(120,4) // break lines after 99 characters with 4 characters indent
+flm // make sure no foreign includes change the format
+rw(inline, entry)
-zero(99) // don't stop because of warnings
-passes(2) // make two passes (for better error messages)
-restore_at_end // don't let -e<nn> options bleed to other files
-summary() // produce a summary of all produced messages

View File

@ -1,226 +0,0 @@
##############################################################################
# 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, <state-machine.com>.
#
# SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
#
# This software is dual-licensed under the terms of the open source GNU
# General Public License version 3 (or any later version), or alternatively,
# under the terms of one of the closed source Quantum Leaps commercial
# licenses.
#
# The terms of the open source GNU General Public License version 3
# can be found at: <www.gnu.org/licenses/gpl-3.0>
#
# The terms of the closed source Quantum Leaps commercial licenses
# can be found at: <www.state-machine.com/licensing>
#
# Redistributions in source code must retain this top-level comment block.
# Plagiarizing this software to sidestep the license obligations is illegal.
#
# Contact information:
# <www.state-machine.com>
# <info@state-machine.com>
##############################################################################
# examples of invoking this Makefile:
# building configurations: Debug (default), Release and Spy
# make
# make CONF=rel
# make CONF=spy
#
# cleaning configurations: Debug (default), Release, and Spy
# make clean
# make CONF=rel clean
# make CONF=spy clean
#
# NOTE:
# To use this Makefile on Windows, you will need the GNU make utility, which
# is included in the QTools collection for Windows, see:
# https://github.com/QuantumLeaps/qtools
#
#-----------------------------------------------------------------------------
# project name:
#
PROJECT := qp
#-----------------------------------------------------------------------------
# project directories:
#
# location of the QP/C++ framework
QPCPP := ../..
# QP port used in this project
QP_PORT_DIR := .
# list of all source directories used by this project
VPATH = \
$(QPCPP)/src/qf \
$(QPCPP)/src/qs \
$(QP_PORT_DIR)
# list of all include directories needed by this project
INCLUDES = \
-I$(QPCPP)/include \
-I$(QPCPP)/src \
-I$(QP_PORT_DIR)
#-----------------------------------------------------------------------------
# files
#
# C source files
C_SRCS := \
qwin_gui.c
# C++ source files
CPP_SRCS := \
qep_hsm.cpp \
qep_msm.cpp \
qf_actq.cpp \
qf_defer.cpp \
qf_dyn.cpp \
qf_mem.cpp \
qf_ps.cpp \
qf_qact.cpp \
qf_qeq.cpp \
qf_qmact.cpp \
qf_time.cpp \
qf_port.cpp
# C++ QS source files
CPP_QS_SRCS := \
qs.cpp \
qs_rx.cpp \
qs_fp.cpp \
qs_64bit.cpp \
qs_port.cpp
# defines:
DEFINES := -DQWIN_GUI -DQP_API_VERSION=9999
#-----------------------------------------------------------------------------
# MinGW toolset (NOTE: assumed to be on your PATH)
#
# NOTE:
# MinGW toolset is included in the Qtools collection for Windows, see:
# https://github.com/QuantumLeaps/qtools
CC := gcc
CPP := g++
LIB := ar
##############################################################################
# Typically, you should not need to change anything below this line
# basic utilities (included in Qtools for Windows), see:
# https://github.com/QuantumLeaps/qtools
MKDIR := mkdir
RM := rm
#-----------------------------------------------------------------------------
# build options for various configurations
#
LIBFLAGS := rs
ifeq (rel, $(CONF)) # Release configuration .................................
BIN_DIR := rel
# gcc options:
CFLAGS := -c -O3 -fno-pie -std=c99 -pedantic -Wall -Wextra -W \
$(INCLUDES) $(DEFINES) -DNDEBUG
CPPFLAGS := -c -O3 -fno-pie -std=c++11 -pedantic -Wall -Wextra \
-fno-rtti -fno-exceptions \
$(INCLUDES) $(DEFINES) -DNDEBUG
else ifeq (spy, $(CONF)) # Spy configuration ................................
BIN_DIR := spy
# add the QS sources...
C_SRCS += $(C_QS_SRCS)
# gcc options:
CFLAGS := -c -g -O -fno-pie -std=c99 -pedantic -Wall -Wextra -W \
$(INCLUDES) $(DEFINES) -DQ_SPY
CPPFLAGS := -c -g -O -fno-pie -std=c++11 -pedantic -Wall -Wextra \
-fno-rtti -fno-exceptions \
$(INCLUDES) $(DEFINES) -DQ_SPY
else # default Debug configuration .........................................
BIN_DIR := dbg
# gcc options:
CFLAGS := -c -g -O -fno-pie -std=c99 -pedantic -Wall -Wextra -W \
$(INCLUDES) $(DEFINES)
CPPFLAGS := -c -g -O -fno-pie -std=c++11 -pedantic -Wall -Wextra \
-fno-rtti -fno-exceptions \
$(INCLUDES) $(DEFINES)
endif
#-----------------------------------------------------------------------------
C_OBJS := $(patsubst %.c,%.o, $(notdir $(C_SRCS)))
CPP_OBJS := $(patsubst %.cpp,%.o,$(notdir $(CPP_SRCS)))
TARGET_LIB := $(BIN_DIR)/lib$(PROJECT).a
C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS))
C_DEPS_EXT := $(patsubst %.o,%.d, $(C_OBJS_EXT))
CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS))
CPP_DEPS_EXT := $(patsubst %.o,%.d, $(CPP_OBJS_EXT))
# create $(BIN_DIR) if it does not exist
ifeq ("$(wildcard $(BIN_DIR))","")
$(shell $(MKDIR) $(BIN_DIR))
endif
#-----------------------------------------------------------------------------
# rules
#
all: $(TARGET_LIB)
-$(RM) $(BIN_DIR)/*.o
$(TARGET_LIB) : $(ASM_OBJS_EXT) $(C_OBJS_EXT) $(CPP_OBJS_EXT)
$(LIB) $(LIBFLAGS) $@ $^
$(BIN_DIR)/%.o : %.c
$(CC) $(CFLAGS) $< -o $@
$(BIN_DIR)/%.o : %.cpp
$(CPP) $(CPPFLAGS) $< -o $@
#-----------------------------------------------------------------------------
# the clean target
#
.PHONY : clean
clean:
-$(RM) $(BIN_DIR)/*.o $(TARGET_LIB)
#-----------------------------------------------------------------------------
# the show target for debugging
#
show:
@echo PROJECT = $(PROJECT)
@echo CONF = $(CONF)
@echo TARGET_LIB = $(TARGET_LIB)
@echo C_SRCS = $(C_SRCS)
@echo CPP_SRCS = $(CPP_SRCS)
@echo C_OBJS_EXT = $(C_OBJS_EXT)
@echo C_DEPS_EXT = $(C_DEPS_EXT)
@echo CPP_OBJS_EXT = $(CPP_OBJS_EXT)
@echo CPP_DEPS_EXT = $(CPP_DEPS_EXT)

View File

@ -1,51 +1,51 @@
27d2d0d96374af4853a6a31a25ac3ef8 *qpcpp.qm
da3f0e1d1bc147b9e5ee801bc1fdd130 *include/qequeue.hpp
0c7051849804080425142a71b1e9b13b *qpcpp.qm
2c7717f261e842ae0449a321d3c50f3e *include/qequeue.hpp
fe1ff6084ff592ca8d14a6efffec296c *include/qk.hpp
ebf2cb455c1471c2248bbde4b90ce634 *include/qmpool.hpp
344c0ecb3d7f5645a5f4e75aea7956ac *include/qp.hpp
0cf7c36bbbca2e0ebfe61347e9e572e5 *include/qmpool.hpp
1290aa2707d23ea765a131a4c30d7ce9 *include/qp.hpp
61c7a3aa8cb265f478915f39b7fae9cc *include/qp_pkg.hpp
81e2fed348f03200d00b4d7c4473826f *include/qpcpp.hpp
be2da5d56117fd172f12c8b6589f6402 *include/qs.hpp
d59808009be96849963572ffcbf9dceb *include/qs_dummy.hpp
db4013ceefb33498f5d38e15d0cb9323 *include/qs_pkg.hpp
2a36b08d4f3ec92da6ae6f7c18ad83ca *include/qsafe.h
f59bf88705afe5b0acc999f8b47a6745 *include/qsafe.h
e66cf5dd191fb0e7c1f8660fb477b860 *include/qstamp.hpp
d42a19307ba3c0c5b890431767f35b42 *include/qv.hpp
c0bc33e3823dde00803a301c4b85637d *include/qxk.hpp
ccc88dc7734a312ee0e33c437db7f3eb *src/qf/CMakeLists.txt
88c84e634597fafced2012faea838750 *src/qf/qep_hsm.cpp
becbd953c6da010daddf4907784e9766 *src/qf/qep_msm.cpp
43c0ce7d29c9dd18691899c883b3f5eb *src/qf/qep_hsm.cpp
dec4234285d4efd40b3ae6f680bc7179 *src/qf/qep_msm.cpp
8b5c1ece58069ed5582864fd2dc58167 *src/qf/qf_act.cpp
8fca896aa3dee712f6c844a0f31c130e *src/qf/qf_actq.cpp
eba1e6d624f4b1c7c82b2f98ef3e9198 *src/qf/qf_actq.cpp
39b02b596faa57abfa96b0f7c3f7fb82 *src/qf/qf_defer.cpp
069220fa20ca5bd9e0ddfcb2f4f8f0ba *src/qf/qf_dyn.cpp
0d3572af3a2acbf7144b27be35fa018a *src/qf/qf_mem.cpp
40218fcd6cbb521f2c8ae5f7c0d5c04e *src/qf/qf_ps.cpp
7b797a3a69836d0aba3c600130606f01 *src/qf/qf_dyn.cpp
f23875214b4c4c905bdb0567d900b36b *src/qf/qf_mem.cpp
37cfa5b9419f1e00608267ff29fbc1a8 *src/qf/qf_ps.cpp
19cf8976578a43e93bfbb51dbe932b6c *src/qf/qf_qact.cpp
46f954811c55e933e016bb36ab22adcd *src/qf/qf_qeq.cpp
816dc7182f4014539f6f5304782ddb7b *src/qf/qf_qmact.cpp
c49e1c15e6d6e035668d910c8d13a684 *src/qf/qf_time.cpp
c551aafbf9ecba93cfdb12f81fbfba61 *src/qf/qf_time.cpp
4dc7ca60248f4c13034e6f2481c7663d *src/qk/CMakeLists.txt
5670063d7e71927b7d5c98a6db38c351 *src/qk/qk.cpp
1a314e2a9fba927f6648772121790c5f *src/qk/qk.cpp
2557d617414f8cbdcbfeaab619d296bb *src/qs/CMakeLists.txt
ecdd6f0f0a7dc56d8bb0c769e67b48fc *src/qs/qs.cpp
bd1870c2a952b47ef613cc67406aca80 *src/qs/qs.cpp
a2ca20b2332d025067645839e4b25711 *src/qs/qs_64bit.cpp
8f6551c7786fdbb106c3d1bc7824c060 *src/qs/qs_fp.cpp
4af89f114491668f7a26af694ff11993 *src/qs/qs_rx.cpp
2655cd10d009075b71a84368fb6bf4d4 *src/qs/qstamp.cpp
180d454ecdbd08f522ff9a9c299de5df *src/qs/qutest.cpp
cf2fae9b29aab50c5cd69d7d519cb0db *src/qv/CMakeLists.txt
80b65ecb456e0a8efaaa14f7f30aac81 *src/qv/qv.cpp
abfb725ec432f1f56b72e2be4c62e9d3 *src/qv/qv.cpp
3c916b7d6a6ce58963153f51801858df *src/qxk/CMakeLists.txt
9a0b0803b84b7c4cf0fe1e34187371f8 *src/qxk/qxk.cpp
efe0395b16911eaff880649a9968d6a3 *src/qxk/qxk_mutex.cpp
7fed39c66ef913b79b82116b54af21de *src/qxk/qxk.cpp
309a3f6772f0cadfa8e50b545852b995 *src/qxk/qxk_mutex.cpp
ce5ff1926bd91dd8683e0232d3e1d471 *src/qxk/qxk_sema.cpp
78ec1d0d6aa9efbdc8b3d09e6deea40e *src/qxk/qxk_xthr.cpp
bf56a383eb7dafafa408d6219b585b40 *ports/lint-plus/au-autosar.lnt
e3e3f3000f9a80a446255ef52f3a6299 *ports/lint-plus/au-autosar19.lnt
2a8fea61bccbe5e8c7536a29f2ec8e98 *ports/lint-plus/au-ds.lnt
ede719cdbc201d14586a3f11e77ced26 *ports/lint-plus/au-ql-cpp11.lnt
dddbecd55afec10d85006f7787e40c7d *ports/lint-plus/options.lnt
3935c8cc585d08999ba9fb9055cc3705 *ports/lint-plus/options.lnt
00e7bc0ddabc998469615ac2ff9d79f1 *ports/lint-plus/qpcpp.lnt
5f789348dba099c2055f737ba756faac *ports/lint-plus/std.lnt
1f3d9dfbf71077abbdb9f27c96879101 *ports/arm-cm/qk/armclang/qk_port.cpp
@ -70,14 +70,14 @@ c6227ba01b71184c9e03ee6c8137ffc2 *ports/arm-cm/qk/gnu/qp_port.hpp
fed596b153b928c8631e2712361049af *ports/arm-cm/qv/iar/qv_port.cpp
fbab3cb88a019df3a12ee56a4a6f90b2 *ports/arm-cm/qxk/armclang/qp_port.hpp
91a3b66c3f12a98bef48b00640ed5e6d *ports/arm-cm/qxk/armclang/qs_port.hpp
347f34d732e241dda4ba56133ce89993 *ports/arm-cm/qxk/armclang/qxk_port.cpp
3e6878ba5e8df9ed733edf9f2da2ae9e *ports/arm-cm/qxk/armclang/qxk_port.cpp
e219623c0ac1ee0fcb24d9b2245e406e *ports/arm-cm/qxk/config/qp_config.hpp
246d7b72e2f0c1e3ba6e699740dbe390 *ports/arm-cm/qxk/gnu/qp_port.hpp
91a3b66c3f12a98bef48b00640ed5e6d *ports/arm-cm/qxk/gnu/qs_port.hpp
1a120fbd8eabd3ee8f36fa9965120147 *ports/arm-cm/qxk/gnu/qxk_port.cpp
f12841a5d59075aa3e1e9cfb683c4b98 *ports/arm-cm/qxk/gnu/qxk_port.cpp
55b897c657e225d775cf6121d6278585 *ports/arm-cm/qxk/iar/qp_port.hpp
91a3b66c3f12a98bef48b00640ed5e6d *ports/arm-cm/qxk/iar/qs_port.hpp
01d7a7198b209b43e49df8df5ca8ea2b *ports/arm-cm/qxk/iar/qxk_port.cpp
bcb7406483cc9280c2b05113f6078cb6 *ports/arm-cm/qxk/iar/qxk_port.cpp
0f3ac7def7c330e85912d95527c94ebc *ports/arm-cm/qutest/qp_port.hpp
4c0ab6f6ad804f0bd70f146d53a1d197 *ports/arm-cm/qutest/qs_port.hpp
a595b03768298546cd9dff7f4e8876f7 *ports/arm-cr/qk/config/qp_config.hpp
@ -148,7 +148,6 @@ e898e8f446a8fcfd84b5092144b21ef3 *ports/posix-qutest/qs_port.hpp
0ac7e3d28e684d07baacdcd0d3e65c4a *ports/posix-qutest/README.md
7955fc33c291eb6b8ebabaae0d6bd0da *ports/posix-qutest/safe_std.h
84541985a09da4e23055531452d74a02 *ports/win32/CMakeLists.txt
ccec9e69c078e6b6889b7cba2e6195dd *ports/win32/Makefile
b98e9825ffcbd8178145207316bf7910 *ports/win32/qf_port.cpp
fc5a9085222501f994b6d517d6624a52 *ports/win32/qp_port.hpp
b53aafe66b369a2e54344c792e481c1c *ports/win32/qs_port.cpp

247
qpcpp.qm
View File

@ -472,27 +472,27 @@ QS_MEM_APP();
QF_CRIT_EXIT();
// drill down into the state hierarchy with initial transitions...
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
do {
QStateHandler path[MAX_NEST_DEPTH_]; // tran entry path array
std::int_fast8_t ip = 0; // tran entry path index
path[0] = m_temp.fun;
static_cast&lt;void&gt;(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG));
while (m_temp.fun != t) {
// note: ip is here the fixed upper loop bound
while ((m_temp.fun != t) &amp;&amp; (ip &lt; (MAX_NEST_DEPTH_ - 1))) {
++ip;
path[ip] = m_temp.fun;
static_cast&lt;void&gt;(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG));
}
QF_CRIT_ENTRY();
// The initial transition source state must be reached
// Too many state nesting levels or &quot;malformed&quot; HSM.
Q_ASSERT_INCRIT(220, m_temp.fun == t);
// too many state nesting levels or &quot;malformed&quot; HSM
Q_ENSURE_INCRIT(220, ip &lt; 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)
@ -520,14 +520,9 @@ do {
QS_CRIT_EXIT();
}
#endif // Q_SPY
--limit;
} while ((r == Q_RET_TRAN) &amp;&amp; (limit &gt; 0));
} while (r == Q_RET_TRAN);
QF_CRIT_ENTRY();
// Loop limit must not be reached.
// Too many state nesting levels or likely &quot;malformed&quot; HSM
Q_ENSURE_INCRIT(290, limit &gt; 0);
QS_MEM_SYS();
QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId)
@ -567,9 +562,9 @@ QStateHandler t = s;
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(300, (s != Q_STATE_CAST(0))
Q_INVARIANT_INCRIT(302, (s != Q_STATE_CAST(0))
&amp;&amp; (m_state.uint == static_cast&lt;std::uintptr_t&gt;(~m_temp.uint)));
Q_REQUIRE_INCRIT(302, QEvt::verify_(e));
Q_INVARIANT_INCRIT(303, QEvt::verify_(e));
QS_MEM_SYS();
QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId)
@ -585,7 +580,7 @@ QF_CRIT_EXIT();
// process the event hierarchically...
QState r;
m_temp.fun = s;
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
std::int_fast8_t ip = MAX_NEST_DEPTH_; // fixed upper loop bound
do {
s = m_temp.fun;
r = (*s)(this, e); // invoke state handler s
@ -605,11 +600,11 @@ do {
r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); // superstate of s
}
--limit;
} while ((r == Q_RET_SUPER) &amp;&amp; (limit &gt; 0));
--ip;
} while ((r == Q_RET_SUPER) &amp;&amp; (ip &gt; 0));
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(310, limit &gt; 0);
Q_ENSURE_INCRIT(310, ip &gt; 0);
QF_CRIT_EXIT();
if (r &gt;= Q_RET_TRAN) { // regular tran. taken?
@ -620,21 +615,21 @@ if (r &gt;= Q_RET_TRAN) { // regular tran. taken?
path[2] = s; // tran. source
// exit current state to tran. source s...
limit = MAX_NEST_DEPTH_; // loop hard limit
for (; (t != s) &amp;&amp; (limit &gt; 0); t = m_temp.fun) {
ip = MAX_NEST_DEPTH_; // fixed upper loop bound
for (; (t != s) &amp;&amp; (ip &gt; 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&lt;void&gt;(QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG));
}
--limit;
--ip;
}
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(320, limit &gt; 0);
Q_ENSURE_INCRIT(320, ip &gt; 0);
QF_CRIT_EXIT();
std::int_fast8_t ip = hsm_tran(path, qsId); // take the tran.
ip = hsm_tran(path, qsId); // take the tran.
#ifdef Q_SPY
if (r == Q_RET_TRAN_HIST) {
@ -651,6 +646,7 @@ if (r &gt;= Q_RET_TRAN) { // regular tran. taken?
#endif // Q_SPY
// execute state entry actions in the desired order...
// note: ip is the fixed upper loop bound
for (; ip &gt;= 0; --ip) {
// enter path[ip]
if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG)
@ -681,6 +677,7 @@ if (r &gt;= Q_RET_TRAN) { // regular tran. taken?
// find superstate
static_cast&lt;void&gt;(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG));
// note: ip is the fixed upper loop bound
while ((m_temp.fun != t) &amp;&amp; (ip &lt; (MAX_NEST_DEPTH_ - 1))) {
++ip;
path[ip] = m_temp.fun;
@ -689,14 +686,14 @@ if (r &gt;= Q_RET_TRAN) { // regular tran. taken?
QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG));
}
QF_CRIT_ENTRY();
// The initial transition source state must be reached.
// Too many state nesting levels or &quot;malformed&quot; HSM.
Q_ASSERT_INCRIT(330, m_temp.fun == t);
// too many state nesting levels or &quot;malformed&quot; HSM
Q_ENSURE_INCRIT(330, ip &lt; 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)
@ -762,17 +759,17 @@ m_temp.uint = ~m_state.uint;
<parameter name="state" type="QStateHandler const"/>
<code>QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(602, m_state.uint
== static_cast&lt;std::uintptr_t&gt;(~m_temp.uint));
Q_INVARIANT_INCRIT(602, m_state.uint
== static_cast&lt;std::uintptr_t&gt;(~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 limit = MAX_NEST_DEPTH_ + 1; // loop hard limit
std::int_fast8_t lbound = MAX_NEST_DEPTH_ + 1; // fixed upper loop bound
QState r = Q_RET_SUPER;
for (; (r != Q_RET_IGNORED) &amp;&amp; (limit &gt; 0); --limit) {
for (; (r != Q_RET_IGNORED) &amp;&amp; (lbound &gt; 0); --lbound) {
if (s == state) { // do the states match?
inState = true; // 'true' means that match found
break; // break out of the for-loop
@ -784,7 +781,7 @@ for (; (r != Q_RET_IGNORED) &amp;&amp; (limit &gt; 0); --limit) {
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(690, limit &gt; 0);
Q_ENSURE_INCRIT(690, lbound &gt; 0);
QF_CRIT_EXIT();
#ifndef Q_UNSAFE
@ -798,12 +795,13 @@ return inState; // return the status</code>
<specifiers>noexcept</specifiers>
<!--${QEP::QHsm::childState::parent}-->
<parameter name="parent" type="QStateHandler const"/>
<code>QStateHandler child = m_state.fun; // start with the current state
<code>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 = MAX_NEST_DEPTH_; // fixed upper loop bound
do {
// is this the parent of the current child?
if (m_temp.fun == parent) {
@ -814,7 +812,9 @@ do {
child = m_temp.fun;
r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG);
}
} while (r != Q_RET_IGNORED); // QHsm::top() state not reached
--lbound;
} while ((r != Q_RET_IGNORED) // QHsm::top() state not reached
&amp;&amp; (lbound &gt; 0));
#ifndef Q_UNSAFE
m_temp.uint = ~m_state.uint;
@ -822,10 +822,12 @@ m_temp.uint = ~m_state.uint;
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(890, isFound);
// NOTE: the following postcondition can only succeed when
// (lbound &gt; 0), so no extra check is necessary.
Q_ENSURE_INCRIT(890, isFound);
QF_CRIT_EXIT();
return child; // return the child</code>
return child;</code>
</operation>
<!--${QEP::QHsm::getStateHandler}-->
<operation name="getStateHandler?def Q_SPY" type="QStateHandler" visibility="0x00" properties="0x06">
@ -894,6 +896,7 @@ else {
t = m_temp.fun; // save source-&gt;super
// find target-&gt;super-&gt;super...
// note: ip is the fixed upper loop bound
QState r = QHSM_RESERVED_EVT_(path[1], Q_EMPTY_SIG);
while ((r == Q_RET_SUPER)
&amp;&amp; (ip &lt; (MAX_NEST_DEPTH_ - 1)))
@ -910,9 +913,10 @@ else {
}
}
QF_CRIT_ENTRY();
// Tran. source must be found within the nesting depth
// Too many state nesting levels or &quot;malformed&quot; HSM.
Q_ASSERT_INCRIT(510, r != Q_RET_SUPER);
// NOTE: The following postcondition succeeds only when
// ip &lt; QHSM_MAX_NEST_DEPTH, so no additional check is necessary
// too many state nesting levels or &quot;malformed&quot; HSM.
Q_ENSURE_INCRIT(510, r != Q_RET_SUPER);
QF_CRIT_EXIT();
// the LCA not found yet?
@ -928,6 +932,7 @@ else {
// == target-&gt;super-&gt;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
@ -944,7 +949,7 @@ else {
// (g) check each source-&gt;super-&gt;...
// for each target-&gt;super...
r = Q_RET_IGNORED; // keep looping
std::int_fast8_t limit = MAX_NEST_DEPTH_;
std::int_fast8_t lbound = MAX_NEST_DEPTH_;
do {
// exit from t
if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG)
@ -969,10 +974,10 @@ else {
}
} while (iq &gt;= 0);
--limit;
} while ((r != Q_RET_HANDLED) &amp;&amp; (limit &gt; 0));
--lbound;
} while ((r != Q_RET_HANDLED) &amp;&amp; (lbound &gt; 0));
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(530, limit &gt; 0);
Q_ASSERT_INCRIT(530, lbound &gt; 0);
QF_CRIT_EXIT();
}
}
@ -1037,15 +1042,15 @@ QF_CRIT_EXIT();
m_state.obj = m_temp.tatbl-&gt;target;
// drill down into the state hierarchy with initial transitions...
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
std::int_fast8_t lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
do {
// execute the tran. table
r = execTatbl_(m_temp.tatbl, qsId);
--limit;
} while ((r &gt;= Q_RET_TRAN_INIT) &amp;&amp; (limit &gt; 0));
--lbound;
} while ((r &gt;= Q_RET_TRAN_INIT) &amp;&amp; (lbound &gt; 0));
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(290, limit &gt; 0);
Q_ENSURE_INCRIT(290, lbound &gt; 0);
QS_MEM_SYS();
QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId)
@ -1084,9 +1089,9 @@ QMState const *t = s;
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(300, (s != nullptr)
Q_INVARIANT_INCRIT(300, (s != nullptr)
&amp;&amp; (m_state.uint == static_cast&lt;std::uintptr_t&gt;(~m_temp.uint)));
Q_REQUIRE_INCRIT(302, QEvt::verify_(e));
Q_INVARIANT_INCRIT(302, QEvt::verify_(e));
QS_MEM_SYS();
QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId)
@ -1101,7 +1106,7 @@ QF_CRIT_EXIT();
// scan the state hierarchy up to the top state...
QState r;
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
std::int_fast8_t lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
do {
r = (*t-&gt;stateHandler)(this, e); // call state handler function
@ -1134,10 +1139,10 @@ do {
t = t-&gt;superstate; // advance to the superstate
}
--limit;
} while ((t != nullptr) &amp;&amp; (limit &gt; 0));
--lbound;
} while ((t != nullptr) &amp;&amp; (lbound &gt; 0));
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(310, limit &gt; 0);
Q_ASSERT_INCRIT(310, lbound &gt; 0);
QF_CRIT_EXIT();
if (r &gt;= Q_RET_TRAN) { // any kind of tran. taken?
@ -1150,7 +1155,7 @@ if (r &gt;= Q_RET_TRAN) { // any kind of tran. taken?
QF_CRIT_EXIT();
#endif // Q_SPY
limit = MAX_NEST_DEPTH_; // loop hard limit
lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
do {
// save the tran-action table before it gets clobbered
QMTranActTable const * const tatbl = m_temp.tatbl;
@ -1217,11 +1222,11 @@ if (r &gt;= Q_RET_TRAN) { // any kind of tran. taken?
}
t = s; // set target to the current state
--limit;
} while ((r &gt;= Q_RET_TRAN) &amp;&amp; (limit &gt; 0));
--lbound;
} while ((r &gt;= Q_RET_TRAN) &amp;&amp; (lbound &gt; 0));
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(320, limit &gt; 0);
Q_ASSERT_INCRIT(320, lbound &gt; 0);
QS_MEM_SYS();
QS_BEGIN_PRE_(QS_QEP_TRAN, qsId)
@ -1289,8 +1294,8 @@ m_temp.uint = ~m_state.uint;
<code>bool inState = false; // assume that this SM is not in 'state'
QMState const *s = m_state.obj;
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
for (; (s != nullptr) &amp;&amp; (limit &gt; 0); --limit) {
std::int_fast8_t lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
for (; (s != nullptr) &amp;&amp; (lbound &gt; 0); --lbound) {
if (s-&gt;stateHandler == state) { // match found?
inState = true;
break;
@ -1302,7 +1307,7 @@ for (; (s != nullptr) &amp;&amp; (limit &gt; 0); --limit) {
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(490, limit &gt; 0);
Q_ENSURE_INCRIT(490, lbound &gt; 0);
QF_CRIT_EXIT();
return inState;</code>
@ -1316,8 +1321,8 @@ return inState;</code>
<code>bool inState = false; // assume that this SM is not in 'state'
QMState const *s = m_state.obj;
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
for (; (s != nullptr) &amp;&amp; (limit &gt; 0); --limit) {
std::int_fast8_t lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
for (; (s != nullptr) &amp;&amp; (lbound &gt; 0); --lbound) {
if (s == stateObj) { // match found?
inState = true;
break;
@ -1329,7 +1334,7 @@ for (; (s != nullptr) &amp;&amp; (limit &gt; 0); --limit) {
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(590, limit &gt; 0);
Q_ENSURE_INCRIT(590, lbound &gt; 0);
QF_CRIT_EXIT();
return inState;</code>
@ -1343,9 +1348,9 @@ return inState;</code>
bool isFound = false; // start with the child not found
QMState const *s;
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
std::int_fast8_t lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
for (s = m_state.obj;
(s != nullptr) &amp;&amp; (limit &gt; 0);
(s != nullptr) &amp;&amp; (lbound &gt; 0);
s = s-&gt;superstate)
{
if (s == parent) {
@ -1355,17 +1360,17 @@ for (s = m_state.obj;
else {
child = s;
}
--limit;
--lbound;
}
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(610, limit &gt; 0);
Q_ASSERT_INCRIT(610, lbound &gt; 0);
QF_CRIT_EXIT();
if (!isFound) { // still not found?
limit = MAX_NEST_DEPTH_; // loop hard limit
lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
for (s = m_temp.obj;
(s != nullptr) &amp;&amp; (limit &gt; 0);
(s != nullptr) &amp;&amp; (lbound &gt; 0);
s = s-&gt;superstate)
{
if (s == parent) {
@ -1375,12 +1380,12 @@ if (!isFound) { // still not found?
else {
child = s;
}
--limit;
--lbound;
}
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(690, isFound &amp;&amp; (limit &gt; 0));
Q_ENSURE_INCRIT(690, isFound &amp;&amp; (lbound &gt; 0));
QF_CRIT_EXIT();
return child; // return the child</code>
@ -1403,9 +1408,9 @@ Q_REQUIRE_INCRIT(700, tatbl != nullptr);
QF_CRIT_EXIT();
QState r = Q_RET_NULL;
std::int_fast8_t limit = MAX_TRAN_LENGTH_; // loop hard limit
std::int_fast8_t lbound = MAX_TRAN_LENGTH_; // fixed upper loop bound
QActionHandler const *a = &amp;tatbl-&gt;act[0];
for (; (*a != nullptr) &amp;&amp; (limit &gt; 0); ++a) {
for (; (*a != nullptr) &amp;&amp; (lbound &gt; 0); ++a) {
r = (*(*a))(this); // call the action through the 'a' pointer
#ifdef Q_SPY
QS_CRIT_ENTRY();
@ -1449,7 +1454,7 @@ for (; (*a != nullptr) &amp;&amp; (limit &gt; 0); ++a) {
QS_MEM_APP();
QS_CRIT_EXIT();
#endif // Q_SPY
--limit;
--lbound;
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(790, *a == nullptr);
@ -1476,8 +1481,8 @@ QF_CRIT_STAT
// exit states from the current state to the tran. source state
QMState const *s = cs;
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
for (; (s != ts) &amp;&amp; (limit &gt; 0); --limit) {
std::int_fast8_t lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
for (; (s != ts) &amp;&amp; (lbound &gt; 0); --lbound) {
// exit action provided in state 's'?
if (s-&gt;exitAction != nullptr) {
// execute the exit action
@ -1503,7 +1508,7 @@ for (; (s != ts) &amp;&amp; (limit &gt; 0); --limit) {
}
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(890, limit &gt; 0);
Q_ENSURE_INCRIT(890, lbound &gt; 0);
QF_CRIT_EXIT();</code>
</operation>
<!--${QEP::QMsm::enterHistory_}-->
@ -2161,7 +2166,7 @@ QF_MEM_SYS();
#ifndef Q_UNSAFE
std::uint8_t const pcopy = static_cast&lt;std::uint8_t&gt;(~m_prio_dis);
Q_REQUIRE_INCRIT(102, (QEvt::verify_(e)) &amp;&amp; (m_prio == pcopy));
Q_INVARIANT_INCRIT(102, (QEvt::verify_(e)) &amp;&amp; (m_prio == pcopy));
#endif
QEQueueCtr nFree = m_eQueue.m_nFree; // get volatile into temporary
@ -2300,7 +2305,7 @@ QF_MEM_SYS();
#ifndef Q_UNSAFE
std::uint8_t const pcopy = static_cast&lt;std::uint8_t&gt;(~m_prio_dis);
Q_REQUIRE_INCRIT(202, (QEvt::verify_(e)) &amp;&amp; (m_prio == pcopy));
Q_INVARIANT_INCRIT(202, (QEvt::verify_(e)) &amp;&amp; (m_prio == pcopy));
#endif
#ifdef QXK_HPP_
@ -2466,7 +2471,7 @@ QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(200, sig &lt; static_cast&lt;QSignal&gt;(maxPubSignal_));
Q_REQUIRE_INCRIT(202,
Q_INVARIANT_INCRIT(202,
subscrList_[sig].m_set.verify_(&amp;subscrList_[sig].m_set_dis));
QS_BEGIN_PRE_(QS_QF_PUBLISH, qsId)
@ -2509,9 +2514,9 @@ if (subscrSet.notEmpty()) { // any subscribers?
QF_SCHED_STAT_
QF_SCHED_LOCK_(p); // lock the scheduler up to AO's prio
std::uint_fast8_t limit = QF_MAX_ACTIVE + 1U;
std::uint_fast8_t lbound = QF_MAX_ACTIVE + 1U;
do { // loop over all subscribers
--limit;
--lbound;
// POST() asserts internally if the queue overflows
a-&gt;POST(e, sender);
@ -2533,7 +2538,7 @@ if (subscrSet.notEmpty()) { // any subscribers?
else {
p = 0U; // no more subscribers
}
} while ((p != 0U) &amp;&amp; (limit &gt; 0U));
} while ((p != 0U) &amp;&amp; (lbound &gt; 0U));
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(290, p == 0U);
@ -2564,7 +2569,7 @@ Q_REQUIRE_INCRIT(300, (Q_USER_SIG &lt;= sig)
&amp;&amp; (sig &lt; maxPubSignal_)
&amp;&amp; (0U &lt; p) &amp;&amp; (p &lt;= QF_MAX_ACTIVE)
&amp;&amp; (registry_[p] == this));
Q_REQUIRE_INCRIT(302,
Q_INVARIANT_INCRIT(302,
subscrList_[sig].m_set.verify_(&amp;subscrList_[sig].m_set_dis));
QS_BEGIN_PRE_(QS_QF_ACTIVE_SUBSCRIBE, m_prio)
@ -2597,7 +2602,7 @@ Q_REQUIRE_INCRIT(400, (Q_USER_SIG &lt;= sig)
&amp;&amp; (sig &lt; maxPubSignal_)
&amp;&amp; (0U &lt; p) &amp;&amp; (p &lt;= QF_MAX_ACTIVE)
&amp;&amp; (registry_[p] == this));
Q_REQUIRE_INCRIT(402,
Q_INVARIANT_INCRIT(402,
subscrList_[sig].m_set.verify_(&amp;subscrList_[sig].m_set_dis));
QS_BEGIN_PRE_(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio)
@ -2929,8 +2934,6 @@ QF_CRIT_EXIT();
// reused to hold the tickRate as well as other information
refCtr_ = static_cast&lt;std::uint8_t&gt;(tickRate);</code>
</operation>
<!--${QF::QTimeEvt::~QTimeEvt}-->
<operation name="~QTimeEvt?def Q_XTOR" type="" visibility="0x00" properties="0x00"/>
<!--${QF::QTimeEvt::armX}-->
<operation name="armX" type="void" visibility="0x00" properties="0x00">
<specifiers>noexcept</specifiers>
@ -3159,8 +3162,8 @@ QS_BEGIN_PRE_(QS_QF_TICK, 0U)
QS_END_PRE_()
// scan the linked-list of time events at this rate...
std::uint_fast8_t limit = 2U*QF_MAX_ACTIVE; // loop hard limit
for (; limit &gt; 0U; --limit) {
std::uint_fast8_t lbound = 2U*QF_MAX_ACTIVE; // fixed upper loop bound
for (; lbound &gt; 0U; --lbound) {
QTimeEvt *e = prev-&gt;m_next; // advance down the time evt. list
if (e == nullptr) { // end of the list?
@ -3180,7 +3183,7 @@ for (; limit &gt; 0U; --limit) {
}
// the time event 'e' must be valid
Q_ASSERT_INCRIT(112, QEvt::verify_(e));
Q_INVARIANT_INCRIT(112, QEvt::verify_(e));
if (e-&gt;m_ctr == 0U) { // time event scheduled for removal?
prev-&gt;m_next = e-&gt;m_next;
@ -3269,7 +3272,7 @@ for (; limit &gt; 0U; --limit) {
QF_MEM_SYS();
}
Q_ENSURE_INCRIT(190, limit &gt; 0U);
Q_ENSURE_INCRIT(190, lbound &gt; 0U);
QF_MEM_APP();
QF_CRIT_EXIT();</code>
</operation>
@ -3489,8 +3492,6 @@ QF_CRIT_EXIT();</code>
m_nFree(0U),
m_nMin(0U)</code>
</operation>
<!--${QF::QEQueue::~QEQueue}-->
<operation name="~QEQueue?def Q_XTOR" type="" visibility="0x00" properties="0x00"/>
<!--${QF::QEQueue::init}-->
<operation name="init" type="void" visibility="0x00" properties="0x00">
<specifiers>noexcept</specifiers>
@ -3760,8 +3761,6 @@ return e;</code>
m_nFree(0U),
m_nMin(0U)</code>
</operation>
<!--${QF::QMPool::~QMPool}-->
<operation name="~QMPool?def Q_XTOR" type="" visibility="0x00" properties="0x00"/>
<!--${QF::QMPool::init}-->
<operation name="init" type="void" visibility="0x00" properties="0x00">
<specifiers>noexcept</specifiers>
@ -3850,8 +3849,8 @@ if (m_nFree &gt; static_cast&lt;QMPoolCtr&gt;(margin)) {
QFreeBlock * const fb_next = fb-&gt;m_next;
// the free block must have integrity (duplicate inverse storage)
Q_ASSERT_INCRIT(302, Q_UINTPTR_CAST_(fb_next)
== static_cast&lt;std::uintptr_t&gt;(~fb-&gt;m_next_dis));
Q_INVARIANT_INCRIT(302, Q_UINTPTR_CAST_(fb_next)
== static_cast&lt;std::uintptr_t&gt;(~fb-&gt;m_next_dis));
m_nFree = (m_nFree - 1U); // one free block less
if (m_nFree == 0U) { // is the pool becoming empty?
@ -3929,7 +3928,7 @@ fb-&gt;m_next_dis = static_cast&lt;std::uintptr_t&gt;(
#endif
// set as new head of the free list
m_free_head = static_cast&lt;QFreeBlock *&gt;(block);
m_free_head = fb;
m_nFree = m_nFree + 1U; // one more free block in this pool
@ -4234,7 +4233,7 @@ return e;</code>
<parameter name="e" type="QEvt const * const"/>
<code>QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(402, QEvt::verify_(e));
Q_INVARIANT_INCRIT(402, QEvt::verify_(e));
std::uint_fast8_t const poolNum = e-&gt;getPoolNum_();
@ -4299,7 +4298,7 @@ Q_UNUSED_PAR(evtRef);
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(502, QEvt::verify_(e));
Q_INVARIANT_INCRIT(502, QEvt::verify_(e));
std::uint_fast8_t const poolNum = e-&gt;getPoolNum_();
@ -4330,7 +4329,7 @@ return e;</code>
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(602, QEvt::verify_(e));
Q_INVARIANT_INCRIT(602, QEvt::verify_(e));
#ifdef Q_SPY
std::uint_fast8_t const poolNum = e-&gt;getPoolNum_();
@ -4632,7 +4631,7 @@ gc(evtRef); // recycle the referenced event
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_ASSERT_INCRIT(102, priv_.schedCeil
Q_INVARIANT_INCRIT(102, priv_.schedCeil
== static_cast&lt;std::uint_fast8_t&gt;(~priv_.schedCeil_dis));
if (ceiling &gt; priv_.schedCeil) { // raising the scheduler ceiling?
@ -4658,7 +4657,7 @@ QF_CRIT_EXIT();</code>
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_ASSERT_INCRIT(202, priv_.schedCeil
Q_INVARIANT_INCRIT(202, priv_.schedCeil
== static_cast&lt;std::uint_fast8_t&gt;(~priv_.schedCeil_dis));
if (priv_.schedCeil != 0U) { // actually enabling the scheduler?
@ -4730,10 +4729,10 @@ std::uint_fast8_t pprev = 0U; // previous prio.
for (;;) { // QV event loop...
// check internal integrity (duplicate inverse storage)
Q_ASSERT_INCRIT(302,
Q_INVARIANT_INCRIT(302,
QV::priv_.readySet.verify_(&amp;QV::priv_.readySet_dis));
// check internal integrity (duplicate inverse storage)
Q_ASSERT_INCRIT(303, QV::priv_.schedCeil
Q_INVARIANT_INCRIT(303, QV::priv_.schedCeil
== static_cast&lt;std::uint_fast8_t&gt;(~QV::priv_.schedCeil_dis));
// find the maximum prio. AO ready to run
@ -4908,7 +4907,7 @@ QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(100, !QK_ISR_CONTEXT_());
Q_REQUIRE_INCRIT(102, QK_priv_.lockCeil
Q_INVARIANT_INCRIT(102, QK_priv_.lockCeil
== static_cast&lt;std::uint_fast8_t&gt;(~QK_priv_.lockCeil_dis));
// first store the previous lock prio
@ -4950,7 +4949,7 @@ if (prevCeil != 0xFFU) {
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(202, QK_priv_.lockCeil
Q_INVARIANT_INCRIT(202, QK_priv_.lockCeil
== static_cast&lt;std::uint_fast8_t&gt;(~QK_priv_.lockCeil_dis));
Q_REQUIRE_INCRIT(210, (!QK_ISR_CONTEXT_())
&amp;&amp; (QK_priv_.lockCeil &gt; prevCeil));
@ -5134,7 +5133,7 @@ QF_CRIT_EXIT();</code>
<specifiers>noexcept</specifiers>
<code>// NOTE: this function is entered with interrupts DISABLED
Q_REQUIRE_INCRIT(402,
Q_INVARIANT_INCRIT(402,
QK_priv_.readySet.verify_(&amp;QK_priv_.readySet_dis));
std::uint_fast8_t p;
@ -5145,7 +5144,7 @@ else {
// find the highest-prio AO with non-empty event queue
p = QK_priv_.readySet.findMax();
Q_ASSERT_INCRIT(412, QK_priv_.actThre
Q_INVARIANT_INCRIT(412, QK_priv_.actThre
== static_cast&lt;std::uint_fast8_t&gt;(~QK_priv_.actThre_dis));
// is the AO's prio. below the active preemption-threshold?
@ -5153,7 +5152,7 @@ else {
p = 0U; // no activation needed
}
else {
Q_ASSERT_INCRIT(422, QK_priv_.lockCeil
Q_INVARIANT_INCRIT(422, QK_priv_.lockCeil
== static_cast&lt;std::uint_fast8_t&gt;(~QK_priv_.lockCeil_dis));
// is the AO's prio. below the lock-ceiling?
@ -5161,7 +5160,7 @@ else {
p = 0U; // no activation needed
}
else {
Q_ASSERT_INCRIT(432, QK_priv_.nextPrio
Q_INVARIANT_INCRIT(432, QK_priv_.nextPrio
== static_cast&lt;std::uint_fast8_t&gt;(~QK_priv_.nextPrio_dis));
QK_priv_.nextPrio = p; // next AO to run
#ifndef Q_UNSAFE
@ -5182,7 +5181,7 @@ return p;</code>
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_REQUIRE_INCRIT(502,
Q_INVARIANT_INCRIT(502,
(prio_in == static_cast&lt;std::uint_fast8_t&gt;(~QK_priv_.actPrio_dis))
&amp;&amp; (p == static_cast&lt;std::uint_fast8_t&gt;(~QK_priv_.nextPrio_dis)));
Q_REQUIRE_INCRIT(510, (prio_in &lt;= QF_MAX_ACTIVE)
@ -5207,7 +5206,7 @@ else {
Q_ASSERT_INCRIT(510, a != nullptr);
pthre_in = static_cast&lt;std::uint_fast8_t&gt;(a-&gt;getPThre());
Q_ASSERT_INCRIT(511, pthre_in == static_cast&lt;std::uint_fast8_t&gt;(
Q_INVARIANT_INCRIT(511, pthre_in == static_cast&lt;std::uint_fast8_t&gt;(
~static_cast&lt;std::uint_fast8_t&gt;(a-&gt;m_pthre_dis) &amp; 0xFFU));
}
@ -5217,7 +5216,7 @@ do {
Q_ASSERT_INCRIT(520, a != nullptr); // the AO must be registered
std::uint_fast8_t const pthre
= static_cast&lt;std::uint_fast8_t&gt;(a-&gt;getPThre());
Q_ASSERT_INCRIT(522, pthre == static_cast&lt;std::uint_fast8_t&gt;(
Q_INVARIANT_INCRIT(522, pthre == static_cast&lt;std::uint_fast8_t&gt;(
~static_cast&lt;std::uint_fast8_t&gt;(a-&gt;m_pthre_dis) &amp; 0xFFU));
// set new active prio. and preemption-threshold
@ -5245,6 +5244,7 @@ do {
}
#endif // QF_ON_CONTEXT_SW || Q_SPY
QF_MEM_APP();
QF_INT_ENABLE(); // unconditionally enable interrupts
QP::QEvt const * const e = a-&gt;get_();
@ -5261,7 +5261,7 @@ do {
QF_MEM_SYS();
// internal integrity check (duplicate inverse storage)
Q_ASSERT_INCRIT(532,
Q_INVARIANT_INCRIT(532,
QK_priv_.readySet.verify_(&amp;QK_priv_.readySet_dis));
if (a-&gt;getEQueue().isEmpty()) { // empty queue?
@ -5283,7 +5283,7 @@ do {
p = 0U; // no activation needed
}
else {
Q_ASSERT_INCRIT(542,
Q_INVARIANT_INCRIT(542,
QK_priv_.lockCeil == ~QK_priv_.lockCeil_dis);
// is the AO's prio. below the lock preemption-threshold?
@ -6176,7 +6176,7 @@ if (m_ao.m_eQueue.m_nFree == 0U) {
// is the mutex locked by this thread already (nested locking)?
else if (m_ao.m_osObject == curr) {
// the nesting level beyond the arbitrary but high limit
// the nesting level beyond the arbitrary but high bound
// most likely means cyclic or recursive locking of a mutex.
Q_ASSERT_INCRIT(220, m_ao.m_eQueue.m_nFree &lt; 0xFFU);
@ -6323,7 +6323,7 @@ if (m_ao.m_eQueue.m_nFree == 0U) {
}
// is the mutex locked by this thread already (nested locking)?
else if (m_ao.m_osObject == curr) {
// the nesting level must not exceed the specified limit
// the nesting level must not exceed the specified bound
Q_ASSERT_INCRIT(320, m_ao.m_eQueue.m_nFree &lt; 0xFFU);
// lock one more level
@ -6677,7 +6677,7 @@ else { // starting QXThread
<!--${QXK-extern-C::QXK_sched_}-->
<operation name="QXK_sched_" type="std::uint_fast8_t" visibility="0x00" properties="0x00">
<specifiers>noexcept</specifiers>
<code>Q_REQUIRE_INCRIT(402,
<code>Q_INVARIANT_INCRIT(402,
QXK_priv_.readySet.verify_(&amp;QXK_priv_.readySet_dis));
std::uint_fast8_t p;
@ -6756,6 +6756,7 @@ std::uint_fast8_t p = next-&gt;getPrio();
do {
QXK_priv_.actPrio = p; // next active prio
QF_MEM_APP();
QF_INT_ENABLE(); // unconditionally enable interrupts
QP::QEvt const * const e = next-&gt;get_();
@ -6771,7 +6772,7 @@ do {
QF_MEM_SYS();
// check internal integrity (duplicate inverse storage)
Q_ASSERT_INCRIT(502,
Q_INVARIANT_INCRIT(502,
QXK_priv_.readySet.verify_(&amp;QXK_priv_.readySet_dis));
if (next-&gt;getEQueue().isEmpty()) { // empty queue?
@ -8454,11 +8455,9 @@ if (QS_GLB_CHECK_(rec_) &amp;&amp; QS_LOC_CHECK_(qsId_)) { \
#define QP_HPP_
//============================================================================
#define QP_VERSION 733U
#define QP_VERSION_STR &quot;7.3.3&quot;
//! Encrypted current QP release (7.3.3) and date (2024-03-01)
#define QP_RELEASE 0x70C4F752U
#define QP_VERSION_STR &quot;7.3.5-rc.1&quot;
#define QP_VERSION 735U
#define QP_RELEASE 0x70A1DEF0U
//============================================================================
//! @cond INTERNAL
@ -10871,7 +10870,7 @@ void target_info_pre_(std::uint8_t const isReset) {
QS::u8_raw_(QS_OBJ_PTR_SIZE | (QS_FUN_PTR_SIZE &lt;&lt; 4U));
QS::u8_raw_(QS_TIME_SIZE);
// send the limits...
// send the bounds...
QS::u8_raw_(QF_MAX_ACTIVE);
QS::u8_raw_(QF_MAX_EPOOL | (QF_MAX_TICK_RATE &lt;&lt; 4U));

View File

@ -172,27 +172,27 @@ void QHsm::init(
QF_CRIT_EXIT();
// drill down into the state hierarchy with initial transitions...
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
do {
QStateHandler path[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));
while (m_temp.fun != t) {
// note: ip is here the fixed upper loop bound
while ((m_temp.fun != t) && (ip < (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();
// The initial transition source state must be reached
// Too many state nesting levels or "malformed" HSM.
Q_ASSERT_INCRIT(220, m_temp.fun == t);
// too many state nesting levels or "malformed" HSM
Q_ENSURE_INCRIT(220, ip < 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)
@ -220,14 +220,9 @@ void QHsm::init(
QS_CRIT_EXIT();
}
#endif // Q_SPY
--limit;
} while ((r == Q_RET_TRAN) && (limit > 0));
} while (r == Q_RET_TRAN);
QF_CRIT_ENTRY();
// Loop limit must not be reached.
// Too many state nesting levels or likely "malformed" HSM
Q_ENSURE_INCRIT(290, limit > 0);
QS_MEM_SYS();
QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId)
@ -259,9 +254,9 @@ void QHsm::dispatch(
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(300, (s != Q_STATE_CAST(0))
Q_INVARIANT_INCRIT(302, (s != Q_STATE_CAST(0))
&& (m_state.uint == static_cast<std::uintptr_t>(~m_temp.uint)));
Q_REQUIRE_INCRIT(302, QEvt::verify_(e));
Q_INVARIANT_INCRIT(303, QEvt::verify_(e));
QS_MEM_SYS();
QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId)
@ -277,7 +272,7 @@ void QHsm::dispatch(
// process the event hierarchically...
QState r;
m_temp.fun = s;
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
std::int_fast8_t ip = MAX_NEST_DEPTH_; // fixed upper loop bound
do {
s = m_temp.fun;
r = (*s)(this, e); // invoke state handler s
@ -297,11 +292,11 @@ void QHsm::dispatch(
r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); // superstate of s
}
--limit;
} while ((r == Q_RET_SUPER) && (limit > 0));
--ip;
} while ((r == Q_RET_SUPER) && (ip > 0));
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(310, limit > 0);
Q_ENSURE_INCRIT(310, ip > 0);
QF_CRIT_EXIT();
if (r >= Q_RET_TRAN) { // regular tran. taken?
@ -312,21 +307,21 @@ void QHsm::dispatch(
path[2] = s; // tran. source
// exit current state to tran. source s...
limit = MAX_NEST_DEPTH_; // loop hard limit
for (; (t != s) && (limit > 0); t = m_temp.fun) {
ip = 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));
}
--limit;
--ip;
}
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(320, limit > 0);
Q_ENSURE_INCRIT(320, ip > 0);
QF_CRIT_EXIT();
std::int_fast8_t ip = hsm_tran(path, qsId); // take the tran.
ip = hsm_tran(path, qsId); // take the tran.
#ifdef Q_SPY
if (r == Q_RET_TRAN_HIST) {
@ -343,6 +338,7 @@ void QHsm::dispatch(
#endif // Q_SPY
// 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)
@ -373,6 +369,7 @@ void QHsm::dispatch(
// 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 < (MAX_NEST_DEPTH_ - 1))) {
++ip;
path[ip] = m_temp.fun;
@ -381,14 +378,14 @@ void QHsm::dispatch(
QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG));
}
QF_CRIT_ENTRY();
// The initial transition source state must be reached.
// Too many state nesting levels or "malformed" HSM.
Q_ASSERT_INCRIT(330, m_temp.fun == t);
// too many state nesting levels or "malformed" HSM
Q_ENSURE_INCRIT(330, ip < 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)
@ -452,17 +449,17 @@ void QHsm::dispatch(
bool QHsm::isIn(QStateHandler const state) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(602, m_state.uint
== static_cast<std::uintptr_t>(~m_temp.uint));
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 limit = MAX_NEST_DEPTH_ + 1; // loop hard limit
std::int_fast8_t lbound = MAX_NEST_DEPTH_ + 1; // fixed upper loop bound
QState r = Q_RET_SUPER;
for (; (r != Q_RET_IGNORED) && (limit > 0); --limit) {
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
@ -474,7 +471,7 @@ bool QHsm::isIn(QStateHandler const state) noexcept {
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(690, limit > 0);
Q_ENSURE_INCRIT(690, lbound > 0);
QF_CRIT_EXIT();
#ifndef Q_UNSAFE
@ -486,12 +483,13 @@ bool QHsm::isIn(QStateHandler const state) noexcept {
//${QEP::QHsm::childState} ...................................................
QStateHandler QHsm::childState(QStateHandler const parent) noexcept {
QStateHandler child = m_state.fun; // start with the current state
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 = MAX_NEST_DEPTH_; // fixed upper loop bound
do {
// is this the parent of the current child?
if (m_temp.fun == parent) {
@ -502,7 +500,9 @@ QStateHandler QHsm::childState(QStateHandler const parent) noexcept {
child = m_temp.fun;
r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG);
}
} while (r != Q_RET_IGNORED); // QHsm::top() state not reached
--lbound;
} while ((r != Q_RET_IGNORED) // QHsm::top() state not reached
&& (lbound > 0));
#ifndef Q_UNSAFE
m_temp.uint = ~m_state.uint;
@ -510,10 +510,12 @@ QStateHandler QHsm::childState(QStateHandler const parent) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(890, isFound);
// 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; // return the child
return child;
}
//${QEP::QHsm::hsm_tran} .....................................................
@ -577,6 +579,7 @@ std::int_fast8_t QHsm::hsm_tran(
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 < (MAX_NEST_DEPTH_ - 1)))
@ -593,9 +596,10 @@ std::int_fast8_t QHsm::hsm_tran(
}
}
QF_CRIT_ENTRY();
// Tran. source must be found within the nesting depth
// Too many state nesting levels or "malformed" HSM.
Q_ASSERT_INCRIT(510, r != Q_RET_SUPER);
// 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?
@ -611,6 +615,7 @@ std::int_fast8_t QHsm::hsm_tran(
// == 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
@ -627,7 +632,7 @@ std::int_fast8_t QHsm::hsm_tran(
// (g) check each source->super->...
// for each target->super...
r = Q_RET_IGNORED; // keep looping
std::int_fast8_t limit = MAX_NEST_DEPTH_;
std::int_fast8_t lbound = MAX_NEST_DEPTH_;
do {
// exit from t
if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG)
@ -652,10 +657,10 @@ std::int_fast8_t QHsm::hsm_tran(
}
} while (iq >= 0);
--limit;
} while ((r != Q_RET_HANDLED) && (limit > 0));
--lbound;
} while ((r != Q_RET_HANDLED) && (lbound > 0));
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(530, limit > 0);
Q_ASSERT_INCRIT(530, lbound > 0);
QF_CRIT_EXIT();
}
}

View File

@ -138,15 +138,15 @@ void QMsm::init(
m_state.obj = m_temp.tatbl->target;
// drill down into the state hierarchy with initial transitions...
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
std::int_fast8_t lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
do {
// execute the tran. table
r = execTatbl_(m_temp.tatbl, qsId);
--limit;
} while ((r >= Q_RET_TRAN_INIT) && (limit > 0));
--lbound;
} while ((r >= Q_RET_TRAN_INIT) && (lbound > 0));
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(290, limit > 0);
Q_ENSURE_INCRIT(290, lbound > 0);
QS_MEM_SYS();
QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId)
@ -177,9 +177,9 @@ void QMsm::dispatch(
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(300, (s != nullptr)
Q_INVARIANT_INCRIT(300, (s != nullptr)
&& (m_state.uint == static_cast<std::uintptr_t>(~m_temp.uint)));
Q_REQUIRE_INCRIT(302, QEvt::verify_(e));
Q_INVARIANT_INCRIT(302, QEvt::verify_(e));
QS_MEM_SYS();
QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId)
@ -194,7 +194,7 @@ void QMsm::dispatch(
// scan the state hierarchy up to the top state...
QState r;
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
std::int_fast8_t lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
do {
r = (*t->stateHandler)(this, e); // call state handler function
@ -227,10 +227,10 @@ void QMsm::dispatch(
t = t->superstate; // advance to the superstate
}
--limit;
} while ((t != nullptr) && (limit > 0));
--lbound;
} while ((t != nullptr) && (lbound > 0));
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(310, limit > 0);
Q_ASSERT_INCRIT(310, lbound > 0);
QF_CRIT_EXIT();
if (r >= Q_RET_TRAN) { // any kind of tran. taken?
@ -243,7 +243,7 @@ void QMsm::dispatch(
QF_CRIT_EXIT();
#endif // Q_SPY
limit = MAX_NEST_DEPTH_; // loop hard limit
lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
do {
// save the tran-action table before it gets clobbered
QMTranActTable const * const tatbl = m_temp.tatbl;
@ -310,11 +310,11 @@ void QMsm::dispatch(
}
t = s; // set target to the current state
--limit;
} while ((r >= Q_RET_TRAN) && (limit > 0));
--lbound;
} while ((r >= Q_RET_TRAN) && (lbound > 0));
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(320, limit > 0);
Q_ASSERT_INCRIT(320, lbound > 0);
QS_MEM_SYS();
QS_BEGIN_PRE_(QS_QEP_TRAN, qsId)
@ -375,8 +375,8 @@ 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 limit = MAX_NEST_DEPTH_; // loop hard limit
for (; (s != nullptr) && (limit > 0); --limit) {
std::int_fast8_t lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
for (; (s != nullptr) && (lbound > 0); --lbound) {
if (s->stateHandler == state) { // match found?
inState = true;
break;
@ -388,7 +388,7 @@ bool QMsm::isIn(QStateHandler const state) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(490, limit > 0);
Q_ENSURE_INCRIT(490, lbound > 0);
QF_CRIT_EXIT();
return inState;
@ -399,8 +399,8 @@ bool QMsm::isInState(QMState const * const stateObj) const noexcept {
bool inState = false; // assume that this SM is not in 'state'
QMState const *s = m_state.obj;
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
for (; (s != nullptr) && (limit > 0); --limit) {
std::int_fast8_t lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
for (; (s != nullptr) && (lbound > 0); --lbound) {
if (s == stateObj) { // match found?
inState = true;
break;
@ -412,7 +412,7 @@ bool QMsm::isInState(QMState const * const stateObj) const noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(590, limit > 0);
Q_ENSURE_INCRIT(590, lbound > 0);
QF_CRIT_EXIT();
return inState;
@ -424,9 +424,9 @@ QMState const * QMsm::childStateObj(QMState const * const parent) const noexcept
bool isFound = false; // start with the child not found
QMState const *s;
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
std::int_fast8_t lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
for (s = m_state.obj;
(s != nullptr) && (limit > 0);
(s != nullptr) && (lbound > 0);
s = s->superstate)
{
if (s == parent) {
@ -436,17 +436,17 @@ QMState const * QMsm::childStateObj(QMState const * const parent) const noexcept
else {
child = s;
}
--limit;
--lbound;
}
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(610, limit > 0);
Q_ASSERT_INCRIT(610, lbound > 0);
QF_CRIT_EXIT();
if (!isFound) { // still not found?
limit = MAX_NEST_DEPTH_; // loop hard limit
lbound = MAX_NEST_DEPTH_; // fixed upper loop bound
for (s = m_temp.obj;
(s != nullptr) && (limit > 0);
(s != nullptr) && (lbound > 0);
s = s->superstate)
{
if (s == parent) {
@ -456,12 +456,12 @@ QMState const * QMsm::childStateObj(QMState const * const parent) const noexcept
else {
child = s;
}
--limit;
--lbound;
}
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(690, isFound && (limit > 0));
Q_ENSURE_INCRIT(690, isFound && (lbound > 0));
QF_CRIT_EXIT();
return child; // return the child
@ -484,9 +484,9 @@ QState QMsm::execTatbl_(
QF_CRIT_EXIT();
QState r = Q_RET_NULL;
std::int_fast8_t limit = MAX_TRAN_LENGTH_; // loop hard limit
std::int_fast8_t lbound = MAX_TRAN_LENGTH_; // fixed upper loop bound
QActionHandler const *a = &tatbl->act[0];
for (; (*a != nullptr) && (limit > 0); ++a) {
for (; (*a != nullptr) && (lbound > 0); ++a) {
r = (*(*a))(this); // call the action through the 'a' pointer
#ifdef Q_SPY
QS_CRIT_ENTRY();
@ -530,7 +530,7 @@ QState QMsm::execTatbl_(
QS_MEM_APP();
QS_CRIT_EXIT();
#endif // Q_SPY
--limit;
--lbound;
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(790, *a == nullptr);
@ -556,8 +556,8 @@ void QMsm::exitToTranSource_(
// exit states from the current state to the tran. source state
QMState const *s = cs;
std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit
for (; (s != ts) && (limit > 0); --limit) {
std::int_fast8_t lbound = 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
@ -583,7 +583,7 @@ void QMsm::exitToTranSource_(
}
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(890, limit > 0);
Q_ENSURE_INCRIT(890, lbound > 0);
QF_CRIT_EXIT();
}

View File

@ -91,7 +91,7 @@ bool QActive::post_(
#ifndef Q_UNSAFE
std::uint8_t const pcopy = static_cast<std::uint8_t>(~m_prio_dis);
Q_REQUIRE_INCRIT(102, (QEvt::verify_(e)) && (m_prio == pcopy));
Q_INVARIANT_INCRIT(102, (QEvt::verify_(e)) && (m_prio == pcopy));
#endif
QEQueueCtr nFree = m_eQueue.m_nFree; // get volatile into temporary
@ -234,7 +234,7 @@ void QActive::postLIFO(QEvt const * const e) noexcept {
#ifndef Q_UNSAFE
std::uint8_t const pcopy = static_cast<std::uint8_t>(~m_prio_dis);
Q_REQUIRE_INCRIT(202, (QEvt::verify_(e)) && (m_prio == pcopy));
Q_INVARIANT_INCRIT(202, (QEvt::verify_(e)) && (m_prio == pcopy));
#endif
#ifdef QXK_HPP_

View File

@ -236,7 +236,7 @@ QEvt * newX_(
void gc(QEvt const * const e) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(402, QEvt::verify_(e));
Q_INVARIANT_INCRIT(402, QEvt::verify_(e));
std::uint_fast8_t const poolNum = e->getPoolNum_();
@ -300,7 +300,7 @@ QEvt const * newRef_(
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(502, QEvt::verify_(e));
Q_INVARIANT_INCRIT(502, QEvt::verify_(e));
std::uint_fast8_t const poolNum = e->getPoolNum_();
@ -329,7 +329,7 @@ void deleteRef_(QEvt const * const evtRef) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(602, QEvt::verify_(e));
Q_INVARIANT_INCRIT(602, QEvt::verify_(e));
#ifdef Q_SPY
std::uint_fast8_t const poolNum = e->getPoolNum_();

View File

@ -152,8 +152,8 @@ void * QMPool::get(
QFreeBlock * const fb_next = fb->m_next;
// the free block must have integrity (duplicate inverse storage)
Q_ASSERT_INCRIT(302, Q_UINTPTR_CAST_(fb_next)
== static_cast<std::uintptr_t>(~fb->m_next_dis));
Q_INVARIANT_INCRIT(302, Q_UINTPTR_CAST_(fb_next)
== static_cast<std::uintptr_t>(~fb->m_next_dis));
m_nFree = (m_nFree - 1U); // one free block less
if (m_nFree == 0U) { // is the pool becoming empty?
@ -230,7 +230,7 @@ void QMPool::put(
#endif
// set as new head of the free list
m_free_head = static_cast<QFreeBlock *>(block);
m_free_head = fb;
m_nFree = m_nFree + 1U; // one more free block in this pool

View File

@ -121,7 +121,7 @@ void QActive::publish_(
QF_MEM_SYS();
Q_REQUIRE_INCRIT(200, sig < static_cast<QSignal>(maxPubSignal_));
Q_REQUIRE_INCRIT(202,
Q_INVARIANT_INCRIT(202,
subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis));
QS_BEGIN_PRE_(QS_QF_PUBLISH, qsId)
@ -164,9 +164,9 @@ void QActive::publish_(
QF_SCHED_STAT_
QF_SCHED_LOCK_(p); // lock the scheduler up to AO's prio
std::uint_fast8_t limit = QF_MAX_ACTIVE + 1U;
std::uint_fast8_t lbound = QF_MAX_ACTIVE + 1U;
do { // loop over all subscribers
--limit;
--lbound;
// POST() asserts internally if the queue overflows
a->POST(e, sender);
@ -188,7 +188,7 @@ void QActive::publish_(
else {
p = 0U; // no more subscribers
}
} while ((p != 0U) && (limit > 0U));
} while ((p != 0U) && (lbound > 0U));
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(290, p == 0U);
@ -223,7 +223,7 @@ void QActive::subscribe(enum_t const sig) const noexcept {
&& (sig < maxPubSignal_)
&& (0U < p) && (p <= QF_MAX_ACTIVE)
&& (registry_[p] == this));
Q_REQUIRE_INCRIT(302,
Q_INVARIANT_INCRIT(302,
subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis));
QS_BEGIN_PRE_(QS_QF_ACTIVE_SUBSCRIBE, m_prio)
@ -260,7 +260,7 @@ void QActive::unsubscribe(enum_t const sig) const noexcept {
&& (sig < maxPubSignal_)
&& (0U < p) && (p <= QF_MAX_ACTIVE)
&& (registry_[p] == this));
Q_REQUIRE_INCRIT(402,
Q_INVARIANT_INCRIT(402,
subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis));
QS_BEGIN_PRE_(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio)

View File

@ -300,8 +300,8 @@ void QTimeEvt::tick(
QS_END_PRE_()
// scan the linked-list of time events at this rate...
std::uint_fast8_t limit = 2U*QF_MAX_ACTIVE; // loop hard limit
for (; limit > 0U; --limit) {
std::uint_fast8_t lbound = 2U*QF_MAX_ACTIVE; // fixed upper loop bound
for (; lbound > 0U; --lbound) {
QTimeEvt *e = prev->m_next; // advance down the time evt. list
if (e == nullptr) { // end of the list?
@ -321,7 +321,7 @@ void QTimeEvt::tick(
}
// the time event 'e' must be valid
Q_ASSERT_INCRIT(112, QEvt::verify_(e));
Q_INVARIANT_INCRIT(112, QEvt::verify_(e));
if (e->m_ctr == 0U) { // time event scheduled for removal?
prev->m_next = e->m_next;
@ -410,7 +410,7 @@ void QTimeEvt::tick(
QF_MEM_SYS();
}
Q_ENSURE_INCRIT(190, limit > 0U);
Q_ENSURE_INCRIT(190, lbound > 0U);
QF_MEM_APP();
QF_CRIT_EXIT();
}

View File

@ -79,7 +79,7 @@ QSchedStatus schedLock(std::uint_fast8_t const ceiling) noexcept {
QF_MEM_SYS();
Q_REQUIRE_INCRIT(100, !QK_ISR_CONTEXT_());
Q_REQUIRE_INCRIT(102, QK_priv_.lockCeil
Q_INVARIANT_INCRIT(102, QK_priv_.lockCeil
== static_cast<std::uint_fast8_t>(~QK_priv_.lockCeil_dis));
// first store the previous lock prio
@ -119,7 +119,7 @@ void schedUnlock(QSchedStatus const prevCeil) noexcept {
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(202, QK_priv_.lockCeil
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));
@ -161,7 +161,7 @@ QK_Attr QK_priv_;
std::uint_fast8_t QK_sched_() noexcept {
// NOTE: this function is entered with interrupts DISABLED
Q_REQUIRE_INCRIT(402,
Q_INVARIANT_INCRIT(402,
QK_priv_.readySet.verify_(&QK_priv_.readySet_dis));
std::uint_fast8_t p;
@ -172,7 +172,7 @@ std::uint_fast8_t QK_sched_() noexcept {
// find the highest-prio AO with non-empty event queue
p = QK_priv_.readySet.findMax();
Q_ASSERT_INCRIT(412, QK_priv_.actThre
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?
@ -180,7 +180,7 @@ std::uint_fast8_t QK_sched_() noexcept {
p = 0U; // no activation needed
}
else {
Q_ASSERT_INCRIT(422, QK_priv_.lockCeil
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?
@ -188,7 +188,7 @@ std::uint_fast8_t QK_sched_() noexcept {
p = 0U; // no activation needed
}
else {
Q_ASSERT_INCRIT(432, QK_priv_.nextPrio
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
@ -209,7 +209,7 @@ void QK_activate_() noexcept {
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_REQUIRE_INCRIT(502,
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)
@ -234,7 +234,7 @@ void QK_activate_() noexcept {
Q_ASSERT_INCRIT(510, a != nullptr);
pthre_in = static_cast<std::uint_fast8_t>(a->getPThre());
Q_ASSERT_INCRIT(511, pthre_in == static_cast<std::uint_fast8_t>(
Q_INVARIANT_INCRIT(511, pthre_in == static_cast<std::uint_fast8_t>(
~static_cast<std::uint_fast8_t>(a->m_pthre_dis) & 0xFFU));
}
@ -244,7 +244,7 @@ void QK_activate_() noexcept {
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_ASSERT_INCRIT(522, pthre == static_cast<std::uint_fast8_t>(
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
@ -272,6 +272,7 @@ void QK_activate_() noexcept {
}
#endif // QF_ON_CONTEXT_SW || Q_SPY
QF_MEM_APP();
QF_INT_ENABLE(); // unconditionally enable interrupts
QP::QEvt const * const e = a->get_();
@ -288,7 +289,7 @@ void QK_activate_() noexcept {
QF_MEM_SYS();
// internal integrity check (duplicate inverse storage)
Q_ASSERT_INCRIT(532,
Q_INVARIANT_INCRIT(532,
QK_priv_.readySet.verify_(&QK_priv_.readySet_dis));
if (a->getEQueue().isEmpty()) { // empty queue?
@ -310,7 +311,7 @@ void QK_activate_() noexcept {
p = 0U; // no activation needed
}
else {
Q_ASSERT_INCRIT(542,
Q_INVARIANT_INCRIT(542,
QK_priv_.lockCeil == ~QK_priv_.lockCeil_dis);
// is the AO's prio. below the lock preemption-threshold?

View File

@ -998,7 +998,7 @@ void target_info_pre_(std::uint8_t const isReset) {
QS::u8_raw_(QS_OBJ_PTR_SIZE | (QS_FUN_PTR_SIZE << 4U));
QS::u8_raw_(QS_TIME_SIZE);
// send the limits...
// send the bounds...
QS::u8_raw_(QF_MAX_ACTIVE);
QS::u8_raw_(QF_MAX_EPOOL | (QF_MAX_TICK_RATE << 4U));

View File

@ -81,7 +81,7 @@ void schedDisable(std::uint_fast8_t const ceiling) {
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_ASSERT_INCRIT(102, priv_.schedCeil
Q_INVARIANT_INCRIT(102, priv_.schedCeil
== static_cast<std::uint_fast8_t>(~priv_.schedCeil_dis));
if (ceiling > priv_.schedCeil) { // raising the scheduler ceiling?
@ -108,7 +108,7 @@ void schedEnable() {
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_ASSERT_INCRIT(202, priv_.schedCeil
Q_INVARIANT_INCRIT(202, priv_.schedCeil
== static_cast<std::uint_fast8_t>(~priv_.schedCeil_dis));
if (priv_.schedCeil != 0U) { // actually enabling the scheduler?
@ -186,10 +186,10 @@ int_t run() {
for (;;) { // QV event loop...
// check internal integrity (duplicate inverse storage)
Q_ASSERT_INCRIT(302,
Q_INVARIANT_INCRIT(302,
QV::priv_.readySet.verify_(&QV::priv_.readySet_dis));
// check internal integrity (duplicate inverse storage)
Q_ASSERT_INCRIT(303, QV::priv_.schedCeil
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

View File

@ -175,7 +175,7 @@ QXK_Attr QXK_priv_;
//${QXK-extern-C::QXK_sched_} ................................................
std::uint_fast8_t QXK_sched_() noexcept {
Q_REQUIRE_INCRIT(402,
Q_INVARIANT_INCRIT(402,
QXK_priv_.readySet.verify_(&QXK_priv_.readySet_dis));
std::uint_fast8_t p;
@ -254,6 +254,7 @@ void QXK_activate_() noexcept {
do {
QXK_priv_.actPrio = p; // next active prio
QF_MEM_APP();
QF_INT_ENABLE(); // unconditionally enable interrupts
QP::QEvt const * const e = next->get_();
@ -269,7 +270,7 @@ void QXK_activate_() noexcept {
QF_MEM_SYS();
// check internal integrity (duplicate inverse storage)
Q_ASSERT_INCRIT(502,
Q_INVARIANT_INCRIT(502,
QXK_priv_.readySet.verify_(&QXK_priv_.readySet_dis));
if (next->getEQueue().isEmpty()) { // empty queue?

View File

@ -165,7 +165,7 @@ bool QXMutex::lock(QTimeEvtCtr const nTicks) noexcept {
// is the mutex locked by this thread already (nested locking)?
else if (m_ao.m_osObject == curr) {
// the nesting level beyond the arbitrary but high limit
// the nesting level beyond the arbitrary but high bound
// most likely means cyclic or recursive locking of a mutex.
Q_ASSERT_INCRIT(220, m_ao.m_eQueue.m_nFree < 0xFFU);
@ -312,7 +312,7 @@ bool QXMutex::tryLock() noexcept {
}
// is the mutex locked by this thread already (nested locking)?
else if (m_ao.m_osObject == curr) {
// the nesting level must not exceed the specified limit
// the nesting level must not exceed the specified bound
Q_ASSERT_INCRIT(320, m_ao.m_eQueue.m_nFree < 0xFFU);
// lock one more level