Reference Manual For QP/C++ 8.1.5
Loading...
Searching...
No Matches
qv.cpp
Go to the documentation of this file.
1//============================================================================
2// QP/C++ Real-Time Event Framework (RTEF)
3//
4// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
5//
6// Q u a n t u m L e a P s
7// ------------------------
8// Modern Embedded Software
9//
10// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
11//
12// This software is dual-licensed under the terms of the open-source GNU
13// General Public License (GPL) or under the terms of one of the closed-
14// source Quantum Leaps commercial licenses.
15//
16// Redistributions in source code must retain this top-level comment block.
17// Plagiarizing this software to sidestep the license obligations is illegal.
18//
19// NOTE:
20// The GPL does NOT permit the incorporation of this code into proprietary
21// programs. Please contact Quantum Leaps for commercial licensing options,
22// which expressly supersede the GPL and are designed explicitly for
23// closed-source distribution.
24//
25// Quantum Leaps contact information:
26// <www.state-machine.com/licensing>
27// <info@state-machine.com>
28//============================================================================
29#define QP_IMPL // this is QP implementation
30#include "qp_port.hpp" // QP port
31#include "qp_pkg.hpp" // QP package-scope internal interface
32#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
33#ifdef Q_SPY // QS software tracing enabled?
34 #include "qs_port.hpp" // QS port
35 #include "qs_pkg.hpp" // QS facilities for pre-defined trace records
36#else
37 #include "qs_dummy.hpp" // disable the QS software tracing
38#endif // Q_SPY
39
40// protection against including this source file in a wrong project
41#ifndef QV_HPP_
42 #error Source file included in a project NOT based on the QV kernel
43#endif // QV_HPP_
44
45// unnamed namespace for local definitions with internal linkage
46namespace {
47Q_DEFINE_THIS_MODULE("qv")
48} // unnamed namespace
49
50//============================================================================
51namespace QP {
52
53QV QV::priv_;
54
55//............................................................................
56QV::QV() noexcept
57 : readySet()
58{}
59
60//----------------------------------------------------------------------------
61namespace QF {
62
63//............................................................................
64void init() {
65#ifdef QV_INIT
66 QV_INIT(); // port-specific initialization of the QV kernel
67#endif
68}
69
70//............................................................................
71void stop() {
72 onCleanup(); // cleanup callback
73 // nothing else to do for the QV kernel
74}
75
76//............................................................................
79#ifdef Q_SPY
80 // produce the QS_QF_RUN trace record
81 QS::beginRec_(static_cast<std::uint_fast8_t>(QS_QF_RUN));
82 QS::endRec_();
83#endif // Q_SPY
84
85#ifdef QV_START
86 QV_START(); // port-specific startup of the QV kernel
87#endif
88
89#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
90 std::uint_fast8_t pprev = 0U; // previous prio.
91
92#ifdef QF_ON_CONTEXT_SW
93 // officially switch to the idle cotext
94 QF_onContextSw(nullptr, nullptr);
95#endif // def QF_ON_CONTEXT_SW
96
97#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
98
99 // Application callback: configure and enable individual interrupts.
100 // NOTE: called with interrupts disabled and returns also
101 // with interrupts disabled
102 onStartup();
103
104 for (;;) { // QV event-loop...
105 if (QV::priv_.readySet.notEmpty()) { // any AOs ready to run?
106 // find the maximum prio. AO ready to run
107 std::uint_fast8_t const p = QV::priv_.readySet.findMax();
108 QActive * const a = QActive_registry_[p];
109
110#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
111 if (p != pprev) { // changing threads?
112
114 QS_TIME_PRE(); // timestamp
115 QS_2U8_PRE(static_cast<std::uint8_t>(p),
116 static_cast<std::uint8_t>(pprev));
117 QS_END_PRE()
118
119#ifdef QF_ON_CONTEXT_SW
120 QF_onContextSw(((pprev != 0U)
121 ? QActive_registry_[pprev]
122 : nullptr), a);
123#endif // QF_ON_CONTEXT_SW
124
125 pprev = p; // update previous prio.
126 }
127#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
128
130
131 QEvt const * const e = a->get_(); // queue not empty
132 a->dispatch(e, p); // virtual call
133#if (QF_MAX_EPOOL > 0U)
134 QF::gc(e); // check if the event is garbage, and collect it if so
135#endif
137
138 if (a->m_eQueue.isEmpty()) { // empty queue?
139 QV::priv_.readySet.remove(p);
140 }
141 }
142 else { // no AO ready to run --> idle
143#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
144 if (pprev != 0U) {
146 QS_TIME_PRE(); // timestamp
147 QS_U8_PRE(static_cast<std::uint8_t>(pprev));
148 QS_END_PRE()
149
150#ifdef QF_ON_CONTEXT_SW
151 QF_onContextSw(QActive_registry_[pprev], nullptr);
152#endif // QF_ON_CONTEXT_SW
153
154 pprev = 0U; // update previous prio.
155 }
156#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
157
158 // QV::onIdle() must be called with interrupts DISABLED because
159 // the determination of the idle condition can change at any time
160 // by an interrupt posting events to a queue.
161 //
162 // NOTE: QV::onIdle() MUST enable interrupts internally, ideally
163 // atomically with putting the CPU into a power-saving mode.
164 QV::onIdle();
165
166 QF_INT_DISABLE(); // disable interrupts before looping back
167 }
168 }
169}
170
171} // namespace QF
172
173//----------------------------------------------------------------------------
175 QPrioSpec const prioSpec,
176 QEvtPtr * const qSto,
177 std::uint_fast16_t const qLen,
178 void * const stkSto,
179 std::uint_fast16_t const stkSize,
180 void const * const par)
181{
182 Q_UNUSED_PAR(stkSto); // not needed in QV
183 Q_UNUSED_PAR(stkSize); // not needed in QV
184
187
188 // stack storage must NOT be provided for the AO (QV does not need it)
189 Q_REQUIRE_INCRIT(310, stkSto == nullptr);
190 QF_CRIT_EXIT();
191
192 m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU); // QF-prio.
193 m_pthre = 0U; // not used
194 register_(); // make QF aware of this AO
195
196 m_eQueue.init(qSto, qLen);
197
198 this->init(par, m_prio); // top-most initial tran. (virtual call)
199 QS_FLUSH(); // flush the trace buffer to the host
200}
201
202} // namespace QP
Active Object class (based on the QP::QHsm implementation strategy).
Definition qp.hpp:501
void init(void const *const e, std::uint_fast8_t const qsId) override
Take the top-most initial transition in QActive (delegate to QP::QHsm).
Definition qf_qact.cpp:134
void register_() noexcept
Register this active object to be managed by the framework.
Definition qf_qact.cpp:68
void dispatch(QEvt const *const e, std::uint_fast8_t const qsId) override
Dispatch an event to QActive (delegate to QP::QHsm).
Definition qf_qact.cpp:142
QACTIVE_EQUEUE_TYPE m_eQueue
Port-dependent event-queue type (often QP::QEQueue).
Definition qp.hpp:515
QEvt const * get_() noexcept
Get an event from the event queue of an active object.
Definition qf_actq.cpp:191
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=nullptr)
Starts execution of an active object and registers the object with the framework.
Definition qv.cpp:174
std::uint8_t m_pthre
Preemption-threshold [1..QF_MAX_ACTIVE] of this AO.
Definition qp.hpp:504
std::uint8_t m_prio
QF-priority [1..QF_MAX_ACTIVE] of this AO.
Definition qp.hpp:503
Event class.
Definition qp.hpp:101
QV non-preemptive kernel.
Definition qv.hpp:36
static void onIdle()
QF Active Object Framework namespace \clearpage .
Definition qp.hpp:489
void onCleanup()
Cleanup QF callback.
void gc(QEvt const *const e) noexcept
Recycle a mutable (mutable) event.
Definition qf_dyn.cpp:276
void init()
QF initialization.
Definition qv.cpp:64
int_t run()
Transfers control to QF to run the application.
Definition qv.cpp:77
void stop()
Invoked by the application layer to stop the QF framework and return control to the OS/Kernel (used i...
Definition qv.cpp:71
void onStartup()
Startup QF callback.
QP/C++ Framework namespace \clearpage .
Definition qequeue.hpp:36
@ QS_QF_RUN
QF_run() was entered.
Definition qs.hpp:154
@ QS_SCHED_NEXT
scheduler started next task
Definition qs.hpp:130
@ QS_SCHED_IDLE
scheduler restored the idle task
Definition qs.hpp:131
std::array< QActive *, QF_MAX_ACTIVE+1U > QActive_registry_
Internal array of pointers to the registered Active Objects.
Definition qf_qact.cpp:47
std::uint16_t QPrioSpec
Priority specification for Active Objects in QP.
Definition qp.hpp:423
int int_t
Alias for assertion-ID numbers in QP assertions and return from QP::QF::run() \clearpage .
Definition qp.hpp:87
#define Q_UNUSED_PAR(par_)
Helper macro to mark unused parameters of functions.
Definition qp.hpp:89
void QF_onContextSw(QP::QActive *prev, QP::QActive *next)
QF context switch callback used in built-in kernels (QV/QK/QXK).
QP/C++ Framework in C++ internal (package-scope) interface.
Sample QP/C++ port.
#define QF_CRIT_ENTRY()
Port-specific critical section entry.
Definition qp_port.hpp:57
#define QF_INT_DISABLE()
Port-specific interrupt disable.
Definition qp_port.hpp:52
#define QF_INT_ENABLE()
Port-specific interrupt enable.
Definition qp_port.hpp:53
#define QF_CRIT_EXIT()
Port-specific critical section exit.
Definition qp_port.hpp:58
#define QF_CRIT_STAT
Define the critical section status that was present before entering the critical section.
Definition qp_port.hpp:56
QS (QP/Spy software tracing) internal (package-scope) interface. \clearpage .
#define QS_2U8_PRE(data1_, data2_)
Output two pre-formatted unsigned 8-bit integer data elements.
Definition qs_pkg.hpp:83
#define QS_U8_PRE(data_)
Output pre-formatted unsigned 8-bit integer data element.
Definition qs_pkg.hpp:81
#define QS_END_PRE()
Pre-formatted QS trace record end.
Definition qs_pkg.hpp:79
#define QS_BEGIN_PRE(rec_, qsId_)
Pre-formatted QS trace record begin.
Definition qs_pkg.hpp:73
Sample QS/C++ port.
QP Functional Safety (FuSa) Subsystem.
#define Q_REQUIRE_INCRIT(id_, expr_)
Assertion for checking a precondition (in critical section).
Definition qsafe.h:98
The data type to store in the event queue ring-buffer.
Definition qequeue.hpp:51