QP/C++  8.0.0
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qv.cpp
Go to the documentation of this file.
1//$file${src::qv::qv.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpcpp.qm
4// File: ${src::qv::qv.cpp}
5//
6// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
7// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
8//
9// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
10//
11// Q u a n t u m L e a P s
12// ------------------------
13// Modern Embedded Software
14//
15// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
16//
17// The QP/C++ software is dual-licensed under the terms of the open-source
18// GNU General Public License (GPL) or under the terms of one of the closed-
19// source Quantum Leaps commercial licenses.
20//
21// Redistributions in source code must retain this top-level comment block.
22// Plagiarizing this software to sidestep the license obligations is illegal.
23//
24// NOTE:
25// The GPL does NOT permit the incorporation of this code into proprietary
26// programs. Please contact Quantum Leaps for commercial licensing options,
27// which expressly supersede the GPL and are designed explicitly for
28// closed-source distribution.
29//
30// Quantum Leaps contact information:
31// <www.state-machine.com/licensing>
32// <info@state-machine.com>
33//
34//$endhead${src::qv::qv.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35#define QP_IMPL // this is QP implementation
36#include "qp_port.hpp" // QP port
37#include "qp_pkg.hpp" // QP package-scope interface
38#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
39#ifdef Q_SPY // QS software tracing enabled?
40 #include "qs_port.hpp" // QS port
41 #include "qs_pkg.hpp" // QS facilities for pre-defined trace records
42#else
43 #include "qs_dummy.hpp" // disable the QS software tracing
44#endif // Q_SPY
45
46// protection against including this source file in a wrong project
47#ifndef QV_HPP_
48 #error "Source file included in a project NOT based on the QV kernel"
49#endif // QV_HPP_
50
51// unnamed namespace for local definitions with internal linkage
52namespace {
53Q_DEFINE_THIS_MODULE("qv")
54} // unnamed namespace
55
56//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
57// Check for the minimum required QP version
58#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
59#error qpcpp version 7.3.0 or higher required
60#endif
61//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62//$define${QV::QV-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
63namespace QP {
64namespace QV {
65
66//${QV::QV-base::priv_} ......................................................
68
69//${QV::QV-base::schedDisable} ...............................................
70void schedDisable(std::uint_fast8_t const ceiling) {
73 QF_MEM_SYS();
74
76 == static_cast<std::uint_fast8_t>(~priv_.schedCeil_dis));
77
78 if (ceiling > priv_.schedCeil) { // raising the scheduler ceiling?
79
80 QS_BEGIN_PRE(QS_SCHED_LOCK, 0U)
81 QS_TIME_PRE(); // timestamp
82 // the previous sched ceiling & new sched ceiling
83 QS_2U8_PRE(static_cast<std::uint8_t>(priv_.schedCeil),
84 static_cast<std::uint8_t>(ceiling));
86
87 priv_.schedCeil = ceiling;
88 #ifndef Q_UNSAFE
89 priv_.schedCeil_dis = static_cast<std::uint_fast8_t>(~ceiling);
90 #endif
91 }
92 QF_MEM_APP();
94}
95
96//${QV::QV-base::schedEnable} ................................................
100 QF_MEM_SYS();
101
103 == static_cast<std::uint_fast8_t>(~priv_.schedCeil_dis));
104
105 if (priv_.schedCeil != 0U) { // actually enabling the scheduler?
106
107 QS_BEGIN_PRE(QS_SCHED_UNLOCK, 0U)
108 QS_TIME_PRE(); // timestamp
109 // current sched ceiling (old), previous sched ceiling (new)
110 QS_2U8_PRE(static_cast<std::uint8_t>(priv_.schedCeil), 0U);
111 QS_END_PRE()
112
113 priv_.schedCeil = 0U;
114 #ifndef Q_UNSAFE
115 priv_.schedCeil_dis = ~static_cast<std::uint_fast8_t>(0U);
116 #endif
117 }
118 QF_MEM_APP();
119 QF_CRIT_EXIT();
120}
121
122} // namespace QV
123} // namespace QP
124//$enddef${QV::QV-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
125
126//$define${QV::QF-cust} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
127namespace QP {
128namespace QF {
129
130//${QV::QF-cust::init} .......................................................
131void init() {
132 bzero_(&QF::priv_, sizeof(QF::priv_));
133 bzero_(&QV::priv_, sizeof(QV::priv_));
135
136 #ifndef Q_UNSAFE
137 QV::priv_.readySet.update_(&QV::priv_.readySet_dis);
138 QV::priv_.schedCeil_dis = ~static_cast<std::uint_fast8_t>(0U);
139 #endif
140
141 #ifdef QV_INIT
142 QV_INIT(); // port-specific initialization of the QV kernel
143 #endif
144}
145
146//${QV::QF-cust::stop} .......................................................
147void stop() {
148 onCleanup(); // cleanup callback
149 // nothing else to do for the QV kernel
150}
151
152//${QV::QF-cust::run} ........................................................
154 #ifdef Q_SPY
155 // produce the QS_QF_RUN trace record
157 QF_MEM_SYS();
158 QS::beginRec_(QS_REC_NUM_(QS_QF_RUN));
159 QS::endRec_();
160 QF_MEM_APP();
162 #endif // Q_SPY
163
164 onStartup(); // application-specific startup callback
165
167 QF_MEM_SYS();
168
169 #ifdef QV_START
170 QV_START(); // port-specific startup of the QV kernel
171 #endif
172
173 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
174 std::uint_fast8_t pprev = 0U; // previous prio.
175
176 #ifdef QF_ON_CONTEXT_SW
177 // officially switch to the idle cotext
178 QF_onContextSw(nullptr, nullptr);
179 #endif // def QF_ON_CONTEXT_SW
180
181 #endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
182
183 for (;;) { // QV event loop...
184
185 // check internal integrity (duplicate inverse storage)
187 QV::priv_.readySet.verify_(&QV::priv_.readySet_dis));
188 // check internal integrity (duplicate inverse storage)
189 Q_INVARIANT_INCRIT(303, QV::priv_.schedCeil
190 == static_cast<std::uint_fast8_t>(~QV::priv_.schedCeil_dis));
191
192 // find the maximum prio. AO ready to run
193 std::uint_fast8_t const p = (QV::priv_.readySet.notEmpty()
195 : 0U);
196
197 if (p > QV::priv_.schedCeil) { // is it above the sched ceiling?
198 QActive * const a = QActive::registry_[p];
199
200 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
201 QS_BEGIN_PRE(QS_SCHED_NEXT, p)
202 QS_TIME_PRE(); // timestamp
203 QS_2U8_PRE(static_cast<std::uint8_t>(p),
204 static_cast<std::uint8_t>(pprev));
205 QS_END_PRE()
206
207 #ifdef QF_ON_CONTEXT_SW
208 QF_onContextSw(((pprev != 0U)
209 ? QActive::registry_[pprev]
210 : nullptr), a);
211 #endif // QF_ON_CONTEXT_SW
212
213 pprev = p; // update previous prio.
214 #endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
215
216 QF_MEM_APP();
218
219 QEvt const * const e = a->get_();
220 // NOTE QActive::get_() performs QF_MEM_APP() before return
221
222 // dispatch event (virtual call)
223 a->dispatch(e, a->getPrio());
224 #if (QF_MAX_EPOOL > 0U)
225 gc(e);
226 #endif
228 QF_MEM_SYS();
229
230 if (a->getEQueue().isEmpty()) { // empty queue?
232 #ifndef Q_UNSAFE
233 QV::priv_.readySet.update_(&QV::priv_.readySet_dis);
234 #endif
235 }
236 }
237 else { // no AO ready to run --> idle
238 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
239 if (pprev != 0U) {
240 QS_BEGIN_PRE(QS_SCHED_IDLE, pprev)
241 QS_TIME_PRE(); // timestamp
242 QS_U8_PRE(static_cast<std::uint8_t>(pprev));
243 QS_END_PRE()
244
245 #ifdef QF_ON_CONTEXT_SW
246 QF_onContextSw(QActive::registry_[pprev], nullptr);
247 #endif // QF_ON_CONTEXT_SW
248
249 pprev = 0U; // update previous prio
250 }
251 #endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
252
253 QF_MEM_APP();
254
255 // QV::onIdle() must be called with interrupts DISABLED
256 // because the determination of the idle condition (all event
257 // queues empty) can change at any time by an interrupt posting
258 // events to a queue.
259 //
260 // NOTE: QV::onIdle() MUST enable interrupts internally,
261 // ideally at the same time as putting the CPU into a power-
262 // saving mode.
263 QV::onIdle();
264
266 QF_MEM_SYS();
267 }
268 }
269 #ifdef __GNUC__ // GNU compiler?
270 return 0;
271 #endif
272}
273
274} // namespace QF
275} // namespace QP
276//$enddef${QV::QF-cust} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
277
278//$define${QV::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
279namespace QP {
280
281//${QV::QActive} .............................................................
282
283//${QV::QActive::start} ......................................................
285 QPrioSpec const prioSpec,
286 QEvtPtr * const qSto,
287 std::uint_fast16_t const qLen,
288 void * const stkSto,
289 std::uint_fast16_t const stkSize,
290 void const * const par)
291{
292 Q_UNUSED_PAR(stkSto); // not needed in QV
293 Q_UNUSED_PAR(stkSize); // not needed in QV
294
297 Q_REQUIRE_INCRIT(300, stkSto == nullptr);
298 QF_CRIT_EXIT();
299
300 m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU); // QF-prio.
301 m_pthre = 0U; // not used
302 register_(); // make QF aware of this AO
303
304 m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO
305
306 this->init(par, m_prio); // take the top-most initial tran. (virtual)
307 QS_FLUSH(); // flush the trace buffer to the host
308}
309
310} // namespace QP
311//$enddef${QV::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Active object class (based on the QHsm implementation strategy)
Definition qp.hpp:699
void start(QPrioSpec const prioSpec, QEvtPtr *const qSto, std::uint_fast16_t const qLen, void *const stkSto, std::uint_fast16_t const stkSize, void const *const par)
Definition qv.cpp:284
void init(void const *const e, std::uint_fast8_t const qsId) override
Virtual function to take the top-most initial transition in the state machine.
Definition qp.hpp:756
static QActive * registry_[QF_MAX_ACTIVE+1U]
Definition qp.hpp:725
void register_() noexcept
Definition qf_qact.cpp:67
void dispatch(QEvt const *const e, std::uint_fast8_t const qsId) override
Virtual function to dispatch an event to the state machine.
Definition qp.hpp:765
QACTIVE_EQUEUE_TYPE m_eQueue
Definition qp.hpp:713
QEvt const * get_() noexcept
Definition qf_actq.cpp:355
std::uint8_t m_pthre
Definition qp.hpp:702
std::uint_fast8_t getPrio() const noexcept
Definition qp.hpp:826
QACTIVE_EQUEUE_TYPE const & getEQueue() const noexcept
Definition qp.hpp:838
std::uint8_t m_prio
Definition qp.hpp:701
Event class.
Definition qp.hpp:131
std::uint_fast8_t findMax() const noexcept
Definition qp.hpp:630
void remove(std::uint_fast8_t const n) noexcept
Definition qp.hpp:618
bool notEmpty() const noexcept
Definition qp.hpp:590
void update_(QPSet *const dis) const noexcept
Definition qp.hpp:641
Private attributes of the QV kernel.
Definition qv.hpp:43
QPSet readySet
Definition qv.hpp:45
QPSet readySet_dis
Definition qv.hpp:49
std::uint_fast8_t schedCeil
Definition qv.hpp:46
std::uint_fast8_t schedCeil_dis
Definition qv.hpp:53
QF Active Object Framework namespace.
void onCleanup()
void gc(QEvt const *const e) noexcept
Recycle a mutable (mutable) event.
Definition qf_dyn.cpp:213
void bzero_(void *const start, std::uint_fast16_t const len) noexcept
Definition qf_act.cpp:72
QF::Attr priv_
Definition qf_act.cpp:69
void init()
Definition qv.cpp:131
int_t run()
Definition qv.cpp:153
void stop()
Definition qv.cpp:147
void onStartup()
QV::Attr priv_
Definition qv.cpp:67
void schedEnable()
Definition qv.cpp:97
void onIdle()
void schedDisable(std::uint_fast8_t const ceiling)
Definition qv.cpp:70
QP/C++ framework.
Definition qequeue.hpp:42
QEvt const * QEvtPtr
Pointer to const event instances passed around in QP Framework.
Definition qp.hpp:534
std::uint16_t QPrioSpec
Priority specification for Active Objects in QP.
Definition qp.hpp:531
int int_t
Alias for assertion-ID numbers in QP assertions and return from QP::QF::run()
Definition qp.hpp:96
#define QF_MEM_APP()
Definition qp.hpp:1322
#define Q_UNUSED_PAR(par_)
Helper macro to clearly mark unused parameters of functions.
Definition qp.hpp:498
void QF_onContextSw(QP::QActive *prev, QP::QActive *next)
#define QF_MEM_SYS()
Definition qp.hpp:1317
Internal (package scope) QP/C++ interface.
Sample QP/C++ port.
#define QF_INT_DISABLE()
Disable interrupts.
Definition qp_port.hpp:36
#define QF_INT_ENABLE()
Enable interrupts.
Definition qp_port.hpp:39
#define QS_TIME_PRE()
Definition qs_dummy.hpp:155
#define QS_2U8_PRE(data1_, data2_)
Definition qs_dummy.hpp:152
#define QS_FLUSH()
Definition qs_dummy.hpp:76
#define QS_U8_PRE(data_)
Definition qs_dummy.hpp:151
#define QS_END_PRE()
Definition qs_dummy.hpp:150
#define QS_BEGIN_PRE(rec_, qsId_)
Definition qs_dummy.hpp:149
QS/C++ port to a 32-bit CPU, generic C++ compiler.
QP Functional Safety (FuSa) Subsystem.
#define QF_CRIT_ENTRY()
Definition qsafe.h:58
#define Q_INVARIANT_INCRIT(id_, expr_)
Definition qsafe.h:154
#define QF_CRIT_EXIT()
Definition qsafe.h:62
#define Q_REQUIRE_INCRIT(id_, expr_)
Definition qsafe.h:136
#define QF_CRIT_STAT
Definition qsafe.h:54