QP/C  7.3.4
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.1.1 <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 : 2024-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) % 0x3E8U))
59#error qpc version 7.3.0 or higher required
60#endif
61//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62
63//$define${QF::QActive::subscrList_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
64QSubscrList * QActive_subscrList_;
65//$enddef${QF::QActive::subscrList_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
67//$define${QF::QActive::maxPubSignal_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
68enum_t QActive_maxPubSignal_;
69//$enddef${QF::QActive::maxPubSignal_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
70
71//$define${QF::QActive::psInit} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
72
73//${QF::QActive::psInit} .....................................................
74//! @static @public @memberof QActive
75void QActive_psInit(
76 QSubscrList * const subscrSto,
77 enum_t const maxSignal)
78{
79 QActive_subscrList_ = subscrSto;
80 QActive_maxPubSignal_ = maxSignal;
81
82 // initialize the subscriber list
83 for (enum_t sig = 0; sig < maxSignal; ++sig) {
84 QPSet_setEmpty(&subscrSto[sig].set);
85 #ifndef Q_UNSAFE
86 QPSet_update_(&subscrSto[sig].set, &subscrSto[sig].set_dis);
87 #endif
88 }
89}
90//$enddef${QF::QActive::psInit} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
91
92//$define${QF::QActive::publish_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
93
94//${QF::QActive::publish_} ...................................................
95//! @static @private @memberof QActive
96void QActive_publish_(
97 QEvt const * const e,
98 void const * const sender,
99 uint_fast8_t const qsId)
100{
101 #ifndef Q_SPY
102 Q_UNUSED_PAR(sender);
103 Q_UNUSED_PAR(qsId);
104 #endif
105
106 QSignal const sig = e->sig;
107
110 QF_MEM_SYS();
111
112 Q_REQUIRE_INCRIT(200, sig < (QSignal)QActive_maxPubSignal_);
114 QPSet_verify_(&QActive_subscrList_[sig].set,
115 &QActive_subscrList_[sig].set_dis));
116
117 QS_BEGIN_PRE_(QS_QF_PUBLISH, qsId)
118 QS_TIME_PRE_(); // the timestamp
119 QS_OBJ_PRE_(sender); // the sender object
120 QS_SIG_PRE_(sig); // the signal of the event
121 QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr
122 QS_END_PRE_()
123
124 // is it a mutable event?
125 if (QEvt_getPoolNum_(e) != 0U) {
126 // NOTE: The reference counter of a mutable event is incremented to
127 // prevent premature recycling of the event while the multicasting
128 // is still in progress. At the end of the function, the garbage
129 // collector step (QF_gc()) decrements the reference counter and
130 // recycles the event if the counter drops to zero. This covers the
131 // case when the event was published without any subscribers.
132 QEvt_refCtr_inc_(e);
133 }
134
135 // make a local, modifiable copy of the subscriber set
136 QPSet subscrSet = QActive_subscrList_[sig].set;
137
138 QF_MEM_APP();
139 QF_CRIT_EXIT();
140
141 if (QPSet_notEmpty(&subscrSet)) { // any subscribers?
142 // highest-prio subscriber
143 uint_fast8_t p = QPSet_findMax(&subscrSet);
144
146 QF_MEM_SYS();
147
149 // the AO must be registered with the framework
150 Q_ASSERT_INCRIT(210, a != (QActive *)0);
151
152 QF_MEM_APP();
153 QF_CRIT_EXIT();
154
156 QF_SCHED_LOCK_(p); // lock the scheduler up to AO's prio
157 uint_fast8_t limit = QF_MAX_ACTIVE + 1U;
158 do { // loop over all subscribers
159 --limit;
160
161 // QACTIVE_POST() asserts internally if the queue overflows
162 QACTIVE_POST(a, e, sender);
163
164 QPSet_remove(&subscrSet, p); // remove the handled subscriber
165 if (QPSet_notEmpty(&subscrSet)) { // still more subscribers?
166 p = QPSet_findMax(&subscrSet); // highest-prio subscriber
167
169 QF_MEM_SYS();
170
171 a = QActive_registry_[p];
172 // the AO must be registered with the framework
173 Q_ASSERT_INCRIT(220, a != (QActive *)0);
174
175 QF_MEM_APP();
176 QF_CRIT_EXIT();
177 }
178 else {
179 p = 0U; // no more subscribers
180 }
181 } while ((p != 0U) && (limit > 0U));
182
184 Q_ENSURE_INCRIT(290, p == 0U);
185 QF_CRIT_EXIT();
186
187 QF_SCHED_UNLOCK_(); // unlock the scheduler
188 }
189
190 // The following garbage collection step decrements the reference counter
191 // and recycles the event if the counter drops to zero. This covers both
192 // cases when the event was published with or without any subscribers.
193 #if (QF_MAX_EPOOL > 0U)
194 QF_gc(e); // recycle the event to avoid a leak
195 #endif
196}
197//$enddef${QF::QActive::publish_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
198
199//$define${QF::QActive::subscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
200
201//${QF::QActive::subscribe} ..................................................
202//! @protected @memberof QActive
203void QActive_subscribe(QActive const * const me,
204 enum_t const sig)
205{
206 uint_fast8_t const p = (uint_fast8_t)me->prio;
207
210 QF_MEM_SYS();
211
212 Q_REQUIRE_INCRIT(300, ((enum_t)Q_USER_SIG <= sig)
213 && (sig < QActive_maxPubSignal_)
214 && (0U < p) && (p <= QF_MAX_ACTIVE)
215 && (QActive_registry_[p] == me));
217 QPSet_verify_(&QActive_subscrList_[sig].set,
218 &QActive_subscrList_[sig].set_dis));
219
220 QS_BEGIN_PRE_(QS_QF_ACTIVE_SUBSCRIBE, p)
221 QS_TIME_PRE_(); // timestamp
222 QS_SIG_PRE_(sig); // the signal of this event
223 QS_OBJ_PRE_(me); // this active object
224 QS_END_PRE_()
225
226 // insert the prio. into the subscriber set
227 QPSet_insert(&QActive_subscrList_[sig].set, p);
228 #ifndef Q_UNSAFE
229 QPSet_update_(&QActive_subscrList_[sig].set,
230 &QActive_subscrList_[sig].set_dis);
231 #endif
232
233 QF_MEM_APP();
234 QF_CRIT_EXIT();
235}
236//$enddef${QF::QActive::subscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
237
238//$define${QF::QActive::unsubscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
239
240//${QF::QActive::unsubscribe} ................................................
241//! @protected @memberof QActive
242void QActive_unsubscribe(QActive const * const me,
243 enum_t const sig)
244{
245 uint_fast8_t const p = (uint_fast8_t)me->prio;
246
249 QF_MEM_SYS();
250
251 Q_REQUIRE_INCRIT(400, ((enum_t)Q_USER_SIG <= sig)
252 && (sig < QActive_maxPubSignal_)
253 && (0U < p) && (p <= QF_MAX_ACTIVE)
254 && (QActive_registry_[p] == me));
256 QPSet_verify_(&QActive_subscrList_[sig].set,
257 &QActive_subscrList_[sig].set_dis));
258
259 QS_BEGIN_PRE_(QS_QF_ACTIVE_UNSUBSCRIBE, p)
260 QS_TIME_PRE_(); // timestamp
261 QS_SIG_PRE_(sig); // the signal of this event
262 QS_OBJ_PRE_(me); // this active object
263 QS_END_PRE_()
264
265 // remove the prio. from the subscriber set
266 QPSet_remove(&QActive_subscrList_[sig].set, p);
267 #ifndef Q_UNSAFE
268 QPSet_update_(&QActive_subscrList_[sig].set,
269 &QActive_subscrList_[sig].set_dis);
270 #endif
271
272 QF_MEM_APP();
273 QF_CRIT_EXIT();
274}
275//$enddef${QF::QActive::unsubscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
276
277//$define${QF::QActive::unsubscribeAll} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
278
279//${QF::QActive::unsubscribeAll} .............................................
280//! @protected @memberof QActive
281void QActive_unsubscribeAll(QActive const * const me) {
284 QF_MEM_SYS();
285
286 uint_fast8_t const p = (uint_fast8_t)me->prio;
287
288 Q_REQUIRE_INCRIT(500, (0U < p) && (p <= QF_MAX_ACTIVE)
289 && (QActive_registry_[p] == me));
290 enum_t const maxPubSig = QActive_maxPubSignal_;
291
292 QF_MEM_APP();
293 QF_CRIT_EXIT();
294
295 for (enum_t sig = (enum_t)Q_USER_SIG; sig < maxPubSig; ++sig) {
297 QF_MEM_SYS();
298
299 if (QPSet_hasElement(&QActive_subscrList_[sig].set, p)) {
300 QPSet_remove(&QActive_subscrList_[sig].set, p);
301 #ifndef Q_UNSAFE
302 QPSet_update_(&QActive_subscrList_[sig].set,
303 &QActive_subscrList_[sig].set_dis);
304 #endif
305 QS_BEGIN_PRE_(QS_QF_ACTIVE_UNSUBSCRIBE, p)
306 QS_TIME_PRE_(); // timestamp
307 QS_SIG_PRE_(sig); // the signal of this event
308 QS_OBJ_PRE_(me); // this active object
309 QS_END_PRE_()
310 }
311 QF_MEM_APP();
312 QF_CRIT_EXIT();
313
314 QF_CRIT_EXIT_NOP(); // prevent merging critical sections
315 }
316}
317//$enddef${QF::QActive::unsubscribeAll} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
QActive * QActive_registry_[QF_MAX_ACTIVE+1U]
Definition qf_act.c:64
#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:1284
uint16_t QSignal
Definition qp.h:131
#define Q_UNUSED_PAR(par_)
Definition qp.h:532
@ Q_USER_SIG
offset for the user signals (QP Application)
Definition qp.h:260
#define QF_MEM_SYS()
Definition qp.h:1279
#define QACTIVE_POST(me_, e_, sender_)
Definition qp.h:1203
int enum_t
Definition qp.h:109
#define QF_CRIT_EXIT_NOP()
Definition qp.h:1265
#define QF_MAX_ACTIVE
Definition qp_config.h:112
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_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:800
uint8_t prio
Definition qp.h:805
Event class.
Definition qp.h:147
uint8_t volatile refCtr_
Definition qp.h:156
QSignal sig
Definition qp.h:151
Set of Active Objects of up to QF_MAX_ACTIVE elements.
Definition qp.h:658
Subscriber List (for publish-subscribe)
Definition qp.h:779