QP/C  8.0.0
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 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 GNU
18// 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::qf::qf_ps.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35#define QP_IMPL // this is QP implementation
36#include "qp_port.h" // QP port
37#include "qp_pkg.h" // 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.h" // QS port
41 #include "qs_pkg.h" // QS facilities for pre-defined trace records
42#else
43 #include "qs_dummy.h" // disable the QS software tracing
44#endif // Q_SPY
45
46Q_DEFINE_THIS_MODULE("qf_ps")
47
48//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
49// Check for the minimum required QP version
50#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
51#error qpc version 7.3.0 or higher required
52#endif
53//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
54//$define${QF::QActive::subscrList_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
55QSubscrList * QActive_subscrList_;
56//$enddef${QF::QActive::subscrList_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
57
58//$define${QF::QActive::maxPubSignal_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
59enum_t QActive_maxPubSignal_;
60//$enddef${QF::QActive::maxPubSignal_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
61
62//$define${QF::QActive::psInit} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
63
64//${QF::QActive::psInit} .....................................................
65//! @static @public @memberof QActive
66void QActive_psInit(
67 QSubscrList * const subscrSto,
68 enum_t const maxSignal)
69{
70 QActive_subscrList_ = subscrSto;
71 QActive_maxPubSignal_ = maxSignal;
72
73 // initialize the subscriber list
74 for (enum_t sig = 0; sig < maxSignal; ++sig) {
75 QPSet_setEmpty(&subscrSto[sig].set);
76 #ifndef Q_UNSAFE
77 QPSet_update_(&subscrSto[sig].set, &subscrSto[sig].set_dis);
78 #endif
79 }
80}
81//$enddef${QF::QActive::psInit} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
82
83//$define${QF::QActive::publish_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
84
85//${QF::QActive::publish_} ...................................................
86//! @static @private @memberof QActive
87void QActive_publish_(
88 QEvt const * const e,
89 void const * const sender,
90 uint_fast8_t const qsId)
91{
92 #ifndef Q_SPY
93 Q_UNUSED_PAR(sender);
94 Q_UNUSED_PAR(qsId);
95 #endif
96
97 QSignal const sig = e->sig;
98
101 QF_MEM_SYS();
102
103 Q_REQUIRE_INCRIT(200, sig < (QSignal)QActive_maxPubSignal_);
105 QPSet_verify_(&QActive_subscrList_[sig].set,
106 &QActive_subscrList_[sig].set_dis));
107
108 QS_BEGIN_PRE(QS_QF_PUBLISH, qsId)
109 QS_TIME_PRE(); // the timestamp
110 QS_OBJ_PRE(sender); // the sender object
111 QS_SIG_PRE(sig); // the signal of the event
112 QS_2U8_PRE(QEvt_getPoolNum_(e), e->refCtr_);
113 QS_END_PRE()
114
115 // is it a mutable event?
116 if (QEvt_getPoolNum_(e) != 0U) {
117 // NOTE: The reference counter of a mutable event is incremented to
118 // prevent premature recycling of the event while the multicasting
119 // is still in progress. At the end of the function, the garbage
120 // collector step (QF_gc()) decrements the reference counter and
121 // recycles the event if the counter drops to zero. This covers the
122 // case when the event was published without any subscribers.
123 QEvt_refCtr_inc_(e);
124 }
125
126 // make a local, modifiable copy of the subscriber set
127 QPSet subscrSet = QActive_subscrList_[sig].set;
128
129 QF_MEM_APP();
130 QF_CRIT_EXIT();
131
132 if (QPSet_notEmpty(&subscrSet)) { // any subscribers?
133 // highest-prio subscriber
134 uint_fast8_t p = QPSet_findMax(&subscrSet);
135
137 QF_MEM_SYS();
138
139 QActive *a = QActive_registry_[p];
140 // the AO must be registered with the framework
141 Q_ASSERT_INCRIT(210, a != (QActive *)0);
142
143 QF_MEM_APP();
144 QF_CRIT_EXIT();
145
147 QF_SCHED_LOCK_(p); // lock the scheduler up to AO's prio
148 uint_fast8_t lbound = QF_MAX_ACTIVE + 1U; // fixed upper loop bound
149 do { // loop over all subscribers
150 --lbound;
151
152 // QACTIVE_POST() asserts internally if the queue overflows
153 QACTIVE_POST(a, e, sender);
154
155 QPSet_remove(&subscrSet, p); // remove the handled subscriber
156 if (QPSet_notEmpty(&subscrSet)) { // still more subscribers?
157 p = QPSet_findMax(&subscrSet); // highest-prio subscriber
158
160 QF_MEM_SYS();
161
162 a = QActive_registry_[p];
163 // the AO must be registered with the framework
164 Q_ASSERT_INCRIT(220, a != (QActive *)0);
165
166 QF_MEM_APP();
167 QF_CRIT_EXIT();
168 }
169 else {
170 p = 0U; // no more subscribers
171 }
172 } while ((p != 0U) && (lbound > 0U));
173
175 // NOTE: the following postcondition can only succeed when
176 // (lbound > 0), so no extra check for lbound is necessary.
177 Q_ENSURE_INCRIT(290, p == 0U); // all subscribers processed
178 QF_CRIT_EXIT();
179
180 QF_SCHED_UNLOCK_(); // unlock the scheduler
181 }
182
183 // The following garbage collection step decrements the reference counter
184 // and recycles the event if the counter drops to zero. This covers both
185 // cases when the event was published with or without any subscribers.
186 #if (QF_MAX_EPOOL > 0U)
187 QF_gc(e); // recycle the event to avoid a leak
188 #endif
189}
190//$enddef${QF::QActive::publish_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
191
192//$define${QF::QActive::subscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
193
194//${QF::QActive::subscribe} ..................................................
195//! @protected @memberof QActive
196void QActive_subscribe(QActive const * const me,
197 enum_t const sig)
198{
199 uint_fast8_t const p = (uint_fast8_t)me->prio;
200
203 QF_MEM_SYS();
204
205 Q_REQUIRE_INCRIT(300, (Q_USER_SIG <= sig)
206 && (sig < QActive_maxPubSignal_)
207 && (0U < p) && (p <= QF_MAX_ACTIVE)
208 && (QActive_registry_[p] == me));
210 QPSet_verify_(&QActive_subscrList_[sig].set,
211 &QActive_subscrList_[sig].set_dis));
212
213 QS_BEGIN_PRE(QS_QF_ACTIVE_SUBSCRIBE, p)
214 QS_TIME_PRE(); // timestamp
215 QS_SIG_PRE(sig); // the signal of this event
216 QS_OBJ_PRE(me); // this active object
217 QS_END_PRE()
218
219 // insert the prio. into the subscriber set
220 QPSet_insert(&QActive_subscrList_[sig].set, p);
221 #ifndef Q_UNSAFE
222 QPSet_update_(&QActive_subscrList_[sig].set,
223 &QActive_subscrList_[sig].set_dis);
224 #endif
225
226 QF_MEM_APP();
227 QF_CRIT_EXIT();
228}
229//$enddef${QF::QActive::subscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
230
231//$define${QF::QActive::unsubscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
232
233//${QF::QActive::unsubscribe} ................................................
234//! @protected @memberof QActive
235void QActive_unsubscribe(QActive const * const me,
236 enum_t const sig)
237{
238 uint_fast8_t const p = (uint_fast8_t)me->prio;
239
242 QF_MEM_SYS();
243
244 Q_REQUIRE_INCRIT(400, (Q_USER_SIG <= sig)
245 && (sig < QActive_maxPubSignal_)
246 && (0U < p) && (p <= QF_MAX_ACTIVE)
247 && (QActive_registry_[p] == me));
249 QPSet_verify_(&QActive_subscrList_[sig].set,
250 &QActive_subscrList_[sig].set_dis));
251
252 QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, p)
253 QS_TIME_PRE(); // timestamp
254 QS_SIG_PRE(sig); // the signal of this event
255 QS_OBJ_PRE(me); // this active object
256 QS_END_PRE()
257
258 // remove the prio. from the subscriber set
259 QPSet_remove(&QActive_subscrList_[sig].set, p);
260 #ifndef Q_UNSAFE
261 QPSet_update_(&QActive_subscrList_[sig].set,
262 &QActive_subscrList_[sig].set_dis);
263 #endif
264
265 QF_MEM_APP();
266 QF_CRIT_EXIT();
267}
268//$enddef${QF::QActive::unsubscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
269
270//$define${QF::QActive::unsubscribeAll} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
271
272//${QF::QActive::unsubscribeAll} .............................................
273//! @protected @memberof QActive
274void QActive_unsubscribeAll(QActive const * const me) {
277 QF_MEM_SYS();
278
279 uint_fast8_t const p = (uint_fast8_t)me->prio;
280
281 Q_REQUIRE_INCRIT(500, (0U < p) && (p <= QF_MAX_ACTIVE)
282 && (QActive_registry_[p] == me));
283 enum_t const maxPubSig = QActive_maxPubSignal_;
284
285 QF_MEM_APP();
286 QF_CRIT_EXIT();
287
288 for (enum_t sig = Q_USER_SIG; sig < maxPubSig; ++sig) {
290 QF_MEM_SYS();
291
292 if (QPSet_hasElement(&QActive_subscrList_[sig].set, p)) {
293 QPSet_remove(&QActive_subscrList_[sig].set, p);
294 #ifndef Q_UNSAFE
295 QPSet_update_(&QActive_subscrList_[sig].set,
296 &QActive_subscrList_[sig].set_dis);
297 #endif
298 QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, p)
299 QS_TIME_PRE(); // timestamp
300 QS_SIG_PRE(sig); // the signal of this event
301 QS_OBJ_PRE(me); // this active object
302 QS_END_PRE()
303 }
304 QF_MEM_APP();
305 QF_CRIT_EXIT();
306
307 QF_CRIT_EXIT_NOP(); // prevent merging critical sections
308 }
309}
310//$enddef${QF::QActive::unsubscribeAll} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#define QF_SCHED_LOCK_(ceil_)
Definition qk.h:141
#define QF_SCHED_UNLOCK_()
Definition qk.h:150
#define QF_SCHED_STAT_
Definition qk.h:138
#define QF_MEM_APP()
Definition qp.h:1276
#define Q_UNUSED_PAR(par_)
Helper macro to clearly mark unused parameters of functions.
Definition qp.h:521
#define Q_USER_SIG
offset for the user signals (QP Application))
Definition qp.h:485
#define QF_MEM_SYS()
Definition qp.h:1271
#define QACTIVE_POST(me_, e_, sender_)
Invoke the direct event posting facility QActive_post_().
Definition qp.h:1195
int enum_t
Definition qp.h:99
#define QF_CRIT_EXIT_NOP()
No-operation for exiting a critical section.
Definition qp.h:1257
uint16_t QSignal
The signal of event QEvt.
Definition qp.h:121
#define QF_MAX_ACTIVE
Maximum # Active Objects in the system (1..64)
Definition qp_config.h:123
Internal (package scope) QP/C interface.
Sample QP/C port.
#define QS_OBJ_PRE(obj_)
Definition qs_dummy.h:150
#define QS_SIG_PRE(sig_)
Definition qs_dummy.h:148
#define QS_TIME_PRE()
Definition qs_dummy.h:147
#define QS_2U8_PRE(data1_, data2_)
Definition qs_dummy.h:144
#define QS_END_PRE()
Definition qs_dummy.h:142
#define QS_BEGIN_PRE(rec_, qsId_)
Definition qs_dummy.h:141
Sample QS/C port.
QP Functional Safety (FuSa) Subsystem.
#define QF_CRIT_ENTRY()
Definition qsafe.h:50
#define Q_ASSERT_INCRIT(id_, expr_)
Definition qsafe.h:64
#define Q_INVARIANT_INCRIT(id_, expr_)
Definition qsafe.h:146
#define Q_ENSURE_INCRIT(id_, expr_)
Definition qsafe.h:137
#define QF_CRIT_EXIT()
Definition qsafe.h:54
#define Q_REQUIRE_INCRIT(id_, expr_)
Definition qsafe.h:128
#define QF_CRIT_STAT
Definition qsafe.h:46
Active object class (based on the QHsm implementation strategy)
Definition qp.h:775
uint8_t prio
QF-priority [1..QF_MAX_ACTIVE] of this AO.
Definition qp.h:780
Event class.
Definition qp.h:131
QSignal sig
Signal of the event (see Event Signal)
Definition qp.h:135
uint8_t volatile refCtr_
Event reference counter.
Definition qp.h:143
Set of Active Objects of up to QF_MAX_ACTIVE elements.
Definition qp.h:630
Subscriber List (for publish-subscribe)
Definition qp.h:751