QP/C  7.4.0-rc.3
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qf_ps.c
Go to the documentation of this file.
1//$file${src::qf::qf_ps.c} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpc.qm
4// File: ${src::qf::qf_ps.c}
5//
6// This code has been generated by QM 6.2.0 <www.state-machine.com/qm>.
7// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
8//
9// This code is covered by the following QP license:
10// License # : LicenseRef-QL-dual
11// Issued to : Any user of the QP/C real-time embedded framework
12// Framework(s) : qpc
13// Support ends : 2025-12-31
14// License scope:
15//
16// Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
17//
18// Q u a n t u m L e a P s
19// ------------------------
20// Modern Embedded Software
21//
22// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
23//
24// This software is dual-licensed under the terms of the open source GNU
25// General Public License version 3 (or any later version), or alternatively,
26// under the terms of one of the closed source Quantum Leaps commercial
27// licenses.
28//
29// The terms of the open source GNU General Public License version 3
30// can be found at: <www.gnu.org/licenses/gpl-3.0>
31//
32// The terms of the closed source Quantum Leaps commercial licenses
33// can be found at: <www.state-machine.com/licensing>
34//
35// Redistributions in source code must retain this top-level comment block.
36// Plagiarizing this software to sidestep the license obligations is illegal.
37//
38// Contact information:
39// <www.state-machine.com/licensing>
40// <info@state-machine.com>
41//
42//$endhead${src::qf::qf_ps.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43#define QP_IMPL // this is QP implementation
44#include "qp_port.h" // QP port
45#include "qp_pkg.h" // QP package-scope interface
46#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
47#ifdef Q_SPY // QS software tracing enabled?
48 #include "qs_port.h" // QS port
49 #include "qs_pkg.h" // QS facilities for pre-defined trace records
50#else
51 #include "qs_dummy.h" // disable the QS software tracing
52#endif // Q_SPY
53
54Q_DEFINE_THIS_MODULE("qf_ps")
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 qpc version 7.3.0 or higher required
60#endif
61//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62//$define${QF::QActive::subscrList_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
63QSubscrList * QActive_subscrList_;
64//$enddef${QF::QActive::subscrList_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
65
66//$define${QF::QActive::maxPubSignal_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
67enum_t QActive_maxPubSignal_;
68//$enddef${QF::QActive::maxPubSignal_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
69
70//$define${QF::QActive::psInit} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
71
72//${QF::QActive::psInit} .....................................................
73//! @static @public @memberof QActive
74void QActive_psInit(
75 QSubscrList * const subscrSto,
76 enum_t const maxSignal)
77{
78 QActive_subscrList_ = subscrSto;
79 QActive_maxPubSignal_ = maxSignal;
80
81 // initialize the subscriber list
82 for (enum_t sig = 0; sig < maxSignal; ++sig) {
83 QPSet_setEmpty(&subscrSto[sig].set);
84 #ifndef Q_UNSAFE
85 QPSet_update_(&subscrSto[sig].set, &subscrSto[sig].set_dis);
86 #endif
87 }
88}
89//$enddef${QF::QActive::psInit} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
90
91//$define${QF::QActive::publish_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
92
93//${QF::QActive::publish_} ...................................................
94//! @static @private @memberof QActive
95void QActive_publish_(
96 QEvt const * const e,
97 void const * const sender,
98 uint_fast8_t const qsId)
99{
100 #ifndef Q_SPY
101 Q_UNUSED_PAR(sender);
102 Q_UNUSED_PAR(qsId);
103 #endif
104
105 QSignal const sig = e->sig;
106
109 QF_MEM_SYS();
110
111 Q_REQUIRE_INCRIT(200, sig < (QSignal)QActive_maxPubSignal_);
113 QPSet_verify_(&QActive_subscrList_[sig].set,
114 &QActive_subscrList_[sig].set_dis));
115
116 QS_BEGIN_PRE_(QS_QF_PUBLISH, qsId)
117 QS_TIME_PRE_(); // the timestamp
118 QS_OBJ_PRE_(sender); // the sender object
119 QS_SIG_PRE_(sig); // the signal of the event
120 QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr
121 QS_END_PRE_()
122
123 // is it a mutable event?
124 if (QEvt_getPoolNum_(e) != 0U) {
125 // NOTE: The reference counter of a mutable event is incremented to
126 // prevent premature recycling of the event while the multicasting
127 // is still in progress. At the end of the function, the garbage
128 // collector step (QF_gc()) decrements the reference counter and
129 // recycles the event if the counter drops to zero. This covers the
130 // case when the event was published without any subscribers.
131 QEvt_refCtr_inc_(e);
132 }
133
134 // make a local, modifiable copy of the subscriber set
135 QPSet subscrSet = QActive_subscrList_[sig].set;
136
137 QF_MEM_APP();
138 QF_CRIT_EXIT();
139
140 if (QPSet_notEmpty(&subscrSet)) { // any subscribers?
141 // highest-prio subscriber
142 uint_fast8_t p = QPSet_findMax(&subscrSet);
143
145 QF_MEM_SYS();
146
147 QActive *a = QActive_registry_[p];
148 // the AO must be registered with the framework
149 Q_ASSERT_INCRIT(210, a != (QActive *)0);
150
151 QF_MEM_APP();
152 QF_CRIT_EXIT();
153
155 QF_SCHED_LOCK_(p); // lock the scheduler up to AO's prio
156 uint_fast8_t lbound = QF_MAX_ACTIVE + 1U; // fixed upper loop bound
157 do { // loop over all subscribers
158 --lbound;
159
160 // QACTIVE_POST() asserts internally if the queue overflows
161 QACTIVE_POST(a, e, sender);
162
163 QPSet_remove(&subscrSet, p); // remove the handled subscriber
164 if (QPSet_notEmpty(&subscrSet)) { // still more subscribers?
165 p = QPSet_findMax(&subscrSet); // highest-prio subscriber
166
168 QF_MEM_SYS();
169
170 a = QActive_registry_[p];
171 // the AO must be registered with the framework
172 Q_ASSERT_INCRIT(220, a != (QActive *)0);
173
174 QF_MEM_APP();
175 QF_CRIT_EXIT();
176 }
177 else {
178 p = 0U; // no more subscribers
179 }
180 } while ((p != 0U) && (lbound > 0U));
181
183 // NOTE: the following postcondition can only succeed when
184 // (lbound > 0), so no extra check for lbound is necessary.
185 Q_ENSURE_INCRIT(290, p == 0U); // all subscribers processed
186 QF_CRIT_EXIT();
187
188 QF_SCHED_UNLOCK_(); // unlock the scheduler
189 }
190
191 // The following garbage collection step decrements the reference counter
192 // and recycles the event if the counter drops to zero. This covers both
193 // cases when the event was published with or without any subscribers.
194 #if (QF_MAX_EPOOL > 0U)
195 QF_gc(e); // recycle the event to avoid a leak
196 #endif
197}
198//$enddef${QF::QActive::publish_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
199
200//$define${QF::QActive::subscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
201
202//${QF::QActive::subscribe} ..................................................
203//! @protected @memberof QActive
204void QActive_subscribe(QActive const * const me,
205 enum_t const sig)
206{
207 uint_fast8_t const p = (uint_fast8_t)me->prio;
208
211 QF_MEM_SYS();
212
213 Q_REQUIRE_INCRIT(300, ((enum_t)Q_USER_SIG <= sig)
214 && (sig < QActive_maxPubSignal_)
215 && (0U < p) && (p <= QF_MAX_ACTIVE)
216 && (QActive_registry_[p] == me));
218 QPSet_verify_(&QActive_subscrList_[sig].set,
219 &QActive_subscrList_[sig].set_dis));
220
221 QS_BEGIN_PRE_(QS_QF_ACTIVE_SUBSCRIBE, p)
222 QS_TIME_PRE_(); // timestamp
223 QS_SIG_PRE_(sig); // the signal of this event
224 QS_OBJ_PRE_(me); // this active object
225 QS_END_PRE_()
226
227 // insert the prio. into the subscriber set
228 QPSet_insert(&QActive_subscrList_[sig].set, p);
229 #ifndef Q_UNSAFE
230 QPSet_update_(&QActive_subscrList_[sig].set,
231 &QActive_subscrList_[sig].set_dis);
232 #endif
233
234 QF_MEM_APP();
235 QF_CRIT_EXIT();
236}
237//$enddef${QF::QActive::subscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
238
239//$define${QF::QActive::unsubscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
240
241//${QF::QActive::unsubscribe} ................................................
242//! @protected @memberof QActive
243void QActive_unsubscribe(QActive const * const me,
244 enum_t const sig)
245{
246 uint_fast8_t const p = (uint_fast8_t)me->prio;
247
250 QF_MEM_SYS();
251
252 Q_REQUIRE_INCRIT(400, ((enum_t)Q_USER_SIG <= sig)
253 && (sig < QActive_maxPubSignal_)
254 && (0U < p) && (p <= QF_MAX_ACTIVE)
255 && (QActive_registry_[p] == me));
257 QPSet_verify_(&QActive_subscrList_[sig].set,
258 &QActive_subscrList_[sig].set_dis));
259
260 QS_BEGIN_PRE_(QS_QF_ACTIVE_UNSUBSCRIBE, p)
261 QS_TIME_PRE_(); // timestamp
262 QS_SIG_PRE_(sig); // the signal of this event
263 QS_OBJ_PRE_(me); // this active object
264 QS_END_PRE_()
265
266 // remove the prio. from the subscriber set
267 QPSet_remove(&QActive_subscrList_[sig].set, p);
268 #ifndef Q_UNSAFE
269 QPSet_update_(&QActive_subscrList_[sig].set,
270 &QActive_subscrList_[sig].set_dis);
271 #endif
272
273 QF_MEM_APP();
274 QF_CRIT_EXIT();
275}
276//$enddef${QF::QActive::unsubscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
277
278//$define${QF::QActive::unsubscribeAll} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
279
280//${QF::QActive::unsubscribeAll} .............................................
281//! @protected @memberof QActive
282void QActive_unsubscribeAll(QActive const * const me) {
285 QF_MEM_SYS();
286
287 uint_fast8_t const p = (uint_fast8_t)me->prio;
288
289 Q_REQUIRE_INCRIT(500, (0U < p) && (p <= QF_MAX_ACTIVE)
290 && (QActive_registry_[p] == me));
291 enum_t const maxPubSig = QActive_maxPubSignal_;
292
293 QF_MEM_APP();
294 QF_CRIT_EXIT();
295
296 for (enum_t sig = (enum_t)Q_USER_SIG; sig < maxPubSig; ++sig) {
298 QF_MEM_SYS();
299
300 if (QPSet_hasElement(&QActive_subscrList_[sig].set, p)) {
301 QPSet_remove(&QActive_subscrList_[sig].set, p);
302 #ifndef Q_UNSAFE
303 QPSet_update_(&QActive_subscrList_[sig].set,
304 &QActive_subscrList_[sig].set_dis);
305 #endif
306 QS_BEGIN_PRE_(QS_QF_ACTIVE_UNSUBSCRIBE, p)
307 QS_TIME_PRE_(); // timestamp
308 QS_SIG_PRE_(sig); // the signal of this event
309 QS_OBJ_PRE_(me); // this active object
310 QS_END_PRE_()
311 }
312 QF_MEM_APP();
313 QF_CRIT_EXIT();
314
315 QF_CRIT_EXIT_NOP(); // prevent merging critical sections
316 }
317}
318//$enddef${QF::QActive::unsubscribeAll} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#define QF_SCHED_LOCK_(ceil_)
Definition qk.h:149
#define QF_SCHED_UNLOCK_()
Definition qk.h:158
#define QF_SCHED_STAT_
Definition qk.h:146
#define QF_MEM_APP()
Definition qp.h:1288
#define Q_UNUSED_PAR(par_)
Helper macro to clearly mark unused parameters of functions.
Definition qp.h:536
@ Q_USER_SIG
offset for the user signals (QP Application)
Definition qp.h:263
#define QF_MEM_SYS()
Definition qp.h:1283
#define QACTIVE_POST(me_, e_, sender_)
Invoke the direct event posting facility QActive_post_().
Definition qp.h:1207
int enum_t
Definition qp.h:107
#define QF_CRIT_EXIT_NOP()
No-operation for exiting a critical section.
Definition qp.h:1269
uint16_t QSignal
The signal of event QEvt.
Definition qp.h:129
#define QF_MAX_ACTIVE
Maximum # Active Objects in the system (1..64)
Definition qp_config.h:118
Internal (package scope) QP/C interface.
Sample QP/C port.
#define QS_TIME_PRE_()
Definition qs.h:450
@ QS_QF_PUBLISH
an event was published to active objects
Definition qs.h:117
@ QS_QF_ACTIVE_UNSUBSCRIBE
an AO unsubscribed to an event
Definition qs.h:96
@ QS_QF_ACTIVE_SUBSCRIBE
an AO subscribed to an event
Definition qs.h:95
QS/C package-scope interface.
Sample QS/C port.
QP Functional Safety (FuSa) Subsystem.
#define QF_CRIT_ENTRY()
Definition qsafe.h:58
#define Q_ASSERT_INCRIT(id_, expr_)
Definition qsafe.h:72
#define Q_INVARIANT_INCRIT(id_, expr_)
Definition qsafe.h:154
#define Q_ENSURE_INCRIT(id_, expr_)
Definition qsafe.h:145
#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
Active object class (based on the QHsm implementation strategy)
Definition qp.h:804
uint8_t prio
QF-priority [1..QF_MAX_ACTIVE] of this AO.
Definition qp.h:809
Event class.
Definition qp.h:145
QSignal sig
Signal of the event (see Event Signal)
Definition qp.h:149
uint8_t volatile refCtr_
Reference counter (for mutable events and 0 for immutable (static) events)
Definition qp.h:154
Set of Active Objects of up to QF_MAX_ACTIVE elements.
Definition qp.h:662
Subscriber List (for publish-subscribe)
Definition qp.h:783