This commit is contained in:
MMS 2025-01-18 18:33:40 -05:00
parent 2b1661fdce
commit df116c8410
104 changed files with 2465 additions and 11396 deletions

View File

@ -9,8 +9,8 @@ Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
The QP/C++ software is dual-licensed under the terms of the open-source
GNU General Public License (GPL) or under the terms of one of the closed-
This software is dual-licensed under the terms of the open-source GNU
General Public License (GPL) or under the terms of one of the closed-
source Quantum Leaps commercial licenses.
Redistributions in source code must retain this top-level comment block.
@ -25,4 +25,4 @@ closed-source distribution.
Quantum Leaps contact information:
<www.state-machine.com/licensing>
<info@state-machine.com>
#48B37CF39D4FD9DE279250B31FD388AFD0BE9B40
#E73B85325051C864FE0E4C672EF7577CB16A80DA

122
README.md
View File

@ -16,6 +16,39 @@ git clone https://github.com/QuantumLeaps/qpcpp --recurse-submodules --depth 1
Alternatively, you can also download one of the stable
[QP/C++ Releases][QP-Rel].
# About QP/C++ Real-Time Embedded Framework
QP/C++ real-time embedded framework (RTEF) is a lightweight implementation of
the [Active Object (a.k.a. Actor) model of computation][AOmod] specifically
tailored for deeply embedded real-time systems, such as microcontrollers (MCUs).
QP/C++ is both a software infrastructure for building applications consisting
of Active Objects (Actors) and a runtime environment for executing the Active
Objects in a deterministic, real-time fashion. Additionally, QP/C++ Framework
supports Hierarchical State Machines with which to specify the behavior of
Active Objects [UML 2.5], [Sutter:10], [ROOM:94]. The QP/C++ Framework can be
viewed as a modern, asynchronous, and truly event driven real-time operating
system (RTOS).
## QP Framework Family
QP/C++ framework is part of the larger QP family consisting of the following
QP editions:
|QP Edition | Language | API | Safety Functions |Certification Artifacts| Licensing
|:----------|:-----------:|:-----------------|:-------------------|:----------------|:---------
| QP/C | C (C11) |same as SafeQP/C |Selected Assertions |Req/Arch/Design | [dual][Lic]
| SafeQP/C | C (C11) |same as QP/C |All Safety Functions|Certification Kit| [commercial][Com]
| QP/C++ | C++ (C++17) |same as SafeQP/C++|Selected Assertions |Req/Arch/Design | [dual][Lic]
| SafeQP/C++| C++ (C++17) |same as QP/C++ |All Safety Functions|Certification Kit| [commercial][Com]
[The documentation](#documentation) of all QP editions includes the
[Requirements][SRS], [Architecture][SAS], and [Design Specifications][SDS],
which are the best source of information about the underlying concepts,
functionality, architecture, and design of the QP Frameworks and the QP
Applications based on the frameworks.
> **NOTE:** The **SafeQP** frameworks additionally contain **Safety Functions**
required to achieve the higher safety integrity levels and come with much more
extensive [Certification Kits][Cert].
# Getting Started with QP/C++
The most recommended way of obtaining QP/C++ is by downloading the
@ -25,7 +58,7 @@ The main advantage of obtaining QP/C++ bundled together like that is
that you get all components, tools and examples ready to go.
### Getting Started Resources
- ["QP/C++ Tutorial"][Tutorial]
- ["QP/C++ Tutorial"][Tut]
describes a series of progressively advanced QP/C++ example applications.
- [Video: "Getting Started with QP Real-Time Embedded Frameworks"][Video]
@ -67,69 +100,11 @@ have been **removed from the open-source GPL distribution**:
the active Support Term. Please contact [Quantum Leaps technical support][Sup]
to get the complete QP/C++ framework distribution.
> NOTE: To request **evaluation** of the complete QP/C++ framework, please contact
> **NOTE:** To request **evaluation** of the complete QP/C++ framework, please contact
Quantum Leaps at: https://www.state-machine.com/contact
# About QP/C++
QP/C++ (Quantum Platform in C++) is a lightweight, open source
[Real-Time Embedded Framework (RTEF)][RTEF] for building modern embedded
software as systems of asynchronous, event-driven [Active Objects][Active]
(actors). The [QP/C++] framework is a member of a [QP] family consisting of
[QP/C++] and [QP/C] frameworks, which are strictly quality controlled,
thoroughly documented, and [commercially licensable][Lic].
## Safer Model of Concurrency
The [QP] framework family implements the
[Active Object model of computation][AO_model], which is **inherently safer**
than the traditional "shared state concurrency" based on explicit mutual
exclusion and managing RTOS threads by blocking. The Active Object model
supports and automatically enforces the following best practices
of concurrent programming:
- Keep data isolated and bound to Active Objects' threads. Threads should
hide (**encapsulate**) their private data and other resources, and not
share them with the rest of the system.
- Communicate among Active Object threads **asynchronously** via [Event
objects][Event]. Using asynchronous events keeps the threads running truly
independently, **without blocking** on each other.
- Active Object threads should spend their lifetime responding to incoming
events, so their mainline should consist of an **event-loop** that handles
events one at a time (to completion), thus avoiding any concurrency hazards
within an Active Object thread itself.
This architecture also provides higher level of abstraction and the *correct*
abstractions to effectively apply [Hierarchical State Machines][HSM],
**modeling** and **code generation** to deeply embedded real-time systems.
## Hierarchical State Machines
The behavior of Active Objects is specified in QP/C++ by means of
[Hierarchical State Machines][HSM] (UML statecharts). The framework
supports manual coding of UML state machines in C as well as automatic
**code generation** by means of the free [QM modeling tool][QM].
## Built-in Real-Time Kernels
The QP/C++ framework can run on standalone on single-chip microcontrollers,
without any traditional RTOS. The framework contains a selection of
**built-in real-time kernels**, such as the [non-preemptive QV kernel][QV],
the [preemptive non-blocking QK kernel][QK], and the preemptive,
[dual-mode QXK kernel][QXK] that provides all the features you might expect
from a traditional RTOS. Native QP ports and ready-to-use examples are provided
for major CPUs, such as ARM Cortex-M (M0/M0+/M3/M4/M7/M23/M33/...).
## Traditional RTOS/OS
QP/C++ can also work with a traditional RTOS, such as ThreadX, embOS, FreeRTOS,
uC/OS-II and Zephyr, as well as with (embedded) Linux (POSIX) and Windows.
## Popularity and Maturity
With 20 years of continuous development, [400+ commercial licensees][Cust],
and many times more open source users worldwide, the QP frameworks are the
most popular such offering on the market. They power countless electronic
products ranging from implantable medical devices to complex weapon systems.
# QP/C++ Documentation
# Documentation
The online HTML documentation for the **latest** version of QP/C++ is located
at: https://www.state-machine.com/qpcpp
@ -159,20 +134,25 @@ If you like this project, please give it a star (in the upper-right corner of yo
[QP]: <https://www.state-machine.com/products/qp>
[QP/C]: <https://github.com/QuantumLeaps/qpc>
[QP/C++]: <https://github.com/QuantumLeaps/qpcpp>
[QS/C++]: <https://www.state-machine.com/qpcpp/srs-qp_qs.html>
[QV]: <https://www.state-machine.com/qpcpp/srs-qp_qv.html>
[QK]: <https://www.state-machine.com/qpcpp/srs-qp_qk.html>
[QXK]: <https://www.state-machine.com/qpcpp/srs-qp_qxk.html>
[Cert]: <https://www.state-machine.com/products/qp#CERT>
[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>
[Com]: <https://www.state-machine.com/licensing#Commercial>
[Cust]: <https://www.state-machine.com/customers>
[Sup]: <mailto:support@state-machine.com>
[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>
[QS]: <https://www.state-machine.com/qpcpp/srs-qp_qs.html>
[QV]: <https://www.state-machine.com/qpcpp/srs-qp_qv.html>
[QK]: <https://www.state-machine.com/qpcpp/srs-qp_qk.html>
[QXK]: <https://www.state-machine.com/qpcpp/srs-qp_qxk.html>
[SRS]: <https://www.state-machine.com/qpcpp/srs-qp.html>
[SAS]: <https://www.state-machine.com/qpcpp/sas-qp.html>
[SDS]: <https://www.state-machine.com/qpcpp/sds-qp.html>
[Active]: <https://www.state-machine.com/qpcpp/srs-qp_ao.html>
[AOmod]: <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>
[Tut]: <https://www.state-machine.com/qpcpp/gs_tut.html>
[QP-Rel]: <https://github.com/QuantumLeaps/qpcpp/releases>

@ -1 +1 @@
Subproject commit 01aad80e4c6f69089ecf7ddc328cad2870505a6e
Subproject commit f8e601d60a88d04bd49e01bb725efd6e13131c1a

View File

@ -1,10 +1,6 @@
//$file${include::qequeue.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${include::qequeue.hpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${include::qequeue.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#ifndef QEQUEUE_HPP_
#define QEQUEUE_HPP_
@ -46,17 +41,16 @@ namespace QP {
#elif (QF_EQUEUE_CTR_SIZE == 2U)
using QEQueueCtr = std::uint16_t;
#else
#error "QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1U or 2U"
#error QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1U or 2U
#endif
class QEvt; // forward declaration
} // namespace QP
//$declare${QF::QEQueue} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//============================================================================
namespace QP {
//${QF::QEQueue} .............................................................
class QEQueue {
private:
QEvt const * volatile m_frontEvt;
@ -65,22 +59,6 @@ private:
QEQueueCtr volatile m_head;
QEQueueCtr volatile m_tail;
QEQueueCtr volatile m_nFree;
#ifndef Q_UNSAFE
std::uintptr_t m_frontEvt_dis;
#endif // ndef Q_UNSAFE
#ifndef Q_UNSAFE
QEQueueCtr m_head_dis;
#endif // ndef Q_UNSAFE
#ifndef Q_UNSAFE
QEQueueCtr m_tail_dis;
#endif // ndef Q_UNSAFE
#ifndef Q_UNSAFE
QEQueueCtr m_nFree_dis;
#endif // ndef Q_UNSAFE
QEQueueCtr m_nMin;
// friends...
@ -97,16 +75,10 @@ public:
m_head(0U),
m_tail(0U),
m_nFree(0U),
#ifndef Q_UNSAFE
m_frontEvt_dis(static_cast<std::uintptr_t>(~0U)),
m_head_dis(static_cast<QEQueueCtr>(~0U)),
m_tail_dis(static_cast<QEQueueCtr>(~0U)),
m_nFree_dis(static_cast<QEQueueCtr>(~0U)),
#endif
m_nMin(0U)
{}
void init(
QEvt const * qSto[],
QEvt const * * const qSto,
std::uint_fast16_t const qLen) noexcept;
bool post(
QEvt const * const e,
@ -120,11 +92,7 @@ public:
return m_nFree;
}
QEQueueCtr getNMin() const noexcept {
#ifndef Q_UNSAFE
return m_nMin;
#else
return 0U;
#endif
}
bool isEmpty() const noexcept {
return m_frontEvt == nullptr;
@ -133,9 +101,11 @@ public:
private:
QEQueue(QEQueue const & other) = delete;
QEQueue & operator=(QEQueue const & other) = delete;
void postFIFO_(
QEvt const * const e,
void const * const sender);
}; // class QEQueue
} // namespace QP
//$enddecl${QF::QEQueue} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#endif // QEQUEUE_HPP_

View File

@ -1,10 +1,6 @@
//$file${include::qk.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${include::qk.hpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,41 +26,19 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${include::qk.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#ifndef QK_HPP_
#define QK_HPP_
//$declare${QK::QSchedStatus} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QK::QSchedStatus} ........................................................
using QSchedStatus = std::uint_fast8_t;
} // namespace QP
//$enddecl${QK::QSchedStatus} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$declare${QK::QK-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
namespace QK {
//${QK::QK-base::schedLock} ..................................................
QSchedStatus schedLock(std::uint_fast8_t const ceiling) noexcept;
//${QK::QK-base::schedUnlock} ................................................
void schedUnlock(QSchedStatus const prevCeil) noexcept;
//${QK::QK-base::onIdle} .....................................................
void onIdle();
} // namespace QK
} // namespace QP
//$enddecl${QK::QK-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
extern "C" {
//$declare${QK-extern-C} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${QK-extern-C::QK_Attr} ....................................................
class QK_Attr {
public:
QP::QPSet readySet;
@ -73,49 +47,37 @@ public:
std::uint_fast8_t actThre;
std::uint_fast8_t lockCeil;
std::uint_fast8_t intNest;
#ifndef Q_UNSAFE
QP::QPSet readySet_dis;
#endif // ndef Q_UNSAFE
#ifndef Q_UNSAFE
std::uint_fast8_t actPrio_dis;
#endif // ndef Q_UNSAFE
#ifndef Q_UNSAFE
std::uint_fast8_t nextPrio_dis;
#endif // ndef Q_UNSAFE
#ifndef Q_UNSAFE
std::uint_fast8_t actThre_dis;
#endif // ndef Q_UNSAFE
#ifndef Q_UNSAFE
std::uint_fast8_t lockCeil_dis;
#endif // ndef Q_UNSAFE
}; // class QK_Attr
//${QK-extern-C::QK_priv_} ...................................................
extern QK_Attr QK_priv_;
//${QK-extern-C::QK_sched_} ..................................................
std::uint_fast8_t QK_sched_() noexcept;
//${QK-extern-C::QK_activate_} ...............................................
std::uint_fast8_t QK_sched_act_(
QP::QActive const * const act,
std::uint_fast8_t const pthre_in) noexcept;
void QK_activate_() noexcept;
//$enddecl${QK-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
} // extern "C"
//============================================================================
namespace QP {
namespace QK {
QSchedStatus schedLock(std::uint_fast8_t const ceiling) noexcept;
void schedUnlock(QSchedStatus const prevCeil) noexcept;
void onIdle();
} // namespace QK
} // namespace QP
//============================================================================
// interface used only for internal implementation, but not in applications
#ifdef QP_IMPL
//$declare${QK-impl} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${QK-impl::QF_SCHED_STAT_} .................................................
// scheduler locking for QK...
#define QF_SCHED_STAT_ QSchedStatus lockStat_;
//${QK-impl::QF_SCHED_LOCK_} .................................................
#define QF_SCHED_LOCK_(ceil_) do { \
if (QK_ISR_CONTEXT_()) { \
lockStat_ = 0xFFU; \
@ -124,32 +86,14 @@ void QK_activate_() noexcept;
} \
} while (false)
//${QK-impl::QF_SCHED_UNLOCK_} ...............................................
#define QF_SCHED_UNLOCK_() do { \
if (lockStat_ != 0xFFU) { \
QK::schedUnlock(lockStat_); \
} \
} while (false)
//${QK-impl::QACTIVE_EQUEUE_WAIT_} ...........................................
// QActive event queue customization for QK...
#define QACTIVE_EQUEUE_WAIT_(me_) (static_cast<void>(0))
//${QK-impl::QACTIVE_EQUEUE_SIGNAL_} .........................................
#ifndef Q_UNSAFE
#define QACTIVE_EQUEUE_SIGNAL_(me_) do { \
QK_priv_.readySet.insert( \
static_cast<std::uint_fast8_t>((me_)->m_prio)); \
QK_priv_.readySet.update_(&QK_priv_.readySet_dis); \
if (!QK_ISR_CONTEXT_()) { \
if (QK_sched_() != 0U) { \
QK_activate_(); \
} \
} \
} while (false)
#endif // ndef Q_UNSAFE
//${QK-impl::QACTIVE_EQUEUE_SIGNAL_} .........................................
#ifdef Q_UNSAFE
#define QACTIVE_EQUEUE_SIGNAL_(me_) do { \
QK_priv_.readySet.insert( \
static_cast<std::uint_fast8_t>((me_)->m_prio)); \
@ -159,28 +103,15 @@ void QK_activate_() noexcept;
} \
} \
} while (false)
#endif // def Q_UNSAFE
//$enddecl${QK-impl} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$declare${QF_EPOOL-impl} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${QF_EPOOL-impl::QF_EPOOL_TYPE_} ...........................................
// QF event pool customization for QK...
#define QF_EPOOL_TYPE_ QMPool
//${QF_EPOOL-impl::QF_EPOOL_INIT_} ...........................................
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \
(p_).init((poolSto_), (poolSize_), (evtSize_))
//${QF_EPOOL-impl::QF_EPOOL_EVENT_SIZE_} .....................................
#define QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize())
//${QF_EPOOL-impl::QF_EPOOL_GET_} ............................................
#define QF_EPOOL_GET_(p_, e_, m_, qsId_) \
((e_) = static_cast<QEvt *>((p_).get((m_), (qsId_))))
//${QF_EPOOL-impl::QF_EPOOL_PUT_} ............................................
#define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_)))
//$enddecl${QF_EPOOL-impl} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#endif // QP_IMPL

View File

@ -1,10 +1,6 @@
//$file${include::qmpool.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${include::qmpool.hpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${include::qmpool.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#ifndef QMPOOL_HPP_
#define QMPOOL_HPP_
@ -42,6 +37,12 @@
#define QF_MPOOL_CTR_SIZE 2U
#endif
#define QF_MPOOL_EL(evType_) struct { \
void * sto_[((sizeof(evType_) - 1U) / sizeof(void *)) + \
(sizeof(evType_) < (2U * sizeof(void *)) ? 2U : 1U)]; \
}
//============================================================================
namespace QP {
#if (QF_MPOOL_SIZ_SIZE == 1U)
@ -51,7 +52,7 @@ namespace QP {
#elif (QF_MPOOL_SIZ_SIZE == 4U)
using QMPoolSize = std::uint32_t;
#else
#error "QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U"
#error QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U
#endif
#if (QF_MPOOL_CTR_SIZE == 1U)
@ -61,54 +62,22 @@ namespace QP {
#elif (QF_MPOOL_CTR_SIZE == 4U)
using QMPoolCtr = std::uint32_t;
#else
#error "QF_MPOOL_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U"
#error QF_MPOOL_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U
#endif
} // namespace QP
#define QF_MPOOL_EL(evType_) struct { \
QP::QFreeBlock sto_[((sizeof(evType_) - 1U) / (2U * sizeof(void *))) + 1U]; \
}
//$declare${QF::QFreeBlock} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QFreeBlock} ..........................................................
class QFreeBlock {
private:
QFreeBlock * m_next;
#ifndef Q_UNSAFE
std::uintptr_t m_next_dis;
#endif // ndef Q_UNSAFE
friend class QMPool;
}; // class QFreeBlock
} // namespace QP
//$enddecl${QF::QFreeBlock} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$declare${QF::QMPool} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QMPool} ..............................................................
//============================================================================
class QMPool {
private:
QFreeBlock * m_start;
QFreeBlock * m_end;
QFreeBlock * volatile m_free_head;
void * * m_start;
void * * m_end;
void * * volatile m_freeHead;
QMPoolSize m_blockSize;
QMPoolCtr m_nTot;
QMPoolCtr volatile m_nFree;
#ifndef Q_UNSAFE
QMPoolCtr m_nMin;
#endif // ndef Q_UNSAFE
#ifndef Q_UNSAFE
std::uintptr_t m_free_head_dis;
#endif // ndef Q_UNSAFE
#ifndef Q_UNSAFE
std::uintptr_t m_freeHead_dis;
QMPoolCtr m_nFree_dis;
#endif // ndef Q_UNSAFE
@ -116,13 +85,13 @@ public:
QMPool()
: m_start(nullptr),
m_end(nullptr),
m_free_head(nullptr),
m_freeHead(nullptr),
m_blockSize(0U),
m_nTot(0U),
m_nFree(0U)
m_nFree(0U),
m_nMin(0U)
#ifndef Q_UNSAFE
,m_nMin(0U),
m_free_head_dis(static_cast<std::uintptr_t>(~0U)),
,m_freeHead_dis(static_cast<std::uintptr_t>(~0U)),
m_nFree_dis(static_cast<QEQueueCtr>(~0U))
#endif
{}
@ -136,7 +105,9 @@ public:
void put(
void * const block,
std::uint_fast8_t const qsId) noexcept;
QMPoolSize getBlockSize() const noexcept;
QMPoolSize getBlockSize() const noexcept {
return m_blockSize;
}
QMPoolCtr getNMin() const noexcept {
#ifndef Q_UNSAFE
return m_nMin;
@ -168,6 +139,5 @@ public:
}; // class QMPool
} // namespace QP
//$enddecl${QF::QMPool} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#endif // QMPOOL_HPP_

View File

@ -1,10 +1,6 @@
//$file${include::qp.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${include::qp.hpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,17 +26,18 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${include::qp.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#ifndef QP_HPP_
#define QP_HPP_
//============================================================================
#define QP_VERSION_STR "8.0.1"
#define QP_VERSION 801U
#define QP_RELEASE 0x703931CEU
#define QP_VERSION_STR "8.0.2"
#define QP_VERSION 802U
// <VER>=802 <DATE>=250120
#define QP_RELEASE 0x6AEAB45DU
//============================================================================
// default configuration settings
//! @cond INTERNAL
#ifndef Q_SIGNAL_SIZE
@ -88,50 +85,41 @@
#endif
//! @endcond
//============================================================================
// global types/utilities
//$declare${glob-types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${glob-types::int_t} .......................................................
using int_t = int;
//${glob-types::enum_t} ......................................................
using enum_t = int;
//${glob-types::float32_t} ...................................................
using float32_t = float;
//${glob-types::float64_t} ...................................................
using float64_t = double;
//$enddecl${glob-types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$declare${QEP} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
#define Q_UNUSED_PAR(par_) (static_cast<void>(par_))
#define Q_DIM(array_) (sizeof(array_) / sizeof((array_)[0U]))
#define Q_UINT2PTR_CAST(type_, uint_) (reinterpret_cast<type_ *>(uint_))
//============================================================================
namespace QP {
//${QEP::versionStr[]} .......................................................
//! the current QP version number string in ROM, based on #QP_VERSION_STR
constexpr char const versionStr[] {QP_VERSION_STR};
extern char const versionStr[24];
//${QEP::QSignal} ............................................................
// QSignal type
#if (Q_SIGNAL_SIZE == 1U)
using QSignal = std::uint8_t;
#endif // (Q_SIGNAL_SIZE == 1U)
//${QEP::QSignal} ............................................................
#if (Q_SIGNAL_SIZE == 2U)
#elif (Q_SIGNAL_SIZE == 2U)
using QSignal = std::uint16_t;
#endif // (Q_SIGNAL_SIZE == 2U)
//${QEP::QSignal} ............................................................
#if (Q_SIGNAL_SIZE == 4U)
#elif (Q_SIGNAL_SIZE == 4U)
using QSignal = std::uint32_t;
#endif // (Q_SIGNAL_SIZE == 4U)
#endif
//============================================================================
//${QEP::QEvt} ...............................................................
class QEvt {
public:
QSignal sig;
std::uint8_t evtTag_;
std::uint8_t poolNum_;
std::uint8_t volatile refCtr_;
public:
@ -140,44 +128,33 @@ public:
public:
explicit constexpr QEvt(QSignal const s) noexcept
: sig(s),
evtTag_(0x01U),
refCtr_(0x0EU)
poolNum_(0x00U),
refCtr_(0xE0U)
{}
QEvt() = delete;
void init() noexcept {
// no event parameters to initialize
}
void init(DynEvt const dummy) noexcept {
static_cast<void>(dummy);
Q_UNUSED_PAR(dummy);
// no event parameters to initialize
}
bool verify_() const noexcept {
std::uint8_t rc = refCtr_;
return (rc <= 2U*QF_MAX_ACTIVE)
&& (((evtTag_ ^ rc) & 0x0FU) == 0x0FU);
}
std::uint_fast8_t getPoolNum_() const noexcept {
return static_cast<std::uint8_t>(evtTag_ >> 4U);
}
}; // class QEvt
//${QEP::QState} .............................................................
using QEvtPtr = QEvt const *;
//============================================================================
// QEP (hierarchical event processor) types
using QState = std::uint_fast8_t;
//${QEP::QStateHandler} ......................................................
class QXThread; // forward declaration
using QStateHandler = QState (*)(void * const me, QEvt const * const e);
//${QEP::QActionHandler} .....................................................
using QActionHandler = QState (*)(void * const me);
//${QEP::QXThread} ...........................................................
// forward declaration
class QXThread;
//${QEP::QXThreadHandler} ....................................................
using QXThreadHandler = void (*)(QXThread * const me);
//${QEP::QMState} ............................................................
struct QMState {
QMState const *superstate;
QStateHandler const stateHandler;
@ -186,29 +163,22 @@ struct QMState {
QActionHandler const initAction;
};
//${QEP::QMTranActTable} .....................................................
struct QMTranActTable {
QMState const *target;
QActionHandler const act[1];
};
//${QEP::QAsmAttr} ...........................................................
union QAsmAttr {
QStateHandler fun;
QActionHandler act;
QXThreadHandler thr;
QMState const *obj;
QMTranActTable const *tatbl;
#ifndef Q_UNSAFE
std::uintptr_t uint;
#endif
constexpr QAsmAttr() : fun(nullptr) {}
};
//${QEP::Q_USER_SIG} .........................................................
constexpr enum_t Q_USER_SIG {4};
//${QEP::QAsm} ...............................................................
//============================================================================
class QAsm {
protected:
QAsmAttr m_state;
@ -217,8 +187,7 @@ protected:
public:
//! All possible return values from state-handlers
//! @note
//! The order is important for algorithmic correctness.
//! NOTE: The ordering is important for algorithmic correctness.
enum QStateRet : QState {
// unhandled and need to "bubble up"
Q_RET_SUPER, //!< event passed to superstate to handle
@ -289,6 +258,7 @@ public:
return m_state.fun;
}
#endif // def Q_SPY
static QState top(
void * const me,
QEvt const * const e) noexcept
@ -357,7 +327,7 @@ protected:
#endif // ndef Q_SPY
}; // class QAsm
//${QEP::QHsm} ...............................................................
//============================================================================
class QHsm : public QP::QAsm {
protected:
explicit QHsm(QStateHandler const initial) noexcept;
@ -382,12 +352,21 @@ public:
#endif // def Q_SPY
private:
std::int_fast8_t hsm_tran(
std::int_fast8_t tran_simple_(
QStateHandler * const path,
std::uint_fast8_t const qsId);
std::int_fast8_t tran_complex_(
QStateHandler * const path,
std::uint_fast8_t const qsId);
void enter_target_(
QStateHandler * const path,
std::int_fast8_t const depth,
std::uint_fast8_t const qsId);
}; // class QHsm
//${QEP::QMsm} ...............................................................
//============================================================================
class QMsm : public QP::QAsm {
protected:
explicit QMsm(QStateHandler const initial) noexcept;
@ -428,147 +407,84 @@ public:
}; // class QMsm
} // namespace QP
//$enddecl${QEP} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$declare${QEP-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//============================================================================
// QEP-macros
//${QEP-macros::Q_STATE_DECL} ................................................
#define Q_STATE_DECL(state_) \
QP::QState state_ ## _h(QP::QEvt const * const e); \
static QP::QState state_(void * const me, QP::QEvt const * const e)
//${QEP-macros::Q_STATE_DEF} .................................................
#define Q_STATE_DEF(subclass_, state_) \
QP::QState subclass_::state_(void * const me, QP::QEvt const * const e) { \
return static_cast<subclass_ *>(me)->state_ ## _h(e); } \
QP::QState subclass_::state_ ## _h(QP::QEvt const * const e)
//${QEP-macros::Q_HANDLED} ...................................................
#define Q_HANDLED() (Q_RET_HANDLED)
//${QEP-macros::Q_UNHANDLED} .................................................
#define Q_UNHANDLED() (Q_RET_UNHANDLED)
//${QEP-macros::Q_EVT_CAST} ..................................................
#define Q_EVT_CAST(subclass_) (static_cast<subclass_ const *>(e))
#define Q_STATE_CAST(handler_) (reinterpret_cast<QP::QStateHandler>(handler_))
//${QEP-macros::Q_STATE_CAST} ................................................
#define Q_STATE_CAST(handler_) \
(reinterpret_cast<QP::QStateHandler>(handler_))
//${QEP-macros::QM_STATE_DECL} ...............................................
#define QM_STATE_DECL(state_) \
QP::QState state_ ## _h(QP::QEvt const * const e); \
static QP::QState state_(void * const me, QP::QEvt const * const e); \
static QP::QMState const state_ ## _s
//${QEP-macros::QM_ACTION_DECL} ..............................................
#define QM_ACTION_DECL(action_) \
QP::QState action_ ## _h(); \
static QP::QState action_(void * const me)
//${QEP-macros::QM_STATE_DEF} ................................................
#define QM_STATE_DEF(subclass_, state_) \
QP::QState subclass_::state_(void * const me, QP::QEvt const * const e) {\
return static_cast<subclass_ *>(me)->state_ ## _h(e); } \
QP::QState subclass_::state_ ## _h(QP::QEvt const * const e)
//${QEP-macros::QM_ACTION_DEF} ...............................................
#define QM_ACTION_DEF(subclass_, action_) \
QP::QState subclass_::action_(void * const me) { \
return static_cast<subclass_ *>(me)->action_ ## _h(); } \
QP::QState subclass_::action_ ## _h()
//${QEP-macros::QM_HANDLED} ..................................................
#define QM_HANDLED() (Q_RET_HANDLED)
//${QEP-macros::QM_UNHANDLED} ................................................
#define QM_UNHANDLED() (Q_RET_HANDLED)
//${QEP-macros::QM_SUPER} ....................................................
#define QM_SUPER() (Q_RET_SUPER)
//${QEP-macros::QM_STATE_NULL} ...............................................
#define QM_STATE_NULL (nullptr)
//${QEP-macros::Q_ACTION_NULL} ...............................................
#define Q_ACTION_NULL (nullptr)
//${QEP-macros::Q_UNUSED_PAR} ................................................
#define Q_UNUSED_PAR(par_) (static_cast<void>(par_))
//${QEP-macros::Q_DIM} .......................................................
#define Q_DIM(array_) (sizeof(array_) / sizeof((array_)[0U]))
//${QEP-macros::Q_UINT2PTR_CAST} .............................................
#define Q_UINT2PTR_CAST(type_, uint_) (reinterpret_cast<type_ *>(uint_))
//${QEP-macros::INIT} ........................................................
#ifdef Q_SPY
#define INIT(qsId_) init((qsId_))
#endif // def Q_SPY
//${QEP-macros::INIT} ........................................................
#ifndef Q_SPY
#define INIT(dummy) init(0U)
#endif // ndef Q_SPY
//${QEP-macros::DISPATCH} ....................................................
#ifdef Q_SPY
#define DISPATCH(e_, qsId_) dispatch((e_), (qsId_))
#endif // def Q_SPY
//${QEP-macros::DISPATCH} ....................................................
#ifndef Q_SPY
#else
#define INIT(dummy) init(0U)
#define DISPATCH(e_, dummy) dispatch((e_), 0U)
#endif // ndef Q_SPY
//$enddecl${QEP-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$declare${QF::types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//============================================================================
namespace QP {
//${QF::types::QPrioSpec} ....................................................
using QPrioSpec = std::uint16_t;
//${QF::types::QEvtPtr} ......................................................
using QEvtPtr = QEvt const *;
//${QF::types::QTimeEvtCtr} ..................................................
#if (QF_TIMEEVT_CTR_SIZE == 1U)
using QTimeEvtCtr = std::uint8_t;
#endif // (QF_TIMEEVT_CTR_SIZE == 1U)
//${QF::types::QTimeEvtCtr} ..................................................
#if (QF_TIMEEVT_CTR_SIZE == 2U)
#elif (QF_TIMEEVT_CTR_SIZE == 2U)
using QTimeEvtCtr = std::uint16_t;
#endif // (QF_TIMEEVT_CTR_SIZE == 2U)
//${QF::types::QTimeEvtCtr} ..................................................
#if (QF_TIMEEVT_CTR_SIZE == 4U)
#elif (QF_TIMEEVT_CTR_SIZE == 4U)
using QTimeEvtCtr = std::uint32_t;
#endif // (QF_TIMEEVT_CTR_SIZE == 4U)
//${QF::types::QPSetBits} ....................................................
#if (QF_MAX_ACTIVE <= 8U)
using QPSetBits = std::uint8_t;
#endif // (QF_MAX_ACTIVE <= 8U)
//${QF::types::QPSetBits} ....................................................
#if (8U < QF_MAX_ACTIVE) && (QF_MAX_ACTIVE <= 16U)
#elif (8U < QF_MAX_ACTIVE) && (QF_MAX_ACTIVE <= 16U)
using QPSetBits = std::uint16_t;
#endif // (8U < QF_MAX_ACTIVE) && (QF_MAX_ACTIVE <= 16U)
//${QF::types::QPSetBits} ....................................................
#if (16 < QF_MAX_ACTIVE)
#elif (16 < QF_MAX_ACTIVE)
using QPSetBits = std::uint32_t;
#endif // (16 < QF_MAX_ACTIVE)
//${QF::types::QF_LOG2} ......................................................
#ifndef QF_LOG2
std::uint_fast8_t QF_LOG2(QP::QPSetBits x) noexcept;
std::uint_fast8_t QF_LOG2(QP::QPSetBits const bitmask) noexcept;
#endif // ndef QF_LOG2
//${QF::types::QPSet} ........................................................
//============================================================================
class QPSet {
private:
QPSetBits m_bits[((QF_MAX_ACTIVE + (8U*sizeof(QPSetBits))) - 1U)/(8U*sizeof(QPSetBits))];
@ -637,65 +553,34 @@ public:
#endif
}
#ifndef Q_UNSAFE
void update_(QPSet * const dis) const noexcept {
dis->m_bits[0] = ~m_bits[0];
#if (QF_MAX_ACTIVE > 32U)
dis->m_bits[1] = ~m_bits[1];
#endif
}
#endif // ndef Q_UNSAFE
#ifndef Q_UNSAFE
bool verify_(QPSet const * const dis) const noexcept {
#if (QF_MAX_ACTIVE <= 32U)
return m_bits[0] == static_cast<QPSetBits>(~dis->m_bits[0]);
#else
return (m_bits[0] == static_cast<QPSetBits>(~dis->m_bits[0]))
&& (m_bits[1] == static_cast<QPSetBits>(~dis->m_bits[1]));
#endif
}
#endif // ndef Q_UNSAFE
}; // class QPSet
//${QF::types::QSubscrList} ..................................................
//============================================================================
class QSubscrList {
private:
QPSet m_set;
#ifndef Q_UNSAFE
QPSet m_set_dis;
#endif // ndef Q_UNSAFE
// friends...
friend class QActive;
}; // class QSubscrList
//${QF::types::QPtrDis} ......................................................
//============================================================================
class QPtrDis {
private:
std::uintptr_t m_ptr_dis;
// friends...
friend class QTimeEvt;
// friends...
friend class QXThread;
public:
QPtrDis(void const * const ptr = nullptr) noexcept;
}; // class QPtrDis
//${QF::types::QEQueue} ......................................................
class QEQueue;
class QEQueue; // forward declaration
} // namespace QP
//$enddecl${QF::types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$declare${QF::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QActive} .............................................................
//============================================================================
class QActive : public QP::QAsm {
protected:
std::uint8_t m_prio;
@ -714,14 +599,6 @@ protected:
#endif // def QACTIVE_EQUEUE_TYPE
public:
#ifndef Q_UNSAFE
std::uint8_t m_prio_dis;
#endif // ndef Q_UNSAFE
#ifndef Q_UNSAFE
std::uint8_t m_pthre_dis;
#endif // ndef Q_UNSAFE
static QActive * registry_[QF_MAX_ACTIVE + 1U];
static QSubscrList * subscrList_;
static enum_t maxPubSignal_;
@ -745,11 +622,6 @@ protected:
{
m_state.fun = Q_STATE_CAST(&top);
m_temp.fun = initial;
#ifndef Q_UNSAFE
m_prio_dis = static_cast<std::uint8_t>(~m_prio);
m_pthre_dis = static_cast<std::uint8_t>(~m_pthre);
#endif
}
public:
@ -873,15 +745,14 @@ public:
void * par,
void const * sender) noexcept;
#endif // def QF_ISR_API
private:
void postFIFO_(
QEvt const * const e,
void const * const sender);
}; // class QActive
} // namespace QP
//$enddecl${QF::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$declare${QF::QMActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QMActive} ............................................................
//============================================================================
class QMActive : public QP::QActive {
protected:
QMActive(QStateHandler const initial) noexcept;
@ -917,26 +788,13 @@ public:
}
}; // class QMActive
} // namespace QP
//$enddecl${QF::QMActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$declare${QF::QTimeEvt} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QTimeEvt} ............................................................
//============================================================================
class QTimeEvt : public QP::QEvt {
private:
QTimeEvt * volatile m_next;
#ifndef Q_UNSAFE
std::uintptr_t m_next_dis;
#endif // ndef Q_UNSAFE
void * m_act;
QTimeEvtCtr volatile m_ctr;
#ifndef Q_UNSAFE
QTimeEvtCtr m_ctr_dis;
#endif // ndef Q_UNSAFE
QTimeEvtCtr m_interval;
std::uint8_t m_tickRate;
std::uint8_t m_flags;
@ -944,10 +802,6 @@ private:
public:
static QTimeEvt timeEvtHead_[QF_MAX_TICK_RATE];
#ifndef Q_UNSAFE
static QPtrDis timeEvtHead_dis_[QF_MAX_TICK_RATE];
#endif // ndef Q_UNSAFE
private:
friend class QXThread;
@ -1002,15 +856,13 @@ private:
QTimeEvt() noexcept;
QTimeEvt(QTimeEvt const & other) = delete;
QTimeEvt & operator=(QTimeEvt const & other) = delete;
QTimeEvt *expire_(
QTimeEvt * const prev_link,
QActive const * const act,
std::uint_fast8_t const tickRate) noexcept;
}; // class QTimeEvt
} // namespace QP
//$enddecl${QF::QTimeEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$declare${QF::QTicker} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QTicker} .............................................................
//============================================================================
class QTicker : public QP::QActive {
public:
explicit QTicker(std::uint_fast8_t const tickRate) noexcept;
@ -1026,29 +878,17 @@ public:
void trig_(void const * const sender) noexcept;
}; // class QTicker
} // namespace QP
//$enddecl${QF::QTicker} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$declare${QF::QF-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//============================================================================
namespace QF {
//${QF::QF-base::init} .......................................................
void init();
//${QF::QF-base::stop} .......................................................
void stop();
//${QF::QF-base::run} ........................................................
int_t run();
//${QF::QF-base::onStartup} ..................................................
void onStartup();
//${QF::QF-base::onCleanup} ..................................................
void onCleanup();
//${QF::QF-base::psInit} .....................................................
//! @deprecated
inline void psInit(
QSubscrList * const subscrSto,
@ -1057,7 +897,6 @@ inline void psInit(
QActive::psInit(subscrSto, maxSignal);
}
//${QF::QF-base::publish_} ...................................................
//! @deprecated
inline void publish_(
QEvt const * const e,
@ -1067,7 +906,6 @@ inline void publish_(
QActive::publish_(e, sender, qsId);
}
//${QF::QF-base::tick} .......................................................
//! @deprecated
inline void tick(
std::uint_fast8_t const tickRate,
@ -1076,63 +914,47 @@ inline void tick(
QTimeEvt::tick(tickRate, sender);
}
//${QF::QF-base::getQueueMin} ................................................
//! @deprecated
inline std::uint_fast16_t getQueueMin(std::uint_fast8_t const prio) noexcept {
return QActive::getQueueMin(prio);
}
//${QF::QF-base::NO_MARGIN} ..................................................
constexpr std::uint_fast16_t NO_MARGIN {0xFFFFU};
} // namespace QF
} // namespace QP
//$enddecl${QF::QF-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$declare${QF::QF-dyn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
namespace QF {
//${QF::QF-dyn::poolInit} ....................................................
//============================================================================
// QF dynamic memory facilities
void poolInit(
void * const poolSto,
std::uint_fast32_t const poolSize,
std::uint_fast16_t const evtSize) noexcept;
//${QF::QF-dyn::poolGetMaxBlockSize} .........................................
std::uint_fast16_t poolGetMaxBlockSize() noexcept;
//${QF::QF-dyn::getPoolMin} ..................................................
std::uint_fast16_t getPoolMin(std::uint_fast8_t const poolNum) noexcept;
//${QF::QF-dyn::newX_} .......................................................
QEvt * newX_(
std::uint_fast16_t const evtSize,
std::uint_fast16_t const margin,
enum_t const sig) noexcept;
//${QF::QF-dyn::gc} ..........................................................
void gc(QEvt const * const e) noexcept;
//${QF::QF-dyn::newRef_} .....................................................
QEvt const * newRef_(
QEvt const * const e,
QEvt const * const evtRef) noexcept;
//${QF::QF-dyn::deleteRef_} ..................................................
void deleteRef_(QEvt const * const evtRef) noexcept;
//${QF::QF-dyn::q_new} .......................................................
#ifndef QEVT_PAR_INIT
template<class evtT_>
inline evtT_ * q_new(enum_t const sig) {
return static_cast<evtT_*>(
QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, sig));
}
#endif // ndef QEVT_PAR_INIT
//${QF::QF-dyn::q_new} .......................................................
#ifdef QEVT_PAR_INIT
template<class evtT_>
inline evtT_ * q_new_x(
std::uint_fast16_t const margin,
enum_t const sig)
{
return static_cast<evtT_*>(QP::QF::newX_(sizeof(evtT_), margin, sig));
}
#else
template<class evtT_, typename... Args>
inline evtT_ * q_new(
enum_t const sig,
@ -1143,21 +965,6 @@ inline evtT_ * q_new(
e->init(args...); // e cannot be nullptr
return e;
}
#endif // def QEVT_PAR_INIT
//${QF::QF-dyn::q_new_x} .....................................................
#ifndef QEVT_PAR_INIT
template<class evtT_>
inline evtT_ * q_new_x(
std::uint_fast16_t const margin,
enum_t const sig)
{
return static_cast<evtT_*>(QP::QF::newX_(sizeof(evtT_), margin, sig));
}
#endif // ndef QEVT_PAR_INIT
//${QF::QF-dyn::q_new_x} .....................................................
#ifdef QEVT_PAR_INIT
template<class evtT_, typename... Args>
inline evtT_ * q_new_x(
std::uint_fast16_t const margin,
@ -1172,7 +979,6 @@ inline evtT_ * q_new_x(
}
#endif // def QEVT_PAR_INIT
//${QF::QF-dyn::q_new_ref} ...................................................
template<class evtT_>
inline void q_new_ref(
QP::QEvt const * const e,
@ -1181,32 +987,25 @@ inline void q_new_ref(
evtRef = static_cast<evtT_ const *>(QP::QF::newRef_(e, evtRef));
}
//${QF::QF-dyn::q_delete_ref} ................................................
template<class evtT_>
inline void q_delete_ref(evtT_ const *& evtRef) {
QP::QF::deleteRef_(evtRef);
evtRef = nullptr;
}
//${QF::QF-dyn::newXfromISR_} ................................................
#ifdef QF_ISR_API
QEvt * newXfromISR_(
std::uint_fast16_t const evtSize,
std::uint_fast16_t const margin,
enum_t const sig) noexcept;
#endif // def QF_ISR_API
//${QF::QF-dyn::gcFromISR} ...................................................
#ifdef QF_ISR_API
void gcFromISR(QEvt const * e) noexcept;
#endif // def QF_ISR_API
} // namespace QF
} // namespace QP
//$enddecl${QF::QF-dyn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
extern "C" {
//$declare${QF-extern-C} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${QF-extern-C::QF_onContextSw} .............................................
#ifdef QF_ON_CONTEXT_SW
@ -1214,113 +1013,55 @@ void QF_onContextSw(
QP::QActive * prev,
QP::QActive * next);
#endif // def QF_ON_CONTEXT_SW
//$enddecl${QF-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
} // extern "C"
//$declare${QF-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//============================================================================
// QF base facilities
//${QF-macros::Q_PRIO} .......................................................
#define Q_PRIO(prio_, pthre_) \
(static_cast<QP::QPrioSpec>((prio_) | (pthre_) << 8U))
//${QF-macros::Q_NEW} ........................................................
#ifndef QEVT_PAR_INIT
#define Q_NEW(evtT_, sig_) (QP::QF::q_new<evtT_>((sig_)))
#endif // ndef QEVT_PAR_INIT
//${QF-macros::Q_NEW} ........................................................
#ifdef QEVT_PAR_INIT
#define Q_NEW(evtT_, sig_, ...) (QP::QF::q_new<evtT_>((sig_), __VA_ARGS__))
#endif // def QEVT_PAR_INIT
//${QF-macros::Q_NEW_X} ......................................................
#ifndef QEVT_PAR_INIT
#define Q_NEW_X(evtT_, margin_, sig_) (QP::QF::q_new_x<evtT_>((margin_), (sig_)))
#endif // ndef QEVT_PAR_INIT
//${QF-macros::Q_NEW_X} ......................................................
#ifdef QEVT_PAR_INIT
#else
#define Q_NEW(evtT_, sig_, ...) (QP::QF::q_new<evtT_>((sig_), __VA_ARGS__))
#define Q_NEW_X(evtT_, margin_, sig_, ...) (QP::QF::q_new_x<evtT_>((margin_), (sig_), __VA_ARGS__))
#endif // def QEVT_PAR_INIT
#endif // QEVT_PAR_INIT
//${QF-macros::Q_NEW_REF} ....................................................
#define Q_NEW_REF(evtRef_, evtT_) (QP::QF::q_new_ref<evtT_>(e, (evtRef_)))
//${QF-macros::Q_DELETE_REF} .................................................
#define Q_DELETE_REF(evtRef_) do { \
QP::QF::deleteRef_((evtRef_)); \
(evtRef_) = nullptr; \
} while (false)
//${QF-macros::PUBLISH} ......................................................
#ifdef Q_SPY
#define PUBLISH(e_, sender_) \
publish_((e_), (sender_), (sender_)->getPrio())
#endif // def Q_SPY
//${QF-macros::PUBLISH} ......................................................
#ifndef Q_SPY
#define PUBLISH(e_, dummy) publish_((e_), nullptr, 0U)
#endif // ndef Q_SPY
//${QF-macros::POST} .........................................................
#ifdef Q_SPY
#define POST(e_, sender_) post_((e_), QP::QF::NO_MARGIN, (sender_))
#endif // def Q_SPY
//${QF-macros::POST} .........................................................
#ifndef Q_SPY
#define POST(e_, dummy) post_((e_), QP::QF::NO_MARGIN, nullptr)
#endif // ndef Q_SPY
//${QF-macros::POST_X} .......................................................
#ifdef Q_SPY
#define POST_X(e_, margin_, sender_) \
post_((e_), (margin_), (sender_))
#endif // def Q_SPY
//${QF-macros::POST_X} .......................................................
#ifndef Q_SPY
#define POST_X(e_, margin_, dummy) post_((e_), (margin_), nullptr)
#endif // ndef Q_SPY
//${QF-macros::TICK_X} .......................................................
#ifdef Q_SPY
#define TICK_X(tickRate_, sender_) tick((tickRate_), (sender_))
#endif // def Q_SPY
//${QF-macros::TICK_X} .......................................................
#ifndef Q_SPY
#define TICK_X(tickRate_, dummy) tick((tickRate_), nullptr)
#endif // ndef Q_SPY
//${QF-macros::TICK} .........................................................
#define TICK(sender_) TICK_X(0U, (sender_))
//${QF-macros::TRIG} .........................................................
#ifdef Q_SPY
#define TRIG(sender_) trig_((sender_))
#endif // def Q_SPY
//${QF-macros::TRIG} .........................................................
#ifndef Q_SPY
#else
#define PUBLISH(e_, dummy) publish_((e_), nullptr, 0U)
#define POST(e_, dummy) post_((e_), QP::QF::NO_MARGIN, nullptr)
#define POST_X(e_, margin_, dummy) post_((e_), (margin_), nullptr)
#define TICK_X(tickRate_, dummy) tick((tickRate_), nullptr)
#define TRIG(sender_) trig_(nullptr)
#endif // ndef Q_SPY
//${QF-macros::QF_CRIT_EXIT_NOP} .............................................
#define TICK(sender_) TICK_X(0U, (sender_))
#ifndef QF_CRIT_EXIT_NOP
#define QF_CRIT_EXIT_NOP() (static_cast<void>(0))
#endif // ndef QF_CRIT_EXIT_NOP
//${QF-macros::QF_MEM_SYS} ...................................................
#ifndef QF_MEM_SYS
#define QF_MEM_SYS() (static_cast<void>(0))
#endif // ndef QF_MEM_SYS
//============================================================================
// memory protection facilities
//${QF-macros::QF_MEM_APP} ...................................................
#ifndef QF_MEM_APP
#define QF_MEM_APP() (static_cast<void>(0))
#endif // ndef QF_MEM_APP
//$enddecl${QF-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#ifdef QF_MEM_ISOLATE
#error Memory isolation not supported in this QP edition, need SafeQP
#endif // def QF_MEM_ISOLATE
#endif // QP_HPP_

View File

@ -1,10 +1,6 @@
//$file${include::qp_pkg.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${include::qp_pkg.hpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,68 +26,54 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${include::qp_pkg.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#ifndef QP_PKG_HPP_
#define QP_PKG_HPP_
//$declare${QF::QF-pkg} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//============================================================================
#define QF_CONST_CAST_(type_, ptr_) const_cast<type_>(ptr_)
#define Q_PTR2UINT_CAST_(ptr_) (reinterpret_cast<std::uintptr_t>(ptr_))
#define QF_PTR_RANGE_(x_, min_, max_) (((min_) <= (x_)) && ((x_) <= (max_)))
//============================================================================
namespace QP {
namespace QF {
//${QF::QF-pkg::Attr} ........................................................
class Attr {
public:
#if (QF_MAX_EPOOL > 0U)
QF_EPOOL_TYPE_ ePool_[QF_MAX_EPOOL];
#endif // (QF_MAX_EPOOL > 0U)
#if (QF_MAX_EPOOL > 0U)
std::uint_fast8_t maxPool_;
#endif // (QF_MAX_EPOOL > 0U)
#if (QF_MAX_EPOOL == 0U)
#else
std::uint8_t dummy;
#endif // (QF_MAX_EPOOL == 0U)
}; // class Attr
//${QF::QF-pkg::priv_} .......................................................
extern QF::Attr priv_;
//${QF::QF-pkg::bzero_} ......................................................
void bzero_(
void * const start,
std::uint_fast16_t const len) noexcept;
} // namespace QF
} // namespace QP
//$enddecl${QF::QF-pkg} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#define QF_CONST_CAST_(type_, ptr_) const_cast<type_>(ptr_)
#define Q_PTR2UINT_CAST_(ptr_) (reinterpret_cast<std::uintptr_t>(ptr_))
#define QF_PTR_RANGE_(x_, min_, max_) (((min_) <= (x_)) && ((x_) <= (max_)))
namespace QP {
//============================================================================
// Bitmasks are for the QTimeEvt::flags attribute
constexpr std::uint8_t QTE_FLAG_IS_LINKED {1U << 7U};
constexpr std::uint8_t QTE_FLAG_WAS_DISARMED {1U << 6U};
//============================================================================
inline void QEvt_refCtr_inc_(QEvt const * const e) noexcept {
// NOTE: this function must be called inside a critical section
std::uint8_t rc = e->refCtr_ + 1U;
(QF_CONST_CAST_(QEvt*, e))->refCtr_ = rc; // cast away 'const'
#ifndef Q_UNSAFE
(QF_CONST_CAST_(QEvt*, e))->evtTag_ = (e->evtTag_ & 0xF0U) | ((~rc) & 0x0FU);
#endif
}
inline void QEvt_refCtr_dec_(QEvt const * const e) noexcept {
// NOTE: this function must be called inside a critical section
std::uint8_t rc = e->refCtr_ - 1U;
(QF_CONST_CAST_(QEvt*, e))->refCtr_ = rc; // cast away 'const'
#ifndef Q_UNSAFE
(QF_CONST_CAST_(QEvt*, e))->evtTag_ = (e->evtTag_ & 0xF0U) | ((~rc) & 0x0FU);
#endif
}
} // namespace QP

View File

@ -1,10 +1,6 @@
//$file${include::qpcpp.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${include::qpcpp.hpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${include::qpcpp.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#ifndef QPCPP_HPP_
#define QPCPP_HPP_
@ -51,7 +46,7 @@
// QP API compatibility layer...
//============================================================================
#if (QP_API_VERSION < 750)
#if (QP_API_VERSION < 800)
#define QM_SM_STATE_DECL(subm_, state_) error "submachines no longer supported"
#define qm_super_sub(sm_state_) error "submachines no longer supported"
@ -64,7 +59,7 @@
#define QEVT_PAR_INIT
#endif
//! @deprecated plain 'char' is no longer forbidden in MISRA/AUTOSAR-C++
//! @deprecated plain 'char' is no longer forbidden in MISRA-C++:2023
using char_t = char;
//! @deprecated assertion failure handler
@ -111,123 +106,11 @@ using char_t = char;
#define Q_ALLEGE(expr_) Q_ALLEGE_ID(__LINE__, (expr_))
//! Static (compile-time) assertion.
//!
//! @deprecated
//! Use Q_ASSERT_STATIC() or better yet `static_assert()` instead.
//!
#define Q_ASSERT_COMPILE(expr_) Q_ASSERT_STATIC(expr_)
//! @deprecated use QP::QF::NO_MARGIN instead
#define QF_NO_MARGIN QP::QF::NO_MARGIN
//============================================================================
#if (QP_API_VERSION < 691)
//! @deprecated enable the QS global filter
#define QS_FILTER_ON(rec_) QS_GLB_FILTER((rec_))
//! @deprecated disable the QS global filter
#define QS_FILTER_OFF(rec_) QS_GLB_FILTER(-(rec_))
//! @deprecated enable the QS local filter for SM (state machine) object
#define QS_FILTER_SM_OBJ(obj_) (static_cast<void>(0))
//! @deprecated enable the QS local filter for AO (active objects)
#define QS_FILTER_AO_OBJ(obj_) (static_cast<void>(0))
//! @deprecated enable the QS local filter for MP (memory pool) object
#define QS_FILTER_MP_OBJ(obj_) (static_cast<void>(0))
//! @deprecated enable the QS local filter for EQ (event queue) object
#define QS_FILTER_EQ_OBJ(obj_) (static_cast<void>(0))
//! @deprecated enable the QS local filter for TE (time event) object
#define QS_FILTER_TE_OBJ(obj_) (static_cast<void>(0))
#ifdef Q_SPY
//! @deprecated local Filter for a generic application object `obj_`.
#define QS_FILTER_AP_OBJ(obj_) \
(QP::QS::filt_.loc_AP = (obj_))
//! @deprecated begin of a user QS record, instead use QS_BEGIN_ID()
#define QS_BEGIN(rec_, obj_) \
if (QS_GLB_FILTER_(rec_) && \
((QP::QS::filt_.loc[QP::QS::AP_OBJ] == nullptr) \
|| (QP::QS::filt_.loc_AP == (obj_)))) \
{ \
QS_CRIT_STAT \
QS_CRIT_ENTRY(); \
QP::QS::beginRec_(static_cast<std::uint_fast8_t>(rec_)); \
QS_TIME_PRE();
//! @deprecated output hex-formatted std::uint32_t to the QS record
#define QS_U32_HEX(width_, data_) \
(QP::QS::u32_fmt_(static_cast<std::uint8_t>( \
(static_cast<std::uint8_t>((width_) << 4)) | QS_HEX_FMT), (data_)))
#else
#define QS_FILTER_AP_OBJ(obj_) (static_cast<void>(0))
#define QS_BEGIN(rec_, obj_) if (false) {
#define QS_U32_HEX(width_, data_) (Q_UNUSED_PAR(0))
#endif // def Q_SPY
//============================================================================
#if (QP_API_VERSION < 680)
//! @deprecated
//! Macro to specify a tran. in the "me->" impl-strategy.
//! Instead use the new impl-strategy without the "me->" pointer, where
//! you call tran(Q_STATE_CAST(target_)).
#define Q_TRAN(target_) (me->tran(Q_STATE_CAST(target_)))
//! @deprecated
//! Macro to specify a tran-to-history in the "me->" impl-strategy.
//! Instead use the new impl-strategy without the "me->" pointer, where
//! you call tran_hist(Q_STATE_CAST(hist_)).
#define Q_TRAN_HIST(hist_) (me->tran_hist((hist_)))
//! @deprecated
//! Macro to specify the superstate in the "me->" impl-strategy.
//! Instead use the new impl-strategy without the "me->" pointer, where
//! you call super(state_)).
#define Q_SUPER(state_) (me->super(Q_STATE_CAST(state_)))
//! @deprecated
//! Macro to call in a QM state entry-handler. Applicable only to QMSMs.
//! Instead use the new impl-strategy without the "me->" pointer, where
//! the QM-generated code calls qm_entry(Q_STATE_CAST(state_)).
#define QM_ENTRY(state_) (me->qm_entry((state_)))
//! @deprecated
//! Macro to call in a QM state exit-handler. Applicable only to QMSMs.
//! Instead use the new impl-strategy without the "me->" pointer, where
//! the QM-generated code calls qm_exit(Q_STATE_CAST(state_)).
#define QM_EXIT(state_) (me->qm_exit((state_)))
//! @deprecated
//! Macro to call in a QM state-handler when it executes a tran.
//! Instead use the new impl-strategy without the "me->" pointer, where
//! the QM-generated code calls qm_tran((tatbl_)).
#define QM_TRAN(tatbl_) (me->qm_tran((tatbl_)))
//! @deprecated
//! Macro to call in a QM state-handler when it executes an initial tran.
//! Instead use the new impl-strategy without the "me->" pointer, where
//! the QM-generated code calls qm_tran_init((tatbl_)).
#define QM_TRAN_INIT(tatbl_) (me->qm_tran_init((tatbl_)))
//! @deprecated
//! Macro to call in a QM state-handler when it executes a tran-to-history.
//! Instead use the new impl-strategy without the "me->" pointer, where
//! the QM-generated code calls qm_tran_hist((history_), (tatbl_)).
#define QM_TRAN_HIST(history_, tatbl_) \
(me->qm_tran_hist((history_), (tatbl_)))
#endif // QP_API_VERSION < 680
#endif // QP_API_VERSION < 691
#endif // QP_API_VERSION < 750
#endif // QP_API_VERSION < 800
#endif // QPCPP_HPP_

View File

@ -1,5 +1,6 @@
//============================================================================
// QP/C++ Spy software tracing target-resident component
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -7,10 +8,9 @@
// ------------------------
// Modern Embedded Software
//
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -31,11 +31,11 @@
#define QS_DUMMY_HPP_
#ifdef Q_SPY
#error "Q_SPY must NOT be defined to include qs_dummy.hpp"
error Q_SPY must NOT be defined to include qs_dummy.hpp
#endif
#ifdef Q_UTEST
#error "Q_UTEST must NOT be defined to include qs_dummy.hpp"
error Q_UTEST must NOT be defined to include qs_dummy.hpp
#endif
#define QS_INIT(arg_) (true)
@ -166,9 +166,6 @@ void QS_onTestLoop(void);
#define QS_CRIT_ENTRY() static_cast<void>(0)
#define QS_CRIT_EXIT() static_cast<void>(0)
#define QS_MEM_SYS() static_cast<void>(0)
#define QS_MEM_APP() static_cast<void>(0)
#define QS_TR_CRIT_ENTRY() static_cast<void>(0)
#define QS_TR_CRIT_EXIT() static_cast<void>(0)
#define QS_TR_ISR_ENTRY(isrnest_, prio_) static_cast<void>(0)

View File

@ -1,52 +1,34 @@
//$file${include::qsafe.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//============================================================================
// SafeQP/C Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Model: qpc.qm
// File: ${include::qsafe.h}
//
// 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:
// License # : LicenseRef-QL-dual
// Issued to : Any user of the QP/C real-time embedded framework
// Framework(s) : qpc
// Support ends : 2024-12-31
// License scope:
//
// Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
// SPDX-License-Identifier: 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.
// This software is licensed under the terms of the Quantum Leaps commercial
// licenses. Please contact Quantum Leaps for more information about the
// available licensing options.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <www.gnu.org/licenses/gpl-3.0>
// RESTRICTIONS
// You may NOT :
// (a) redistribute, encumber, sell, rent, lease, sublicense, or otherwise
// transfer rights in this software,
// (b) remove or alter any trademark, logo, copyright or other proprietary
// notices, legends, symbols or labels present in this software,
// (c) plagiarize this software to sidestep the licensing obligations.
//
// 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:
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${include::qsafe.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#ifndef QSAFE_H_
#define QSAFE_H_
#ifdef __cplusplus
extern "C" {
#endif
// QF-FuSa enabled ===========================================================
#ifndef Q_UNSAFE
@ -62,21 +44,15 @@ extern "C" {
#define QF_CRIT_EXIT() ((void)0)
#endif
//$declare${QP-FuSa::enabled} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${QP-FuSa::enabled::Q_DEFINE_THIS_MODULE} ..................................
#define Q_DEFINE_THIS_MODULE(name_) \
static char const Q_this_module_[] = name_;
//${QP-FuSa::enabled::Q_ASSERT_INCRIT} .......................................
#define Q_ASSERT_INCRIT(id_, expr_) \
((expr_) ? ((void)0) : Q_onError(&Q_this_module_[0], (id_)))
//${QP-FuSa::enabled::Q_ERROR_INCRIT} ........................................
#define Q_ERROR_INCRIT(id_) \
(Q_onError(&Q_this_module_[0], (id_)))
//${QP-FuSa::enabled::Q_ASSERT_ID} ...........................................
#define Q_ASSERT_ID(id_, expr_) do { \
QF_CRIT_STAT \
QF_CRIT_ENTRY(); \
@ -84,99 +60,64 @@ extern "C" {
QF_CRIT_EXIT(); \
} while (false)
//${QP-FuSa::enabled::Q_ERROR_ID} ............................................
#define Q_ERROR_ID(id_) do { \
QF_CRIT_STAT \
QF_CRIT_ENTRY(); \
Q_onError(&Q_this_module_[0], (id_)); \
QF_CRIT_EXIT(); \
} while (false)
//$enddecl${QP-FuSa::enabled} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// QF-FuSa disabled ==========================================================
#else
//$declare${QP-FuSa::disabled} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${QP-FuSa::disabled::Q_DEFINE_THIS_MODULE} .................................
#define Q_DEFINE_THIS_MODULE(name_)
//${QP-FuSa::disabled::Q_ASSERT_INCRIT} ......................................
#define Q_ASSERT_INCRIT(id_, expr_) ((void)0)
//${QP-FuSa::disabled::Q_ERROR_INCRIT} .......................................
#define Q_ERROR_INCRIT(id_) ((void)0)
//${QP-FuSa::disabled::Q_ASSERT_ID} ..........................................
#define Q_ASSERT_ID(id_, expr_) ((void)0)
//${QP-FuSa::disabled::Q_ERROR_ID} ...........................................
#define Q_ERROR_ID(id_) ((void)0)
//$enddecl${QP-FuSa::disabled} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#endif
#endif // QF-FuSa disabled
//============================================================================
//$declare1${QP-FuSa} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${QP-FuSa::Q_DEFINE_THIS_FILE} .............................................
#define Q_DEFINE_THIS_FILE Q_DEFINE_THIS_MODULE(__FILE__)
//${QP-FuSa::Q_ASSERT} .......................................................
#define Q_ASSERT(expr_) Q_ASSERT_ID(__LINE__, (expr_))
//${QP-FuSa::Q_ERROR} ........................................................
#define Q_ERROR() Q_ERROR_ID(__LINE__)
//${QP-FuSa::Q_REQUIRE_ID} ...................................................
#define Q_REQUIRE_ID(id_, expr_) Q_ASSERT_ID((id_), (expr_))
//${QP-FuSa::Q_REQUIRE} ......................................................
#define Q_REQUIRE(expr_) Q_ASSERT(expr_)
//${QP-FuSa::Q_REQUIRE_INCRIT} ...............................................
#define Q_REQUIRE_INCRIT(id_, expr_) Q_ASSERT_INCRIT((id_), (expr_))
//${QP-FuSa::Q_ENSURE_ID} ....................................................
#define Q_ENSURE_ID(id_, expr_) Q_ASSERT_ID((id_), (expr_))
//${QP-FuSa::Q_ENSURE} .......................................................
#define Q_ENSURE(expr_) Q_ASSERT(expr_)
//${QP-FuSa::Q_ENSURE_INCRIT} ................................................
#define Q_ENSURE_INCRIT(id_, expr_) Q_ASSERT_INCRIT((id_), (expr_))
//${QP-FuSa::Q_INVARIANT_ID} .................................................
#define Q_INVARIANT_ID(id_, expr_) Q_ASSERT_ID((id_), (expr_))
//${QP-FuSa::Q_INVARIANT} ....................................................
#define Q_INVARIANT(expr_) Q_ASSERT(expr_)
//${QP-FuSa::Q_INVARIANT_INCRIT} .............................................
#define Q_INVARIANT_INCRIT(id_, expr_) Q_ASSERT_INCRIT((id_), (expr_))
//${QP-FuSa::Q_ASSERT_STATIC} ................................................
#ifndef Q_ASSERT_STATIC
#define Q_ASSERT_STATIC(expr_) extern char Q_static_assert_[(expr_) ? 1 : -1]
#endif // ndef Q_ASSERT_STATIC
//${QP-FuSa::Q_NORETURN} .....................................................
#ifndef Q_NORETURN
#define Q_NORETURN _Noreturn void
#endif // ndef Q_NORETURN
//${QP-FuSa::int_t} ..........................................................
// Is this header file used outside QP?
#ifndef QP_VERSION
#define Q_DIM(array_) (sizeof(array_) / sizeof((array_)[0U]))
#endif // ndef QP_VERSION
//============================================================================
#ifdef __cplusplus
extern "C" {
#endif
#ifndef QP_VERSION
typedef int int_t;
#endif // ndef QP_VERSION
//${QP-FuSa::Q_onError} ......................................................
Q_NORETURN Q_onError(
char const * const module,
int_t const id);
//${QP-FuSa::Q_DIM} ..........................................................
#ifndef QP_VERSION
#define Q_DIM(array_) (sizeof(array_) / sizeof((array_)[0U]))
#endif // ndef QP_VERSION
//$enddecl${QP-FuSa} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#ifdef __cplusplus
}
#endif

View File

@ -1,10 +1,6 @@
//$file${include::qstamp.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${include::qstamp.hpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${include::qstamp.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#ifndef QSTAMP_HPP_
#define QSTAMP_HPP_

View File

@ -1,10 +1,6 @@
//$file${include::qv.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${include::qv.hpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,97 +26,53 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${include::qv.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#ifndef QV_HPP_
#define QV_HPP_
//$declare${QV::QV-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
namespace QV {
//${QV::QV-base::Attr} .......................................................
//============================================================================
class Attr {
public:
QPSet readySet;
std::uint_fast8_t schedCeil;
#ifndef Q_UNSAFE
QPSet readySet_dis;
#endif // ndef Q_UNSAFE
#ifndef Q_UNSAFE
std::uint_fast8_t schedCeil_dis;
#endif // ndef Q_UNSAFE
}; // class Attr
//${QV::QV-base::priv_} ......................................................
extern QV::Attr priv_;
//${QV::QV-base::schedDisable} ...............................................
void schedDisable(std::uint_fast8_t const ceiling);
//${QV::QV-base::schedEnable} ................................................
void schedEnable();
//${QV::QV-base::onIdle} .....................................................
void onIdle();
} // namespace QV
} // namespace QP
//$enddecl${QV::QV-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
// interface used only for internal implementation, but not in applications
#ifdef QP_IMPL
//$declare${QV-impl} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${QV-impl::QF_SCHED_STAT_} .................................................
// scheduler locking for QV (not needed)...
#define QF_SCHED_STAT_
//${QV-impl::QF_SCHED_LOCK_} .................................................
#define QF_SCHED_LOCK_(dummy) (static_cast<void>(0))
//${QV-impl::QF_SCHED_UNLOCK_} ...............................................
#define QF_SCHED_UNLOCK_() (static_cast<void>(0))
//${QV-impl::QACTIVE_EQUEUE_WAIT_} ...........................................
// QActive event queue customization for QV...
#define QACTIVE_EQUEUE_WAIT_(me_) (static_cast<void>(0))
//${QV-impl::QACTIVE_EQUEUE_SIGNAL_} .........................................
#ifndef Q_UNSAFE
#define QACTIVE_EQUEUE_SIGNAL_(me_) \
QV::priv_.readySet.insert((me_)->m_prio); \
QV::priv_.readySet.update_(&QV::priv_.readySet_dis)
#endif // ndef Q_UNSAFE
//${QV-impl::QACTIVE_EQUEUE_SIGNAL_} .........................................
#ifdef Q_UNSAFE
#define QACTIVE_EQUEUE_SIGNAL_(me_) \
(QV::priv_.readySet.insert((me_)->m_prio))
#endif // def Q_UNSAFE
//$enddecl${QV-impl} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$declare${QF_EPOOL-impl} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${QF_EPOOL-impl::QF_EPOOL_TYPE_} ...........................................
// QF event pool customization for QV...
#define QF_EPOOL_TYPE_ QMPool
//${QF_EPOOL-impl::QF_EPOOL_INIT_} ...........................................
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \
(p_).init((poolSto_), (poolSize_), (evtSize_))
//${QF_EPOOL-impl::QF_EPOOL_EVENT_SIZE_} .....................................
#define QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize())
//${QF_EPOOL-impl::QF_EPOOL_GET_} ............................................
#define QF_EPOOL_GET_(p_, e_, m_, qsId_) \
((e_) = static_cast<QEvt *>((p_).get((m_), (qsId_))))
//${QF_EPOOL-impl::QF_EPOOL_PUT_} ............................................
#define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_)))
//$enddecl${QF_EPOOL-impl} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#endif // QP_IMPL

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -35,9 +35,9 @@
// <o>QP API compatibility version (QP_API_VERSION)
// <0=> 0 (Maximum compatibility)
// <691=>691 (QP 6.9.1 or newer)
// <734=>7.3.4 (QP 7.3.4 or newer)
// <750=>750 (QP 7.5.0 or newer)
// <9999=>9999 (Latest only)
// <i>QP API backwards compatibility with the QP/C API version.
// <i>QP API backwards compatibility with the QP API version.
// <i>Lower QP_API_VERSION values enable backwards compatibility
// <i>with lower (older) QP API versions.
// <i>For example, QP_API_VERSION==691 will enable the compatibility
@ -191,7 +191,7 @@
// </c>
// <c2>Enable memory isolation (QF_MEM_ISOLATE)
// <i>Memory isolation (requires MPU)
// <i>Memory isolation (supported in SafeQP only, requires MPU)
// <i>NOTE: implies QF_ON_CONTEXT_SW.
//#define QF_MEM_ISOLATE
// </c>
@ -201,11 +201,13 @@
//..........................................................................
// <h>QV/QK/QXK built-in kernels (ARM Cortex-M)
#if (__ARM_ARCH > 6)
// <c2>Kernel uses critical section based on BASEPRI (QF_USE_BASEPRI)
// <i>If not selected, critical section will be based on PRIMASK
// <i>NOTE: The BASEPRI threshold can be adjusted in the "Text Editor" mode.
//#define QF_USE_BASEPRI 0x3F
// </c>
#endif // (__ARM_ARCH > 6)
// <c2>QK Kernel uses IRQ for return-from-preemption
// <i>NOTE: Use "editor mode" to edit QK_USE_IRQ_NUM

View File

@ -1,5 +1,6 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
@ -8,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -1,5 +1,6 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
@ -8,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -1,5 +1,6 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
@ -8,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -1,5 +1,6 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
@ -8,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -1,5 +1,6 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
@ -8,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -1,5 +1,6 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
@ -8,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -191,7 +191,7 @@
// </c>
// <c2>Enable memory isolation (QF_MEM_ISOLATE)
// <i>Memory isolation (requires MPU)
// <i>Memory isolation (supported in SafeQP only, requires MPU)
// <i>NOTE: implies QF_ON_CONTEXT_SW.
//#define QF_MEM_ISOLATE
// </c>

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-11-22
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to ARM Cortex-R, preemptive QK kernel, GNU-ARM
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to ARM Cortex-R, preemptive QK kernel, IAR-ARM
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to ARM Cortex-R, preemptive QK kernel, TI-ARM
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-11-22
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C port to ARM Cortex-R, cooperative QV kernel, GNU-ARM
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to Cortex-R, cooperative QV kernel, IAR-ARM
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to ARM Cortex-R, cooperative QV kernel, TI-ARM
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -191,7 +191,7 @@
// </c>
// <c2>Enable memory isolation (QF_MEM_ISOLATE)
// <i>Memory isolation (requires MPU)
// <i>Memory isolation (supported in SafeQP only, requires MPU)
// <i>NOTE: implies QF_ON_CONTEXT_SW.
//#define QF_MEM_ISOLATE
// </c>

View File

@ -7,7 +7,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -25,12 +25,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-26
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QF/C++ port to embOS RTOS kernel, generic C++11 compiler
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -206,9 +200,6 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin,
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(200, e != nullptr);
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(201, e->verify_());
#endif // ndef Q_UNSAFE
std::uint_fast16_t nFree =
static_cast<std::uint_fast16_t>(m_eQueue.maxMsg - m_eQueue.nofMsg);
@ -237,12 +228,13 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin,
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object (recipient)
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(nFree); // # free entries
QS_EQC_PRE(0U); // min # free entries (unknown)
QS_END_PRE()
if (e->getPoolNum_() != 0U) { // is it a pool event?
if (e->poolNum_ != 0U) { // is it a pool event?
Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e); // increment the reference counter
}
QF_CRIT_EXIT();
@ -260,7 +252,7 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin,
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object (recipient)
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr
QS_2U8_PRE(e->poolNum_, e->refCtr_); // poolNum & refCtr
QS_EQC_PRE(nFree); // # free entries
QS_EQC_PRE(margin); // margin requested
QS_END_PRE()
@ -275,20 +267,18 @@ void QActive::postLIFO(QEvt const * const e) noexcept {
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(300, e != nullptr);
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(301, e->verify_());
#endif // ndef Q_UNSAFE
QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(m_eQueue.maxMsg - m_eQueue.nofMsg); // # free entries
QS_EQC_PRE(0U); // min # free entries (unknown)
QS_END_PRE()
if (e->getPoolNum_() != 0U) { // is it a pool event?
if (e->poolNum_ != 0U) { // is it a pool event?
Q_ASSERT_INCRIT(305, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e); // increment the reference counter
}
QF_CRIT_EXIT();
@ -311,7 +301,7 @@ QEvt const *QActive::get_() noexcept {
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr
QS_2U8_PRE(e->poolNum_, e->refCtr_); // poolNum & refCtr
QS_EQC_PRE(m_eQueue.maxMsg - m_eQueue.nofMsg); // # free
QS_END_PRE()
QS_CRIT_EXIT();

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to embOS RTOS (v5), generic C++11 compiler
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -1,4 +1,7 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
@ -7,7 +10,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -15,22 +18,15 @@
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
// The GPL does NOT permit the incorporation of this code into proprietary
// programs. Please contact Quantum Leaps for commercial licensing options,
// which expressly supersede the GPL and are designed explicitly for
// closed-source distribution.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-10-29
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QF/C++ port to FreeRTOS 10.x, generic C++11 compiler
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-level interface
@ -43,11 +39,11 @@
#endif // Q_SPY
#if ( configSUPPORT_STATIC_ALLOCATION == 0 )
#error "This QP/C++ port to FreeRTOS requires configSUPPORT_STATIC_ALLOCATION"
#error This QP/C++ port to FreeRTOS requires configSUPPORT_STATIC_ALLOCATION
#endif
#if ( configMAX_PRIORITIES < QF_MAX_ACTIVE )
#error "FreeRTOS configMAX_PRIORITIES must not be less than QF_MAX_ACTIVE"
#error FreeRTOS configMAX_PRIORITIES must not be less than QF_MAX_ACTIVE
#endif
namespace { // unnamed local namespace
@ -181,7 +177,7 @@ void QActive::start(
// The FreeRTOS priority of the AO thread can be specified in two ways:
//
// 1. Implictily based on the AO's priority (by the formula specified
// 1. Implicitly based on the AO's priority (by the formula specified
// in the macro FREERTOS_TASK_PRIO(), see qp_port.h). This option
// is chosen, when the higher-byte of the prioSpec parameter is set
// to zero.
@ -195,7 +191,7 @@ void QActive::start(
// so it is the responsibility of the application to ensure that
// it is consistent with the AO's priority. An example of
// inconsistent setting would be assigning FreeRTOS priorities that
// would result in a different relative priritization of AO's threads
// would result in a different relative prioritization of AO's threads
// than indicated by the AO priorities assigned.
//
UBaseType_t freertos_prio = (prioSpec >> 8U);
@ -257,46 +253,48 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin,
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(200, e != nullptr);
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(201, e->verify_());
#endif // ndef Q_UNSAFE
// the number of free slots available in the queue
std::uint_fast16_t nFree =
static_cast<std::uint_fast16_t>(FREERTOS_QUEUE_GET_FREE());
bool status;
// required margin available?
bool status = false; // assume that event cannot be posted
if (margin == QF::NO_MARGIN) {
if (nFree > 0U) {
if (nFree > 0U) { // free entries available in the queue?
status = true; // can post
}
else {
status = false; // cannot post
else { // no free entries available
// The queue overflows, but QF_NO_MARGIN indicates that
// the "event delivery guarantee" is required.
Q_ERROR_INCRIT(210); // must be able to post the event
}
}
else if (nFree > margin) {
else if (nFree > margin) { // enough free entries?
status = true; // can post
}
else {
status = false; // cannot post
// empty
}
if (status) { // can post the event?
#if (QF_MAX_EPOOL > 0U)
if (e->poolNum_ != 0U) { // is it a mutable event?
Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e); // increment the reference counter
}
#endif // (QF_MAX_EPOOL > 0U)
if (status) { // can post the event?
QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_prio)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object (recipient)
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(static_cast<QEQueueCtr>(nFree)); // # free entries
QS_EQC_PRE(0U); // min # free entries (unknown)
QS_END_PRE()
if (e->getPoolNum_() != 0U) { // is it a pool event?
QEvt_refCtr_inc_(e); // increment the reference counter
}
QF_CRIT_EXIT();
BaseType_t err = xQueueSendToBack(
@ -305,49 +303,56 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin,
QF_CRIT_ENTRY();
// posting to the FreeRTOS message queue must succeed, see NOTE3
Q_ASSERT_INCRIT(220, err == pdPASS);
QF_CRIT_EXIT();
#ifdef Q_UNSAFE
Q_UNUSED_PAR(err);
#endif
}
else { // cannot post the event
else { // event cannot be posted
QS_BEGIN_PRE(QS_QF_ACTIVE_POST_ATTEMPT, m_prio)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object (recipient)
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(static_cast<QEQueueCtr>(nFree)); // # free entries
QS_EQC_PRE(margin); // margin requested
QS_END_PRE()
}
QF_CRIT_EXIT();
#if (QF_MAX_EPOOL > 0U)
QF::gc(e); // recycle the event to avoid a leak
#endif // (QF_MAX_EPOOL > 0U)
}
return status;
}
//............................................................................
void QActive::postLIFO(QEvt const * const e) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(300, e != nullptr);
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(301, e->verify_());
#endif // ndef Q_UNSAFE
#if (QF_MAX_EPOOL > 0U)
if (e->poolNum_ != 0U) { // is it a mutable event?
Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e); // increment the reference counter
}
#endif // (QF_MAX_EPOOL > 0U)
QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->evtTag_, e->refCtr_); // pool Id & refCtr of the evt
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(static_cast<QEQueueCtr>(FREERTOS_QUEUE_GET_FREE()));
QS_EQC_PRE(0U); // min # free entries (unknown)
QS_END_PRE()
if (e->getPoolNum_() != 0U) { // is it a pool event?
QEvt_refCtr_inc_(e); // increment the reference counter
}
QF_CRIT_EXIT();
BaseType_t err = xQueueSendToFront(
@ -373,7 +378,7 @@ QEvt const *QActive::get_(void) noexcept {
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); // pool Id&ref Count
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(static_cast<QEQueueCtr>(FREERTOS_QUEUE_GET_FREE()));
QS_END_PRE()
QS_CRIT_EXIT();
@ -390,76 +395,80 @@ bool QActive::postFromISR(QEvt const * const e,
{
UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
Q_REQUIRE_INCRIT(500, e != nullptr);
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(501, e->verify_());
#endif // ndef Q_UNSAFE
Q_REQUIRE_INCRIT(400, e != nullptr);
// find the number of free slots available in the queue
// the number of free slots available in the FreeRTOS queue
std::uint_fast16_t const nFree =
static_cast<std::uint_fast16_t>(FREERTOS_QUEUE_GET_FREE());
bool status;
// required margin available?
bool status = false; // assume that event cannot be posted
if (margin == QF::NO_MARGIN) {
if (nFree > 0U) {
if (nFree > 0U) { // free entries available in the queue?
status = true; // can post
}
else { // no free entries available
// The queue overflows, but QF_NO_MARGIN indicates that
// the "event delivery guarantee" is required.
Q_ERROR_INCRIT(410); // must be able to post the event
}
}
else if (nFree > margin) { // enough free entries?
status = true; // can post
}
else {
status = false; // cannot post
Q_ERROR_INCRIT(510); // must be able to post the event
// empty
}
#if (QF_MAX_EPOOL > 0U)
if (e->poolNum_ != 0U) { // is it a mutable event?
Q_ASSERT_INCRIT(405, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e); // increment the reference counter
}
else if (nFree > margin) {
status = true; // can post
}
else {
status = false; // cannot post
}
#endif // (QF_MAX_EPOOL > 0U)
if (status) { // can post the event?
QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_prio)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object (recipient)
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(nFree); // # free entries available
QS_EQC_PRE(0U); // min # free entries (unknown)
QS_END_PRE()
if (e->getPoolNum_() != 0U) { // is it a pool event?
QEvt_refCtr_inc_(e); // increment the reference counter
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
BaseType_t err = xQueueSendToBackFromISR(m_eQueue,
static_cast<void const *>(&e),
static_cast<BaseType_t*>(par));
// posting to the FreeRTOS message queue must succeed
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
Q_ASSERT_INCRIT(520, err == pdPASS);
// posting to the FreeRTOS message queue must succeed, see NOTE3
Q_ASSERT_INCRIT(420, err == pdPASS);
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
#ifdef Q_UNSAFE
Q_UNUSED_PAR(err);
#endif
}
else {
else { // event cannot be posted
QS_BEGIN_PRE(QS_QF_ACTIVE_POST_ATTEMPT, m_prio)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object (recipient)
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(nFree); // # free entries available
QS_EQC_PRE(margin); // margin requested
QS_END_PRE()
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
#if (QF_MAX_EPOOL > 0U)
QF::gcFromISR(e); // recycle the event to avoid a leak
#endif // (QF_MAX_EPOOL > 0U)
}
return status;
@ -469,72 +478,88 @@ void QActive::publishFromISR(QEvt const *e,
void *par,
void const * const sender) noexcept
{
Q_REQUIRE_INCRIT(600, e != nullptr);
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(601, e->verify_());
#endif // ndef Q_UNSAFE
Q_REQUIRE_INCRIT(500, e != nullptr);
QSignal const sig = e->sig;
UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
// the published signal must be within the configured range
Q_REQUIRE_INCRIT(610, sig < QActive::maxPubSignal_);
Q_REQUIRE_INCRIT(611,
subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis));
Q_REQUIRE_INCRIT(510, sig < QActive::maxPubSignal_);
QS_BEGIN_PRE(QS_QF_PUBLISH, 0U)
QS_TIME_PRE(); // the timestamp
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(sig); // the signal of the event
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_END_PRE()
// is it a dynamic event?
if (e->getPoolNum_() != 0U) {
// NOTE: The reference counter of a dynamic event is incremented to
// is it a mutable event?
if (e->poolNum_ != 0U) {
// NOTE: The reference counter of a mutable event is incremented to
// prevent premature recycling of the event while the multicasting
// is still in progress. At the end of the function, the garbage
// collector step (QF::gcFromISR()) decrements the reference counter
// and recycles the event if the counter drops to zero. This covers
// the case when the event was published without any subscribers.
Q_ASSERT_INCRIT(505, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e);
}
// make a local, modifiable copy of the subscriber list
// make a local, modifiable copy of the subscriber set
QPSet subscrSet = QActive::subscrList_[sig].m_set;
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
if (subscrSet.notEmpty()) { // any subscribers?
// the highest-prio subscriber
std::uint_fast8_t p = subscrSet.findMax();
// no need to lock the scheduler in the ISR context
do { // loop over all subscribers
// the prio of the AO must be registered with the framework
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
Q_ASSERT_INCRIT(620, registry_[p] != nullptr);
// no need to lock the scheduler in the ISR context
QActive *a = registry_[p];
Q_ASSERT_INCRIT(520, a != nullptr);
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
// POST_FROM_ISR() asserts if the queue overflows
registry_[p]->POST_FROM_ISR(e, par, sender);
//QF_SCHED_LOCK_(p); // no scheduler locking in FreeRTOS
do { // loop over all subscribers
// QACTIVE_POST() asserts internally if the queue overflows
a->POST_FROM_ISR(e, par, sender);
subscrSet.remove(p); // remove the handled subscriber
if (subscrSet.notEmpty()) { // still more subscribers?
p = subscrSet.findMax(); // the highest-prio subscriber
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
a = registry_[p];
// the AO must be registered with the framework
Q_ASSERT_INCRIT(530, a != nullptr);
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
}
else {
p = 0U; // no more subscribers
}
} while (p != 0U);
// no need to unlock the scheduler in the ISR context
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
Q_ASSERT_INCRIT(590, p == 0U); // all subscribers processed
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
//QF_SCHED_UNLOCK_(); // no scheduler locking in FreeRTOS
}
#if (QF_MAX_EPOOL > 0U)
// The following garbage collection step decrements the reference counter
// and recycles the event if the counter drops to zero. This covers both
// cases when the event was published with or without any subscribers.
QF::gcFromISR(e);
#endif // (QF_MAX_EPOOL > 0U)
}
//............................................................................
void QTimeEvt::tickFromISR(std::uint_fast8_t const tickRate,
void *pxHigherPriorityTaskWoken,
@ -546,75 +571,47 @@ void QTimeEvt::tickFromISR(std::uint_fast8_t const tickRate,
UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
Q_REQUIRE_INCRIT(700, tickRate < Q_DIM(timeEvtHead_));
Q_REQUIRE_INCRIT(600, tickRate < Q_DIM(timeEvtHead_));
QTimeEvt *prev = &timeEvtHead_[tickRate];
#ifdef Q_SPY
QS_BEGIN_PRE(QS_QF_TICK, 0U)
prev->m_ctr = (prev->m_ctr + 1U);
QS_TEC_PRE(prev->m_ctr); // tick ctr
QS_U8_PRE(tickRate); // tick rate
QS_END_PRE()
#endif // def Q_SPY
// scan the linked-list of time events at this rate...
std::uint_fast8_t lbound = 2U*QF_MAX_ACTIVE; // fixed upper loop bound
for (; lbound > 0U; --lbound) {
Q_ASSERT_INCRIT(710, prev != nullptr); // sanity check
while (true) {
Q_ASSERT_INCRIT(610, prev != nullptr); // sanity check
QTimeEvt *te = prev->m_next; // advance down the time evt. list
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(711,
Q_PTR2UINT_CAST_(te) ==
static_cast<std::uintptr_t>(~prev->m_next_dis));
#endif // ndef Q_UNSAFE
if (te == nullptr) { // end of the list?
// any new time events armed since the last QTimeEvt_tick_()?
if (timeEvtHead_[tickRate].m_act != nullptr) {
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(712,
Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) ==
static_cast<std::uintptr_t>(
~timeEvtHead_dis_[tickRate].m_ptr_dis));
#endif // ndef Q_UNSAFE
// NO any new time events armed since the last QTimeEvt_tick_()?
if (timeEvtHead_[tickRate].m_act == nullptr) {
break; // terminate the for-loop
}
prev->m_next = timeEvtHead_[tickRate].toTimeEvt();
timeEvtHead_[tickRate].m_act = nullptr;
#ifndef Q_UNSAFE
prev->m_next_dis =
static_cast<std::uintptr_t>(
~Q_PTR2UINT_CAST_(prev->m_next));
timeEvtHead_dis_[tickRate].m_ptr_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr));
#endif // ndef Q_UNSAFE
te = prev->m_next; // switch to the new list
}
else { // all currently armed time events are processed
break; // terminate the for-loop
}
}
// the time event 'te' must be valid
Q_ASSERT_INCRIT(720, te != nullptr);
Q_INVARIANT_INCRIT(721, te->verify_());
Q_ASSERT_INCRIT(640, te != nullptr);
QTimeEvtCtr ctr = te->m_ctr;
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(722, ctr ==
static_cast<QTimeEvtCtr>(~te->m_ctr_dis));
#endif // ndef Q_UNSAFE
if (ctr == 0U) { // time event scheduled for removal?
prev->m_next = te->m_next;
#ifndef Q_UNSAFE
prev->m_next_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(te->m_next));
#endif // ndef Q_UNSAFE
// mark time event 'te' as NOT linked
te->m_flags &= static_cast<std::uint8_t>(~QTE_FLAG_IS_LINKED);
// do NOT advance the prev pointer
// exit crit. section to reduce latency
@ -622,42 +619,7 @@ void QTimeEvt::tickFromISR(std::uint_fast8_t const tickRate,
}
else if (ctr == 1U) { // is time event about to expire?
QActive * const act = te->toActive();
if (te->m_interval != 0U) { // periodic time evt?
te->m_ctr = te->m_interval; // rearm the time event
#ifndef Q_UNSAFE
te->m_ctr_dis = static_cast<QTimeEvtCtr>(~te->m_interval);
#endif // ndef Q_UNSAFE
prev = te; // advance to this time event
}
else { // one-shot time event: automatically disarm
te->m_ctr = 0U;
prev->m_next = te->m_next;
#ifndef Q_UNSAFE
te->m_ctr_dis =
static_cast<QTimeEvtCtr>(~static_cast<QTimeEvtCtr>(0U));
prev->m_next_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(te->m_next));
#endif // ndef Q_UNSAFE
// mark time event 'te' as NOT linked
te->m_flags &=
static_cast<std::uint8_t>(~QTE_FLAG_IS_LINKED);
// do NOT advance the prev pointer
QS_BEGIN_PRE(QS_QF_TIMEEVT_AUTO_DISARM, act->m_prio)
QS_OBJ_PRE(te); // this time event object
QS_OBJ_PRE(act); // the target AO
QS_U8_PRE(tickRate); // tick rate
QS_END_PRE()
}
QS_BEGIN_PRE(QS_QF_TIMEEVT_POST, act->m_prio)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(te); // the time event object
QS_SIG_PRE(te->sig); // signal of this time event
QS_OBJ_PRE(act); // the target AO
QS_U8_PRE(tickRate); // tick rate
QS_END_PRE()
prev = te->expire_(prev, act, tickRate);
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
@ -669,9 +631,6 @@ void QTimeEvt::tickFromISR(std::uint_fast8_t const tickRate,
else { // time event keeps timing out
--ctr; // decrement the tick counter
te->m_ctr = ctr; // update the original
#ifndef Q_UNSAFE
te->m_ctr_dis = static_cast<QTimeEvtCtr>(~ctr);
#endif // ndef Q_UNSAFE
prev = te; // advance to this time event
@ -681,16 +640,15 @@ void QTimeEvt::tickFromISR(std::uint_fast8_t const tickRate,
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
}
Q_ENSURE_INCRIT(890, lbound > 0U);
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
}
//............................................................................
QEvt *QF::newXfromISR_(std::uint_fast16_t const evtSize,
std::uint_fast16_t const margin,
enum_t const sig) noexcept
{
// find the pool index that fits the requested event size...
// find the pool number that fits the requested event size...
std::uint_fast8_t poolNum = 0U; // zero-based poolNum initially
for (; poolNum < priv_.maxPool_; ++poolNum) {
if (evtSize <= QF_EPOOL_EVENT_SIZE_(priv_.ePool_[poolNum])) {
@ -702,28 +660,29 @@ QEvt *QF::newXfromISR_(std::uint_fast16_t const evtSize,
// precondition:
// - cannot run out of registered pools
Q_REQUIRE_INCRIT(800, poolNum < priv_.maxPool_);
Q_REQUIRE_INCRIT(700, poolNum < priv_.maxPool_);
++poolNum; // convert to 1-based poolNum
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
// get event e (port-dependent)...
QEvt *e;
#ifdef Q_SPY
QEvt *e = static_cast<QEvt *>(
e = static_cast<QEvt *>(
priv_.ePool_[poolNum - 1U].getFromISR(((margin != QF::NO_MARGIN)
? margin : 0U),
static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum));
#else
QEvt *e = static_cast<QEvt *>(
e = static_cast<QEvt *>(
priv_.ePool_[poolNum - 1U].getFromISR(((margin != QF::NO_MARGIN)
? margin : 0U), 0U));
#endif
if (e != nullptr) { // was e allocated correctly?
e->sig = static_cast<QSignal>(sig); // set the signal
e->poolNum_ = poolNum;
e->refCtr_ = 0U;
e->evtTag_ = static_cast<std::uint8_t>((poolNum << 4U) | 0x0FU);
#ifdef Q_SPY
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
@ -742,7 +701,7 @@ QEvt *QF::newXfromISR_(std::uint_fast16_t const evtSize,
// This assertion means that the event allocation failed,
// and this failure cannot be tolerated. The most frequent
// reason is an event leak in the application.
Q_ASSERT_INCRIT(820, margin != QF::NO_MARGIN);
Q_ASSERT_INCRIT(720, margin != QF::NO_MARGIN);
QS_BEGIN_PRE(QS_QF_NEW_ATTEMPT,
static_cast<uint_fast8_t>(QS_EP_ID) + poolNum)
@ -762,12 +721,9 @@ QEvt *QF::newXfromISR_(std::uint_fast16_t const evtSize,
void QF::gcFromISR(QEvt const * const e) noexcept {
UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
Q_REQUIRE_INCRIT(700, e != nullptr);
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(701, e->verify_());
#endif
Q_REQUIRE_INCRIT(800, e != nullptr);
std::uint_fast8_t const poolNum = e->getPoolNum_();
std::uint_fast8_t const poolNum = e->poolNum_;
if (poolNum != 0U) { // is it a pool event (mutable)?
@ -780,6 +736,7 @@ void QF::gcFromISR(QEvt const * const e) noexcept {
QS_2U8_PRE(poolNum, e->refCtr_);
QS_END_PRE()
Q_ASSERT_INCRIT(805, e->refCtr_ > 0U);
QEvt_refCtr_dec_(e); // decrement the ref counter
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
@ -790,19 +747,19 @@ void QF::gcFromISR(QEvt const * const e) noexcept {
static_cast<uint_fast8_t>(QS_EP_ID) + poolNum)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of the event
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);//poolNum & refCtr
QS_2U8_PRE(poolNum, e->refCtr_);
QS_END_PRE()
// pool number must be in range
Q_ASSERT_INCRIT(710, (poolNum <= priv_.maxPool_)
Q_ASSERT_INCRIT(810, (poolNum <= priv_.maxPool_)
&& (poolNum <= QF_MAX_EPOOL));
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
// NOTE: casting 'const' away is legit because 'e' is a pool event
#ifdef Q_SPY
// cast 'const' away in (QEvt *)e is OK because it's a pool event
priv_.ePool_[poolNum - 1U].putFromISR(QF_CONST_CAST_(QEvt*, e),
static_cast<uint_fast8_t>(QS_EP_ID) + e->getPoolNum_());
static_cast<uint_fast8_t>(QS_EP_ID) + e->poolNum_);
#else
priv_.ePool_[poolNum - 1U].putFromISR(QF_CONST_CAST_(QEvt*, e), 0U);
#endif
@ -823,74 +780,50 @@ void *QMPool::getFromISR(std::uint_fast16_t const margin,
UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
// get volatile into temporaries
QFreeBlock *fb = m_free_head;
void * *pfb = static_cast<void**>(m_freeHead); // pointer to free block
QMPoolCtr nFree = m_nFree;
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(801, Q_PTR2UINT_CAST_(fb)
== static_cast<std::uintptr_t>(~m_free_head_dis));
Q_INVARIANT_INCRIT(802, nFree == static_cast<QMPoolCtr>(~m_nFree_dis));
#endif // ndef Q_UNSAFE
// have more free blocks than the requested margin?
if (nFree > static_cast<QMPoolCtr>(margin)) {
Q_ASSERT_INCRIT(810, fb != nullptr);
Q_ASSERT_INCRIT(910, pfb != nullptr);
QFreeBlock * const fb_next = fb->m_next;
#ifndef Q_UNSAFE
// the free block must have integrity (duplicate inverse storage)
Q_INVARIANT_INCRIT(811, Q_PTR2UINT_CAST_(fb_next)
== static_cast<std::uintptr_t>(~fb->m_next_dis));
#endif // ndef Q_UNSAFE
void ** const pfb_next = static_cast<void**>(pfb[0]); // fast temporary
--nFree; // one less free block
if (nFree == 0U) { // is the pool becoming empty?
// pool is becoming empty, so the next free block must be NULL
Q_ASSERT_INCRIT(820, fb_next == nullptr);
Q_ASSERT_INCRIT(920, pfb_next == nullptr);
m_nFree = 0U;
#ifndef Q_UNSAFE
m_nFree_dis = static_cast<QMPoolCtr>(~m_nFree);
m_nFree = 0U; // no more free blocks
m_nMin = 0U; // remember that the pool got empty
#endif // ndef Q_UNSAFE
}
else {
else { // the pool is NOT empty
// the next free-block pointer must be in range
Q_INVARIANT_INCRIT(930,
QF_PTR_RANGE_(pfb_next, m_start, m_end));
m_nFree = nFree; // update the original
#ifndef Q_UNSAFE
m_nFree_dis = static_cast<QMPoolCtr>(~nFree);
// The pool is not empty, so the next free-block pointer
// must be in range.
Q_INVARIANT_INCRIT(830,
QF_PTR_RANGE_(fb_next, m_start, m_end));
// is the # free blocks the new minimum so far?
if (m_nMin > nFree) {
if (m_nMin > nFree) { // is this the new minimum?
m_nMin = nFree; // remember the minimum so far
}
#endif // ndef Q_UNSAFE
}
m_free_head = fb_next; // set the head to the next free block
#ifndef Q_UNSAFE
m_free_head_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(fb_next));
#endif // ndef Q_UNSAFE
m_freeHead = pfb_next; // set the head to the next free block
// change the allocated block contents so that it is different
// than a free block inside the pool.
pfb[0] = &m_end[1]; // invalid location beyond the end
QS_BEGIN_PRE(QS_QF_MPOOL_GET, qsId)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(this); // this memory pool
QS_MPC_PRE(nFree); // # of free blocks in the pool
#ifndef Q_UNSAFE
QS_MPC_PRE(nFree); // # free blocks in the pool
QS_MPC_PRE(m_nMin); // min # free blocks ever in the pool
#else
QS_MPC_PRE(0U); // min # free blocks (not available)
#endif // ndef Q_UNSAFE
QS_END_PRE()
}
else { // don't have enough free blocks at this point
fb = nullptr;
pfb = nullptr;
QS_BEGIN_PRE(QS_QF_MPOOL_GET_ATTEMPT, qsId)
QS_TIME_PRE(); // timestamp
@ -902,7 +835,7 @@ void *QMPool::getFromISR(std::uint_fast16_t const margin,
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
return fb; // return the block or nullptr to the caller
return pfb; // return the block or nullptr to the caller
}
//............................................................................
void QMPool::putFromISR(void *block,
@ -912,33 +845,22 @@ void QMPool::putFromISR(void *block,
Q_UNUSED_PAR(qsId);
#endif
QFreeBlock * const fb = static_cast<QFreeBlock *>(block);
void * * const pfb = static_cast<void**>(block);
UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
// get volatile into temporaries
QFreeBlock * const free_head = m_free_head;
void ** const freeHead = static_cast<void**>(m_freeHead);
QMPoolCtr nFree = m_nFree;
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(901, Q_PTR2UINT_CAST_(free_head)
== static_cast<std::uintptr_t>(~m_free_head_dis));
Q_INVARIANT_INCRIT(902, nFree == static_cast<QMPoolCtr>(~m_nFree_dis));
#endif // ndef Q_UNSAFE
Q_REQUIRE_INCRIT(910, nFree < m_nTot);
Q_REQUIRE_INCRIT(911, QF_PTR_RANGE_(fb, m_start, m_end));
Q_REQUIRE_INCRIT(1000, nFree < m_nTot);
Q_REQUIRE_INCRIT(1010, QF_PTR_RANGE_(pfb, m_start, m_end));
++nFree; // one more free block in this pool
m_free_head = fb; // set as new head of the free list
m_freeHead = pfb; // set as new head of the free list
m_nFree = nFree;
fb->m_next = free_head; // link into the list
#ifndef Q_UNSAFE
m_free_head_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(fb));
m_nFree_dis = static_cast<QMPoolCtr>(~nFree);
fb->m_next_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(free_head));
#endif
pfb[0] = freeHead; // link into the list
QS_BEGIN_PRE(QS_QF_MPOOL_PUT, qsId)
QS_TIME_PRE(); // timestamp

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to FreeRTOS 10.x generic C++11 compiler
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to MSP430, preemptive QK kernel
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 16-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ to MSP40, QUTEST unit test harness, generic C++11 compiler
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
@ -42,12 +36,8 @@
// no-return function specifier (C++11 Standard)
#define Q_NORETURN [[ noreturn ]] void
// QF configuration for QK -- data members of the QActive class...
// QActive event queue type
#define QACTIVE_EQUEUE_TYPE QEQueue
// QACTIVE_OS_OBJ_TYPE not used in this port
// QACTIVE_THREAD_TYPE not used in this port
// QF interrupt disable/enable
#define QF_INT_DISABLE() (++QP::QF::intLock_)
@ -74,26 +64,21 @@
//============================================================================
// interface used only inside QF implementation, but not in applications
#ifdef QP_IMPL
// QUTest scheduler locking (not used)
#define QF_SCHED_STAT_
#define QF_SCHED_LOCK_(dummy) ((void)0)
#define QF_SCHED_UNLOCK_() ((void)0)
#define QF_SCHED_LOCK_(dummy) (static_cast<void>(0))
#define QF_SCHED_UNLOCK_() (static_cast<void>(0))
// native event queue operations
// native QEQueue operations
#define QACTIVE_EQUEUE_WAIT_(me_) (static_cast<void>(0))
#ifndef Q_UNSAFE
#define QACTIVE_EQUEUE_SIGNAL_(me_) \
QF::readySet_.insert(static_cast<std::uint_fast8_t>((me_)->m_prio));
QF::readySet_.update_(&QF::readySet_dis)
#else
#define QACTIVE_EQUEUE_SIGNAL_(me_) \
QF::readySet_.insert(static_cast<std::uint_fast8_t>((me_)->m_prio))
#endif
(QP::QS::tstPriv_.readySet.insert( \
static_cast<std::uint_fast8_t>((me_)->m_prio)))
// native QF event pool operations
// native QMPool operations
#define QF_EPOOL_TYPE_ QMPool
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \
(p_).init((poolSto_), (poolSize_), (evtSize_))

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 16-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to MSP430, cooperative QV kernel
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 16-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -1,32 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-19
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QF/C++ port to POSIX-QV (single-threaded)
// expose features from the 2008 POSIX standard (IEEE Standard 1003.1-2008)
#define _POSIX_C_SOURCE 200809L
@ -188,9 +188,6 @@ void init() {
pthread_cond_init(&condVar_, NULL);
readySet_.setEmpty();
#ifndef Q_UNSAFE
readySet_.update_(&readySet_dis_);
#endif
// lock memory so we're never swapped out to disk
//mlockall(MCL_CURRENT | MCL_FUTURE); // un-comment when supported
@ -282,9 +279,6 @@ int run() {
QF_CRIT_ENTRY();
if (a->getEQueue().isEmpty()) { // empty queue?
readySet_.remove(p);
#ifndef Q_UNSAFE
readySet_.update_(&readySet_dis_);
#endif
}
}
else {
@ -318,9 +312,6 @@ void stop() {
// unblock the event-loop so it can terminate
readySet_.insert(1U);
#ifndef Q_UNSAFE
readySet_.update_(&readySet_dis_);
#endif
pthread_cond_signal(&condVar_);
}
//............................................................................
@ -406,9 +397,6 @@ void QActive::stop() {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF::readySet_.remove(m_prio);
#ifndef Q_UNSAFE
QF::readySet_.update_(&QF::readySet_dis_);
#endif
QF_CRIT_EXIT();
unregister_();

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to POSIX-QV (signgle threaded), generic C++11
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
@ -97,16 +91,9 @@ void onClockTick();
// QF event queue customization for POSIX-QV...
#define QACTIVE_EQUEUE_WAIT_(me_) (static_cast<void>(0))
#ifndef Q_UNSAFE
#define QACTIVE_EQUEUE_SIGNAL_(me_) \
QF::readySet_.insert((me_)->m_prio); \
QF::readySet_.update_(&QF::readySet_dis_); \
pthread_cond_signal(&QP::QF::condVar_)
#else
#define QACTIVE_EQUEUE_SIGNAL_(me_) \
QF::readySet_.insert((me_)->m_prio); \
pthread_cond_signal(&QP::QF::condVar_)
#endif
// native QF event pool operations
#define QF_EPOOL_TYPE_ QMPool

View File

@ -1,38 +1,38 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// 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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-07-18
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to POSIX
// expose features from the 2008 POSIX standard (IEEE Standard 1003.1-2008)
#define _POSIX_C_SOURCE 200809L
#ifndef Q_SPY
#error "Q_SPY must be defined to compile qs_port.cpp"
#error Q_SPY must be defined to compile qs_port.cpp
#endif // Q_SPY
#define QP_IMPL // this is QP implementation

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to POSIX/Win32
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -1,32 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-19
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QF/C++ port to POSIX (multithreaded with P-threads)
// expose features from the 2008 POSIX standard (IEEE Standard 1003.1-2008)
#define _POSIX_C_SOURCE 200809L

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to POSIX (multithreaded with P-threads), generic C++11
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_

View File

@ -1,38 +1,38 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// 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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-07-18
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to POSIX
// expose features from the 2008 POSIX standard (IEEE Standard 1003.1-2008)
#define _POSIX_C_SOURCE 200809L
#ifndef Q_SPY
#error "Q_SPY must be defined to compile qs_port.cpp"
#error Q_SPY must be defined to compile qs_port.cpp
#endif // Q_SPY
#define QP_IMPL // this is QP implementation

View File

@ -1,38 +1,32 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to POSIX/Win32
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C dummy port
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_

View File

@ -7,7 +7,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -25,12 +25,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-26
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QF/C++ port to ThreadX (a.k.a. Azure RTOS), generic C++11 compiler
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -165,9 +159,6 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin,
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(200, e != nullptr);
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(201, e->verify_());
#endif // ndef Q_UNSAFE
std::uint_fast16_t nFree =
static_cast<std::uint_fast16_t>(m_eQueue.tx_queue_available_storage);
@ -196,12 +187,13 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin,
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object (recipient)
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(nFree); // # free entries available
QS_EQC_PRE(0U); // min # free entries (unknown)
QS_END_PRE()
if (e->getPoolNum_() != 0U) { // is it a pool event?
if (e->poolNum_ != 0U) { // is it a pool event?
Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e); // increment the reference counter
}
QF_CRIT_EXIT();
@ -220,7 +212,7 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin,
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object (recipient)
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(nFree); // # free entries
QS_EQC_PRE(0U); // min # free entries (unknown)
QS_END_PRE()
@ -236,21 +228,18 @@ void QActive::postLIFO(QEvt const * const e) noexcept {
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(300, e != nullptr);
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(301, e->verify_());
#endif // ndef Q_UNSAFE
QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(m_eQueue.tx_queue_available_storage); // # free
QS_EQC_PRE(0U); // min # free entries (unknown)
QS_END_PRE()
if (e->getPoolNum_() != 0U) { // is it a pool event?
if (e->poolNum_ != 0U) { // is it a pool event?
Q_ASSERT_INCRIT(305, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e); // increment the reference counter
}
QF_CRIT_EXIT();
@ -276,7 +265,7 @@ QEvt const *QActive::get_(void) noexcept {
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(m_eQueue.tx_queue_available_storage); // # free
QS_END_PRE()
QF_CRIT_EXIT();

View File

@ -1,6 +1,4 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
@ -9,7 +7,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +25,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to ThreadX (a.k.a, Azure RTOS), generic C++11 compiler
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
@ -53,7 +45,7 @@
#ifndef QF_MAX_ACTIVE
#define QF_MAX_ACTIVE (TX_MAX_PRIORITIES - QF_TX_PRIO_OFFSET)
#else
#error "QF_MAX_ACTIVE shouild not be externally defined in QP-ThreadX port"
#error QF_MAX_ACTIVE shouild not be externally defined in QP-ThreadX port
#endif
// mapping between QF-priority and TX-priority, see NOTE1

View File

@ -1,38 +1,30 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -7,7 +7,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -25,12 +25,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-26
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QF/C++ port to uC-OS2 RTOS, generic C++11 compiler
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -207,9 +201,6 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin,
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(200, e != nullptr);
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(201, e->verify_());
#endif
std::uint_fast16_t const nFree = static_cast<std::uint_fast16_t>(
reinterpret_cast<OS_Q_DATA *>(m_eQueue)->OSQSize
@ -239,12 +230,13 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin,
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object (recipient)
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(nFree); // # free entries
QS_EQC_PRE(0U); // min # free entries (unknown)
QS_END_PRE()
if (e->getPoolNum_() != 0U) { // is it a pool event?
if (e->poolNum_ != 0U) { // is it a pool event?
Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e); // increment the reference counter
}
QF_CRIT_EXIT();
@ -267,7 +259,7 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin,
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object (recipient)
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(nFree); // # free entries available
QS_EQC_PRE(margin); // margin requested
QS_END_PRE()
@ -283,22 +275,20 @@ void QActive::postLIFO(QEvt const * const e) noexcept {
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(300, e != nullptr);
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(301, e->verify_());
#endif
QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
// # free entries
QS_EQC_PRE(reinterpret_cast<OS_Q *>(m_eQueue)->OSQSize
- reinterpret_cast<OS_Q *>(m_eQueue)->OSQEntries);
QS_EQC_PRE(0U); // min # free entries (unknown)
QS_END_PRE()
if (e->getPoolNum_() != 0U) { // is it a pool event?
if (e->poolNum_ != 0U) { // is it a pool event?
Q_ASSERT_INCRIT(305, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e); // increment the reference counter
}
QF_CRIT_EXIT();
@ -328,7 +318,7 @@ QEvt const *QActive::get_(void) noexcept {
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
// # free entries
QS_EQC_PRE(reinterpret_cast<OS_Q *>(m_eQueue)->OSQSize
- reinterpret_cast<OS_Q *>(m_eQueue)->OSQEntries);

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to uC-OS2 RTOS, generic C++11 compiler
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_

View File

@ -1,38 +1,30 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <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>
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -22,12 +22,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-19
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QF/C++ port to Win32 (single-threaded, like the QV kernel)
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -114,10 +108,6 @@ void init() {
win32Event_ = CreateEvent(NULL, FALSE, FALSE, NULL);
readySet_.setEmpty();
#ifndef Q_UNSAFE
readySet_.update_(&readySet_dis_);
#endif
}
//............................................................................
@ -149,8 +139,6 @@ int run() {
QS_END_PRE()
while (l_isRunning) {
Q_ASSERT_INCRIT(300, readySet_.verify_(&readySet_dis_));
// find the maximum priority AO ready to run
if (readySet_.notEmpty()) {
std::uint_fast8_t p = readySet_.findMax();
@ -169,9 +157,6 @@ int run() {
QF_CRIT_ENTRY();
if (a->getEQueue().isEmpty()) { // empty queue?
readySet_.remove(p);
#ifndef Q_UNSAFE
readySet_.update_(&readySet_dis_);
#endif
}
}
else {
@ -200,9 +185,6 @@ void stop() {
// unblock the event-loop so it can terminate
readySet_.insert(1U);
#ifndef Q_UNSAFE
readySet_.update_(&readySet_dis_);
#endif
SetEvent(win32Event_);
}
//............................................................................
@ -272,9 +254,6 @@ void QActive::stop() {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF::readySet_.remove(m_prio);
#ifndef Q_UNSAFE
QF::readySet_.update_(&QF::readySet_dis_);
#endif
QF_CRIT_EXIT();
unregister_(); // remove this AO from QF

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to Win32-QV (single-threaded), generic C++11
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
@ -104,16 +98,9 @@ void onClockTick();
// QF event queue customization for Win32-QV...
#define QACTIVE_EQUEUE_WAIT_(me_) (static_cast<void>(0))
#ifndef Q_UNSAFE
#define QACTIVE_EQUEUE_SIGNAL_(me_) \
QF::readySet_.insert((me_)->m_prio); \
QF::readySet_.update_(&QF::readySet_dis_); \
static_cast<void>(SetEvent(QP::QF::win32Event_))
#else
#define QACTIVE_EQUEUE_SIGNAL_(me_) \
QF::readySet_.insert((me_)->m_prio); \
static_cast<void>(SetEvent(QP::QF::win32Event_))
#endif
// native QF event pool operations
#define QF_EPOOL_TYPE_ QMPool

View File

@ -22,15 +22,8 @@
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-11
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to Win32 API
//!
#ifndef Q_SPY
#error "Q_SPY must be defined to compile qs_port.cpp"
#error Q_SPY must be defined to compile qs_port.cpp
#endif // Q_SPY
#define QP_IMPL // this is QP implementation

View File

@ -27,12 +27,6 @@
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to POSIX/Win32
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

View File

@ -22,12 +22,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-19
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QF/C++ port to Win32 (multithreaded)
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface

View File

@ -9,7 +9,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to Win32 (multithreaded), generic C++11
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
@ -104,7 +98,8 @@ void onClockTick();
#define QACTIVE_EQUEUE_WAIT_(me_) \
while ((me_)->m_eQueue.m_frontEvt == nullptr) { \
QF_CRIT_EXIT(); \
static_cast<void>(WaitForSingleObject((me_)->m_osObject, INFINITE)); \
static_cast<void>(WaitForSingleObject( \
(me_)->m_osObject, INFINITE)); \
QF_CRIT_ENTRY(); \
}

View File

@ -22,15 +22,8 @@
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-11
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to Win32 API
//!
#ifndef Q_SPY
#error "Q_SPY must be defined to compile qs_port.cpp"
#error Q_SPY must be defined to compile qs_port.cpp
#endif // Q_SPY
#define QP_IMPL // this is QP implementation

View File

@ -27,12 +27,6 @@
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-06-06
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QS/C++ port to POSIX/Win32
#ifndef QS_PORT_HPP_
#define QS_PORT_HPP_

6731
qpcpp.qm

File diff suppressed because it is too large Load Diff

View File

@ -1,162 +0,0 @@
bda783a346fb750c7a1fe32dc0a8ca52609cb5f4 *qpcpp.qm
46578fc304c597329289978acee1027c8c533335 *include/qequeue.hpp
1a8e0b05536b89c1cd3806782ae1a21dd4ceca69 *include/qk.hpp
cb1c39aabacb619060924356f7c8e900686538e0 *include/qmpool.hpp
559a9ca895f97f38c5d3bb0511675f321e041911 *include/qp.hpp
bf47a939e525fa575673f89b8106bcee166240a2 *include/qp_pkg.hpp
e5b0d14c9e6994b82a5cd9200bde46bd179bfb20 *include/qpcpp.hpp
d4f14d2ed18ef725ea17d0a97b78ae22a283c96b *include/qs.hpp
88220a7d892fee54053b467b596dc6b536aaf8be *include/qs_dummy.hpp
9694f10e44d53563599410d37dd1c5a19cf1788b *include/qs_pkg.hpp
49d2620b0afa9e74d73680495c3e8a931e5d8f73 *include/qsafe.h
09e9ffe95120ba17a49d7039b5316f2614710dab *include/qstamp.hpp
73749ed396bbc0419971769a47069448c8136960 *include/qv.hpp
05b617dad20f07f07b64dccf84f9b7cd9b8d2bb7 *include/qxk.hpp
0199f3eeb6c02b8cc890ee4c6f6d344569a0858f *include/README.md
71899ce74eeb04f333ed00d53f87719f722a39ab *src/qf/CMakeLists.txt
864d627f2600987a2194c57093e1f210e0de2a7a *src/qf/qep_hsm.cpp
d3242def2b23df5b9704bb3b0411fd01de6c0a67 *src/qf/qep_msm.cpp
62f87a60d04e1c98f40162a166ec14a1f2f1252f *src/qf/qf_act.cpp
07671fb85e9b2492b0ea37b853d7e0eea42bf637 *src/qf/qf_actq.cpp
ed83f5f8b3533cc97ffc2a85aeeb63f29b4f1dd8 *src/qf/qf_defer.cpp
f41d8815460d26f5bbf89e40dcb607b6a3ddeaa8 *src/qf/qf_dyn.cpp
974493184d40e0a2f698c6e63e0bc450343ef591 *src/qf/qf_mem.cpp
ef51e4840107b0ed6ec97e170ac2689e1b1fdb95 *src/qf/qf_ps.cpp
08b490d7505a7ff6fe493058975eb9f0a82daa3d *src/qf/qf_qact.cpp
23892cde4fd7226e899026884e07b01e32d0aef4 *src/qf/qf_qeq.cpp
5fc4874b74779641454e2d8e7960a5bf3d130115 *src/qf/qf_qmact.cpp
04dd9fbddc336f096bd214f8e7368d7a6dce43c8 *src/qf/qf_time.cpp
7cdab433e81612862fd27f0cf792d38e1197d064 *src/qk/CMakeLists.txt
1be4743dc14186779abb96b4bd16ba9a99d3314d *src/qk/qk.cpp
eb28260d471fc752ca54b2c1e2d763f28432c2c1 *src/qs/CMakeLists.txt
66fd2a553c8ae6709dfe286b6ccce002208251f1 *src/qs/qs.cpp
2ca73a0d38dd7b544864d72fd337f29c7dae2a85 *src/qs/qs_64bit.cpp
349c18625bd2cceda297e1c98a85a9fa9538cef9 *src/qs/qs_fp.cpp
ad4e3a9faacc038cb51a7773ffc42903be947a22 *src/qs/qs_rx.cpp
8008d9c24757b2bb02e85123aa89a3a33090921d *src/qs/qstamp.cpp
92338453dc612419b0e16e0560e761312d0f3900 *src/qs/qutest.cpp
b6d93a16f5b176d3da4888a7efb265730337f46d *src/qv/CMakeLists.txt
f530563e062ff7ea84763f6e799bf4ca1cb73054 *src/qv/qv.cpp
2d0c3d3d93e4d4ac8e2218b9ed68e6269b02419e *src/qxk/qxk.cpp
e0e633a980e4c04a85f877e810ce77ad51903e87 *src/qxk/qxk_mutex.cpp
8e15812d14f250866dfa8a96fe5b14638ca2c4ae *src/qxk/qxk_sema.cpp
58e6a9354a1c7c4d53204b7ad2fad05d6eb3117c *src/qxk/qxk_xthr.cpp
81f1a6dbcebd0b5df9e437902ffbe0fecdd03d25 *ports/arm-cm/qk/armclang/qk_port.cpp
7119fc94c0b5560ab8e3197a83917667e311e415 *ports/arm-cm/qk/armclang/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/armclang/qs_port.hpp
5f2353117f9940b0ea891d2e0bd486e0d024b67c *ports/arm-cm/qk/gnu/qk_port.cpp
7119fc94c0b5560ab8e3197a83917667e311e415 *ports/arm-cm/qk/gnu/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/gnu/qs_port.hpp
2b9c1112e3e5be79ce2b1799adfd5e812467765b *ports/arm-cm/qk/iar/qk_port.cpp
f54416674c33ffd19408f02af60f7d69b8613797 *ports/arm-cm/qk/iar/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/iar/qs_port.hpp
9cc71aed12d57408252019035aff449ce028372c *ports/arm-cm/qv/armclang/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/armclang/qs_port.hpp
90b14adcd8f8b29de3358073c39bd4161f5ce2eb *ports/arm-cm/qv/armclang/qv_port.cpp
bed3687b29555f6fa9c721cf34a098218f64e1ad *ports/arm-cm/qv/gnu/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/gnu/qs_port.hpp
b2d5e72b65813bdc37bcab3c8cd9107bda009131 *ports/arm-cm/qv/gnu/qv_port.cpp
424864680661227e4ab418b2af905d4bd92767ad *ports/arm-cm/qv/iar/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/iar/qs_port.hpp
15fb0660dff33295bad38facfc7aacca928133a3 *ports/arm-cm/qv/iar/qv_port.cpp
9e248cb426d8495e5cd677ff79cd3b9ced2a76a5 *ports/arm-cm/qxk/armclang/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qxk/armclang/qs_port.hpp
16423aebab91be16d8c2c7b128d8494709a6a746 *ports/arm-cm/qxk/armclang/qxk_port.cpp
9ec8ed9717f9130b23252d2c381f779617165932 *ports/arm-cm/qxk/gnu/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qxk/gnu/qs_port.hpp
75fc7a6c1b0775832f3e0e0e2bbacc19f56ddc94 *ports/arm-cm/qxk/gnu/qxk_port.cpp
f40b0ea4761d187ac7d4460a161efb9b4f3e6ef6 *ports/arm-cm/qxk/iar/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qxk/iar/qs_port.hpp
44509ff079ba173a28076f3fa1488582a6ef48a1 *ports/arm-cm/qxk/iar/qxk_port.cpp
69256fd1a5b81db3e3174cba9196bf9da925e098 *ports/arm-cm/qutest/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qutest/qs_port.hpp
1194c26fdfc9665a04cc3d01e6de49afe1698376 *ports/arm-cr/qk/gnu/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/gnu/qs_port.hpp
a8f4351725564e449206909176d09bc58cd6f45d *ports/arm-cr/qk/iar/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/iar/qs_port.hpp
7203200deaa5dbb4746434d4a3d79a160d4ccf4b *ports/arm-cr/qk/ti/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/ti/qs_port.hpp
fd3e4b882efb671f2522ae83bfde016ea416d4a7 *ports/arm-cr/qv/gnu/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qv/gnu/qs_port.hpp
fafbe56ae4266a412cb1b6db6e146fbfe5022b4a *ports/arm-cr/qv/iar/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qv/iar/qs_port.hpp
78d39f7479a0ea046e77607740e4211d9e4cb60f *ports/arm-cr/qv/ti/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qv/ti/qs_port.hpp
bc080e68d0edfc28da2df882ed3661cf99f2942c *ports/msp430/qk/qp_port.hpp
197ec45394793b79a29afe5bb31b6de1ad78ad00 *ports/msp430/qk/qs_port.hpp
7b2654746a747c427b5ee1dd7f8b4b82c372a040 *ports/msp430/qv/qp_port.hpp
197ec45394793b79a29afe5bb31b6de1ad78ad00 *ports/msp430/qv/qs_port.hpp
650f628d87a39c559a87c6f849c58fb9a8e777a7 *ports/msp430/qutest/qp_port.hpp
197ec45394793b79a29afe5bb31b6de1ad78ad00 *ports/msp430/qutest/qs_port.hpp
8614593b911e6db6f634d972e79093e964756556 *ports/config/qp_config.hpp
b6b5d23c618976a6fbed51dc5a13e227928e1d4b *ports/embos/CMakeLists.txt
0b5ad806f47800c1481c9af3d88c1bff3cb1d784 *ports/embos/qf_port.cpp
5e28aa0e89239f970e4b5e85be4e5c3b6a34dd69 *ports/embos/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/embos/qs_port.hpp
e4f00894f86806af6d88d38e831a8fc0ad36059e *ports/freertos/CMakeLists.txt
699baf504d4d3df68b0e66196c48516490e795be *ports/freertos/qf_port.cpp
c7efbc2cc8425c0e21d5bd892584b3e2ff7a145b *ports/freertos/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/freertos/qs_port.hpp
18df978f665338c757f1a2a284c2acc779bd59d3 *ports/threadx/CMakeLists.txt
90717daaf983e8425a9939d17f732ce3d4646bb4 *ports/threadx/qf_port.cpp
f0d61f6806b0207e56dd75f8aaac55c4b1393996 *ports/threadx/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/threadx/qs_port.hpp
46699d3c8ad92f9c98ea5e03e72d4190a7794aa4 *ports/threadx/README.md
0ab8b95f50fa767b951c6f56efe86789623b7127 *ports/uc-os2/CMakeLists.txt
3624f6191213536a8be528185d97d1e35b1fa369 *ports/uc-os2/qf_port.cpp
528d3c2c337c639f3879d24da74369facea0bca6 *ports/uc-os2/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/uc-os2/qs_port.hpp
227dedab24f1e20440103a0cabc210b4b5adedef *ports/qep-only/CMakeLists.txt
6d75bdbb41cd68d2fcab63d0eb8ff91f96f52c24 *ports/qep-only/qp_port.hpp
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/qep-only/safe_std.h
12255313ebcf963d29d91bee4c917bb6ab2f9e1d *ports/posix/CMakeLists.txt
9119c0c12ecc34d41cba8da898496c1f99ea47ac *ports/posix/qf_port.cpp
56956443bf38d12075ce2ddc53f8a0e8b86f135b *ports/posix/qp_port.hpp
66922bad40ecb6b213858f935849569713457f71 *ports/posix/qs_port.cpp
f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/posix/qs_port.hpp
e6a5523e16619370638f6305687cd480d1e3744b *ports/posix/README.md
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix/safe_std.h
493900b9aa5475785c65458332995a184690d43f *ports/posix-qv/CMakeLists.txt
819137bb54242fd0279ed152fe874decb9fd3c16 *ports/posix-qv/qf_port.cpp
f458af1511007d6ba2a4a0a0e40d74e03719ceb1 *ports/posix-qv/qp_port.hpp
66922bad40ecb6b213858f935849569713457f71 *ports/posix-qv/qs_port.cpp
f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/posix-qv/qs_port.hpp
e2e295c371bc14f0089a888b07d98c657dea07bf *ports/posix-qv/README.md
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix-qv/safe_std.h
c9969a454b540a3b1abd3dd5cc46fb211663310e *ports/posix-qutest/CMakeLists.txt
edfa2baff22735f98a094e315db11c40ed07e5e8 *ports/posix-qutest/qp_port.hpp
f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/posix-qutest/qs_port.hpp
772fdcf6a4ca3e3303016384de92874ec06c11fe *ports/posix-qutest/qutest_port.cpp
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix-qutest/safe_std.h
06b76c6c30ea880876b47ee27115178ff62ea66b *ports/win32/CMakeLists.txt
48dfd18fce993f237138d5d99f2fb0e385efbe93 *ports/win32/qf_port.cpp
ea88910c991455756433cff5338a62ed3d181bf2 *ports/win32/qp_port.hpp
6e6aef4b105bd807de96922fcb5698b695fce7e2 *ports/win32/qs_port.cpp
f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/win32/qs_port.hpp
40f18295a0013cbba3c6b270d1d70748ec1d325a *ports/win32/qwin_gui.c
ddc62932b46bbc0ad147193d0dd7efa28127c6c4 *ports/win32/qwin_gui.h
ad6de94157c477eacb61f321870b5f8c1a09a5cd *ports/win32/README.md
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32/safe_std.h
dd5b9a8736e1a1171f7d8565e29e1acb6f7a9691 *ports/win32-qv/CMakeLists.txt
55381dce63d87ddee340d5a153f6054c4fbf5c0e *ports/win32-qv/qf_port.cpp
b2c8d14a04c2bbf3f6f0f3dae097e485a55dc008 *ports/win32-qv/qp_port.hpp
6e6aef4b105bd807de96922fcb5698b695fce7e2 *ports/win32-qv/qs_port.cpp
f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/win32-qv/qs_port.hpp
40f18295a0013cbba3c6b270d1d70748ec1d325a *ports/win32-qv/qwin_gui.c
ddc62932b46bbc0ad147193d0dd7efa28127c6c4 *ports/win32-qv/qwin_gui.h
ddd27415c3d1df6d8c210966e8915c407b15bf58 *ports/win32-qv/README.md
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32-qv/safe_std.h
3c23c06f425a8d8dbb18d1f191ac6cab483a8e51 *ports/win32-qutest/CMakeLists.txt
edfa2baff22735f98a094e315db11c40ed07e5e8 *ports/win32-qutest/qp_port.hpp
f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/win32-qutest/qs_port.hpp
5bda26c8c82914e6cc16685e4adc02cbc32c5291 *ports/win32-qutest/qutest_port.cpp
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32-qutest/safe_std.h
76dd9078dc4311d53d3862d44177a8660258da6d *zephyr/CMakeLists.txt
36a0252cf0bfd6be0d345c48c00b2300f8917f05 *zephyr/Kconfig
2eb2a922e18b4760a68151ebee1b6282d20b4692 *zephyr/module.yml
36ceff869a883b6cb0a262755e3bf03d790f3a87 *zephyr/qf_port.cpp
109c291df50110f185adc17bcdf8becc0a79346c *zephyr/qp-zephyr.jpg
76548c9e125899106122946cdba17b7da1a32c91 *zephyr/qp_port.hpp
d414f620c05844bbad1988f0951509856acc63db *zephyr/qs_port.hpp
50863abaf410b184dbe28b36f6e63b74e26af26e *zephyr/qutest_port.cpp
791248d57ce8dfa6497728c7c2d0734c2c581625 *zephyr/README.md

163
qpcpp_8.0.2.sha1 Normal file
View File

@ -0,0 +1,163 @@
10c35486e20dc82668e4a77ec1a4cc427ba92b21 *include/qequeue.hpp
2af472589274db820aa2a3e7928d7100d2f87cb3 *include/qk.hpp
7394e76571868dfaea3c297e9d00e9f429cbdc3c *include/qmpool.hpp
acc36cf4768e1707256f9891edb39850ad754ab0 *include/qp.hpp
4a28afe5b5fabfa5ce45c2eb07c63388d8cd92b1 *include/qp_pkg.hpp
c8c44d7959d255f98aac76f6040433aaa20956b6 *include/qpcpp.hpp
0b4b406267c65182e40565ce01f510554827f005 *include/qs.hpp
40f446662e01fcd410b0be8f7813dcd86995f22a *include/qs_dummy.hpp
007ade6761260b32bf34ebaaea633977f0cff881 *include/qs_pkg.hpp
cf142966637ce4c4ae831017e8a77fb1fe3a678a *include/qsafe.h
87c77d984d77178533b4e76eb204c4e265b23e9e *include/qstamp.hpp
0e7a9cc9d0511828380e5cd5ee2d7f35ed1bf317 *include/qv.hpp
1cb8c24e0188d17c3c0ca4c12fe88f8c04a9e1e7 *include/qxk.hpp
0199f3eeb6c02b8cc890ee4c6f6d344569a0858f *include/README.md
71899ce74eeb04f333ed00d53f87719f722a39ab *src/qf/CMakeLists.txt
750abbc6caf645de293f5107b10fba3fdbb107c9 *src/qf/qep_hsm.cpp
875f0a15305079a6d5861d66fbcceb8333e9b75b *src/qf/qep_msm.cpp
43eef9ea75c14b1378fc01772bf5e4bdc0621ba2 *src/qf/qf_act.cpp
a8608d5b17afbe82161b01bf0a2edfdc8bbc5a44 *src/qf/qf_actq.cpp
42aa87da9938aea033cda394b2677743d9733149 *src/qf/qf_defer.cpp
19e4d2302186284364543182f6f5af5133516827 *src/qf/qf_dyn.cpp
a06e9252217812cebd30b93fee4c0e4892b7e8e3 *src/qf/qf_mem.cpp
91de7f212c546469f0b7ac9127ccc02860bd6abe *src/qf/qf_ps.cpp
dffd53a967ea218a38c23e71d1aec228a5641b66 *src/qf/qf_qact.cpp
1171eac0c4d4a69a1994e0e9461b785d5ce9803b *src/qf/qf_qeq.cpp
06a3f2fc2b976f7948cac34a434b00ebfbf4a198 *src/qf/qf_qmact.cpp
685aaac6419b8e86e8d6a8029bd2210bb582322c *src/qf/qf_time.cpp
7cdab433e81612862fd27f0cf792d38e1197d064 *src/qk/CMakeLists.txt
5c7393e1bf2f1f336ffda9b4ccfda7849bae6842 *src/qk/qk.cpp
eb28260d471fc752ca54b2c1e2d763f28432c2c1 *src/qs/CMakeLists.txt
450e30ae7919195dc76d934297e3bacd39eed7dc *src/qs/qs.cpp
a49e4cc82d27458d880e3cea5edf7111228b5c83 *src/qs/qs_64bit.cpp
a79389856629896857f68345a0aa908c07d5ac92 *src/qs/qs_fp.cpp
0f206dfea5178ff9d5217b64d112053abb415627 *src/qs/qs_rx.cpp
6e68d4e35a2743c33c45792c922ce065639b8bf5 *src/qs/qstamp.cpp
b4a201fc64467596edadda63dd7f0c8e8344f99d *src/qs/qutest.cpp
b6d93a16f5b176d3da4888a7efb265730337f46d *src/qv/CMakeLists.txt
1588af3ba142febd147eace532cd1993c53a0d11 *src/qv/qv.cpp
2242492063a43fbb9d1725bc243ab30018634bfc *src/qxk/qxk.cpp
97f0a0bd72757e02e422d1a1d7ecb53343295942 *src/qxk/qxk_mutex.cpp
7081b032e0db0675840a6c8b75edf4d47d13c9c7 *src/qxk/qxk_sema.cpp
70982d9277482d775c967aaf745e9c4c442aef19 *src/qxk/qxk_xthr.cpp
99754876405825cd0cd3a6257f27525455288c9d *ports/arm-cm/config/qp_config.hpp
ae09530b01a3ce4f2cdc5dc007c97dcc0e08bae1 *ports/arm-cm/qk/armclang/qk_port.cpp
5e2f09fa46a4a3bfd1c84126c845c9d86849f306 *ports/arm-cm/qk/armclang/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qk/armclang/qs_port.hpp
4e10609efc099d39294cd0713e304b3de812fac6 *ports/arm-cm/qk/gnu/qk_port.cpp
5e2f09fa46a4a3bfd1c84126c845c9d86849f306 *ports/arm-cm/qk/gnu/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qk/gnu/qs_port.hpp
eebf9abd3858d108b12735c308c52725b777a676 *ports/arm-cm/qk/iar/qk_port.cpp
52b074dacb05c7af593a56a375f4462c1de1ed8f *ports/arm-cm/qk/iar/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qk/iar/qs_port.hpp
2c0ec84bc34f1368c8ea5ccde2cdf08eb7aaed5f *ports/arm-cm/qv/armclang/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qv/armclang/qs_port.hpp
fd3556c0d6af1042ecafeefa6d9aff66d1a39244 *ports/arm-cm/qv/armclang/qv_port.cpp
8e732484b6a9742d4e54bfe33c30b01a87ab02a3 *ports/arm-cm/qv/gnu/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qv/gnu/qs_port.hpp
1399bbbce01a1269e41463d35c3431061e8b16a3 *ports/arm-cm/qv/gnu/qv_port.cpp
f26fb7762d713962854dc16b3bc82ebdd03c33c9 *ports/arm-cm/qv/iar/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qv/iar/qs_port.hpp
839ccd47dc6e513c5b850a1a6c9158d4909920e1 *ports/arm-cm/qv/iar/qv_port.cpp
d4edac916a2df8dc2880467d01792f22f5939177 *ports/arm-cm/qxk/armclang/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qxk/armclang/qs_port.hpp
c6804025f48f7ea744db38ad5d7955696c1ccdcf *ports/arm-cm/qxk/armclang/qxk_port.cpp
d4edac916a2df8dc2880467d01792f22f5939177 *ports/arm-cm/qxk/gnu/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qxk/gnu/qs_port.hpp
eec76849164d90d48cfd080dced937b07627e8c4 *ports/arm-cm/qxk/gnu/qxk_port.cpp
2db00521dc7bdca6467f9c7978f4a47daf375688 *ports/arm-cm/qxk/iar/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qxk/iar/qs_port.hpp
c6dbe8a03de76baad665faf5a50c863d38334b58 *ports/arm-cm/qxk/iar/qxk_port.cpp
b83cf186b80decce5fdeb5f66080d7a88d9436e3 *ports/arm-cm/qutest/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cm/qutest/qs_port.hpp
5808649f96e035b70d0d752602883528aacb283a *ports/arm-cr/config/qp_config.hpp
496bf7670fae59aa34ea0a7dfde8bb4d70a6a2a9 *ports/arm-cr/qk/gnu/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cr/qk/gnu/qs_port.hpp
1dd57dbde83ee29ef6a40cd6150aeaa181937957 *ports/arm-cr/qk/iar/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cr/qk/iar/qs_port.hpp
410cfb06e914a9a7efa9d321e8e63e8b132e5567 *ports/arm-cr/qk/ti/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cr/qk/ti/qs_port.hpp
ad5ba7bf199209edb6683128638d596c8056a1a0 *ports/arm-cr/qv/gnu/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cr/qv/gnu/qs_port.hpp
631549a2f7f4aab54d469b4f711e79e499b604be *ports/arm-cr/qv/iar/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cr/qv/iar/qs_port.hpp
75a60334fe636906329001ed18f5c54033ed9d04 *ports/arm-cr/qv/ti/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/arm-cr/qv/ti/qs_port.hpp
18596df7b34eb99db5d580d4f1c2b2a43e3ab3a3 *ports/msp430/qk/qp_port.hpp
6577bacc46c9a9f0cc27893506be39b1e69dd240 *ports/msp430/qk/qs_port.hpp
90e2a0391ea79ae8507a06356a06e8c1f942daee *ports/msp430/qv/qp_port.hpp
6577bacc46c9a9f0cc27893506be39b1e69dd240 *ports/msp430/qv/qs_port.hpp
55012fd62bb201af549da0c39d6ef85ea225790a *ports/msp430/qutest/qp_port.hpp
6577bacc46c9a9f0cc27893506be39b1e69dd240 *ports/msp430/qutest/qs_port.hpp
ea650ce477ced748760fdad526ea964be5c5ff95 *ports/config/qp_config.hpp
b6b5d23c618976a6fbed51dc5a13e227928e1d4b *ports/embos/CMakeLists.txt
670c6241eb418c66d46fc024fec33a623a2c2457 *ports/embos/qf_port.cpp
b80f7433aa174c6560ba1fd7f4ae2f2c94938906 *ports/embos/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/embos/qs_port.hpp
e4f00894f86806af6d88d38e831a8fc0ad36059e *ports/freertos/CMakeLists.txt
19acb29335a0244d1838102237aa4b8330df2f6a *ports/freertos/qf_port.cpp
96b4b2111d90b5326bed4de44e05830ada4e8678 *ports/freertos/qp_port.hpp
e46cc02128baae0e52ff5dce6537f1a3d3f6c514 *ports/freertos/qs_port.hpp
18df978f665338c757f1a2a284c2acc779bd59d3 *ports/threadx/CMakeLists.txt
931be3f4d0a2761d69ac8285d128fe1668731604 *ports/threadx/qf_port.cpp
29ab3ac5a56faaaf5d866a43d2e4edff7013a1ae *ports/threadx/qp_port.hpp
0182f7957f25390579a30b7ab56604819f9a3773 *ports/threadx/qs_port.hpp
46699d3c8ad92f9c98ea5e03e72d4190a7794aa4 *ports/threadx/README.md
0ab8b95f50fa767b951c6f56efe86789623b7127 *ports/uc-os2/CMakeLists.txt
989f46b139112b66f31f516266db338971bdef7f *ports/uc-os2/qf_port.cpp
1b511d790891f3f1fb78f6c7272c20205a4eb0dd *ports/uc-os2/qp_port.hpp
0182f7957f25390579a30b7ab56604819f9a3773 *ports/uc-os2/qs_port.hpp
227dedab24f1e20440103a0cabc210b4b5adedef *ports/qep-only/CMakeLists.txt
c96963c82a774605baab1839214e8bd32d173a68 *ports/qep-only/qp_port.hpp
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/qep-only/safe_std.h
12255313ebcf963d29d91bee4c917bb6ab2f9e1d *ports/posix/CMakeLists.txt
720ff5c7ed5de9f9630ce5b80d34d157f0cb8151 *ports/posix/qf_port.cpp
c735c52b19b7692464902aca05dcd13cb7d2236e *ports/posix/qp_port.hpp
b566671ee550bd9735005b04f474cac6eb3301dd *ports/posix/qs_port.cpp
0242b0613d7133442426f5834f2677e77b32014b *ports/posix/qs_port.hpp
e6a5523e16619370638f6305687cd480d1e3744b *ports/posix/README.md
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix/safe_std.h
493900b9aa5475785c65458332995a184690d43f *ports/posix-qv/CMakeLists.txt
0e0243f24a521c6c135c548b22854543a5cdf4b1 *ports/posix-qv/qf_port.cpp
2909abe049eff960b4008efaa9c6a12eff5a6517 *ports/posix-qv/qp_port.hpp
b566671ee550bd9735005b04f474cac6eb3301dd *ports/posix-qv/qs_port.cpp
0242b0613d7133442426f5834f2677e77b32014b *ports/posix-qv/qs_port.hpp
e2e295c371bc14f0089a888b07d98c657dea07bf *ports/posix-qv/README.md
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix-qv/safe_std.h
c9969a454b540a3b1abd3dd5cc46fb211663310e *ports/posix-qutest/CMakeLists.txt
2c96ee69ca3c443a1224c4eacb83bbfb3cb60300 *ports/posix-qutest/qp_port.hpp
0242b0613d7133442426f5834f2677e77b32014b *ports/posix-qutest/qs_port.hpp
24b9c9258b3621ac757439cc7e93b817ffe9fefe *ports/posix-qutest/qutest_port.cpp
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix-qutest/safe_std.h
06b76c6c30ea880876b47ee27115178ff62ea66b *ports/win32/CMakeLists.txt
0c2a046c664038d547e8dc8ba9573c599c087c60 *ports/win32/qf_port.cpp
6d89a4f5c91649cfff645f13a24cc632522797d4 *ports/win32/qp_port.hpp
a816ee62f507984cdbc37ac190b9f8a23a461bfb *ports/win32/qs_port.cpp
9daff0910db201c165600d3e55458f2ebec2dcc8 *ports/win32/qs_port.hpp
40f18295a0013cbba3c6b270d1d70748ec1d325a *ports/win32/qwin_gui.c
ddc62932b46bbc0ad147193d0dd7efa28127c6c4 *ports/win32/qwin_gui.h
ad6de94157c477eacb61f321870b5f8c1a09a5cd *ports/win32/README.md
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32/safe_std.h
dd5b9a8736e1a1171f7d8565e29e1acb6f7a9691 *ports/win32-qv/CMakeLists.txt
eebb50308338c99e97d4f99272f37a4e9989d9ea *ports/win32-qv/qf_port.cpp
4b947280e9b569adb81afe7d72abca402bc39e9d *ports/win32-qv/qp_port.hpp
a816ee62f507984cdbc37ac190b9f8a23a461bfb *ports/win32-qv/qs_port.cpp
9daff0910db201c165600d3e55458f2ebec2dcc8 *ports/win32-qv/qs_port.hpp
40f18295a0013cbba3c6b270d1d70748ec1d325a *ports/win32-qv/qwin_gui.c
ddc62932b46bbc0ad147193d0dd7efa28127c6c4 *ports/win32-qv/qwin_gui.h
ddd27415c3d1df6d8c210966e8915c407b15bf58 *ports/win32-qv/README.md
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32-qv/safe_std.h
3c23c06f425a8d8dbb18d1f191ac6cab483a8e51 *ports/win32-qutest/CMakeLists.txt
2c96ee69ca3c443a1224c4eacb83bbfb3cb60300 *ports/win32-qutest/qp_port.hpp
9daff0910db201c165600d3e55458f2ebec2dcc8 *ports/win32-qutest/qs_port.hpp
2b66a9145abdee9e280c67f78fe892c069bfabea *ports/win32-qutest/qutest_port.cpp
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32-qutest/safe_std.h
76dd9078dc4311d53d3862d44177a8660258da6d *zephyr/CMakeLists.txt
36a0252cf0bfd6be0d345c48c00b2300f8917f05 *zephyr/Kconfig
2eb2a922e18b4760a68151ebee1b6282d20b4692 *zephyr/module.yml
bab81f1bd3833d059c0e2276380d82ed18aa514e *zephyr/qf_port.cpp
109c291df50110f185adc17bcdf8becc0a79346c *zephyr/qp-zephyr.jpg
b91b2672da8f3108e103f44d649e90afec956e46 *zephyr/qp_port.hpp
e390a0d4bef60bf18fa5ce4527c3d4e5eef0a473 *zephyr/qs_port.hpp
986dbb809e35eace3e8b2b9941df76c7153a8c0c *zephyr/qutest_port.cpp
791248d57ce8dfa6497728c7c2d0734c2c581625 *zephyr/README.md

View File

@ -1,6 +1,6 @@
@setlocal
set VERSION=8.0.1
set VERSION=8.0.2
:: usage
@echo Usage: qppcp_sha1 [gen]
@ -15,14 +15,15 @@ goto end
)
@echo generating qpcpp_%VERSION%.sha1...
@sha1sum qpcpp.qm ^
@sha1sum ^
include/* ^
src/qf/* src/qk/* src/qs/* src/qv/* src/qxk/* ^
ports/arm-cm/qk/armclang/* ports/arm-cm/qk/config/* ports/arm-cm/qk/gnu/* ports/arm-cm/qk/iar/* ^
ports/arm-cm/qv/armclang/* ports/arm-cm/qv/config/* ports/arm-cm/qv/gnu/* ports/arm-cm/qv/iar/* ^
ports/arm-cm/qxk/armclang/* ports/arm-cm/qxk/config/* ports/arm-cm/qxk/gnu/* ports/arm-cm/qxk/iar/* ^
ports/arm-cm/config/* ^
ports/arm-cm/qk/armclang/* ports/arm-cm/qk/gnu/* ports/arm-cm/qk/iar/* ^
ports/arm-cm/qv/armclang/* ports/arm-cm/qv/gnu/* ports/arm-cm/qv/iar/* ^
ports/arm-cm/qxk/armclang/* ports/arm-cm/qxk/gnu/* ports/arm-cm/qxk/iar/* ^
ports/arm-cm/qutest/* ^
ports/arm-cr/qk/config/* ^
ports/arm-cr/config/* ^
ports/arm-cr/qk/gnu/* ports/arm-cr/qk/iar/* ports/arm-cr/qk/ti/* ^
ports/arm-cr/qv/gnu/* ports/arm-cr/qv/iar/* ports/arm-cr/qv/ti/* ^
ports/msp430/qk/* ports/msp430/qv/* ports/msp430/qutest/* ^

View File

@ -1,10 +1,6 @@
//$file${src::qf::qep_hsm.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qf::qep_hsm.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qf::qep_hsm.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
@ -42,13 +37,17 @@
#include "qs_dummy.hpp" // disable the QS software tracing
#endif // Q_SPY
//============================================================================
//! @cond INTERNAL
// unnamed namespace for local definitions with internal linkage
namespace {
Q_DEFINE_THIS_MODULE("qep_hsm")
// maximum depth of state nesting in a QHsm (including the top level)
// must be >= 3
static constexpr std::int_fast8_t QHSM_MAX_NEST_DEPTH_ {6};
//! @cond INTERNAL
// immutable events corresponding to the reserved signals.
static QP::QEvt const l_reservedEvt_[4] {
QP::QEvt(static_cast<QP::QSignal>(QP::QHsm::Q_EMPTY_SIG)),
@ -57,90 +56,118 @@ static QP::QEvt const l_reservedEvt_[4] {
QP::QEvt(static_cast<QP::QSignal>(QP::QHsm::Q_INIT_SIG))
};
// maximum depth of state nesting in a QHsm (including the top level)
// must be >= 3
static constexpr std::int_fast8_t QHSM_MAX_NEST_DEPTH_ {6};
//! @endcond
} // unnamed namespace
// helper macro to handle reserved event in an QHsm
//============================================================================
//! @cond INTERNAL
// internal helper macro to pass a reserved event into the state handler
#define QHSM_RESERVED_EVT_(state_, sig_) \
((*(state_))(this, &l_reservedEvt_[(sig_)]))
// helper macro to trace state entry
#define QS_STATE_ENTRY_(state_, qsId_) \
#ifdef Q_SPY
// helper macro to trace state action (entry/exit)
#define QS_STATE_ACT_(rec_, state_) \
QS_CRIT_ENTRY(); \
QS_MEM_SYS(); \
QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, (qsId_)) \
QS_BEGIN_PRE((rec_), qsId) \
QS_OBJ_PRE(this); \
QS_FUN_PRE(state_); \
QS_END_PRE() \
QS_MEM_APP(); \
QS_CRIT_EXIT()
// helper macro to trace state exit
#define QS_STATE_EXIT_(state_, qsId_) \
// internal helper macro to top-most init
#define QS_TOP_INIT_(rec_, trg_) \
QS_CRIT_ENTRY(); \
QS_MEM_SYS(); \
QS_BEGIN_PRE(QS_QEP_STATE_EXIT, (qsId_)) \
QS_BEGIN_PRE((rec_), qsId) \
QS_TIME_PRE(); \
QS_OBJ_PRE(this); \
QS_FUN_PRE(trg_); \
QS_END_PRE() \
QS_CRIT_EXIT()
// internal helper macro to trace transition segment
#define QS_TRAN_SEG_(rec_, src_, trg_) \
QS_CRIT_ENTRY(); \
QS_BEGIN_PRE((rec_), qsId) \
QS_OBJ_PRE(this); \
QS_FUN_PRE(src_); \
QS_FUN_PRE(trg_); \
QS_END_PRE() \
QS_CRIT_EXIT()
// internal helper macro to trace transition action
#define QS_TRAN_ACT_(rec_, state_) \
QS_CRIT_ENTRY(); \
QS_BEGIN_PRE((rec_), qsId) \
QS_SIG_PRE(e->sig); \
QS_OBJ_PRE(this); \
QS_FUN_PRE(state_); \
QS_END_PRE() \
QS_MEM_APP(); \
QS_CRIT_EXIT()
// internal helper macro to trace transition begin/end
#define QS_TRAN0_(rec_, trg_) \
QS_CRIT_ENTRY(); \
QS_BEGIN_PRE((rec_), qsId) \
QS_TIME_PRE(); \
QS_SIG_PRE(e->sig); \
QS_OBJ_PRE(this); \
QS_FUN_PRE(trg_); \
QS_END_PRE() \
QS_CRIT_EXIT()
// internal helper macro to trace regulsr transition
#define QS_TRAN_END_(rec_, src_, trg_) \
QS_CRIT_ENTRY(); \
QS_BEGIN_PRE((rec_), qsId) \
QS_TIME_PRE(); \
QS_SIG_PRE(e->sig); \
QS_OBJ_PRE(this); \
QS_FUN_PRE(src_); \
QS_FUN_PRE(trg_); \
QS_END_PRE() \
QS_CRIT_EXIT()
#else
#define QS_STATE_ACT_(rec_, state_) (static_cast<void>(0))
#define QS_TOP_INIT_(rec_, trg_) (static_cast<void>(0))
#define QS_TRAN_SEG_(rec_, src_, trg_) (static_cast<void>(0))
#define QS_TRAN_ACT_(rec_, state_) (static_cast<void>(0))
#define QS_TRAN0_(rec_, trg_) (static_cast<void>(0))
#define QS_TRAN_END_(rec_, src_, trg_) (static_cast<void>(0))
#endif
//! @endcond
//============================================================================
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
#error qpcpp version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QEP::versionStr[]} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
} // namespace QP
//$enddef${QEP::versionStr[]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QEP::QHsm} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QEP::QHsm} ...............................................................
//${QEP::QHsm::QHsm} .........................................................
//............................................................................
QHsm::QHsm(QStateHandler const initial) noexcept
: QAsm()
{
m_state.fun = Q_STATE_CAST(&top);
m_state.fun = &top;
m_temp.fun = initial;
}
//${QEP::QHsm::init} .........................................................
//............................................................................
void QHsm::init(
void const * const e,
std::uint_fast8_t const qsId)
{
QF_CRIT_STAT
QState r;
// produce QS dictionary for QP::QHsm::top()
#ifdef Q_SPY
QS_CRIT_ENTRY();
QS_MEM_SYS();
bool isDone = true;
if ((QS::priv_.flags & 0x01U) == 0U) {
QS::priv_.flags |= 0x01U;
r = Q_RET_HANDLED;
isDone = false;
}
else {
r = Q_RET_IGNORED;
}
QS_MEM_APP();
QS_CRIT_EXIT();
if (r == Q_RET_HANDLED) {
if (!isDone) {
QS_FUN_DICTIONARY(&QP::QHsm::top);
}
#else
@ -150,97 +177,49 @@ void QHsm::init(
QStateHandler t = m_state.fun;
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(200, (m_temp.fun != nullptr)
Q_REQUIRE_INCRIT(200,
(m_temp.fun != nullptr)
&& (t == Q_STATE_CAST(&top)));
QF_CRIT_EXIT();
// execute the top-most initial tran.
r = (*m_temp.fun)(this, Q_EVT_CAST(QEvt));
QState r = (*m_temp.fun)(this, Q_EVT_CAST(QEvt));
QF_CRIT_ENTRY();
// the top-most initial tran. must be taken
Q_ASSERT_INCRIT(210, r == Q_RET_TRAN);
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId)
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(t); // the source state
QS_FUN_PRE(m_temp.fun); // the target of the initial tran.
QS_END_PRE()
QS_MEM_APP();
QF_CRIT_EXIT();
// drill down into the state hierarchy with initial transitions...
do {
QStateHandler path[QHSM_MAX_NEST_DEPTH_]; // tran. entry path array
std::int_fast8_t ip = 0; // tran. entry path index
QS_TRAN_SEG_(QS_QEP_STATE_INIT, t, m_temp.fun);
// drill down into the state hierarchy with initial transitions...
QStateHandler path[QHSM_MAX_NEST_DEPTH_]; // tran. entry path array
path[0] = m_temp.fun;
static_cast<void>(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG));
// note: ip is here the fixed upper loop bound
while ((m_temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) {
++ip;
std::int_fast8_t ip = 1; // tran. entry path index (also the loop bound)
for (; (m_temp.fun != t) && (ip < QHSM_MAX_NEST_DEPTH_); ++ip) {
path[ip] = m_temp.fun;
static_cast<void>(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG));
}
QF_CRIT_ENTRY();
// too many state nesting levels or "malformed" HSM
Q_ENSURE_INCRIT(220, ip < QHSM_MAX_NEST_DEPTH_);
// must NOT be too many state nesting levels or "malformed" HSM
Q_ASSERT_INCRIT(220, ip <= QHSM_MAX_NEST_DEPTH_);
QF_CRIT_EXIT();
m_temp.fun = path[0];
enter_target_(&path[0], ip - 1, qsId);
t = path[0];
// retrace the entry path in reverse (desired) order...
// note: ip is the fixed upper loop bound
do {
// enter path[ip]
if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG)
== Q_RET_HANDLED)
{
QS_STATE_ENTRY_(path[ip], qsId);
}
--ip;
} while (ip >= 0);
t = path[0]; // current state becomes the new source
r = QHSM_RESERVED_EVT_(t, Q_INIT_SIG); // execute initial tran.
#ifdef Q_SPY
if (r == Q_RET_TRAN) {
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId)
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(t); // the source state
QS_FUN_PRE(m_temp.fun); // the target of the initial tran.
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
}
#endif // Q_SPY
} while (r == Q_RET_TRAN);
QF_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_INIT_TRAN, qsId)
QS_TIME_PRE(); // time stamp
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(t); // the new active state
QS_END_PRE()
QS_MEM_APP();
QF_CRIT_EXIT();
QS_TOP_INIT_(QS_QEP_INIT_TRAN, t);
m_state.fun = t; // change the current active state
#ifndef Q_UNSAFE
m_temp.uint = ~m_state.uint;
#ifdef Q_UNSAFE
Q_UNUSED_PAR(r);
#endif
}
//${QEP::QHsm::dispatch} .....................................................
//............................................................................
void QHsm::dispatch(
QEvt const * const e,
std::uint_fast8_t const qsId)
@ -254,64 +233,39 @@ void QHsm::dispatch(
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(300, (e != nullptr) && (s != nullptr));
Q_INVARIANT_INCRIT(301,
e->verify_()
&& (m_state.uint == static_cast<std::uintptr_t>(~m_temp.uint)));
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_DISPATCH, qsId)
QS_TIME_PRE(); // time stamp
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(s); // the current state
QS_END_PRE()
QS_MEM_APP();
Q_REQUIRE_INCRIT(300,
(e != nullptr)
&& (s != nullptr));
QF_CRIT_EXIT();
QS_TRAN0_(QS_QEP_DISPATCH, s);
QState r = Q_RET_SUPER;
// process the event hierarchically...
QState r;
m_temp.fun = s;
std::int_fast8_t ip = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound
do {
std::int_fast8_t ip = QHSM_MAX_NEST_DEPTH_;
// NOTE: ip is the fixed loop upper bound
for (; ip > 0; --ip) {
s = m_temp.fun;
r = (*s)(this, e); // invoke state handler s
if (r == Q_RET_UNHANDLED) { // unhandled due to a guard?
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_UNHANDLED, qsId)
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(s); // the current state
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
QS_TRAN_ACT_(QS_QEP_UNHANDLED, s);
r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); // superstate of s
}
--ip;
} while ((r == Q_RET_SUPER) && (ip > 0));
if (r != Q_RET_SUPER) { // event NOT "bubbled up"
break;
}
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(310, ip > 0);
Q_ASSERT_INCRIT(310, ip > 0);
QF_CRIT_EXIT();
if (r >= Q_RET_TRAN) { // tran. (regular or history) taken?
#ifdef Q_SPY
if (r == Q_RET_TRAN_HIST) { // tran. to history?
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_TRAN_HIST, qsId)
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(s); // tran. to history source
QS_FUN_PRE(m_temp.fun); // tran. to history target
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
QS_TRAN_SEG_(QS_QEP_TRAN_HIST, s, m_temp.fun);
}
#endif // Q_SPY
@ -321,207 +275,87 @@ void QHsm::dispatch(
path[2] = s; // tran. source
// exit current state to tran. source s...
ip = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound
for (; (t != s) && (ip > 0); t = m_temp.fun) {
while (t != s) {
// exit from t
if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) == Q_RET_HANDLED) {
QS_STATE_EXIT_(t, qsId);
QS_STATE_ACT_(QS_QEP_STATE_EXIT, t);
// find superstate of t
static_cast<void>(QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG));
}
--ip;
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(320, ip > 0);
QF_CRIT_EXIT();
ip = hsm_tran(&path[0], qsId); // take the tran.
// execute state entry actions in the desired order...
// note: ip is the fixed upper loop bound
for (; ip >= 0; --ip) {
// enter path[ip]
if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG)
== Q_RET_HANDLED)
{
QS_STATE_ENTRY_(path[ip], qsId);
}
}
t = path[0]; // stick the target into register
m_temp.fun = t; // update the next state
// drill into the target hierarchy...
while (QHSM_RESERVED_EVT_(t, Q_INIT_SIG) == Q_RET_TRAN) {
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId)
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(t); // the source (pseudo)state
QS_FUN_PRE(m_temp.fun); // the target of the tran.
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
ip = 0;
path[0] = m_temp.fun;
// find superstate
static_cast<void>(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG));
// note: ip is the fixed upper loop bound
while ((m_temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) {
++ip;
path[ip] = m_temp.fun;
// find superstate
static_cast<void>(
QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG));
}
QF_CRIT_ENTRY();
// too many state nesting levels or "malformed" HSM
Q_ENSURE_INCRIT(330, ip < QHSM_MAX_NEST_DEPTH_);
QF_CRIT_EXIT();
m_temp.fun = path[0];
// retrace the entry path in reverse (correct) order...
// note: ip is the fixed upper loop bound
do {
// enter path[ip]
if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG)
== Q_RET_HANDLED)
{
QS_STATE_ENTRY_(path[ip], qsId);
}
--ip;
} while (ip >= 0);
t = path[0]; // current state becomes the new source
t = m_temp.fun;
}
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_TRAN, qsId)
QS_TIME_PRE(); // time stamp
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(s); // the source of the tran.
QS_FUN_PRE(t); // the new active state
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
// take the tran...
ip = tran_simple_(&path[0], qsId);
if (ip < -1) { // not a simple tran.?
ip = tran_complex_(&path[0], qsId);
}
enter_target_(&path[0], ip, qsId);
t = path[0];
QS_TRAN_END_(QS_QEP_TRAN, s, t);
}
#ifdef Q_SPY
else if (r == Q_RET_HANDLED) {
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_INTERN_TRAN, qsId)
QS_TIME_PRE(); // time stamp
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(s); // the source state
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
QS_TRAN0_(QS_QEP_INTERN_TRAN, s);
}
else {
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_IGNORED, qsId)
QS_TIME_PRE(); // time stamp
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(m_state.fun); // the current state
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
QS_TRAN0_(QS_QEP_IGNORED, m_state.fun);
}
#endif // Q_SPY
m_state.fun = t; // change the current active state
#ifndef Q_UNSAFE
m_temp.uint = ~m_state.uint;
#endif
}
//${QEP::QHsm::isIn} .........................................................
//............................................................................
bool QHsm::isIn(QStateHandler const state) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_INVARIANT_INCRIT(602,
m_state.uint == static_cast<std::uintptr_t>(~m_temp.uint));
QF_CRIT_EXIT();
bool inState = false; // assume that this HSM is not in 'state'
// scan the state hierarchy bottom-up
QStateHandler s = m_state.fun;
std::int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_ + 1; // fixed upper loop bound
QState r = Q_RET_SUPER;
for (; (r != Q_RET_IGNORED) && (lbound > 0); --lbound) {
while (r != Q_RET_IGNORED) {
if (s == state) { // do the states match?
inState = true; // 'true' means that match found
break; // break out of the for-loop
}
else {
r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG);
s = m_temp.fun;
}
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(690, lbound > 0);
QF_CRIT_EXIT();
#ifndef Q_UNSAFE
m_temp.uint = ~m_state.uint;
#endif
return inState; // return the status
}
//${QEP::QHsm::childState} ...................................................
//............................................................................
QStateHandler QHsm::childState(QStateHandler const parent) noexcept {
QStateHandler child = m_state.fun; // start with current state
bool isFound = false; // start with the child not found
// establish stable state configuration
m_temp.fun = child;
QState r;
std::int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound
do {
// is this the parent of the current child?
if (m_temp.fun == parent) {
isFound = true; // child is found
r = Q_RET_IGNORED; // break out of the loop
}
else {
child = m_temp.fun;
r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG);
}
--lbound;
} while ((r != Q_RET_IGNORED) // the top state not reached
&& (lbound > 0));
#ifndef Q_UNSAFE
m_temp.uint = ~m_state.uint;
#else
Q_UNUSED_PAR(isFound);
bool isFound = false; // assume the child state NOT found
#endif
QStateHandler child = m_state.fun; // start with current state
m_temp.fun = child; // establish stable state configuration
QState r = Q_RET_SUPER;
while (r != Q_RET_IGNORED) {
// have the parent of the current child?
if (m_temp.fun == parent) {
#ifndef Q_UNSAFE
isFound = true; // indicate that child state was found
#endif
break;
}
child = m_temp.fun;
r = QHSM_RESERVED_EVT_(child, Q_EMPTY_SIG);
}
QF_CRIT_STAT
QF_CRIT_ENTRY();
// NOTE: the following postcondition can only succeed when
// (lbound > 0), so no extra check is necessary.
Q_ENSURE_INCRIT(890, isFound);
Q_ASSERT_INCRIT(590, isFound);
QF_CRIT_EXIT();
return child;
}
//${QEP::QHsm::hsm_tran} .....................................................
std::int_fast8_t QHsm::hsm_tran(
//............................................................................
//! @private @memberof QHsm
std::int_fast8_t QHsm::tran_simple_(
QStateHandler * const path,
std::uint_fast8_t const qsId)
{
@ -529,16 +363,16 @@ std::int_fast8_t QHsm::hsm_tran(
Q_UNUSED_PAR(qsId);
#endif
std::int_fast8_t ip = -1; // tran. entry path index
QStateHandler t = path[0];
QStateHandler const s = path[2];
QF_CRIT_STAT
std::int_fast8_t ip = 0; // tran. entry path index
QS_CRIT_STAT
// (a) check source==target (tran. to self)...
if (s == t) {
// exit source s
if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) {
QS_STATE_EXIT_(s, qsId);
QS_STATE_ACT_(QS_QEP_STATE_EXIT, s);
}
ip = 0; // enter the target
}
@ -560,61 +394,76 @@ std::int_fast8_t QHsm::hsm_tran(
if (m_temp.fun == t) {
// exit source s
if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) {
QS_STATE_EXIT_(s, qsId);
QS_STATE_ACT_(QS_QEP_STATE_EXIT, s);
}
ip = 0; // enter the target
}
else {
// (d) check source->super==target...
if (m_temp.fun == path[0]) {
else if (m_temp.fun == path[0]) {
// exit source s
if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) {
QS_STATE_EXIT_(s, qsId);
QS_STATE_ACT_(QS_QEP_STATE_EXIT, s);
}
ip = -1; // do not enter the target
}
else {
path[1] = t; // save the superstate of target
ip = -2; // cause execution of complex tran.
}
}
}
return ip;
}
//............................................................................
//! @private @memberof QHsm
std::int_fast8_t QHsm::tran_complex_(
QStateHandler * const path,
std::uint_fast8_t const qsId)
{
#ifndef Q_SPY
Q_UNUSED_PAR(qsId);
#endif
// (e) check rest of source==target->super->super..
// and store the entry path along the way
std::int_fast8_t iq = 0; // indicate that LCA was found
ip = 1; // enter target and its superstate
path[1] = t; // save the superstate of target
t = m_temp.fun; // save source->super
std::int_fast8_t ip = 1; // enter target and its superstate
QStateHandler const s = path[2]; // source state
QStateHandler t = m_temp.fun; // source->super
QF_CRIT_STAT
// find target->super->super...
// note: ip is the fixed upper loop bound
QState r = QHSM_RESERVED_EVT_(path[1], Q_EMPTY_SIG);
while ((r == Q_RET_SUPER)
&& (ip < (QHSM_MAX_NEST_DEPTH_ - 1)))
{
while ((r == Q_RET_SUPER) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) {
++ip;
path[ip] = m_temp.fun; // store the entry path
if (m_temp.fun == s) { // is it the source?
iq = 1; // indicate that the LCA found
--ip; // do not enter the source
r = Q_RET_HANDLED; // terminate the loop
break; // terminate the loop
}
else { // it is not the source, keep going up
r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG);
}
}
QF_CRIT_ENTRY();
// NOTE: The following postcondition succeeds only when
// ip < QHSM_MAX_NEST_DEPTH, so no additional check is necessary
// too many state nesting levels or "malformed" HSM.
Q_ENSURE_INCRIT(510, r != Q_RET_SUPER);
Q_INVARIANT_INCRIT(711, ip < (QHSM_MAX_NEST_DEPTH_ - 1));
QF_CRIT_EXIT();
// the LCA not found yet?
if (iq == 0) {
// exit source s
if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG)
== Q_RET_HANDLED)
{
QS_STATE_EXIT_(s, qsId);
}
// (f) check the rest of source->super
// == target->super->super...
// exit source s
#ifndef Q_SPY
static_cast<void>(QHSM_RESERVED_EVT_(s, Q_EXIT_SIG));
#else
if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) {
QS_STATE_ACT_(QS_QEP_STATE_EXIT, s);
}
#endif // def Q_SPY
// (f) check the rest of
// source->super == target->super->super...
iq = ip;
r = Q_RET_IGNORED; // indicate that the LCA NOT found
// note: iq is the fixed upper loop bound
@ -622,59 +471,107 @@ std::int_fast8_t QHsm::hsm_tran(
if (t == path[iq]) { // is this the LCA?
r = Q_RET_HANDLED; // indicate the LCA found
ip = iq - 1; // do not enter the LCA
iq = -1; // cause termination of the loop
break; // terminate the loop
}
else {
--iq; // try lower superstate of target
}
} while (iq >= 0);
// the LCA not found yet?
if (r != Q_RET_HANDLED) {
if (r != Q_RET_HANDLED) { // the LCA still not found?
// (g) check each source->super->...
// for each target->super...
r = Q_RET_IGNORED; // keep looping
std::int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_;
do {
r = Q_RET_SUPER; // keep looping
while (r != Q_RET_HANDLED) {
// exit from t
if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG)
== Q_RET_HANDLED)
{
QS_STATE_EXIT_(t, qsId);
if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) == Q_RET_HANDLED) {
QS_STATE_ACT_(QS_QEP_STATE_EXIT, t);
// find superstate of t
static_cast<void>(
QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG));
static_cast<void>(QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG));
}
t = m_temp.fun; // set to super of t
iq = ip;
do {
// is this the LCA?
if (t == path[iq]) {
if (t == path[iq]) { // is this the LCA?
ip = iq - 1; // do not enter the LCA
iq = -1; // break out of inner loop
r = Q_RET_HANDLED; // break outer loop
break; // terminate the inner loop
}
else {
--iq;
}
--iq; // try lower superstate of target
} while (iq >= 0);
--lbound;
} while ((r != Q_RET_HANDLED) && (lbound > 0));
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(530, lbound > 0);
QF_CRIT_EXIT();
}
}
}
}
}
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(590, ip < QHSM_MAX_NEST_DEPTH_);
QF_CRIT_EXIT();
return ip;
}
//............................................................................
//! @private @memberof QHsm
void QHsm::enter_target_(
QStateHandler * const path,
std::int_fast8_t const depth,
std::uint_fast8_t const qsId)
{
#ifndef Q_SPY
Q_UNUSED_PAR(qsId);
#endif
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(800, depth < QHSM_MAX_NEST_DEPTH_);
QF_CRIT_EXIT();
std::int_fast8_t ip = depth;
// execute state entry actions in the desired order...
// note: ip is the fixed upper loop bound
for (; ip >= 0; --ip) {
// enter path[ip]
if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG)
== Q_RET_HANDLED)
{
QS_STATE_ACT_(QS_QEP_STATE_ENTRY, path[ip]);
}
}
QStateHandler t = path[0];
m_temp.fun = t; // update the next state
// drill into the target hierarchy...
while (QHSM_RESERVED_EVT_(t, Q_INIT_SIG) == Q_RET_TRAN) {
QS_TRAN_SEG_(QS_QEP_STATE_INIT, t, m_temp.fun);
ip = 0;
path[0] = m_temp.fun;
// find superstate
static_cast<void>(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG));
// note: ip is the fixed upper loop bound
while ((m_temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) {
++ip;
path[ip] = m_temp.fun;
// find superstate
static_cast<void>(QHSM_RESERVED_EVT_(
m_temp.fun, Q_EMPTY_SIG));
}
QF_CRIT_ENTRY();
// too many state nesting levels or "malformed" HSM
Q_INVARIANT_INCRIT(891, ip < QHSM_MAX_NEST_DEPTH_);
QF_CRIT_EXIT();
m_temp.fun = path[0];
// retrace the entry path in reverse (correct) order...
// note: ip is the fixed upper loop bound
do {
// enter path[ip]
if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) == Q_RET_HANDLED) {
QS_STATE_ACT_(QS_QEP_STATE_ENTRY, path[ip]);
}
--ip;
} while (ip >= 0);
t = path[0]; // current state becomes the new source
}
}
} // namespace QP
//$enddef${QEP::QHsm} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,10 +1,6 @@
//$file${src::qf::qep_msm.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qf::qep_msm.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qf::qep_msm.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
@ -42,16 +37,18 @@
#include "qs_dummy.hpp" // disable the QS software tracing
#endif // Q_SPY
//============================================================================
//! @cond INTERNAL
// unnamed namespace for local definitions with internal linkage
namespace {
Q_DEFINE_THIS_MODULE("qep_msm")
// maximum depth of entry levels in a MSM for tran. to history.
static constexpr std::int_fast8_t QMSM_MAX_ENTRY_DEPTH_ {4};
//! @cond INTERNAL
// top-state object for QMsm-style state machines
QP::QMState const l_msm_top_s = {
constexpr QP::QMState l_msm_top_s = {
nullptr,
nullptr,
nullptr,
@ -59,32 +56,75 @@ QP::QMState const l_msm_top_s = {
nullptr
};
// maximum depth of state nesting in a QMsm (including the top level)
static constexpr std::int_fast8_t QMSM_MAX_NEST_DEPTH_ {8};
// maximum length of transition-action array
static constexpr std::int_fast8_t QMSM_MAX_TRAN_LENGTH_ {2*QMSM_MAX_NEST_DEPTH_};
// maximum depth of entry levels in a MSM for tran. to history.
static constexpr std::int_fast8_t QMSM_MAX_ENTRY_DEPTH_ {4};
} // unnamed namespace
//! @endcond
//============================================================================
#ifdef Q_SPY
// helper macro to trace state action (entry/exit)
#define QS_STATE_ACT_(rec_, state_) \
QS_CRIT_ENTRY(); \
QS_BEGIN_PRE((rec_), qsId) \
QS_OBJ_PRE(this); \
QS_FUN_PRE(state_); \
QS_END_PRE() \
QS_CRIT_EXIT()
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
#error qpcpp version 7.3.0 or higher required
// internal helper macro to top-most init
#define QS_TOP_INIT_(rec_, trg_) \
QS_CRIT_ENTRY(); \
QS_BEGIN_PRE((rec_), qsId) \
QS_TIME_PRE(); \
QS_OBJ_PRE(this); \
QS_FUN_PRE(trg_); \
QS_END_PRE() \
QS_CRIT_EXIT()
// internal helper macro to trace transition segment
#define QS_TRAN_SEG_(rec_, src_, trg_) \
QS_CRIT_ENTRY(); \
QS_BEGIN_PRE((rec_), qsId) \
QS_OBJ_PRE(this); \
QS_FUN_PRE(src_); \
QS_FUN_PRE(trg_); \
QS_END_PRE() \
QS_CRIT_EXIT()
// internal helper macro to trace transition begin/end
#define QS_TRAN0_(rec_, trg_) \
QS_CRIT_ENTRY(); \
QS_BEGIN_PRE((rec_), qsId) \
QS_TIME_PRE(); \
QS_SIG_PRE(e->sig); \
QS_OBJ_PRE(this); \
QS_FUN_PRE(trg_); \
QS_END_PRE() \
QS_CRIT_EXIT()
// internal helper macro to trace regulsr transition
#define QS_TRAN_END_(rec_, src_, trg_) \
QS_CRIT_ENTRY(); \
QS_BEGIN_PRE((rec_), qsId) \
QS_TIME_PRE(); \
QS_SIG_PRE(e->sig); \
QS_OBJ_PRE(this); \
QS_FUN_PRE(src_); \
QS_FUN_PRE(trg_); \
QS_END_PRE() \
QS_CRIT_EXIT()
#else
#define QS_STATE_ACT_(rec_, state_) (static_cast<void>(0))
#define QS_TOP_INIT_(rec_, trg_) (static_cast<void>(0))
#define QS_TRAN_SEG_(rec_, src_, trg_) (static_cast<void>(0))
#define QS_TRAN0_(rec_, trg_) (static_cast<void>(0))
#define QS_TRAN_END_(rec_, src_, trg_) (static_cast<void>(0))
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QEP::QMsm} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//! @endcond
//============================================================================
namespace QP {
//${QEP::QMsm} ...............................................................
//${QEP::QMsm::QMsm} .........................................................
//............................................................................
QMsm::QMsm(QStateHandler const initial) noexcept
: QAsm()
{
@ -92,7 +132,7 @@ QMsm::QMsm(QStateHandler const initial) noexcept
m_temp.fun = initial; // the initial tran. handler
}
//${QEP::QMsm::init} .........................................................
//............................................................................
void QMsm::init(
void const * const e,
std::uint_fast8_t const qsId)
@ -103,7 +143,8 @@ void QMsm::init(
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(200, (m_temp.fun != nullptr)
Q_REQUIRE_INCRIT(200,
(m_temp.fun != nullptr)
&& (m_state.obj == &l_msm_top_s));
QF_CRIT_EXIT();
@ -113,47 +154,24 @@ void QMsm::init(
QF_CRIT_ENTRY();
// the top-most initial tran. must be taken
Q_ASSERT_INCRIT(210, r == Q_RET_TRAN_INIT);
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId)
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(m_state.obj->stateHandler); // source state
QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target state
QS_END_PRE()
QS_MEM_APP();
QF_CRIT_EXIT();
QS_TRAN_SEG_(QS_QEP_STATE_INIT,
m_state.obj->stateHandler, m_temp.tatbl->target->stateHandler);
// set state to the last tran. target
m_state.obj = m_temp.tatbl->target;
// drill down into the state hierarchy with initial transitions...
std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound
do {
while (r >= Q_RET_TRAN_INIT) {
// execute the tran. table
r = execTatbl_(m_temp.tatbl, qsId);
--lbound;
} while ((r >= Q_RET_TRAN_INIT) && (lbound > 0));
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(290, lbound > 0);
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_INIT_TRAN, qsId)
QS_TIME_PRE(); // time stamp
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(m_state.obj->stateHandler); // the new current state
QS_END_PRE()
QS_MEM_APP();
QF_CRIT_EXIT();
#ifndef Q_UNSAFE
m_temp.uint = ~m_state.uint;
#endif
}
//${QEP::QMsm::dispatch} .....................................................
QS_TOP_INIT_(QS_QEP_INIT_TRAN, m_state.obj->stateHandler);
}
//............................................................................
void QMsm::dispatch(
QEvt const * const e,
std::uint_fast8_t const qsId)
@ -167,86 +185,54 @@ void QMsm::dispatch(
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(300, (e != nullptr) && (s != nullptr));
Q_INVARIANT_INCRIT(301,
e->verify_()
&& (m_state.uint == static_cast<std::uintptr_t>(~m_temp.uint)));
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_DISPATCH, qsId)
QS_TIME_PRE(); // time stamp
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(s->stateHandler); // the current state handler
QS_END_PRE()
QS_MEM_APP();
Q_REQUIRE_INCRIT(300,
(e != nullptr)
&& (s != nullptr));
QF_CRIT_EXIT();
QS_TRAN0_(QS_QEP_DISPATCH, s->stateHandler);
// scan the state hierarchy up to the top state...
QState r;
std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound
do {
QState r = Q_RET_SUPER;
while (t != nullptr) {
r = (*t->stateHandler)(this, e); // call state handler function
// event handled? (the most frequent case)
if (r >= Q_RET_HANDLED) {
if (r >= Q_RET_HANDLED) { // event handled? (the most frequent case)
break; // done scanning the state hierarchy
}
// event unhandled and passed to the superstate?
else if (r == Q_RET_SUPER) {
t = t->superstate; // advance to the superstate
}
else { // event unhandled due to a guard
QF_CRIT_ENTRY();
// event must be unhandled due to a guard evaluating to 'false'
Q_ASSERT_INCRIT(310, r == Q_RET_UNHANDLED);
QS_MEM_SYS();
#ifdef Q_SPY
if (r == Q_RET_UNHANDLED) { // event unhandled due to a guard?
QS_CRIT_ENTRY();
QS_BEGIN_PRE(QS_QEP_UNHANDLED, qsId)
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(t->stateHandler); // the current state
QS_SIG_PRE(e->sig);
QS_OBJ_PRE(this);
QS_FUN_PRE(t->stateHandler);
QS_END_PRE()
QS_MEM_APP();
QF_CRIT_EXIT();
QS_CRIT_EXIT();
}
#endif
t = t->superstate; // advance to the superstate
}
--lbound;
} while ((t != nullptr) && (lbound > 0));
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(320, lbound > 0);
QF_CRIT_EXIT();
if (r >= Q_RET_TRAN) { // any kind of tran. taken?
QF_CRIT_ENTRY();
// the tran. source state must not be nullptr
// the tran. source state must not be NULL
Q_ASSERT_INCRIT(330, t != nullptr);
QF_CRIT_EXIT();
#ifdef Q_SPY
QMState const * const ts = t; // for saving tran. table
QMState const * const ts = t; // tran. source for QS tracing
#endif // Q_SPY
QMTranActTable const *tatbl;
if (r == Q_RET_TRAN_HIST) { // was it tran. to history?
QMState const * const hist = m_state.obj; // save history
m_state.obj = s; // restore the original state
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_TRAN_HIST, qsId)
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(t->stateHandler); // source state handler
QS_FUN_PRE(hist->stateHandler); // target state handler
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
QS_TRAN_SEG_(QS_QEP_TRAN_HIST,
t->stateHandler, hist->stateHandler);
// save the tran-action table before it gets clobbered
tatbl = m_temp.tatbl;
QMTranActTable const *tatbl = m_temp.tatbl;
exitToTranSource_(s, t, qsId);
static_cast<void>(execTatbl_(tatbl, qsId));
r = enterHistory_(hist, qsId);
@ -254,151 +240,81 @@ void QMsm::dispatch(
t = s; // set target to the current state
}
lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound
while ((r >= Q_RET_TRAN) && (lbound > 0)) {
while (r >= Q_RET_TRAN) {
// save the tran-action table before it gets clobbered
tatbl = m_temp.tatbl;
QMTranActTable const *tatbl = m_temp.tatbl;
m_temp.obj = nullptr; // clear
exitToTranSource_(s, t, qsId);
r = execTatbl_(tatbl, qsId);
s = m_state.obj;
t = s; // set target to the current state
--lbound;
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(360, lbound > 0);
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_TRAN, qsId)
QS_TIME_PRE(); // time stamp
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(ts->stateHandler); // the tran. source
QS_FUN_PRE(s->stateHandler); // the new active state
QS_END_PRE()
QS_MEM_APP();
QF_CRIT_EXIT();
QS_TRAN_END_(QS_QEP_TRAN, ts->stateHandler, s->stateHandler);
}
#ifdef Q_SPY
// was the event handled?
else if (r == Q_RET_HANDLED) {
else if (r == Q_RET_HANDLED) { // was the event handled?
QF_CRIT_ENTRY();
// internal tran. source can't be nullptr
// internal tran. source can't be NULL
Q_ASSERT_INCRIT(380, t != nullptr);
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_INTERN_TRAN, qsId)
QS_TIME_PRE(); // time stamp
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(t->stateHandler); // the source state
QS_END_PRE()
QS_MEM_APP();
QF_CRIT_EXIT();
QS_TRAN0_(QS_QEP_INTERN_TRAN, t->stateHandler);
}
// event bubbled to the 'top' state?
else if (t == nullptr) {
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_IGNORED, qsId)
QS_TIME_PRE(); // time stamp
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(s->stateHandler); // the current state
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
else if (t == nullptr) { // event bubbled to the 'top' state?
QS_TRAN0_(QS_QEP_IGNORED, s->stateHandler);
}
#endif // Q_SPY
else {
// empty
}
#ifndef Q_UNSAFE
m_temp.uint = ~m_state.uint;
#endif
}
//${QEP::QMsm::isIn} .........................................................
//............................................................................
bool QMsm::isIn(QStateHandler const state) noexcept {
bool inState = false; // assume that this SM is not in 'state'
QMState const *s = m_state.obj;
std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound
for (; (s != nullptr) && (lbound > 0); --lbound) {
while (s != nullptr) {
if (s->stateHandler == state) { // match found?
inState = true;
break;
}
else {
s = s->superstate; // advance to the superstate
}
}
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(490, lbound > 0);
QF_CRIT_EXIT();
return inState;
}
//${QEP::QMsm::childStateObj} ................................................
QMState const * QMsm::childStateObj(QMState const * const parent) const noexcept {
QMState const *child = m_state.obj;
bool isFound = false; // start with the child not found
QMState const *s;
std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound
for (s = m_state.obj;
(s != nullptr) && (lbound > 0);
s = s->superstate)
//............................................................................
QMState const * QMsm::childStateObj(QMState const * const parent)
const noexcept
{
QMState const *s = m_state.obj; // start with current state
QMState const *child = s;
bool isFound = false; // assume the child NOT found
while (s != nullptr) {
if (s == parent) {
isFound = true; // child is found
break;
}
else {
child = s;
}
--lbound;
s = s->superstate;
}
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(680, lbound > 0);
Q_ASSERT_INCRIT(590, isFound);
QF_CRIT_EXIT();
if (!isFound) { // still not found?
lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound
for (s = m_temp.obj;
(s != nullptr) && (lbound > 0);
s = s->superstate)
{
if (s == parent) {
isFound = true; // child is found
break;
}
else {
child = s;
}
--lbound;
}
}
QF_CRIT_ENTRY();
// NOTE: the following postcondition can only succeed when
// (lbound > 0), so no extra check is necessary.
Q_ENSURE_INCRIT(690, isFound);
QF_CRIT_EXIT();
#ifdef Q_UNSAFE
Q_UNUSED_PAR(isFound);
#endif
return child; // return the child
}
//${QEP::QMsm::execTatbl_} ...................................................
//............................................................................
QState QMsm::execTatbl_(
QMTranActTable const * const tatbl,
std::uint_fast8_t const qsId)
@ -411,48 +327,33 @@ QState QMsm::execTatbl_(
QF_CRIT_ENTRY();
// precondition:
// - the tran-action table pointer must not be NULL
Q_REQUIRE_INCRIT(700, tatbl != nullptr);
Q_REQUIRE_INCRIT(600, tatbl != nullptr);
QF_CRIT_EXIT();
QState r = Q_RET_NULL;
std::int_fast8_t lbound = QMSM_MAX_TRAN_LENGTH_; // fixed upper loop bound
QActionHandler const *a = &tatbl->act[0];
for (; (*a != nullptr) && (lbound > 0); ++a) {
while (*a != nullptr) {
r = (*(*a))(this); // call the action through the 'a' pointer
--lbound;
++a;
#ifdef Q_SPY
QS_CRIT_ENTRY();
QS_MEM_SYS();
if (r == Q_RET_ENTRY) {
QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, qsId)
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(m_temp.obj->stateHandler); // entered state
QS_END_PRE()
QS_STATE_ACT_(QS_QEP_STATE_ENTRY, m_temp.obj->stateHandler);
}
else if (r == Q_RET_EXIT) {
QS_BEGIN_PRE(QS_QEP_STATE_EXIT, qsId)
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(m_temp.obj->stateHandler); // exited state
QS_END_PRE()
QS_STATE_ACT_(QS_QEP_STATE_EXIT, m_temp.obj->stateHandler);
}
else if (r == Q_RET_TRAN_INIT) {
QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId)
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(tatbl->target->stateHandler); // source
QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target
QS_END_PRE()
QS_TRAN_SEG_(QS_QEP_STATE_INIT,
tatbl->target->stateHandler,
m_temp.tatbl->target->stateHandler);
}
else {
// empty
}
QS_MEM_APP();
QS_CRIT_EXIT();
#endif // Q_SPY
}
QF_CRIT_ENTRY();
// NOTE: the following postcondition can only succeed when
// (lbound > 0), so no extra check is necessary.
Q_ENSURE_INCRIT(790, *a == nullptr);
Q_ASSERT_INCRIT(690, *a == nullptr);
QF_CRIT_EXIT();
m_state.obj = (r >= Q_RET_TRAN)
@ -461,7 +362,7 @@ QState QMsm::execTatbl_(
return r;
}
//${QEP::QMsm::exitToTranSource_} ............................................
//............................................................................
void QMsm::exitToTranSource_(
QMState const * const cs,
QMState const * const ts,
@ -470,36 +371,23 @@ void QMsm::exitToTranSource_(
#ifndef Q_SPY
Q_UNUSED_PAR(qsId);
#endif
QF_CRIT_STAT
QS_CRIT_STAT
// exit states from the current state to the tran. source state
QMState const *s = cs;
std::int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound
for (; (s != ts) && (lbound > 0); --lbound) {
while (s != ts) {
// exit action provided in state 's'?
if (s->exitAction != nullptr) {
// execute the exit action
static_cast<void>((*s->exitAction)(this));
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_STATE_EXIT, qsId)
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(s->stateHandler); // the exited state handler
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
QS_STATE_ACT_(QS_QEP_STATE_EXIT, m_temp.obj->stateHandler);
}
s = s->superstate; // advance to the superstate
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(890, lbound > 0);
QF_CRIT_EXIT();
}
//${QEP::QMsm::enterHistory_} ................................................
//............................................................................
QState QMsm::enterHistory_(
QMState const * const hist,
std::uint_fast8_t const qsId)
@ -511,8 +399,8 @@ QState QMsm::enterHistory_(
// record the entry path from current state to history
QMState const *epath[QMSM_MAX_ENTRY_DEPTH_];
QMState const *s = hist;
std::int_fast8_t i = 0; // tran. entry path index
while ((s != m_state.obj) && (i < (QMSM_MAX_ENTRY_DEPTH_ - 1))) {
std::int_fast8_t i = 0; // tran. entry path index & fixed upper loop bound
while ((s != m_state.obj) && (i < QMSM_MAX_ENTRY_DEPTH_)) {
if (s->entryAction != nullptr) {
epath[i] = s;
++i;
@ -521,51 +409,34 @@ QState QMsm::enterHistory_(
}
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(910, s == m_state.obj);
Q_ASSERT_INCRIT(810, i <= QMSM_MAX_ENTRY_DEPTH_);
QF_CRIT_EXIT();
// retrace the entry path in reverse (desired) order...
while (i > 0) {
--i;
(*epath[i]->entryAction)(this); // run entry action in epath[i]
// NOTE: i the fixed upper loop bound
for (i = i - 1; i >= 0; --i) {
// run entry action in epath[i]
static_cast<void>((*epath[i]->entryAction)(this));
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, qsId)
QS_OBJ_PRE(this);
QS_FUN_PRE(epath[i]->stateHandler); // entered state handler
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
QS_STATE_ACT_(QS_QEP_STATE_ENTRY, epath[i]->stateHandler);
}
m_state.obj = hist; // set current state to the tran. target
// initial tran. present?
QState r;
QState r = Q_RET_NULL;
if (hist->initAction != nullptr) {
r = (*hist->initAction)(this); // execute the tran. action
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId)
QS_OBJ_PRE(this); // this state machine object
QS_FUN_PRE(hist->stateHandler); // source
QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
}
else {
r = Q_RET_NULL;
}
QS_TRAN_SEG_(QS_QEP_STATE_INIT,
hist->stateHandler, m_temp.tatbl->target->stateHandler);
}
return r;
}
//${QEP::QMsm::topQMState} ...................................................
//............................................................................
QMState const * QMsm::topQMState() const noexcept {
return &l_msm_top_s;
}
} // namespace QP
//$enddef${QEP::QMsm} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,10 +1,6 @@
//$file${src::qf::qf_act.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qf::qf_act.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qf::qf_act.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -48,27 +43,17 @@ namespace {
//Q_DEFINE_THIS_MODULE("qf_act")
} // unnamed namespace
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
#error qpcpp version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::registry_[QF_MAX_ACTIVE + 1U]} vvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
// QP version string embedded in the binary image
char const versionStr[] = "QP/C++ " QP_VERSION_STR;
QActive * QActive::registry_[QF_MAX_ACTIVE + 1U];
} // namespace QP
//$enddef${QF::QActive::registry_[QF_MAX_ACTIVE + 1U]} ^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QF-pkg} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
namespace QF {
//${QF::QF-pkg::priv_} .......................................................
QF::Attr priv_;
//${QF::QF-pkg::bzero_} ......................................................
void bzero_(
void * const start,
std::uint_fast16_t const len) noexcept
@ -81,57 +66,47 @@ void bzero_(
}
} // namespace QF
} // namespace QP
//$enddef${QF::QF-pkg} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::types::QF_LOG2} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::types::QF_LOG2} ......................................................
//............................................................................
#ifndef QF_LOG2
std::uint_fast8_t QF_LOG2(QP::QPSetBits x) noexcept {
static std::uint8_t const log2LUT[16] = {
std::uint_fast8_t QF_LOG2(QP::QPSetBits const bitmask) noexcept {
static constexpr std::uint8_t log2LUT[16] = {
0U, 1U, 2U, 2U, 3U, 3U, 3U, 3U,
4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U
};
std::uint_fast8_t n = 0U;
QP::QPSetBits t;
QP::QPSetBits x = bitmask;
QP::QPSetBits tmp;
#if (QF_MAX_ACTIVE > 16U)
t = static_cast<QP::QPSetBits>(x >> 16U);
if (t != 0U) {
tmp = static_cast<QP::QPSetBits>(x >> 16U);
if (tmp != 0U) {
n += 16U;
x = t;
x = tmp;
}
#endif
#if (QF_MAX_ACTIVE > 8U)
t = (x >> 8U);
if (t != 0U) {
tmp = (x >> 8U);
if (tmp != 0U) {
n += 8U;
x = t;
x = tmp;
}
#endif
t = (x >> 4U);
if (t != 0U) {
tmp = (x >> 4U);
if (tmp != 0U) {
n += 4U;
x = t;
x = tmp;
}
return n + log2LUT[x];
}
#endif // ndef QF_LOG2
} // namespace QP
//$enddef${QF::types::QF_LOG2} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//............................................................................
#ifndef Q_UNSAFE
//$define${QF::types::QPtrDis} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::types::QPtrDis} ......................................................
//${QF::types::QPtrDis::QPtrDis} .............................................
QPtrDis::QPtrDis(void const * const ptr) noexcept
: m_ptr_dis(static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(ptr)))
{}
#endif
} // namespace QP
//$enddef${QF::types::QPtrDis} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#endif

View File

@ -1,10 +1,6 @@
//$file${src::qf::qf_actq.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qf::qf_actq.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qf::qf_actq.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -49,16 +44,9 @@ namespace {
Q_DEFINE_THIS_MODULE("qf_actq")
} // unnamed namespace
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
#error qpcpp version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::post_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QActive::post_} ......................................................
//............................................................................
bool QActive::post_(
QEvt const * const e,
std::uint_fast16_t const margin,
@ -78,66 +66,109 @@ bool QActive::post_(
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(200, e != nullptr);
QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary
#ifndef Q_UNSAFE
QEQueueCtr dis = static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis);
Q_INVARIANT_INCRIT(201, e->verify_() && (tmp == dis));
#endif // ndef Q_UNSAFE
// test-probe#1 for faking queue overflow
QS_TEST_PROBE_DEF(&QActive::post_)
QS_TEST_PROBE_ID(1,
tmp = 0U; // fake no free events
)
QEQueueCtr const nFree = m_eQueue.m_nFree; // get volatile into temporary
// required margin available?
bool status;
bool status = false; // assume that event cannot be posted
if (margin == QF::NO_MARGIN) {
if (tmp > 0U) { // free entries available in the queue?
if (nFree > 0U) { // free entries available in the queue?
status = true; // can post
}
else { // no free entries available
status = false; // cannot post
// The queue overflows, but QF_NO_MARGIN indicates that
// the "event delivery guarantee" is required.
Q_ERROR_INCRIT(210); // must be able to post the event
}
}
else if (tmp > static_cast<QEQueueCtr>(margin)) {
else if (nFree > static_cast<QEQueueCtr>(margin)) { // enough free?
status = true; // can post
}
else { // the # free entries below the requested margin
status = false; // cannot post, but don't assert
else {
// empty
}
// is it a mutable event?
if (e->getPoolNum_() != 0U) {
#if (QF_MAX_EPOOL > 0U)
if (e->poolNum_ != 0U) { // is it a mutable event?
Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e); // increment the reference counter
}
#endif // (QF_MAX_EPOOL > 0U)
if (status) { // can post the event?
postFIFO_(e, sender);
QF_CRIT_EXIT();
}
else { // event cannot be posted
QS_BEGIN_PRE(QS_QF_ACTIVE_POST_ATTEMPT, m_prio)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object (recipient)
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(nFree); // # free entries
QS_EQC_PRE(margin); // margin requested
QS_END_PRE()
#ifdef Q_UTEST
if (QS_LOC_CHECK_(m_prio)) {
QF_CRIT_EXIT();
QS::onTestPost(sender, this, e, status);
QF_CRIT_ENTRY();
}
#endif // def Q_USTEST
QF_CRIT_EXIT();
#if (QF_MAX_EPOOL > 0U)
QF::gc(e); // recycle the event to avoid a leak
#endif // (QF_MAX_EPOOL > 0U)
}
return status;
}
//............................................................................
void QActive::postLIFO(QEvt const * const e) noexcept {
#ifdef Q_UTEST // test?
#if (Q_UTEST != 0) // testing QP-stub?
if (m_temp.fun == Q_STATE_CAST(0)) { // QActiveDummy?
static_cast<QActiveDummy *>(this)->QActiveDummy::fakePostLIFO(e);
return;
}
#endif // (Q_UTEST != 0)
#endif // def Q_UTEST
QF_CRIT_STAT
QF_CRIT_ENTRY();
// the posted event must be be valid (which includes not NULL)
Q_REQUIRE_INCRIT(300, e != nullptr);
QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary
// The queue must NOT overflow for the LIFO posting policy.
Q_REQUIRE_INCRIT(310, tmp != 0U);
if (e->poolNum_ != 0U) { // is it a mutable event?
Q_ASSERT_INCRIT(305, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e); // increment the reference counter
}
if (status) { // can post the event?
--tmp; // one free entry just used up
m_eQueue.m_nFree = tmp; // update the original
#ifndef Q_UNSAFE
m_eQueue.m_nFree_dis = static_cast<QEQueueCtr>(~tmp);
#endif // ndef Q_UNSAFE
if (m_eQueue.m_nMin > tmp) {
m_eQueue.m_nMin = tmp; // update minimum so far
}
QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_prio)
QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(tmp); // # free entries
QS_EQC_PRE(m_eQueue.m_nMin); // min # free entries
QS_END_PRE()
@ -147,24 +178,133 @@ bool QActive::post_(
// as producing the #QS_QF_ACTIVE_POST trace record, which are:
// the local filter for this AO ('m_prio') is set
if (QS_LOC_CHECK_(m_prio)) {
QF_MEM_APP();
QF_CRIT_EXIT();
QS::onTestPost(sender, this, e, status);
QS::onTestPost(nullptr, this, e, true);
QF_CRIT_ENTRY();
QF_MEM_SYS();
}
#endif // def Q_UTEST
QEvt const * const frontEvt = m_eQueue.m_frontEvt;
m_eQueue.m_frontEvt = e; // deliver the event directly to the front
if (frontEvt != nullptr) { // was the queue NOT empty?
tmp = m_eQueue.m_tail; // get volatile into temporary;
++tmp;
if (tmp == m_eQueue.m_end) { // need to wrap the tail?
tmp = 0U; // wrap around
}
m_eQueue.m_tail = tmp;
m_eQueue.m_ring[tmp] = frontEvt;
}
else { // queue was empty
QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue
}
QF_CRIT_EXIT();
}
//............................................................................
QEvt const * QActive::get_() noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
// wait for event to arrive directly (depends on QP port)
// NOTE: might use assertion-IDs 400-409
QACTIVE_EQUEUE_WAIT_(this); // wait for event to arrive directly
// always remove event from the front
QEvt const * const e = m_eQueue.m_frontEvt;
QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary
Q_REQUIRE_INCRIT(410, e != nullptr); // queue must NOT be empty
++tmp; // one more free event in the queue
m_eQueue.m_nFree = tmp; // update the # free
if (tmp <= m_eQueue.m_end) { // any events in the ring buffer?
QS_BEGIN_PRE(QS_QF_ACTIVE_GET, m_prio)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(tmp); // # free entries
QS_END_PRE()
// remove event from the tail
tmp = m_eQueue.m_tail; // get volatile into temporary
QEvt const * const frontEvt = m_eQueue.m_ring[tmp];
Q_ASSERT_INCRIT(430, frontEvt != nullptr);
m_eQueue.m_frontEvt = frontEvt; // update the original
if (tmp == 0U) { // need to wrap the tail?
tmp = m_eQueue.m_end;
}
--tmp; // advance the tail (counter-clockwise)
m_eQueue.m_tail = tmp; // update the original
}
else {
m_eQueue.m_frontEvt = nullptr; // the queue becomes empty
// all entries in the queue must be free (+1 for fronEvt)
Q_ASSERT_INCRIT(440, tmp == (m_eQueue.m_end + 1U));
QS_BEGIN_PRE(QS_QF_ACTIVE_GET_LAST, m_prio)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_END_PRE()
}
QF_CRIT_EXIT();
return e;
}
//............................................................................
void QActive::postFIFO_(
QEvt const * const e,
void const * const sender)
{
// NOTE: this helper function is called *inside* critical section
#ifndef Q_SPY
Q_UNUSED_PAR(sender);
#endif
QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary
--tmp; // one free entry just used up
m_eQueue.m_nFree = tmp; // update the original
if (m_eQueue.m_nMin > tmp) {
m_eQueue.m_nMin = tmp; // update minimum so far
}
QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_prio)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object (recipient)
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(tmp); // # free entries
QS_EQC_PRE(m_eQueue.m_nMin); // min # free entries
QS_END_PRE()
#ifdef Q_UTEST
if (QS_LOC_CHECK_(m_prio)) {
QF_CRIT_EXIT();
QS::onTestPost(sender, this, e, true); // QUTEst callback
QF_CRIT_ENTRY();
}
#endif // def Q_UTEST
if (m_eQueue.m_frontEvt == nullptr) { // is the queue empty?
m_eQueue.m_frontEvt = e; // deliver event directly
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(211, m_eQueue.m_frontEvt_dis
== static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr)));
m_eQueue.m_frontEvt_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(e));
#endif // ndef Q_UNSAFE
#ifdef QXK_HPP_
if (m_state.act == nullptr) { // eXtended thread?
@ -179,10 +319,6 @@ bool QActive::post_(
}
else { // queue was not empty, insert event into the ring-buffer
tmp = m_eQueue.m_head; // get volatile into temporary
#ifndef Q_UNSAFE
dis = static_cast<QEQueueCtr>(~m_eQueue.m_head_dis);
Q_INVARIANT_INCRIT(212, tmp == dis);
#endif // ndef Q_UNSAFE
m_eQueue.m_ring[tmp] = e; // insert e into buffer
if (tmp == 0U) { // need to wrap the head?
@ -191,272 +327,20 @@ bool QActive::post_(
--tmp; // advance the head (counter-clockwise)
m_eQueue.m_head = tmp; // update the original
#ifndef Q_UNSAFE
m_eQueue.m_head_dis = static_cast<QEQueueCtr>(~tmp);
#endif // ndef Q_UNSAFE
}
}
QF_MEM_APP();
QF_CRIT_EXIT();
}
else { // event cannot be posted
QS_BEGIN_PRE(QS_QF_ACTIVE_POST_ATTEMPT, m_prio)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_EQC_PRE(tmp); // # free entries
QS_EQC_PRE(margin); // margin requested
QS_END_PRE()
//============================================================================
#ifdef Q_UTEST
// callback to examine the posted event under the same conditions
// as producing the #QS_QF_ACTIVE_POST trace record, which are:
// the local filter for this AO ('m_prio') is set
if (QS_LOC_CHECK_(m_prio)) {
QF_MEM_APP();
QF_CRIT_EXIT();
QS::onTestPost(sender, this, e, status);
QF_CRIT_ENTRY();
QF_MEM_SYS();
}
#endif // def Q_USTEST
QF_MEM_APP();
QF_CRIT_EXIT();
#if (QF_MAX_EPOOL > 0U)
QF::gc(e); // recycle the event to avoid a leak
#endif // (QF_MAX_EPOOL > 0U)
}
return status;
}
} // namespace QP
//$enddef${QF::QActive::post_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::postLIFO} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QActive::postLIFO} ...................................................
void QActive::postLIFO(QEvt const * const e) noexcept {
#ifdef Q_UTEST // test?
#if (Q_UTEST != 0) // testing QP-stub?
if (m_temp.fun == Q_STATE_CAST(0)) { // QActiveDummy?
static_cast<QActiveDummy *>(this)->QActiveDummy::fakePostLIFO(e);
return;
}
#endif // (Q_UTEST != 0)
#endif // def Q_UTEST
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(300, e != nullptr);
QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary
#ifndef Q_UNSAFE
QEQueueCtr dis = static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis);
Q_INVARIANT_INCRIT(301, e->verify_() && (tmp == dis));
#endif // ndef Q_UNSAFE
// test-probe#1 for faking queue overflow
QS_TEST_PROBE_DEF(&QActive::postLIFO)
QS_TEST_PROBE_ID(1,
tmp = 0U; // fake no free events
)
// The queue must NOT overflow for the LIFO posting policy.
Q_REQUIRE_INCRIT(310, tmp != 0U);
if (e->getPoolNum_() != 0U) {
QEvt_refCtr_inc_(e); // increment the reference counter
}
--tmp; // one free entry just used up
m_eQueue.m_nFree = tmp; // update the original
#ifndef Q_UNSAFE
m_eQueue.m_nFree_dis = static_cast<QEQueueCtr>(~tmp);
#endif // ndef Q_UNSAFE
if (m_eQueue.m_nMin > tmp) {
m_eQueue.m_nMin = tmp; // update minimum so far
}
QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_EQC_PRE(tmp); // # free entries
QS_EQC_PRE(m_eQueue.m_nMin); // min # free entries
QS_END_PRE()
#ifdef Q_UTEST
// callback to examine the posted event under the same conditions
// as producing the #QS_QF_ACTIVE_POST trace record, which are:
// the local filter for this AO ('m_prio') is set
if (QS_LOC_CHECK_(m_prio)) {
QF_MEM_APP();
QF_CRIT_EXIT();
QS::onTestPost(nullptr, this, e, true);
QF_CRIT_ENTRY();
QF_MEM_SYS();
}
#endif // def Q_UTEST
QEvt const * const frontEvt = m_eQueue.m_frontEvt;
m_eQueue.m_frontEvt = e; // deliver the event directly to the front
#ifndef Q_UNSAFE
m_eQueue.m_frontEvt_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(e));
#endif // ndef Q_UNSAFE
if (frontEvt != nullptr) { // was the queue NOT empty?
tmp = m_eQueue.m_tail; // get volatile into temporary;
#ifndef Q_UNSAFE
dis = static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis);
Q_INVARIANT_INCRIT(311, tmp == dis);
#endif // ndef Q_UNSAFE
++tmp;
if (tmp == m_eQueue.m_end) { // need to wrap the tail?
tmp = 0U; // wrap around
}
m_eQueue.m_tail = tmp;
#ifndef Q_UNSAFE
m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~tmp);
#endif // ndef Q_UNSAFE
m_eQueue.m_ring[tmp] = frontEvt;
}
else { // queue was empty
QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue
}
QF_MEM_APP();
QF_CRIT_EXIT();
}
} // namespace QP
//$enddef${QF::QActive::postLIFO} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::get_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QActive::get_} .......................................................
QEvt const * QActive::get_() noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
// wait for event to arrive directly (depends on QP port)
// NOTE: might use assertion-IDs 400-409
QACTIVE_EQUEUE_WAIT_(this); // wait for event to arrive directly
// always remove evt from the front
QEvt const * const e = m_eQueue.m_frontEvt;
QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into tmp
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(410, e != nullptr); // queue must NOT be empty
Q_INVARIANT_INCRIT(411, Q_PTR2UINT_CAST_(e)
== static_cast<std::uintptr_t>(~m_eQueue.m_frontEvt_dis));
QEQueueCtr dis = static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis);
Q_INVARIANT_INCRIT(412, tmp == dis);
#endif // ndef Q_UNSAFE
++tmp; // one more free event in the queue
m_eQueue.m_nFree = tmp; // update the # free
#ifndef Q_UNSAFE
m_eQueue.m_nFree_dis = static_cast<QEQueueCtr>(~tmp);
#endif // ndef Q_UNSAFE
if (tmp <= m_eQueue.m_end) { // any events in the ring buffer?
QS_BEGIN_PRE(QS_QF_ACTIVE_GET, m_prio)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_EQC_PRE(tmp); // # free entries
QS_END_PRE()
// remove event from the tail
tmp = m_eQueue.m_tail; // get volatile into temporary
#ifndef Q_UNSAFE
dis = static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis);
Q_INVARIANT_INCRIT(420, tmp == dis);
#endif // ndef Q_UNSAFE
QEvt const * const frontEvt = m_eQueue.m_ring[tmp];
#ifndef Q_UNSAFE
Q_ASSERT_INCRIT(421, frontEvt != nullptr);
m_eQueue.m_frontEvt_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(frontEvt));
#endif // ndef Q_UNSAFE
m_eQueue.m_frontEvt = frontEvt; // update the original
if (tmp == 0U) { // need to wrap the tail?
tmp = m_eQueue.m_end;
}
--tmp; // advance the tail (counter-clockwise)
m_eQueue.m_tail = tmp; // update the original
#ifndef Q_UNSAFE
m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~tmp);
#endif // ndef Q_UNSAFE
}
else {
m_eQueue.m_frontEvt = nullptr; // the queue becomes empty
#ifndef Q_UNSAFE
m_eQueue.m_frontEvt_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr));
#endif // ndef Q_UNSAFE
// all entries in the queue must be free (+1 for fronEvt)
Q_ASSERT_INCRIT(310, tmp == (m_eQueue.m_end + 1U));
QS_BEGIN_PRE(QS_QF_ACTIVE_GET_LAST, m_prio)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_END_PRE()
}
QF_MEM_APP();
QF_CRIT_EXIT();
return e;
}
} // namespace QP
//$enddef${QF::QActive::get_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QTicker} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QTicker} .............................................................
//${QF::QTicker::QTicker} ....................................................
QTicker::QTicker(std::uint_fast8_t const tickRate) noexcept
: QActive(nullptr)
{
// reuse m_head for tick-rate
m_eQueue.m_head = static_cast<QEQueueCtr>(tickRate);
#ifndef Q_UNSAFE
m_eQueue.m_head_dis = static_cast<QEQueueCtr>(~tickRate);
#endif // ndef Q_UNSAFE
}
//${QF::QTicker::init} .......................................................
//............................................................................
void QTicker::init(
void const * const e,
std::uint_fast8_t const qsId)
@ -466,18 +350,11 @@ void QTicker::init(
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
m_eQueue.m_tail = 0U;
#ifndef Q_UNSAFE
m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~0U);
#endif // ndef Q_UNSAFE
QF_MEM_APP();
QF_CRIT_EXIT();
}
//${QF::QTicker::dispatch} ...................................................
//............................................................................
void QTicker::dispatch(
QEvt const * const e,
std::uint_fast8_t const qsId)
@ -487,26 +364,13 @@ void QTicker::dispatch(
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
// get volatile into temporaries
QEQueueCtr nTicks = m_eQueue.m_tail;
QEQueueCtr const tickRate = m_eQueue.m_head;
#ifndef Q_UNSAFE
Q_REQUIRE_INCRIT(700, nTicks > 0U);
Q_INVARIANT_INCRIT(701, nTicks
== static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis));
Q_INVARIANT_INCRIT(702, tickRate
== static_cast<QEQueueCtr>(~m_eQueue.m_head_dis));
#endif // ndef Q_UNSAFE
Q_REQUIRE_INCRIT(800, nTicks > 0U);
m_eQueue.m_tail = 0U; // clear # ticks
#ifndef Q_UNSAFE
m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~0U);
#endif // ndef Q_UNSAFE
QF_MEM_APP();
QF_CRIT_EXIT();
for (; nTicks > 0U; --nTicks) {
@ -515,7 +379,7 @@ void QTicker::dispatch(
}
}
//${QF::QTicker::trig_} ......................................................
//............................................................................
void QTicker::trig_(void const * const sender) noexcept {
#ifndef Q_SPY
Q_UNUSED_PAR(sender);
@ -525,51 +389,27 @@ void QTicker::trig_(void const * const sender) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
QEQueueCtr nTicks = m_eQueue.m_tail; // get volatile into temporary
if (m_eQueue.m_frontEvt == nullptr) {
#ifndef Q_UNSAFE
Q_REQUIRE_INCRIT(800, nTicks == 0U);
Q_REQUIRE_INCRIT(801, m_eQueue.m_nFree == 1U);
Q_INVARIANT_INCRIT(802, m_eQueue.m_frontEvt_dis
== static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr)));
Q_INVARIANT_INCRIT(803,
1U == static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis));
Q_INVARIANT_INCRIT(804,
0U == static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis));
#endif // ndef Q_UNSAFE
Q_REQUIRE_INCRIT(900,
(m_eQueue.m_nFree == 1U)
&& (nTicks == 0U));
m_eQueue.m_frontEvt = &tickEvt; // deliver event directly
m_eQueue.m_nFree = 0U;
#ifndef Q_UNSAFE
m_eQueue.m_frontEvt_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(&tickEvt));
m_eQueue.m_nFree_dis = static_cast<QEQueueCtr>(~0U);
#endif // ndef Q_UNSAFE
QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue
}
else {
#ifndef Q_UNSAFE
Q_REQUIRE_INCRIT(810, (nTicks > 0U) && (nTicks < 0xFFU));
Q_REQUIRE_INCRIT(811, m_eQueue.m_nFree == 0U);
Q_INVARIANT_INCRIT(812, m_eQueue.m_frontEvt_dis
== static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(&tickEvt)));
Q_INVARIANT_INCRIT(813,
0U == static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis));
Q_INVARIANT_INCRIT(814,
nTicks == static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis));
#endif // ndef Q_UNSAFE
Q_REQUIRE_INCRIT(910, (nTicks > 0U) && (nTicks < 0xFFU));
Q_REQUIRE_INCRIT(920, m_eQueue.m_nFree == 0U);
}
++nTicks; // account for one more tick event
m_eQueue.m_tail = nTicks; // update the original
#ifndef Q_UNSAFE
m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~nTicks);
#endif // ndef Q_UNSAFE
QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_prio)
QS_TIME_PRE(); // timestamp
@ -581,9 +421,7 @@ void QTicker::trig_(void const * const sender) noexcept {
QS_EQC_PRE(0U); // min # free entries
QS_END_PRE()
QF_MEM_APP();
QF_CRIT_EXIT();
}
} // namespace QP
//$enddef${QF::QTicker} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,10 +1,6 @@
//$file${src::qf::qf_defer.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qf::qf_defer.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qf::qf_defer.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -48,16 +43,9 @@ namespace {
Q_DEFINE_THIS_MODULE("qf_defer")
} // unnamed namespace
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
#error qpcpp version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::defer} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QActive::defer} ......................................................
//............................................................................
bool QActive::defer(
QEQueue * const eq,
QEvt const * const e) const noexcept
@ -66,27 +54,19 @@ bool QActive::defer(
QS_CRIT_STAT
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QF_ACTIVE_DEFER, m_prio)
QS_TIME_PRE(); // time stamp
QS_OBJ_PRE(this); // this active object
QS_OBJ_PRE(eq); // the deferred queue
QS_SIG_PRE(e->sig); // the signal of the event
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
return status;
}
} // namespace QP
//$enddef${QF::QActive::defer} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::recall} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QActive::recall} .....................................................
//............................................................................
bool QActive::recall(QEQueue * const eq) noexcept {
QEvt const * const e = eq->get(m_prio); // get evt from deferred queue
QF_CRIT_STAT
@ -96,15 +76,14 @@ bool QActive::recall(QEQueue * const eq) noexcept {
postLIFO(e); // post it to the _front_ of the AO's queue
QF_CRIT_ENTRY();
QF_MEM_SYS();
if (e->getPoolNum_() != 0U) { // is it a mutable event?
if (e->poolNum_ != 0U) { // is it a mutable event?
// after posting to the AO's queue the event must be referenced
// at least twice: once in the deferred event queue (eq->get()
// did NOT decrement the reference counter) and once in the
// AO's event queue.
Q_ASSERT_INCRIT(210, e->refCtr_ >= 2U);
Q_ASSERT_INCRIT(205, e->refCtr_ >= 2U);
// we need to decrement the reference counter once, to account
// for removing the event from the deferred event queue.
@ -116,17 +95,15 @@ bool QActive::recall(QEQueue * const eq) noexcept {
QS_OBJ_PRE(this); // this active object
QS_OBJ_PRE(eq); // the deferred queue
QS_SIG_PRE(e->sig); // the signal of the event
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_END_PRE()
QF_MEM_APP();
QF_CRIT_EXIT();
recalled = true;
}
else {
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QF_ACTIVE_RECALL_ATTEMPT, m_prio)
QS_TIME_PRE(); // time stamp
@ -134,7 +111,6 @@ bool QActive::recall(QEQueue * const eq) noexcept {
QS_OBJ_PRE(eq); // the deferred queue
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
recalled = false;
@ -142,13 +118,7 @@ bool QActive::recall(QEQueue * const eq) noexcept {
return recalled;
}
} // namespace QP
//$enddef${QF::QActive::recall} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::flushDeferred} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QActive::flushDeferred} ..............................................
//............................................................................
std::uint_fast16_t QActive::flushDeferred(
QEQueue * const eq,
std::uint_fast16_t const num) const noexcept
@ -171,4 +141,3 @@ std::uint_fast16_t QActive::flushDeferred(
}
} // namespace QP
//$enddef${QF::QActive::flushDeferred} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,10 +1,6 @@
//$file${src::qf::qf_dyn.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qf::qf_dyn.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qf::qf_dyn.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -50,17 +45,10 @@ namespace {
Q_DEFINE_THIS_MODULE("qf_dyn")
} // unnamed namespace
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
#error qpcpp version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QF-dyn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
namespace QF {
//${QF::QF-dyn::poolInit} ....................................................
//............................................................................
void poolInit(
void * const poolSto,
std::uint_fast32_t const poolSize,
@ -71,16 +59,14 @@ void poolInit(
// see precondition{qf_dyn,200} and precondition{qf_dyn,201}
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(200, poolNum < QF_MAX_EPOOL);
Q_REQUIRE_INCRIT(100, poolNum < QF_MAX_EPOOL);
if (poolNum > 0U) {
Q_REQUIRE_INCRIT(201,
Q_REQUIRE_INCRIT(110,
QF_EPOOL_EVENT_SIZE_(priv_.ePool_[poolNum - 1U]) < evtSize);
}
priv_.maxPool_ = poolNum + 1U; // one more pool
QF_MEM_APP();
QF_CRIT_EXIT();
// perform the port-dependent initialization of the event-pool
@ -99,38 +85,34 @@ void poolInit(
#endif // Q_SPY
}
//${QF::QF-dyn::poolGetMaxBlockSize} .........................................
//............................................................................
std::uint_fast16_t poolGetMaxBlockSize() noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
std::uint_fast16_t const max_size =
QF_EPOOL_EVENT_SIZE_(priv_.ePool_[priv_.maxPool_ - 1U]);
QF_MEM_APP();
QF_CRIT_EXIT();
return max_size;
}
//${QF::QF-dyn::getPoolMin} ..................................................
//............................................................................
std::uint_fast16_t getPoolMin(std::uint_fast8_t const poolNum) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(400, (poolNum <= QF_MAX_EPOOL)
Q_REQUIRE_INCRIT(300, (poolNum <= QF_MAX_EPOOL)
&& (0U < poolNum) && (poolNum <= priv_.maxPool_));
std::uint_fast16_t const min = static_cast<std::uint_fast16_t>(
priv_.ePool_[poolNum - 1U].getNMin());
QF_MEM_APP();
QF_CRIT_EXIT();
return min;
}
//${QF::QF-dyn::newX_} .......................................................
//............................................................................
QEvt * newX_(
std::uint_fast16_t const evtSize,
std::uint_fast16_t const margin,
@ -138,10 +120,9 @@ QEvt * newX_(
{
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
// find the pool id that fits the requested event size...
std::uint_fast8_t poolNum = 0U; // zero-based poolNum initially
std::uint8_t poolNum = 0U; // zero-based poolNum initially
for (; poolNum < priv_.maxPool_; ++poolNum) {
if (evtSize <= QF_EPOOL_EVENT_SIZE_(priv_.ePool_[poolNum])) {
break;
@ -150,15 +131,14 @@ QEvt * newX_(
// precondition:
// - cannot run out of registered pools
Q_REQUIRE_INCRIT(300, poolNum < priv_.maxPool_);
Q_REQUIRE_INCRIT(400, poolNum < priv_.maxPool_);
++poolNum; // convert to 1-based poolNum
QF_MEM_APP();
QF_CRIT_EXIT();
// get event e (port-dependent)...
QEvt *e;
// get event `e` out of the event pool (port-dependent)...
QEvt *e = nullptr;
#ifdef Q_SPY
QF_EPOOL_GET_(priv_.ePool_[poolNum - 1U], e,
((margin != NO_MARGIN) ? margin : 0U),
@ -170,18 +150,16 @@ QEvt * newX_(
if (e != nullptr) { // was e allocated correctly?
e->sig = static_cast<QSignal>(sig); // set the signal
e->evtTag_ = static_cast<std::uint8_t>((poolNum << 4U) | 0x0FU);
e->poolNum_ = poolNum;
e->refCtr_ = 0U; // initialize the reference counter to 0
QS_CRIT_ENTRY();
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QF_NEW,
static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
QS_TIME_PRE(); // timestamp
QS_EVS_PRE(evtSize); // the size of the event
QS_SIG_PRE(sig); // the signal of the event
QS_END_PRE()
QS_MEM_APP();
QS_CRIT_EXIT();
}
else { // event was not allocated
@ -190,16 +168,14 @@ QEvt * newX_(
// This assertion means that the event allocation failed,
// and this failure cannot be tolerated. The most frequent
// reason is an event leak in the application.
Q_ASSERT_INCRIT(320, margin != NO_MARGIN);
Q_ASSERT_INCRIT(420, margin != NO_MARGIN);
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QF_NEW_ATTEMPT,
static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
QS_TIME_PRE(); // timestamp
QS_EVS_PRE(evtSize); // the size of the event
QS_SIG_PRE(sig); // the signal of the event
QS_END_PRE()
QS_MEM_APP();
QF_CRIT_EXIT();
}
@ -209,17 +185,16 @@ QEvt * newX_(
return e;
}
//${QF::QF-dyn::gc} ..........................................................
//............................................................................
void gc(QEvt const * const e) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(400, e != nullptr);
Q_INVARIANT_INCRIT(401, e->verify_());
std::uint_fast8_t const poolNum = e->getPoolNum_();
Q_REQUIRE_INCRIT(500, e != nullptr);
std::uint_fast8_t const poolNum = e->poolNum_;
if (poolNum != 0U) { // is it a pool event (mutable)?
QF_MEM_SYS();
if (e->refCtr_ > 1U) { // isn't this the last reference?
@ -230,9 +205,9 @@ void gc(QEvt const * const e) noexcept {
QS_2U8_PRE(poolNum, e->refCtr_);
QS_END_PRE()
Q_ASSERT_INCRIT(505, e->refCtr_ > 0U);
QEvt_refCtr_dec_(e); // decrement the ref counter
QF_MEM_APP();
QF_CRIT_EXIT();
}
else { // this is the last reference to this event, recycle it
@ -245,9 +220,8 @@ void gc(QEvt const * const e) noexcept {
QS_END_PRE()
// pool number must be in range
Q_ASSERT_INCRIT(410, (poolNum <= priv_.maxPool_)
Q_ASSERT_INCRIT(510, (poolNum <= priv_.maxPool_)
&& (poolNum <= QF_MAX_EPOOL));
QF_MEM_APP();
QF_CRIT_EXIT();
// NOTE: casting 'const' away is legit because it's a pool event
@ -266,7 +240,7 @@ void gc(QEvt const * const e) noexcept {
}
}
//${QF::QF-dyn::newRef_} .....................................................
//............................................................................
QEvt const * newRef_(
QEvt const * const e,
QEvt const * const evtRef) noexcept
@ -278,52 +252,47 @@ QEvt const * newRef_(
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(500, e != nullptr);
Q_INVARIANT_INCRIT(501, e->verify_());
Q_REQUIRE_INCRIT(600, e != nullptr);
std::uint_fast8_t const poolNum = e->getPoolNum_();
std::uint_fast8_t const poolNum = e->poolNum_;
Q_UNUSED_PAR(poolNum); // might be unused
Q_REQUIRE_INCRIT(501, (poolNum != 0U)
Q_REQUIRE_INCRIT(610, (poolNum != 0U)
&& (evtRef == nullptr));
Q_ASSERT_INCRIT(605, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e); // increments the ref counter
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QF_NEW_REF,
static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of the event
QS_2U8_PRE(poolNum, e->refCtr_);
QS_END_PRE()
QS_MEM_APP();
QF_CRIT_EXIT();
return e;
}
//${QF::QF-dyn::deleteRef_} ..................................................
//............................................................................
void deleteRef_(QEvt const * const evtRef) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QEvt const * const e = evtRef;
Q_REQUIRE_INCRIT(600, e != nullptr);
Q_INVARIANT_INCRIT(601, e->verify_());
Q_REQUIRE_INCRIT(700, e != nullptr);
#ifdef Q_SPY
std::uint_fast8_t const poolNum = e->getPoolNum_();
#endif
std::uint_fast8_t const poolNum = e->poolNum_;
QS_MEM_SYS();
QS_BEGIN_PRE(QS_QF_DELETE_REF,
static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of the event
QS_2U8_PRE(poolNum, e->refCtr_);
QS_END_PRE()
QS_MEM_APP();
#endif // def Q_SPY
QF_CRIT_EXIT();
@ -334,6 +303,5 @@ void deleteRef_(QEvt const * const evtRef) noexcept {
} // namespace QF
} // namespace QP
//$enddef${QF::QF-dyn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#endif // (QF_MAX_EPOOL > 0U) mutable events configured

View File

@ -1,10 +1,6 @@
//$file${src::qf::qf_mem.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qf::qf_mem.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,15 +26,14 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qf::qf_mem.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
#ifdef Q_SPY // QS software tracing enabled?
#include "qs_port.hpp" // QS port
#include "qs_pkg.hpp" // QS facilities for pre-defined trace records
#include "qs_pkg.hpp" // QS package-scope internal interface
#else
#include "qs_dummy.hpp" // disable the QS software tracing
#endif // Q_SPY
@ -48,18 +43,9 @@ namespace {
Q_DEFINE_THIS_MODULE("qf_mem")
} // unnamed namespace
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
#error qpcpp version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QMPool} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QMPool} ..............................................................
//${QF::QMPool::init} ........................................................
//............................................................................
void QMPool::init(
void * const poolSto,
std::uint_fast32_t const poolSize,
@ -67,30 +53,24 @@ void QMPool::init(
{
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(100, poolSto != nullptr);
Q_REQUIRE_INCRIT(101,
poolSize >= static_cast<std::uint_fast32_t>(sizeof(QFreeBlock)));
Q_REQUIRE_INCRIT(102,
static_cast<std::uint_fast16_t>(blockSize + sizeof(QFreeBlock))
> blockSize);
m_free_head = static_cast<QFreeBlock *>(poolSto);
m_freeHead = static_cast<void * *>(poolSto);
// find # free blocks in a memory block, NO DIVISION
// find # free links in a memory block, see NOTE1
m_blockSize = static_cast<QMPoolSize>(2U * sizeof(void *));
std::uint_fast16_t nblocks = 1U;
std::uint_fast16_t inext = 2U;
while (m_blockSize < static_cast<QMPoolSize>(blockSize)) {
m_blockSize += static_cast<QMPoolSize>(sizeof(QFreeBlock));
++nblocks;
m_blockSize += static_cast<QMPoolSize>(sizeof(void *));
++inext;
}
// the pool buffer must fit at least one rounded-up block
Q_ASSERT_INCRIT(110, poolSize >= m_blockSize);
// start at the head of the free list
QFreeBlock *fb = m_free_head;
void * *pfb = m_freeHead; // pointer to free block
std::uint32_t nTot = 1U; // the last block already in the list
// chain all blocks together in a free-list...
@ -98,41 +78,29 @@ void QMPool::init(
size >= static_cast<std::uint_fast32_t>(m_blockSize);
size -= static_cast<std::uint_fast32_t>(m_blockSize))
{
fb->m_next = &fb[nblocks]; // point next link to next block
#ifndef Q_UNSAFE
fb->m_next_dis = ~Q_PTR2UINT_CAST_(fb->m_next);
#endif
fb = fb->m_next; // advance to the next block
pfb[0] = &pfb[inext]; // set the next link to next free block
pfb = static_cast<void * *>(pfb[0]); // advance to the next block
++nTot; // one more free block in the pool
}
pfb[0] = nullptr; // the last link points to NULL
// dynamic range check
#if (QF_MPOOL_CTR_SIZE == 1U)
Q_ENSURE_INCRIT(190, nTot < 0xFFU);
Q_ASSERT_INCRIT(190, nTot < 0xFFU);
#elif (QF_MPOOL_CTR_SIZE == 2U)
Q_ENSURE_INCRIT(190, nTot < 0xFFFFU);
Q_ASSERT_INCRIT(190, nTot < 0xFFFFU);
#endif
fb->m_next = nullptr; // the last link points to NULL
m_nTot = static_cast<QMPoolCtr>(nTot);
m_nFree = m_nTot; // all blocks are free
m_start = static_cast<QFreeBlock *>(poolSto); // original start
m_end = fb; // the last block in this pool
#ifndef Q_UNSAFE
m_free_head_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(m_free_head));
m_nFree_dis = static_cast<QMPoolCtr>(~m_nFree);
m_start = static_cast<void * *>(poolSto); // original start
m_end = pfb; // the last block in this pool
m_nMin = m_nTot; // the minimum # free blocks
fb->m_next_dis = ~Q_PTR2UINT_CAST_(fb->m_next);
#endif
QF_MEM_APP();
QF_CRIT_EXIT();
}
//${QF::QMPool::get} .........................................................
//............................................................................
void * QMPool::get(
std::uint_fast16_t const margin,
std::uint_fast8_t const qsId) noexcept
@ -143,93 +111,67 @@ void * QMPool::get(
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
// get volatile into temporaries
QFreeBlock *fb = m_free_head;
void * *pfb = m_freeHead; // pointer to free block
QMPoolCtr nFree = m_nFree;
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(301, Q_PTR2UINT_CAST_(fb)
== static_cast<std::uintptr_t>(~m_free_head_dis));
Q_INVARIANT_INCRIT(302, nFree == static_cast<QMPoolCtr>(~m_nFree_dis));
#endif // ndef Q_UNSAFE
// have more free blocks than the requested margin?
if (nFree > static_cast<QMPoolCtr>(margin)) {
Q_ASSERT_INCRIT(310, fb != nullptr);
Q_ASSERT_INCRIT(310, pfb != nullptr);
QFreeBlock * const fb_next = fb->m_next;
#ifndef Q_UNSAFE
// the free block must have integrity (duplicate inverse storage)
Q_INVARIANT_INCRIT(311, Q_PTR2UINT_CAST_(fb_next)
== static_cast<std::uintptr_t>(~fb->m_next_dis));
#endif // ndef Q_UNSAFE
// fast temporary
void * * const pfb_next = static_cast<void * *>(pfb[0]);
--nFree; // one less free block
if (nFree == 0U) { // is the pool becoming empty?
// pool is becoming empty, so the next free block must be NULL
Q_ASSERT_INCRIT(320, fb_next == nullptr);
Q_ASSERT_INCRIT(320, pfb_next == nullptr);
m_nFree = 0U;
#ifndef Q_UNSAFE
m_nFree_dis = static_cast<QMPoolCtr>(~m_nFree);
m_nFree = 0U; // no more free blocks
m_nMin = 0U; // remember that the pool got empty
#endif // ndef Q_UNSAFE
}
else {
else { // the pool is NOT empty
// the next free-block pointer must be in range
Q_ASSERT_INCRIT(330, QF_PTR_RANGE_(pfb_next, m_start, m_end));
m_nFree = nFree; // update the original
#ifndef Q_UNSAFE
m_nFree_dis = static_cast<QMPoolCtr>(~nFree);
// The pool is not empty, so the next free-block pointer
// must be in range.
Q_INVARIANT_INCRIT(330,
QF_PTR_RANGE_(fb_next, m_start, m_end));
// is the # free blocks the new minimum so far?
if (m_nMin > nFree) {
if (m_nMin > nFree) { // is this the new minimum?
m_nMin = nFree; // remember the minimum so far
}
#endif // ndef Q_UNSAFE
}
m_free_head = fb_next; // set the head to the next free block
#ifndef Q_UNSAFE
m_free_head_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(fb_next));
#endif // ndef Q_UNSAFE
m_freeHead = pfb_next; // set the head to the next free block
// change the allocated block contents so that it is different
// than a free block inside the pool.
pfb[0] = &m_end[1]; // invalid location beyond the end
QS_BEGIN_PRE(QS_QF_MPOOL_GET, qsId)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(this); // this memory pool
QS_MPC_PRE(nFree); // # of free blocks in the pool
#ifndef Q_UNSAFE
QS_MPC_PRE(nFree); // # free blocks in the pool
QS_MPC_PRE(m_nMin); // min # free blocks ever in the pool
#else
QS_MPC_PRE(0U); // min # free blocks (not available)
#endif // ndef Q_UNSAFE
QS_END_PRE()
}
else { // don't have enough free blocks at this point
fb = nullptr;
pfb = nullptr;
QS_BEGIN_PRE(QS_QF_MPOOL_GET_ATTEMPT, qsId)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(this); // this memory pool
QS_MPC_PRE(nFree); // # of free blocks in the pool
QS_MPC_PRE(nFree); // # free blocks in the pool
QS_MPC_PRE(margin); // the requested margin
QS_END_PRE()
}
QF_MEM_APP();
QF_CRIT_EXIT();
return fb; // return the block or nullptr to the caller
return pfb; // return the block or nullptr to the caller
}
//${QF::QMPool::put} .........................................................
//............................................................................
void QMPool::put(
void * const block,
std::uint_fast8_t const qsId) noexcept
@ -238,39 +180,23 @@ void QMPool::put(
Q_UNUSED_PAR(qsId);
#endif
QFreeBlock * const fb = static_cast<QFreeBlock *>(block);
void * * const pfb = static_cast<void * *>(block); // pointer to free block
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
// get volatile into temporaries
QFreeBlock * const free_head = m_free_head;
void * * const freeHead = m_freeHead;
QMPoolCtr nFree = m_nFree;
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(401, Q_PTR2UINT_CAST_(free_head)
== static_cast<std::uintptr_t>(~m_free_head_dis));
Q_INVARIANT_INCRIT(402, nFree == static_cast<QMPoolCtr>(~m_nFree_dis));
Q_REQUIRE_INCRIT(410, nFree < m_nTot);
Q_REQUIRE_INCRIT(411, QF_PTR_RANGE_(fb, m_start, m_end));
// the block must not be in the pool already
Q_REQUIRE_INCRIT(412, Q_PTR2UINT_CAST_(fb->m_next)
!= static_cast<std::uintptr_t>(~fb->m_next_dis));
#endif // ndef Q_UNSAFE
Q_REQUIRE_INCRIT(400, nFree < m_nTot);
Q_REQUIRE_INCRIT(410, QF_PTR_RANGE_(pfb, m_start, m_end));
++nFree; // one more free block in this pool
m_free_head = fb; // set as new head of the free list
m_freeHead = pfb; // set as new head of the free list
m_nFree = nFree;
fb->m_next = free_head; // link into the list
#ifndef Q_UNSAFE
m_free_head_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(fb));
m_nFree_dis = static_cast<QMPoolCtr>(~nFree);
fb->m_next_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(free_head));
#endif
pfb[0] = freeHead; // link into the list
QS_BEGIN_PRE(QS_QF_MPOOL_PUT, qsId)
QS_TIME_PRE(); // timestamp
@ -278,14 +204,18 @@ void QMPool::put(
QS_MPC_PRE(nFree); // the # free blocks in the pool
QS_END_PRE()
QF_MEM_APP();
QF_CRIT_EXIT();
}
//${QF::QMPool::getBlockSize} ................................................
QMPoolSize QMPool::getBlockSize() const noexcept {
return m_blockSize;
}
} // namespace QP
//$enddef${QF::QMPool} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
// NOTE1:
// The memory buffer for the pool is organized as an array of void* pointers
// (see void * data type). These pointers are used to form a linked-list
// of free blocks in the pool. The first location pfb[0] is the actual link.
// The second location pfb[1] is used in SafeQP as the redundant "duplicate
// storage" for the link at pfb[0]. Even though the "duplicate storage" is NOT
// used in this QP edition, the minimum number of number of void* pointers
// (void * data type) inside a memory block is still kept at 2 to maintain
// the same policy for sizing the memory blocks.

View File

@ -1,10 +1,6 @@
//$file${src::qf::qf_ps.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qf::qf_ps.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qf::qf_ps.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -48,30 +43,12 @@ namespace {
Q_DEFINE_THIS_MODULE("qf_ps")
} // unnamed namespace
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
#error qpcpp version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::subscrList_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
QSubscrList * QActive::subscrList_;
} // namespace QP
//$enddef${QF::QActive::subscrList_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::maxPubSignal_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
enum_t QActive::maxPubSignal_;
} // namespace QP
//$enddef${QF::QActive::maxPubSignal_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::psInit} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QActive::psInit} .....................................................
//............................................................................
void QActive::psInit(
QSubscrList * const subscrSto,
enum_t const maxSignal) noexcept
@ -82,19 +59,10 @@ void QActive::psInit(
// initialize the subscriber list
for (enum_t sig = 0; sig < maxSignal; ++sig) {
subscrSto[sig].m_set.setEmpty();
#ifndef Q_UNSAFE
subscrSto[sig].m_set.update_(&subscrSto[sig].m_set_dis);
#endif
}
}
} // namespace QP
//$enddef${QF::QActive::psInit} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::publish_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QActive::publish_} ...................................................
//............................................................................
void QActive::publish_(
QEvt const * const e,
void const * const sender,
@ -109,34 +77,31 @@ void QActive::publish_(
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(200, sig < static_cast<QSignal>(maxPubSignal_));
Q_INVARIANT_INCRIT(202,
subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis));
QS_BEGIN_PRE(QS_QF_PUBLISH, qsId)
QS_TIME_PRE(); // the timestamp
QS_OBJ_PRE(sender); // the sender object
QS_SIG_PRE(e->sig); // the signal of the event
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_END_PRE()
// is it a mutable event?
if (e->getPoolNum_() != 0U) {
if (e->poolNum_ != 0U) {
// NOTE: The reference counter of a mutable event is incremented to
// prevent premature recycling of the event while the multicasting
// is still in progress. At the end of the function, the garbage
// collector step (QF::gc()) decrements the reference counter and
// recycles the event if the counter drops to zero. This covers the
// case when the event was published without any subscribers.
Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e);
}
// make a local, modifiable copy of the subscriber set
QPSet subscrSet = subscrList_[sig].m_set;
QF_MEM_APP();
QF_CRIT_EXIT();
if (subscrSet.notEmpty()) { // any subscribers?
@ -144,21 +109,16 @@ void QActive::publish_(
std::uint_fast8_t p = subscrSet.findMax();
QF_CRIT_ENTRY();
QF_MEM_SYS();
QActive *a = registry_[p];
// the AO must be registered with the framework
Q_ASSERT_INCRIT(210, a != nullptr);
QF_MEM_APP();
QF_CRIT_EXIT();
QF_SCHED_STAT_
QF_SCHED_LOCK_(p); // lock the scheduler up to AO's prio
std::uint_fast8_t lbound = QF_MAX_ACTIVE + 1U;
do { // loop over all subscribers
--lbound;
// POST() asserts internally if the queue overflows
a->POST(e, sender);
@ -167,22 +127,20 @@ void QActive::publish_(
p = subscrSet.findMax(); // highest-prio subscriber
QF_CRIT_ENTRY();
QF_MEM_SYS();
a = registry_[p];
// the AO must be registered with the framework
Q_ASSERT_INCRIT(220, a != nullptr);
QF_MEM_APP();
QF_CRIT_EXIT();
}
else {
p = 0U; // no more subscribers
}
} while ((p != 0U) && (lbound > 0U));
} while (p != 0U);
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(290, p == 0U);
Q_ASSERT_INCRIT(290, p == 0U); // all subscribers processed
QF_CRIT_EXIT();
QF_SCHED_UNLOCK_(); // unlock the scheduler
@ -192,30 +150,21 @@ void QActive::publish_(
// and recycles the event if the counter drops to zero. This covers both
// cases when the event was published with or without any subscribers.
#if (QF_MAX_EPOOL > 0U)
QF::gc(e);
QF::gc(e); // recycle the event to avoid a leak
#endif
}
} // namespace QP
//$enddef${QF::QActive::publish_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::subscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QActive::subscribe} ..................................................
//............................................................................
void QActive::subscribe(enum_t const sig) const noexcept {
std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio);
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(300, (Q_USER_SIG <= sig)
&& (sig < maxPubSignal_)
&& (0U < p) && (p <= QF_MAX_ACTIVE)
&& (registry_[p] == this));
Q_INVARIANT_INCRIT(302,
subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis));
QS_BEGIN_PRE(QS_QF_ACTIVE_SUBSCRIBE, m_prio)
QS_TIME_PRE(); // timestamp
@ -225,36 +174,23 @@ void QActive::subscribe(enum_t const sig) const noexcept {
// insert the prio. into the subscriber set
subscrList_[sig].m_set.insert(p);
#ifndef Q_UNSAFE
subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis);
#endif
QF_MEM_APP();
QF_CRIT_EXIT();
}
} // namespace QP
//$enddef${QF::QActive::subscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::unsubscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QActive::unsubscribe} ................................................
//............................................................................
void QActive::unsubscribe(enum_t const sig) const noexcept {
std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio);
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(400, (Q_USER_SIG <= sig)
&& (sig < maxPubSignal_)
&& (0U < p) && (p <= QF_MAX_ACTIVE)
&& (registry_[p] == this));
Q_INVARIANT_INCRIT(402,
subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis));
QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio)
QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, p)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
@ -262,25 +198,14 @@ void QActive::unsubscribe(enum_t const sig) const noexcept {
// remove the prio. from the subscriber set
subscrList_[sig].m_set.remove(p);
#ifndef Q_UNSAFE
subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis);
#endif
QF_MEM_APP();
QF_CRIT_EXIT();
}
} // namespace QP
//$enddef${QF::QActive::unsubscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::unsubscribeAll} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QActive::unsubscribeAll} .............................................
//............................................................................
void QActive::unsubscribeAll() const noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio);
@ -288,25 +213,19 @@ void QActive::unsubscribeAll() const noexcept {
&& (registry_[p] == this));
enum_t const maxPubSig = maxPubSignal_;
QF_MEM_APP();
QF_CRIT_EXIT();
for (enum_t sig = Q_USER_SIG; sig < maxPubSig; ++sig) {
QF_CRIT_ENTRY();
QF_MEM_SYS();
if (subscrList_[sig].m_set.hasElement(p)) {
subscrList_[sig].m_set.remove(p);
#ifndef Q_UNSAFE
subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis);
#endif
QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(sig); // the signal of this event
QS_OBJ_PRE(this); // this active object
QS_END_PRE()
}
QF_MEM_APP();
QF_CRIT_EXIT();
QF_CRIT_EXIT_NOP(); // prevent merging critical sections
@ -314,4 +233,3 @@ void QActive::unsubscribeAll() const noexcept {
}
} // namespace QP
//$enddef${QF::QActive::unsubscribeAll} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,10 +1,6 @@
//$file${src::qf::qf_qact.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qf::qf_qact.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qf::qf_qact.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -48,34 +43,20 @@ namespace {
Q_DEFINE_THIS_MODULE("qf_qact")
} // unnamed namespace
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
#error qpcpp version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
} // namespace QP
//$enddef${QF::QActive::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::register_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QActive::register_} ..................................................
//............................................................................
void QActive::register_() noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
if (m_pthre == 0U) { // preemption-threshold not defined?
m_pthre = m_prio; // apply the default
}
#ifndef Q_UNSAFE
Q_REQUIRE_INCRIT(100, (0U < m_prio) && (m_prio <= QF_MAX_ACTIVE)
Q_REQUIRE_INCRIT(100,
(0U < m_prio) && (m_prio <= QF_MAX_ACTIVE)
&& (registry_[m_prio] == nullptr)
&& (m_prio <= m_pthre));
@ -98,43 +79,30 @@ void QActive::register_() noexcept {
}
}
Q_ASSERT_INCRIT(190, (prev_thre <= m_pthre)
Q_ASSERT_INCRIT(190,
(prev_thre <= m_pthre)
&& (m_pthre <= next_thre));
m_prio_dis = static_cast<std::uint8_t>(~m_prio);
m_pthre_dis = static_cast<std::uint8_t>(~m_pthre);
#endif // Q_UNSAFE
// register the AO at the QF-prio.
registry_[m_prio] = this;
QF_MEM_APP();
QF_CRIT_EXIT();
}
} // namespace QP
//$enddef${QF::QActive::register_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QActive::unregister_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QActive::unregister_} ................................................
//............................................................................
void QActive::unregister_() noexcept {
std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio);
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(200, (0U < p) && (p <= QF_MAX_ACTIVE)
&& (registry_[p] == this));
registry_[p] = nullptr; // free-up the priority level
m_state.fun = nullptr; // invalidate the state
QF_MEM_APP();
QF_CRIT_EXIT();
}
} // namespace QP
//$enddef${QF::QActive::unregister_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,10 +1,6 @@
//$file${src::qf::qf_qeq.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qf::qf_qeq.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qf::qf_qeq.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -48,32 +43,22 @@ namespace {
Q_DEFINE_THIS_MODULE("qf_qeq")
} // unnamed namespace
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
#error qpcpp version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QEQueue} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QEQueue} .............................................................
//${QF::QEQueue::init} .......................................................
//............................................................................
void QEQueue::init(
QEvt const * qSto[],
QEvt const * * const qSto,
std::uint_fast16_t const qLen) noexcept
{
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
#if (QF_EQUEUE_CTR_SIZE == 1U)
Q_REQUIRE_INCRIT(100, qLen < 0xFFU);
#endif
m_frontEvt = nullptr; // no events in the queue
m_ring = &qSto[0];
m_ring = qSto;
m_end = static_cast<QEQueueCtr>(qLen);
if (qLen > 0U) {
m_head = 0U;
@ -82,18 +67,10 @@ void QEQueue::init(
m_nFree = static_cast<QEQueueCtr>(qLen + 1U); //+1 for frontEvt
m_nMin = m_nFree;
#ifndef Q_UNSAFE
m_frontEvt_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(m_frontEvt));
m_head_dis = static_cast<QEQueueCtr>(~m_head);
m_tail_dis = static_cast<QEQueueCtr>(~m_tail);
m_nFree_dis = static_cast<QEQueueCtr>(~m_nFree);
#endif
QF_MEM_APP();
QF_CRIT_EXIT();
}
//${QF::QEQueue::post} .......................................................
//............................................................................
bool QEQueue::post(
QEvt const * const e,
std::uint_fast16_t const margin,
@ -105,67 +82,44 @@ bool QEQueue::post(
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(200, e != nullptr);
Q_INVARIANT_INCRIT(201, e->verify_());
QEQueueCtr tmp = m_nFree; // get volatile into temporary
#ifndef Q_UNSAFE
QEQueueCtr dis = static_cast<QEQueueCtr>(~m_nFree_dis);
Q_INVARIANT_INCRIT(201, tmp == dis);
#endif // ndef Q_UNSAFE
// test-probe#1 for faking queue overflow
QS_TEST_PROBE_DEF(&QEQueue::post)
QS_TEST_PROBE_ID(1,
tmp = 0U; // fake no free events
)
// required margin available?
bool status;
if (((margin == QF::NO_MARGIN) && (tmp > 0U))
|| (tmp > static_cast<QEQueueCtr>(margin)))
{
// can the queue accept the event?
bool status = ((margin == QF::NO_MARGIN) && (tmp > 0U))
|| (tmp > static_cast<QEQueueCtr>(margin));
if (status) {
// is it a mutable event?
if (e->getPoolNum_() != 0U) {
if (e->poolNum_ != 0U) {
Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e); // increment the reference counter
}
--tmp; // one free entry just used up
m_nFree = tmp; // update the original
#ifndef Q_UNSAFE
m_nFree_dis = static_cast<QEQueueCtr>(~tmp);
#endif // ndef Q_UNSAFE
if (m_nMin > tmp) {
if (m_nMin > tmp) { // is this the new minimum?
m_nMin = tmp; // update minimum so far
}
#ifdef Q_SPY
QS_BEGIN_PRE(QS_QF_EQUEUE_POST, qsId)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of the event
QS_OBJ_PRE(this); // this queue object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(tmp); // # free entries
QS_EQC_PRE(m_nMin); // min # free entries
QS_END_PRE()
#endif // def Q_SPY
if (m_frontEvt == nullptr) { // is the queue empty?
m_frontEvt = e; // deliver event directly
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(211, m_frontEvt_dis
== static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr)));
m_frontEvt_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(e));
#endif // ndef Q_UNSAFE
}
else { // queue was not empty, insert event into the ring-buffer
tmp = m_head; // get volatile into temporary
#ifndef Q_UNSAFE
dis = static_cast<QEQueueCtr>(~m_head_dis);
Q_INVARIANT_INCRIT(212, tmp == dis);
#endif // ndef Q_UNSAFE
m_ring[tmp] = e; // insert e into buffer
if (tmp == 0U) { // need to wrap the head?
@ -174,35 +128,30 @@ bool QEQueue::post(
--tmp; // advance head (counter-clockwise)
m_head = tmp; // update the original
#ifndef Q_UNSAFE
m_head_dis = static_cast<QEQueueCtr>(~tmp);
#endif // ndef Q_UNSAFE
}
status = true; // event posted successfully
}
else { // event cannot be posted
// dropping events must be acceptable
Q_ASSERT_INCRIT(210, margin != QF::NO_MARGIN);
Q_ASSERT_INCRIT(230, margin != QF::NO_MARGIN);
#ifdef Q_SPY
QS_BEGIN_PRE(QS_QF_EQUEUE_POST_ATTEMPT, qsId)
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this queue object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(tmp); // # free entries
QS_EQC_PRE(margin); // margin requested
QS_END_PRE()
status = false; // event not posted
#endif // def Q_SPY
}
QF_MEM_APP();
QF_CRIT_EXIT();
return status;
}
//${QF::QEQueue::postLIFO} ...................................................
//............................................................................
void QEQueue::postLIFO(
QEvt const * const e,
std::uint_fast8_t const qsId) noexcept
@ -213,38 +162,23 @@ void QEQueue::postLIFO(
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(300, e != nullptr);
Q_INVARIANT_INCRIT(301, e->verify_());
QEQueueCtr tmp = m_nFree; // get volatile into temporary
#ifndef Q_UNSAFE
QEQueueCtr dis = static_cast<QEQueueCtr>(~m_nFree_dis);
Q_INVARIANT_INCRIT(301, tmp == dis);
#endif // ndef Q_UNSAFE
// test-probe#1 for faking queue overflow
QS_TEST_PROBE_DEF(&QEQueue::postLIFO)
QS_TEST_PROBE_ID(1,
tmp = 0U; // fake no free events
)
// must be able to LIFO-post the event
Q_REQUIRE_INCRIT(310, tmp != 0U);
if (e->getPoolNum_() != 0U) { // is it a mutable event?
if (e->poolNum_ != 0U) { // is it a mutable event?
Q_ASSERT_INCRIT(305, e->refCtr_ < (2U * QF_MAX_ACTIVE));
QEvt_refCtr_inc_(e); // increment the reference counter
}
--tmp; // one free entry just used up
m_nFree = tmp; // update the original
#ifndef Q_UNSAFE
m_nFree_dis = static_cast<QEQueueCtr>(~tmp);
#endif // ndef Q_UNSAFE
if (m_nMin > tmp) {
if (m_nMin > tmp) { // is this the new minimum?
m_nMin = tmp; // update minimum so far
}
@ -252,39 +186,28 @@ void QEQueue::postLIFO(
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this queue object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(tmp); // # free entries
QS_EQC_PRE(m_nMin); // min # free entries
QS_END_PRE()
QEvt const * const frontEvt = m_frontEvt; // read into temporary
m_frontEvt = e; // deliver the event directly to the front
#ifndef Q_UNSAFE
m_frontEvt_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(e));
#endif // ndef Q_UNSAFE
if (frontEvt != nullptr) { // was the queue NOT empty?
tmp = m_tail; // get volatile into temporary;
#ifndef Q_UNSAFE
dis = static_cast<QEQueueCtr>(~m_tail_dis);
Q_INVARIANT_INCRIT(311, tmp == dis);
#endif // ndef Q_UNSAFE
++tmp;
if (tmp == m_end) { // need to wrap the tail?
tmp = 0U; // wrap around
}
m_tail = tmp;
#ifndef Q_UNSAFE
m_tail_dis = static_cast<QEQueueCtr>(~tmp);
#endif
m_ring[tmp] = frontEvt;
}
QF_MEM_APP();
QF_CRIT_EXIT();
}
//${QF::QEQueue::get} ........................................................
//............................................................................
QEvt const * QEQueue::get(std::uint_fast8_t const qsId) noexcept {
#ifndef Q_SPY
Q_UNUSED_PAR(qsId);
@ -292,27 +215,15 @@ QEvt const * QEQueue::get(std::uint_fast8_t const qsId) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
QEvt const * const e = m_frontEvt; // always remove evt from the front
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(411, Q_PTR2UINT_CAST_(e)
== static_cast<std::uintptr_t>(~m_frontEvt_dis));
#endif // ndef Q_UNSAFE
if (e != nullptr) { // was the queue not empty?
QEQueueCtr tmp = m_nFree; // get volatile into temporary
#ifndef Q_UNSAFE
QEQueueCtr const dis = static_cast<QEQueueCtr>(~m_nFree_dis);
Q_INVARIANT_INCRIT(412, tmp == dis);
#endif // ndef Q_UNSAFE
++tmp; // one more free event in the queue
m_nFree = tmp; // update the # free
#ifndef Q_UNSAFE
m_nFree_dis = static_cast<QEQueueCtr>(~tmp);
#endif // ndef Q_UNSAFE
// any events in the ring buffer?
if (tmp <= m_end) {
@ -321,17 +232,15 @@ QEvt const * QEQueue::get(std::uint_fast8_t const qsId) noexcept {
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this queue object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_EQC_PRE(tmp); // # free entries
QS_END_PRE()
tmp = m_tail; // get volatile into temporary
QEvt const * const frontEvt = m_ring[tmp];
#ifndef Q_UNSAFE
Q_ASSERT_INCRIT(421, frontEvt != nullptr);
m_frontEvt_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(frontEvt));
#endif // ndef Q_UNSAFE
Q_ASSERT_INCRIT(420, frontEvt != nullptr);
m_frontEvt = frontEvt; // update the original
if (tmp == 0U) { // need to wrap the tail?
@ -339,16 +248,9 @@ QEvt const * QEQueue::get(std::uint_fast8_t const qsId) noexcept {
}
--tmp; // advance the tail (counter-clockwise)
m_tail = tmp; // update the original
#ifndef Q_UNSAFE
m_tail_dis = static_cast<QEQueueCtr>(~tmp);
#endif // ndef Q_UNSAFE
}
else {
m_frontEvt = nullptr; // queue becomes empty
#ifndef Q_UNSAFE
m_frontEvt_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr));
#endif // ndef Q_UNSAFE
// all entries in the queue must be free (+1 for frontEvt)
Q_INVARIANT_INCRIT(440, tmp == (m_end + 1U));
@ -357,16 +259,14 @@ QEvt const * QEQueue::get(std::uint_fast8_t const qsId) noexcept {
QS_TIME_PRE(); // timestamp
QS_SIG_PRE(e->sig); // the signal of this event
QS_OBJ_PRE(this); // this queue object
QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
QS_2U8_PRE(e->poolNum_, e->refCtr_);
QS_END_PRE()
}
}
QF_MEM_APP();
QF_CRIT_EXIT();
return e;
}
} // namespace QP
//$enddef${QF::QEQueue} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,10 +1,6 @@
//$file${src::qf::qf_qmact.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qf::qf_qmact.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qf::qf_qmact.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -48,18 +43,9 @@ namespace {
//Q_DEFINE_THIS_MODULE("qf_qmact")
} // unnamed namespace
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
#error qpcpp version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QMActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QMActive} ............................................................
//${QF::QMActive::QMActive} ..................................................
//............................................................................
QMActive::QMActive(QStateHandler const initial) noexcept
: QActive(initial)
{
@ -68,4 +54,3 @@ QMActive::QMActive(QStateHandler const initial) noexcept
}
} // namespace QP
//$enddef${QF::QMActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,10 +1,6 @@
//$file${src::qf::qf_time.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qf::qf_time.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// SafeQP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -12,26 +8,24 @@
// ------------------------
// Modern Embedded Software
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
// SPDX-License-Identifier: LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
// This software is licensed under the terms of the Quantum Leaps commercial
// licenses. Please contact Quantum Leaps for more information about the
// available licensing options.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// NOTE:
// The GPL does NOT permit the incorporation of this code into proprietary
// programs. Please contact Quantum Leaps for commercial licensing options,
// which expressly supersede the GPL and are designed explicitly for
// closed-source distribution.
// RESTRICTIONS
// You may NOT :
// (a) redistribute, encumber, sell, rent, lease, sublicense, or otherwise
// transfer rights in this software,
// (b) remove or alter any trademark, logo, copyright or other proprietary
// notices, legends, symbols or labels present in this software,
// (c) plagiarize this software to sidestep the licensing obligations.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qf::qf_time.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -48,37 +42,20 @@ namespace {
Q_DEFINE_THIS_MODULE("qf_time")
} // unnamed namespace
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
#error qpcpp version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QF::QTimeEvt} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QF::QTimeEvt} ............................................................
QTimeEvt QTimeEvt::timeEvtHead_[QF_MAX_TICK_RATE];
#ifndef Q_UNSAFE
QPtrDis QTimeEvt::timeEvtHead_dis_[QF_MAX_TICK_RATE];
#endif // ndef Q_UNSAFE
//${QF::QTimeEvt::QTimeEvt} ..................................................
//............................................................................
QTimeEvt::QTimeEvt(
QActive * const act,
QSignal const sig,
std::uint_fast8_t const tickRate) noexcept
: QEvt(sig),
m_next(nullptr),
#ifndef Q_UNSAFE
m_next_dis(static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr))),
#endif
m_act(act),
m_ctr(0U),
#ifndef Q_UNSAFE
m_ctr_dis(static_cast<QTimeEvtCtr>(~static_cast<QTimeEvtCtr>(0U))),
#endif
m_interval(0U),
m_tickRate(0U),
m_flags(0U)
@ -89,19 +66,16 @@ QTimeEvt::QTimeEvt(
&& (tickRate < QF_MAX_TICK_RATE));
QF_CRIT_EXIT();
// adjust the settings from the QEvt(sig) ctor
evtTag_ = 0x0FU;
refCtr_ = 0U;
refCtr_ = 0U; // adjust from the QEvt(sig) ctor
}
//${QF::QTimeEvt::armX} ......................................................
//............................................................................
void QTimeEvt::armX(
std::uint32_t const nTicks,
std::uint32_t const interval) noexcept
{
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
// dynamic range checks
#if (QF_TIMEEVT_CTR_SIZE == 1U)
@ -110,8 +84,6 @@ void QTimeEvt::armX(
Q_REQUIRE_INCRIT(400, (nTicks < 0xFFFFU) && (interval < 0xFFFFU));
#endif
Q_REQUIRE_INCRIT(401, verify_() && (nTicks != 0U));
QTimeEvtCtr const ctr = m_ctr;
std::uint8_t const tickRate = m_tickRate;
#ifdef Q_SPY
@ -119,26 +91,23 @@ void QTimeEvt::armX(
static_cast<QActive const *>(m_act)->m_prio;
#endif // def Q_SPY
Q_REQUIRE_INCRIT(410, (ctr == 0U)
Q_REQUIRE_INCRIT(410,
(nTicks != 0U)
&& (ctr == 0U)
&& (m_act != nullptr)
&& (tickRate < QF_MAX_TICK_RATE));
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(411, ctr == static_cast<QTimeEvtCtr>(~m_ctr_dis));
#else
#ifdef Q_UNSAFE
Q_UNUSED_PAR(ctr);
#endif // ndef Q_UNSAFE
m_ctr = static_cast<QTimeEvtCtr>(nTicks);
m_interval = static_cast<QTimeEvtCtr>(interval);
#ifndef Q_UNSAFE
m_ctr_dis = static_cast<QTimeEvtCtr>(~nTicks);
#endif // ndef Q_UNSAFE
// is the time event unlinked?
// NOTE: For the duration of a single clock tick of the specified tick
// rate a time event can be disarmed and yet still linked into the list
// because un-linking is performed exclusively in the QF_tickX() function.
// because un-linking is performed exclusively in the QTimeEvt::tick().
if ((m_flags & QTE_FLAG_IS_LINKED) == 0U) {
m_flags |= QTE_FLAG_IS_LINKED; // mark as linked
@ -148,22 +117,8 @@ void QTimeEvt::armX(
// list is appended to the main list of armed time events based on
// timeEvtHead_[tickRate].next. Again, this is to keep any
// changes to the main list exclusively inside QTimeEvt::tick().
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(420,
Q_PTR2UINT_CAST_(m_next) ==
static_cast<std::uintptr_t>(~m_next_dis));
Q_INVARIANT_INCRIT(411,
Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) ==
static_cast<std::uintptr_t>(~timeEvtHead_dis_[tickRate].m_ptr_dis));
#endif
m_next = timeEvtHead_[tickRate].toTimeEvt();
timeEvtHead_[tickRate].m_act = this;
#ifndef Q_UNSAFE
m_next_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(m_next));
timeEvtHead_dis_[tickRate].m_ptr_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(this));
#endif // ndef Q_UNSAFE
}
QS_BEGIN_PRE(QS_QF_TIMEEVT_ARM, qsId)
@ -175,36 +130,26 @@ void QTimeEvt::armX(
QS_U8_PRE(tickRate); // tick rate
QS_END_PRE()
QF_MEM_APP();
QF_CRIT_EXIT();
}
//${QF::QTimeEvt::disarm} ....................................................
//............................................................................
bool QTimeEvt::disarm() noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(500, verify_());
QTimeEvtCtr const ctr = m_ctr;
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(501, ctr == static_cast<QTimeEvtCtr>(~m_ctr_dis));
#endif // ndef Q_UNSAFE
#ifdef Q_SPY
std::uint_fast8_t const qsId = static_cast<QActive *>(m_act)->m_prio;
#endif
// was the time event actually armed?
bool wasArmed;
bool wasArmed = false;
if (ctr != 0U) {
wasArmed = true;
m_flags |= QTE_FLAG_WAS_DISARMED;
m_ctr = 0U; // schedule removal from the list
#ifndef Q_UNSAFE
m_ctr_dis = static_cast<QTimeEvtCtr>(~static_cast<QTimeEvtCtr>(0U));
#endif // ndef Q_UNSAFE
QS_BEGIN_PRE(QS_QF_TIMEEVT_DISARM, qsId)
QS_TIME_PRE(); // timestamp
@ -216,7 +161,6 @@ bool QTimeEvt::disarm() noexcept {
QS_END_PRE()
}
else { // the time event was already disarmed automatically
wasArmed = false;
m_flags &= static_cast<std::uint8_t>(~QTE_FLAG_WAS_DISARMED);
QS_BEGIN_PRE(QS_QF_TIMEEVT_DISARM_ATTEMPT, qsId)
@ -227,17 +171,15 @@ bool QTimeEvt::disarm() noexcept {
QS_END_PRE()
}
QF_MEM_APP();
QF_CRIT_EXIT();
return wasArmed;
}
//${QF::QTimeEvt::rearm} .....................................................
//............................................................................
bool QTimeEvt::rearm(std::uint32_t const nTicks) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
// dynamic range checks
#if (QF_TIMEEVT_CTR_SIZE == 1U)
@ -246,36 +188,29 @@ bool QTimeEvt::rearm(std::uint32_t const nTicks) noexcept {
Q_REQUIRE_INCRIT(600, nTicks < 0xFFFFU);
#endif
Q_REQUIRE_INCRIT(601, verify_() && (nTicks != 0U));
QTimeEvtCtr const ctr = m_ctr;
std::uint8_t const tickRate = m_tickRate;
QTimeEvtCtr const ctr = m_ctr;
Q_REQUIRE_INCRIT(610,
(nTicks != 0U)
&& (m_act != nullptr)
&& (tickRate < QF_MAX_TICK_RATE));
#ifdef Q_SPY
std::uint_fast8_t const qsId = static_cast<QActive *>(m_act)->m_prio;
#endif
Q_REQUIRE_INCRIT(610, (m_act != nullptr)
&& (tickRate < QF_MAX_TICK_RATE));
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(602, ctr == static_cast<QTimeEvtCtr>(~m_ctr_dis));
#endif // ndef Q_UNSAFE
m_ctr = static_cast<QTimeEvtCtr>(nTicks);
#ifndef Q_UNSAFE
m_ctr_dis = static_cast<QTimeEvtCtr>(~nTicks);
#endif // ndef Q_UNSAFE
// is the time evt not running?
bool wasArmed;
// was the time evt not running?
bool wasArmed = false;
if (ctr == 0U) {
wasArmed = false;
// NOTE: For a duration of a single clock tick of the specified
// NOTE: For the duration of a single clock tick of the specified
// tick rate a time event can be disarmed and yet still linked into
// the list, because unlinking is performed exclusively in the
// QTimeEvt::tick() function.
// was the time event unlinked?
// is the time event unlinked?
if ((m_flags & QTE_FLAG_IS_LINKED) == 0U) {
m_flags |= QTE_FLAG_IS_LINKED; // mark as linked
@ -285,22 +220,8 @@ bool QTimeEvt::rearm(std::uint32_t const nTicks) noexcept {
// list is appended to the main list of armed time events based on
// timeEvtHead_[tickRate].next. Again, this is to keep any
// changes to the main list exclusively inside QTimeEvt::tick().
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(620,
Q_PTR2UINT_CAST_(m_next) ==
static_cast<std::uintptr_t>(~m_next_dis));
Q_INVARIANT_INCRIT(611,
Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) ==
static_cast<std::uintptr_t>(~timeEvtHead_dis_[tickRate].m_ptr_dis));
#endif
m_next = timeEvtHead_[tickRate].toTimeEvt();
timeEvtHead_[tickRate].m_act = this;
#ifndef Q_UNSAFE
m_next_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(m_next));
timeEvtHead_dis_[tickRate].m_ptr_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(this));
#endif // ndef Q_UNSAFE
}
}
else { // the time event was armed
@ -316,28 +237,25 @@ bool QTimeEvt::rearm(std::uint32_t const nTicks) noexcept {
QS_2U8_PRE(tickRate, (wasArmed ? 1U : 0U));
QS_END_PRE()
QF_MEM_APP();
QF_CRIT_EXIT();
return wasArmed;
}
//${QF::QTimeEvt::wasDisarmed} ...............................................
//............................................................................
bool QTimeEvt::wasDisarmed() noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
bool const wasDisarmed = (m_flags & QTE_FLAG_WAS_DISARMED) != 0U;
m_flags |= QTE_FLAG_WAS_DISARMED;
QF_MEM_APP();
QF_CRIT_EXIT();
return wasDisarmed;
}
//${QF::QTimeEvt::tick} ......................................................
//............................................................................
void QTimeEvt::tick(
std::uint_fast8_t const tickRate,
void const * const sender) noexcept
@ -348,145 +266,66 @@ void QTimeEvt::tick(
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(800, tickRate < Q_DIM(timeEvtHead_));
QTimeEvt *prev = &timeEvtHead_[tickRate];
#ifdef Q_SPY
QS_BEGIN_PRE(QS_QF_TICK, 0U)
prev->m_ctr = (prev->m_ctr + 1U);
QS_TEC_PRE(prev->m_ctr); // tick ctr
QS_U8_PRE(tickRate); // tick rate
QS_END_PRE()
#endif // def Q_SPY
// scan the linked-list of time events at this rate...
std::uint_fast8_t lbound = 2U*QF_MAX_ACTIVE; // fixed upper loop bound
for (; lbound > 0U; --lbound) {
while (true) {
Q_ASSERT_INCRIT(810, prev != nullptr); // sanity check
QTimeEvt *te = prev->m_next; // advance down the time evt. list
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(811,
Q_PTR2UINT_CAST_(te) ==
static_cast<std::uintptr_t>(~prev->m_next_dis));
#endif // ndef Q_UNSAFE
if (te == nullptr) { // end of the list?
// NO any new time events armed since the last QTimeEvt_tick_()?
if (timeEvtHead_[tickRate].m_act == nullptr) {
break; // terminate the while-loop
}
// any new time events armed since the last QTimeEvt_tick_()?
if (timeEvtHead_[tickRate].m_act != nullptr) {
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(812,
Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) ==
static_cast<std::uintptr_t>(
~timeEvtHead_dis_[tickRate].m_ptr_dis));
#endif // ndef Q_UNSAFE
prev->m_next = timeEvtHead_[tickRate].toTimeEvt();
timeEvtHead_[tickRate].m_act = nullptr;
#ifndef Q_UNSAFE
prev->m_next_dis =
static_cast<std::uintptr_t>(
~Q_PTR2UINT_CAST_(prev->m_next));
timeEvtHead_dis_[tickRate].m_ptr_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr));
#endif // ndef Q_UNSAFE
te = prev->m_next; // switch to the new list
}
else { // all currently armed time events are processed
break; // terminate the for-loop
}
}
// the time event 'te' must be valid
Q_ASSERT_INCRIT(820, te != nullptr);
Q_INVARIANT_INCRIT(821, te->verify_());
Q_ASSERT_INCRIT(840, te != nullptr);
QTimeEvtCtr ctr = te->m_ctr;
#ifndef Q_UNSAFE
Q_INVARIANT_INCRIT(822, ctr ==
static_cast<QTimeEvtCtr>(~te->m_ctr_dis));
#endif // ndef Q_UNSAFE
if (ctr == 0U) { // time event scheduled for removal?
prev->m_next = te->m_next;
#ifndef Q_UNSAFE
prev->m_next_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(te->m_next));
#endif // ndef Q_UNSAFE
// mark time event 'te' as NOT linked
te->m_flags &= static_cast<std::uint8_t>(~QTE_FLAG_IS_LINKED);
// do NOT advance the prev pointer
QF_MEM_APP();
QF_CRIT_EXIT(); // exit crit. section to reduce latency
// NOTE: prevent merging critical sections
// In some QF ports the critical section exit takes effect only
// on the next machine instruction. If the next instruction is
// another entry to a critical section, the critical section
// might not be really exited, but rather the two adjacent
// critical sections would be MERGED. The QF_CRIT_EXIT_NOP()
// macro contains minimal code required to prevent such merging
// of critical sections in QF ports, in which it can occur.
QF_CRIT_EXIT_NOP();
}
else if (ctr == 1U) { // is time evt about to expire?
else if (ctr == 1U) { // is time event about to expire?
QActive * const act = te->toActive();
if (te->m_interval != 0U) { // periodic time evt?
te->m_ctr = te->m_interval; // rearm the time event
#ifndef Q_UNSAFE
te->m_ctr_dis = static_cast<QTimeEvtCtr>(~te->m_interval);
#endif // ndef Q_UNSAFE
prev = te; // advance to this time event
}
else { // one-shot time event: automatically disarm
te->m_ctr = 0U;
prev->m_next = te->m_next;
#ifndef Q_UNSAFE
te->m_ctr_dis =
static_cast<QTimeEvtCtr>(~static_cast<QTimeEvtCtr>(0U));
prev->m_next_dis =
static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(te->m_next));
#endif // ndef Q_UNSAFE
// mark time event 'te' as NOT linked
te->m_flags &=
static_cast<std::uint8_t>(~QTE_FLAG_IS_LINKED);
// do NOT advance the prev pointer
QS_BEGIN_PRE(QS_QF_TIMEEVT_AUTO_DISARM, act->m_prio)
QS_OBJ_PRE(te); // this time event object
QS_OBJ_PRE(act); // the target AO
QS_U8_PRE(tickRate); // tick rate
QS_END_PRE()
}
QS_BEGIN_PRE(QS_QF_TIMEEVT_POST, act->m_prio)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(te); // the time event object
QS_SIG_PRE(te->sig); // signal of this time event
QS_OBJ_PRE(act); // the target AO
QS_U8_PRE(tickRate); // tick rate
QS_END_PRE()
prev = te->expire_(prev, act, tickRate);
#ifdef QXK_HPP_
if (te->sig < Q_USER_SIG) {
QXThread::timeout_(act);
QF_MEM_APP();
QF_CRIT_EXIT();
}
else {
QF_MEM_APP();
QF_CRIT_EXIT(); // exit crit. section before posting
// act->POST() asserts if the queue overflows
act->POST(te, sender);
}
#else
QF_MEM_APP();
#else // not QXK
QF_CRIT_EXIT(); // exit crit. section before posting
// act->POST() asserts if the queue overflows
@ -496,65 +335,88 @@ void QTimeEvt::tick(
else { // time event keeps timing out
--ctr; // decrement the tick counter
te->m_ctr = ctr; // update the original
#ifndef Q_UNSAFE
te->m_ctr_dis = static_cast<QTimeEvtCtr>(~ctr);
#endif // ndef Q_UNSAFE
prev = te; // advance to this time event
QF_MEM_APP();
QF_CRIT_EXIT(); // exit crit. section to reduce latency
// prevent merging critical sections, see NOTE above
QF_CRIT_EXIT_NOP();
}
QF_CRIT_ENTRY(); // re-enter crit. section to continue the loop
QF_MEM_SYS();
}
Q_ENSURE_INCRIT(890, lbound > 0U);
QF_MEM_APP();
QF_CRIT_EXIT();
}
//${QF::QTimeEvt::noActive} ..................................................
//............................................................................
bool QTimeEvt::noActive(std::uint_fast8_t const tickRate) noexcept {
// NOTE: this function must be called *inside* critical section
Q_REQUIRE_INCRIT(900, tickRate < QF_MAX_TICK_RATE);
bool inactive;
bool inactive = false;
QF_MEM_SYS();
if (timeEvtHead_[tickRate].m_next != nullptr) {
inactive = false;
// empty
}
else if (timeEvtHead_[tickRate].m_act != nullptr) {
inactive = false;
// empty
}
else {
inactive = true;
}
QF_MEM_APP();
return inactive;
}
//${QF::QTimeEvt::QTimeEvt} ..................................................
//............................................................................
QTimeEvt::QTimeEvt() noexcept
: QEvt(0U),
m_next(nullptr),
#ifndef Q_UNSAFE
m_next_dis(static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr))),
#endif
m_act(nullptr),
m_ctr(0U),
#ifndef Q_UNSAFE
m_ctr_dis(static_cast<QTimeEvtCtr>(~static_cast<QTimeEvtCtr>(0U))),
#endif
m_interval(0U),
m_tickRate(0U),
m_flags(0U)
{}
//............................................................................
QTimeEvt *QTimeEvt::expire_(
QTimeEvt * const prev_link,
QActive const * const act,
std::uint_fast8_t const tickRate) noexcept
{
// NOTE: this helper function is called *inside* critical section
#ifndef Q_SPY
Q_UNUSED_PAR(act);
Q_UNUSED_PAR(tickRate);
#endif
QTimeEvt *prev = prev_link;
if (m_interval != 0U) { // periodic time evt?
m_ctr = m_interval; // rearm the time event
prev = this; // advance to this time event
}
else { // one-shot time event: automatically disarm
m_ctr = 0U;
prev->m_next = m_next;
// mark this time event as NOT linked
m_flags &=
static_cast<std::uint8_t>(~QTE_FLAG_IS_LINKED);
// do NOT advance the prev pointer
QS_BEGIN_PRE(QS_QF_TIMEEVT_AUTO_DISARM, act->m_prio)
QS_OBJ_PRE(this); // this time event object
QS_OBJ_PRE(act); // the target AO
QS_U8_PRE(tickRate); // tick rate
QS_END_PRE()
}
QS_BEGIN_PRE(QS_QF_TIMEEVT_POST, act->m_prio)
QS_TIME_PRE(); // timestamp
QS_OBJ_PRE(this); // the time event object
QS_SIG_PRE(sig); // signal of this time event
QS_OBJ_PRE(act); // the target AO
QS_U8_PRE(tickRate); // tick rate
QS_END_PRE()
return prev;
}
} // namespace QP
//$enddef${QF::QTimeEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,10 +1,6 @@
//$file${src::qk::qk.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qk::qk.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qk::qk.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -45,7 +40,7 @@
// protection against including this source file in a wrong project
#ifndef QK_HPP_
#error "Source file included in a project NOT based on the QK kernel"
#error Source file included in a project NOT based on the QK kernel
#endif // QK_HPP_
// unnamed namespace for local definitions with internal linkage
@ -53,28 +48,18 @@ namespace {
Q_DEFINE_THIS_MODULE("qk")
} // unnamed namespace
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
#error qpcpp version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QK::QK-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
namespace QK {
//${QK::QK-base::schedLock} ..................................................
//............................................................................
QSchedStatus schedLock(std::uint_fast8_t const ceiling) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(100, !QK_ISR_CONTEXT_());
Q_INVARIANT_INCRIT(102, QK_priv_.lockCeil
== static_cast<std::uint_fast8_t>(~QK_priv_.lockCeil_dis));
// first store the previous lock prio
QSchedStatus stat;
QSchedStatus stat = 0xFFU; // assume scheduler NOT locked
if (ceiling > QK_priv_.lockCeil) { // raising the lock ceiling?
QS_BEGIN_PRE(QS_SCHED_LOCK, QK_priv_.actPrio)
QS_TIME_PRE(); // timestamp
@ -88,33 +73,21 @@ QSchedStatus schedLock(std::uint_fast8_t const ceiling) noexcept {
// new status of the lock
QK_priv_.lockCeil = ceiling;
#ifndef Q_UNSAFE
QK_priv_.lockCeil_dis = static_cast<std::uint_fast8_t>(~ceiling);
#endif
}
else {
stat = 0xFFU; // scheduler not locked
}
QF_MEM_APP();
QF_CRIT_EXIT();
return stat; // return the status to be saved in a stack variable
}
//${QK::QK-base::schedUnlock} ................................................
//............................................................................
void schedUnlock(QSchedStatus const prevCeil) noexcept {
// has the scheduler been actually locked by the last QK::schedLock()?
if (prevCeil != 0xFFU) {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_INVARIANT_INCRIT(202, QK_priv_.lockCeil
== static_cast<std::uint_fast8_t>(~QK_priv_.lockCeil_dis));
Q_REQUIRE_INCRIT(210, (!QK_ISR_CONTEXT_())
Q_REQUIRE_INCRIT(200, (!QK_ISR_CONTEXT_())
&& (QK_priv_.lockCeil > prevCeil));
QS_BEGIN_PRE(QS_SCHED_UNLOCK, QK_priv_.actPrio)
QS_TIME_PRE(); // timestamp
// current lock ceiling (old), previous lock ceiling (new)
@ -124,68 +97,44 @@ void schedUnlock(QSchedStatus const prevCeil) noexcept {
// restore the previous lock ceiling
QK_priv_.lockCeil = prevCeil;
#ifndef Q_UNSAFE
QK_priv_.lockCeil_dis = static_cast<std::uint_fast8_t>(~prevCeil);
#endif
// find if any AOs should be run after unlocking the scheduler
if (QK_sched_() != 0U) { // preemption needed?
QK_activate_(); // activate any unlocked AOs
}
QF_MEM_APP();
QF_CRIT_EXIT();
}
}
} // namespace QK
} // namespace QP
//$enddef${QK::QK-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
extern "C" {
//$define${QK-extern-C} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${QK-extern-C::QK_priv_} ...................................................
QK_Attr QK_priv_;
//${QK-extern-C::QK_sched_} ..................................................
//............................................................................
std::uint_fast8_t QK_sched_() noexcept {
// NOTE: this function is entered with interrupts DISABLED
Q_INVARIANT_INCRIT(402,
QK_priv_.readySet.verify_(&QK_priv_.readySet_dis));
std::uint_fast8_t p;
if (QK_priv_.readySet.isEmpty()) {
p = 0U; // no activation needed
}
else {
std::uint_fast8_t p = 0U; // assume NO activation needed
if (QK_priv_.readySet.notEmpty()) {
// find the highest-prio AO with non-empty event queue
p = QK_priv_.readySet.findMax();
Q_INVARIANT_INCRIT(412, QK_priv_.actThre
== static_cast<std::uint_fast8_t>(~QK_priv_.actThre_dis));
// is the AO's prio. below the active preemption-threshold?
if (p <= QK_priv_.actThre) {
p = 0U; // no activation needed
}
else {
Q_INVARIANT_INCRIT(422, QK_priv_.lockCeil
== static_cast<std::uint_fast8_t>(~QK_priv_.lockCeil_dis));
// is the AO's prio. below the lock-ceiling?
if (p <= QK_priv_.lockCeil) {
p = 0U; // no activation needed
}
else {
Q_INVARIANT_INCRIT(432, QK_priv_.nextPrio
== static_cast<std::uint_fast8_t>(~QK_priv_.nextPrio_dis));
QK_priv_.nextPrio = p; // next AO to run
#ifndef Q_UNSAFE
QK_priv_.nextPrio_dis
= static_cast<std::uint_fast8_t>(~QK_priv_.nextPrio);
#endif
}
}
}
@ -193,17 +142,49 @@ std::uint_fast8_t QK_sched_() noexcept {
return p;
}
//${QK-extern-C::QK_activate_} ...............................................
//............................................................................
std::uint_fast8_t QK_sched_act_(
QP::QActive const * const act,
std::uint_fast8_t const pthre_in) noexcept
{
// NOTE: this function is entered with interrupts DISABLED
std::uint_fast8_t p = act->getPrio();
if (act->getEQueue().isEmpty()) { // empty queue?
QK_priv_.readySet.remove(p);
}
if (QK_priv_.readySet.isEmpty()) {
p = 0U; // no activation needed
}
else {
// find new highest-prio AO ready to run...
p = QK_priv_.readySet.findMax();
// NOTE: p is guaranteed to be <= QF_MAX_ACTIVE
// is the new prio. below the initial preemption-threshold?
if (p <= pthre_in) {
p = 0U; // no activation needed
}
else {
// is the AO's prio. below the lock preemption-threshold?
if (p <= QK_priv_.lockCeil) {
p = 0U; // no activation needed
}
}
}
return p;
}
//............................................................................
void QK_activate_() noexcept {
// NOTE: this function is entered with interrupts DISABLED
std::uint_fast8_t const prio_in = QK_priv_.actPrio; // save initial prio.
std::uint_fast8_t p = QK_priv_.nextPrio; // next prio to run
Q_INVARIANT_INCRIT(502,
(prio_in == static_cast<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)
Q_REQUIRE_INCRIT(500, (prio_in <= QF_MAX_ACTIVE)
&& (0U < p) && (p <= QF_MAX_ACTIVE));
#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
@ -211,40 +192,25 @@ void QK_activate_() noexcept {
#endif // QF_ON_CONTEXT_SW || Q_SPY
QK_priv_.nextPrio = 0U; // clear for the next time
#ifndef Q_UNSAFE
QK_priv_.nextPrio_dis = static_cast<std::uint_fast8_t>(~QK_priv_.nextPrio);
#endif
std::uint_fast8_t pthre_in;
QP::QActive *a;
if (prio_in == 0U) { // preempting the idle thread?
pthre_in = 0U;
}
else {
a = QP::QActive::registry_[prio_in];
std::uint_fast8_t pthre_in = 0U; // assume preempting the idle thread
if (prio_in != 0U) { // preempting NOT the idle thread
QP::QActive const * const a = QP::QActive::registry_[prio_in];
Q_ASSERT_INCRIT(510, a != nullptr);
pthre_in = static_cast<std::uint_fast8_t>(a->getPThre());
Q_INVARIANT_INCRIT(511, pthre_in == static_cast<std::uint_fast8_t>(
~static_cast<std::uint_fast8_t>(a->m_pthre_dis) & 0xFFU));
}
// loop until no more ready-to-run AOs of higher pthre than the initial
do {
a = QP::QActive::registry_[p]; // obtain the pointer to the AO
QP::QActive * const a = QP::QActive::registry_[p];
Q_ASSERT_INCRIT(520, a != nullptr); // the AO must be registered
std::uint_fast8_t const pthre
= static_cast<std::uint_fast8_t>(a->getPThre());
Q_INVARIANT_INCRIT(522, pthre == static_cast<std::uint_fast8_t>(
~static_cast<std::uint_fast8_t>(a->m_pthre_dis) & 0xFFU));
// set new active prio. and preemption-threshold
QK_priv_.actPrio = p;
QK_priv_.actThre = pthre;
#ifndef Q_UNSAFE
QK_priv_.actPrio_dis = static_cast<std::uint_fast8_t>(~p);
QK_priv_.actThre_dis = static_cast<std::uint_fast8_t>(~pthre);
#endif
#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
if (p != pprev) { // changing threads?
@ -263,11 +229,9 @@ 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_();
// NOTE QActive_get_() performs QF_MEM_APP() before return
// dispatch event (virtual call)
a->dispatch(e, a->getPrio());
@ -277,86 +241,48 @@ void QK_activate_() noexcept {
// determine the next highest-prio. AO ready to run...
QF_INT_DISABLE(); // unconditionally disable interrupts
QF_MEM_SYS();
p = QK_sched_act_(a, pthre_in); // schedule next AO
// internal integrity check (duplicate inverse storage)
Q_INVARIANT_INCRIT(532,
QK_priv_.readySet.verify_(&QK_priv_.readySet_dis));
if (a->getEQueue().isEmpty()) { // empty queue?
QK_priv_.readySet.remove(p);
#ifndef Q_UNSAFE
QK_priv_.readySet.update_(&QK_priv_.readySet_dis);
#endif
}
if (QK_priv_.readySet.isEmpty()) {
p = 0U; // no activation needed
}
else {
// find new highest-prio AO ready to run...
p = QK_priv_.readySet.findMax();
// is the new prio. below the initial preemption-threshold?
if (p <= pthre_in) {
p = 0U; // no activation needed
}
else {
Q_INVARIANT_INCRIT(542,
QK_priv_.lockCeil == ~QK_priv_.lockCeil_dis);
// is the AO's prio. below the lock preemption-threshold?
if (p <= QK_priv_.lockCeil) {
p = 0U; // no activation needed
}
else {
Q_ASSERT_INCRIT(550, p <= QF_MAX_ACTIVE);
}
}
}
} while (p != 0U);
// restore the active prio. and preemption-threshold
QK_priv_.actPrio = prio_in;
QK_priv_.actThre = pthre_in;
#ifndef Q_UNSAFE
QK_priv_.actPrio_dis = static_cast<std::uint_fast8_t>(~QK_priv_.actPrio);
QK_priv_.actThre_dis = static_cast<std::uint_fast8_t>(~QK_priv_.actThre);
#endif
#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
if (prio_in != 0U) { // resuming an active object?
a = QP::QActive::registry_[prio_in]; // pointer to preempted AO
QS_BEGIN_PRE(QP::QS_SCHED_NEXT, prio_in)
QS_TIME_PRE(); // timestamp
// prio. of the resumed AO, previous prio.
QS_2U8_PRE(prio_in, pprev);
QS_END_PRE()
#ifdef QF_ON_CONTEXT_SW
QF_onContextSw(QP::QActive::registry_[pprev],
QP::QActive::registry_[prio_in]);
#endif // QF_ON_CONTEXT_SW
}
else { // resuming prio.==0 --> idle
a = nullptr; // QK idle loop
QS_BEGIN_PRE(QP::QS_SCHED_IDLE, pprev)
QS_TIME_PRE(); // timestamp
QS_U8_PRE(pprev); // previous prio.
QS_END_PRE()
}
#ifdef QF_ON_CONTEXT_SW
QF_onContextSw(QP::QActive::registry_[pprev], a);
QF_onContextSw(QP::QActive::registry_[pprev], nullptr);
#endif // QF_ON_CONTEXT_SW
}
#endif // QF_ON_CONTEXT_SW || Q_SPY
}
//$enddef${QK-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
} // extern "C"
//$define${QK::QF-cust} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//............................................................................
namespace QP {
namespace QF {
//${QK::QF-cust::init} .......................................................
//............................................................................
void init() {
bzero_(&QF::priv_, sizeof(QF::priv_));
bzero_(&QK_priv_, sizeof(QK_priv_));
@ -365,50 +291,36 @@ void init() {
// setup the QK scheduler as initially locked and not running
QK_priv_.lockCeil = (QF_MAX_ACTIVE + 1U); // scheduler locked
#ifndef Q_UNSAFE
QK_priv_.readySet.update_(&QK_priv_.readySet_dis);
QK_priv_.actPrio_dis = static_cast<std::uint_fast8_t>(~QK_priv_.actPrio);
QK_priv_.nextPrio_dis = static_cast<std::uint_fast8_t>(~QK_priv_.nextPrio);
QK_priv_.actThre_dis = static_cast<std::uint_fast8_t>(~QK_priv_.actThre);
QK_priv_.lockCeil_dis = static_cast<std::uint_fast8_t>(~QK_priv_.lockCeil);
#endif
#ifdef QK_INIT
QK_INIT(); // port-specific initialization of the QK kernel
#endif
}
//${QK::QF-cust::stop} .......................................................
//............................................................................
void stop() {
onCleanup(); // cleanup callback
// nothing else to do for the QK preemptive kernel
onCleanup(); // application-specific cleanup callback
// nothing else to do for the preemptive QK kernel
}
//${QK::QF-cust::run} ........................................................
//............................................................................
int_t run() {
#ifdef Q_SPY
// produce the QS_QF_RUN trace record
QF_INT_DISABLE();
QF_MEM_SYS();
QS::beginRec_(QS_REC_NUM_(QS_QF_RUN));
QS::endRec_();
QF_MEM_APP();
QF_INT_ENABLE();
#endif // Q_SPY
onStartup(); // application-specific startup callback
QF_INT_DISABLE();
QF_MEM_SYS();
#ifdef QK_START
QK_START(); // port-specific startup of the QK kernel
#endif
QK_priv_.lockCeil = 0U; // unlock the QK scheduler
#ifndef Q_UNSAFE
QK_priv_.lockCeil_dis = static_cast<std::uint_fast8_t>(~QK_priv_.lockCeil);
#endif
#ifdef QF_ON_CONTEXT_SW
// officially switch to the idle context
@ -420,7 +332,6 @@ int_t run() {
QK_activate_();
}
QF_MEM_APP();
QF_INT_ENABLE();
for (;;) { // QK idle loop...
@ -433,15 +344,8 @@ int_t run() {
}
} // namespace QF
} // namespace QP
//$enddef${QK::QF-cust} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QK::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QK::QActive} .............................................................
//${QK::QActive::start} ......................................................
//............................................................................
void QActive::start(
QPrioSpec const prioSpec,
QEvtPtr * const qSto,
@ -455,11 +359,9 @@ void QActive::start(
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_REQUIRE_INCRIT(300, (!QK_ISR_CONTEXT_())
&& (stkSto == nullptr));
QF_MEM_APP();
Q_REQUIRE_INCRIT(300,
(stkSto == nullptr));
QF_CRIT_EXIT();
m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU); // QF-prio.
@ -474,13 +376,10 @@ void QActive::start(
// See if this AO needs to be scheduled if QK is already running
QF_CRIT_ENTRY();
QF_MEM_SYS();
if (QK_sched_() != 0U) { // activation needed?
QK_activate_();
}
QF_MEM_APP();
QF_CRIT_EXIT();
}
} // namespace QP
//$enddef${QK::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,10 +1,6 @@
//$file${src::qs::qstamp.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qs::qstamp.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -12,26 +8,24 @@
// ------------------------
// Modern Embedded Software
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
// SPDX-License-Identifier: LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
// This software is licensed under the terms of the Quantum Leaps commercial
// licenses. Please contact Quantum Leaps for more information about the
// available licensing options.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// NOTE:
// The GPL does NOT permit the incorporation of this code into proprietary
// programs. Please contact Quantum Leaps for commercial licensing options,
// which expressly supersede the GPL and are designed explicitly for
// closed-source distribution.
// RESTRICTIONS
// You may NOT :
// (a) redistribute, encumber, sell, rent, lease, sublicense, or otherwise
// transfer rights in this software,
// (b) remove or alter any trademark, logo, copyright or other proprietary
// notices, legends, symbols or labels present in this software,
// (c) plagiarize this software to sidestep the licensing obligations.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qs::qstamp.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#include "qstamp.hpp"
namespace QP {

View File

@ -1,10 +1,6 @@
//$file${src::qv::qv.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//
// Model: qpcpp.qm
// File: ${src::qv::qv.cpp}
//
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// Version 8.0.2
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -14,8 +10,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C++ software is dual-licensed under the terms of the open-source
// GNU General Public License (GPL) or under the terms of one of the closed-
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
@ -30,8 +26,7 @@
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$endhead${src::qv::qv.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//============================================================================
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
@ -45,7 +40,7 @@
// protection against including this source file in a wrong project
#ifndef QV_HPP_
#error "Source file included in a project NOT based on the QV kernel"
#error Source file included in a project NOT based on the QV kernel
#endif // QV_HPP_
// unnamed namespace for local definitions with internal linkage
@ -53,27 +48,15 @@ namespace {
Q_DEFINE_THIS_MODULE("qv")
} // unnamed namespace
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
#error qpcpp version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QV::QV-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
namespace QV {
//${QV::QV-base::priv_} ......................................................
QV::Attr priv_;
//${QV::QV-base::schedDisable} ...............................................
//............................................................................
void schedDisable(std::uint_fast8_t const ceiling) {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_INVARIANT_INCRIT(102, priv_.schedCeil
== static_cast<std::uint_fast8_t>(~priv_.schedCeil_dis));
if (ceiling > priv_.schedCeil) { // raising the scheduler ceiling?
@ -85,22 +68,14 @@ void schedDisable(std::uint_fast8_t const ceiling) {
QS_END_PRE()
priv_.schedCeil = ceiling;
#ifndef Q_UNSAFE
priv_.schedCeil_dis = static_cast<std::uint_fast8_t>(~ceiling);
#endif
}
QF_MEM_APP();
QF_CRIT_EXIT();
}
//${QV::QV-base::schedEnable} ................................................
//............................................................................
void schedEnable() {
QF_CRIT_STAT
QF_CRIT_ENTRY();
QF_MEM_SYS();
Q_INVARIANT_INCRIT(202, priv_.schedCeil
== static_cast<std::uint_fast8_t>(~priv_.schedCeil_dis));
if (priv_.schedCeil != 0U) { // actually enabling the scheduler?
@ -111,39 +86,26 @@ void schedEnable() {
QS_END_PRE()
priv_.schedCeil = 0U;
#ifndef Q_UNSAFE
priv_.schedCeil_dis = ~static_cast<std::uint_fast8_t>(0U);
#endif
}
QF_MEM_APP();
QF_CRIT_EXIT();
}
} // namespace QV
} // namespace QP
//$enddef${QV::QV-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QV::QF-cust} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
namespace QF {
//${QV::QF-cust::init} .......................................................
//............................................................................
void init() {
bzero_(&QF::priv_, sizeof(QF::priv_));
bzero_(&QV::priv_, sizeof(QV::priv_));
bzero_(&QActive::registry_[0], sizeof(QActive::registry_));
#ifndef Q_UNSAFE
QV::priv_.readySet.update_(&QV::priv_.readySet_dis);
QV::priv_.schedCeil_dis = ~static_cast<std::uint_fast8_t>(0U);
#endif
#ifdef QV_INIT
QV_INIT(); // port-specific initialization of the QV kernel
#endif
}
//${QV::QF-cust::stop} .......................................................
//............................................................................
void stop() {
onCleanup(); // cleanup callback
// nothing else to do for the QV kernel
@ -154,17 +116,14 @@ int_t run() {
#ifdef Q_SPY
// produce the QS_QF_RUN trace record
QF_INT_DISABLE();
QF_MEM_SYS();
QS::beginRec_(QS_REC_NUM_(QS_QF_RUN));
QS::endRec_();
QF_MEM_APP();
QF_INT_ENABLE();
#endif // Q_SPY
onStartup(); // application-specific startup callback
QF_INT_DISABLE();
QF_MEM_SYS();
#ifdef QV_START
QV_START(); // port-specific startup of the QV kernel
@ -181,14 +140,6 @@ int_t run() {
#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
for (;;) { // QV event loop...
// check internal integrity (duplicate inverse storage)
Q_INVARIANT_INCRIT(302,
QV::priv_.readySet.verify_(&QV::priv_.readySet_dis));
// check internal integrity (duplicate inverse storage)
Q_INVARIANT_INCRIT(303, QV::priv_.schedCeil
== static_cast<std::uint_fast8_t>(~QV::priv_.schedCeil_dis));
// find the maximum prio. AO ready to run
std::uint_fast8_t const p = (QV::priv_.readySet.notEmpty()
? QV::priv_.readySet.findMax()
@ -213,11 +164,9 @@ int_t run() {
pprev = p; // update previous prio.
#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
QF_MEM_APP();
QF_INT_ENABLE();
QEvt const * const e = a->get_();
// NOTE QActive::get_() performs QF_MEM_APP() before return
// dispatch event (virtual call)
a->dispatch(e, a->getPrio());
@ -225,13 +174,9 @@ int_t run() {
gc(e);
#endif
QF_INT_DISABLE();
QF_MEM_SYS();
if (a->getEQueue().isEmpty()) { // empty queue?
QV::priv_.readySet.remove(p);
#ifndef Q_UNSAFE
QV::priv_.readySet.update_(&QV::priv_.readySet_dis);
#endif
}
}
else { // no AO ready to run --> idle
@ -250,20 +195,15 @@ int_t run() {
}
#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
QF_MEM_APP();
// QV::onIdle() must be called with interrupts DISABLED
// because the determination of the idle condition (all event
// queues empty) can change at any time by an interrupt posting
// events to a queue.
// QV::onIdle() must be called with interrupts DISABLED because
// the determination of the idle condition can change at any time
// by an interrupt posting events to a queue.
//
// NOTE: QV::onIdle() MUST enable interrupts internally,
// ideally at the same time as putting the CPU into a power-
// saving mode.
// NOTE: QV::onIdle() MUST enable interrupts internally, ideally
// atomically with putting the CPU into a power-saving mode.
QV::onIdle();
QF_INT_DISABLE();
QF_MEM_SYS();
}
}
#ifdef __GNUC__ // GNU compiler?
@ -272,15 +212,8 @@ int_t run() {
}
} // namespace QF
} // namespace QP
//$enddef${QV::QF-cust} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${QV::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
namespace QP {
//${QV::QActive} .............................................................
//${QV::QActive::start} ......................................................
//............................................................................
void QActive::start(
QPrioSpec const prioSpec,
QEvtPtr * const qSto,
@ -294,7 +227,8 @@ void QActive::start(
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_REQUIRE_INCRIT(300, stkSto == nullptr);
Q_REQUIRE_INCRIT(300,
stkSto == nullptr);
QF_CRIT_EXIT();
m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU); // QF-prio.
@ -308,4 +242,3 @@ void QActive::start(
}
} // namespace QP
//$enddef${QV::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Some files were not shown because too many files have changed in this diff Show More