QP/C  7.2.2
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} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
2/*
3* Model: qpc.qm
4* File: ${src::qf::qf_ps.c}
5*
6* This code has been generated by QM 5.2.5 <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 : 2023-12-31
14* License scope:
15*
16* Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
17*
18* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
19*
20* This software is dual-licensed under the terms of the open source GNU
21* General Public License version 3 (or any later version), or alternatively,
22* under the terms of one of the closed source Quantum Leaps commercial
23* licenses.
24*
25* The terms of the open source GNU General Public License version 3
26* can be found at: <www.gnu.org/licenses/gpl-3.0>
27*
28* The terms of the closed source Quantum Leaps commercial licenses
29* can be found at: <www.state-machine.com/licensing>
30*
31* Redistributions in source code must retain this top-level comment block.
32* Plagiarizing this software to sidestep the license obligations is illegal.
33*
34* Contact information:
35* <www.state-machine.com/licensing>
36* <info@state-machine.com>
37*/
38/*$endhead${src::qf::qf_ps.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
39/*! @file
40* @brief Publish-Subscribe services
41*/
42#define QP_IMPL /* this is QP implementation */
43#include "qf_port.h" /* QF port */
44#include "qf_pkg.h" /* QF package-scope interface */
45#include "qassert.h" /* QP embedded systems-friendly assertions */
46#ifdef Q_SPY /* QS software tracing enabled? */
47 #include "qs_port.h" /* QS port */
48 #include "qs_pkg.h" /* QS facilities for pre-defined trace records */
49#else
50 #include "qs_dummy.h" /* disable the QS software tracing */
51#endif /* Q_SPY */
52
53Q_DEFINE_THIS_MODULE("qf_ps")
54
55/*==========================================================================*/
56/*$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
57/* Check for the minimum required QP version */
58#if (QP_VERSION < 700U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
59#error qpc version 7.0.0 or higher required
60#endif
61/*$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
62
63/*$define${QF::QActive::subscrList_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
64QSubscrList * QActive_subscrList_;
65/*$enddef${QF::QActive::subscrList_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
66/*$define${QF::QActive::maxPubSignal_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
67enum_t QActive_maxPubSignal_;
68/*$enddef${QF::QActive::maxPubSignal_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
69
70/*$define${QF::QActive::psInit} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
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 /* zero the subscriber list, so that the framework can start correctly
82 * even if the startup code fails to clear the uninitialized data
83 * (as is required by the C Standard).
84 */
85 QF_bzero(subscrSto, (uint_fast16_t)maxSignal * sizeof(QSubscrList));
86}
87/*$enddef${QF::QActive::psInit} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
88/*$define${QF::QActive::publish_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
89
90/*${QF::QActive::publish_} .................................................*/
91/*! @static @private @memberof QActive */
92void QActive_publish_(
93 QEvt const * const e,
94 void const * const sender,
95 uint_fast8_t const qs_id)
96{
97 #ifndef Q_SPY
98 Q_UNUSED_PAR(sender);
99 Q_UNUSED_PAR(qs_id);
100 #endif
101
102 Q_REQUIRE_ID(200, e->sig < (QSignal)QActive_maxPubSignal_);
103
105 QF_CRIT_E_();
106
108 QS_TIME_PRE_(); /* the timestamp */
109 QS_OBJ_PRE_(sender); /* the sender object */
110 QS_SIG_PRE_(e->sig); /* the signal of the event */
111 QS_2U8_PRE_(e->poolId_, e->refCtr_);/* pool Id & ref Count */
113
114 /* is it a dynamic event? */
115 if (e->poolId_ != 0U) {
116 /* NOTE: The reference counter of a dynamic event is incremented to
117 * prevent premature recycling of the event while the multicasting
118 * is still in progress. At the end of the function, the garbage
119 * collector step (QF_gc()) decrements the reference counter and
120 * recycles the event if the counter drops to zero. This covers the
121 * case when the event was published without any subscribers.
122 */
123 QEvt_refCtr_inc_(e);
124 }
125
126 /* make a local, modifiable copy of the subscriber list */
127 QPSet subscrList = QActive_subscrList_[e->sig];
128 QF_CRIT_X_();
129
130 if (QPSet_notEmpty(&subscrList)) { /* any subscribers? */
131 /* the highest-prio subscriber */
132 uint_fast8_t p = QPSet_findMax(&subscrList);
133 QActive *a = QActive_registry_[p];
135
136 QF_SCHED_LOCK_(a->prio); /* lock the scheduler up to AO's prio */
137 do { /* loop over all subscribers */
138 /* the prio of the AO must be registered with the framework */
139 Q_ASSERT_ID(210, a != (QActive *)0);
140
141 /* QACTIVE_POST() asserts internally if the queue overflows */
142 QACTIVE_POST(a, e, sender);
143
144 QPSet_remove(&subscrList, p); /* remove the handled subscriber */
145 if (QPSet_notEmpty(&subscrList)) { /* still more subscribers? */
146 /* highest-prio subscriber */
147 p = QPSet_findMax(&subscrList);
148 a = QActive_registry_[p];
149 }
150 else {
151 p = 0U; /* no more subscribers */
152 }
153 } while (p != 0U);
154 QF_SCHED_UNLOCK_(); /* unlock the scheduler */
155 }
156
157 /* The following garbage collection step decrements the reference counter
158 * and recycles the event if the counter drops to zero. This covers both
159 * cases when the event was published with or without any subscribers.
160 */
161 #if (QF_MAX_EPOOL > 0U)
162 QF_gc(e); /* recycle the event to avoid a leak */
163 #endif
164}
165/*$enddef${QF::QActive::publish_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
166/*$define${QF::QActive::subscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
167
168/*${QF::QActive::subscribe} ................................................*/
169/*! @public @memberof QActive */
170void QActive_subscribe(QActive const * const me,
171 enum_t const sig)
172{
173 uint_fast8_t const p = (uint_fast8_t)me->prio;
174
175 Q_REQUIRE_ID(300, ((enum_t)Q_USER_SIG <= sig)
176 && (sig < QActive_maxPubSignal_)
177 && (0U < p) && (p <= QF_MAX_ACTIVE)
178 && (QActive_registry_[p] == me));
179
181 QF_CRIT_E_();
182
184 QS_TIME_PRE_(); /* timestamp */
185 QS_SIG_PRE_(sig); /* the signal of this event */
186 QS_OBJ_PRE_(me); /* this active object */
188
189 /* set the priority bit */
190 QPSet_insert(&QActive_subscrList_[sig], p);
191
192 QF_CRIT_X_();
193}
194/*$enddef${QF::QActive::subscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
195/*$define${QF::QActive::unsubscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
196
197/*${QF::QActive::unsubscribe} ..............................................*/
198/*! @public @memberof QActive */
199void QActive_unsubscribe(QActive const * const me,
200 enum_t const sig)
201{
202 uint_fast8_t const p = (uint_fast8_t)me->prio;
203
204 Q_REQUIRE_ID(400, ((enum_t)Q_USER_SIG <= sig)
205 && (sig < QActive_maxPubSignal_)
206 && (0U < p) && (p <= QF_MAX_ACTIVE)
207 && (QActive_registry_[p] == me));
208
210 QF_CRIT_E_();
211
213 QS_TIME_PRE_(); /* timestamp */
214 QS_SIG_PRE_(sig); /* the signal of this event */
215 QS_OBJ_PRE_(me); /* this active object */
217
218 /* clear priority bit */
219 QPSet_remove(&QActive_subscrList_[sig], p);
220
221 QF_CRIT_X_();
222}
223/*$enddef${QF::QActive::unsubscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
224/*$define${QF::QActive::unsubscribeAll} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
225
226/*${QF::QActive::unsubscribeAll} ...........................................*/
227/*! @public @memberof QActive */
228void QActive_unsubscribeAll(QActive const * const me) {
229 uint_fast8_t const p = (uint_fast8_t)me->prio;
230
231 Q_REQUIRE_ID(500, (0U < p) && (p <= QF_MAX_ACTIVE)
232 && (QActive_registry_[p] == me));
233
234 for (enum_t sig = (enum_t)Q_USER_SIG; sig < QActive_maxPubSignal_; ++sig) {
236 QF_CRIT_E_();
237 if (QPSet_hasElement(&QActive_subscrList_[sig], p)) {
238 QPSet_remove(&QActive_subscrList_[sig], p);
239
241 QS_TIME_PRE_(); /* timestamp */
242 QS_SIG_PRE_(sig); /* the signal of this event */
243 QS_OBJ_PRE_(me); /* this active object */
245 }
246 QF_CRIT_X_();
247
248 /* prevent merging critical sections */
250 }
251}
252/*$enddef${QF::QActive::unsubscribeAll} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
Customizable and memory-efficient Design by Contract (DbC) for embedded systems.
#define Q_REQUIRE_ID(id_, expr_)
Definition: qassert.h:240
#define Q_ASSERT_ID(id_, expr_)
Definition: qassert.h:103
#define Q_UNUSED_PAR(par_)
Definition: qep.h:1108
@ Q_USER_SIG
Definition: qep.h:331
int enum_t
Definition: qep.h:79
uint16_t QSignal
Definition: qep.h:140
#define QACTIVE_POST(me_, e_, sender_)
Definition: qf.h:2036
#define QF_CRIT_EXIT_NOP()
Definition: qf.h:2201
Internal (package scope) QF/C interface.
#define QF_CRIT_STAT_
Definition: qf_pkg.h:113
#define QF_CRIT_X_()
Definition: qf_pkg.h:143
#define QF_CRIT_E_()
Definition: qf_pkg.h:128
QF/C sample port with all configurable options.
#define QF_MAX_ACTIVE
Definition: qf_port.h:71
#define QF_SCHED_LOCK_(ceil_)
Definition: qk.h:229
#define QF_SCHED_UNLOCK_()
Definition: qk.h:243
#define QF_SCHED_STAT_
Definition: qk.h:221
#define QS_TIME_PRE_()
Definition: qs.h:1313
@ QS_QF_PUBLISH
Definition: qs.h:199
@ QS_QF_ACTIVE_UNSUBSCRIBE
Definition: qs.h:178
@ QS_QF_ACTIVE_SUBSCRIBE
Definition: qs.h:177
Internal (package scope) QS/C interface.
#define QS_BEGIN_NOCRIT_PRE_(rec_, qs_id_)
Definition: qs_pkg.h:136
#define QS_OBJ_PRE_(obj_)
Definition: qs_pkg.h:209
#define QS_END_NOCRIT_PRE_()
Definition: qs_pkg.h:149
#define QS_2U8_PRE_(data1_, data2_)
Definition: qs_pkg.h:163
#define QS_SIG_PRE_(sig_)
Definition: qs_pkg.h:195
QS/C sample port with all configurable options.
Active object class (based on the QHsm implementation strategy)
Definition: qf.h:426
uint8_t prio
Definition: qf.h:480
Event class.
Definition: qep.h:171
QSignal sig
Definition: qep.h:180
uint8_t poolId_
Definition: qep.h:190
uint8_t volatile refCtr_
Definition: qep.h:198
Priority Set of up to QF_MAX_ACTIVE elements.
Definition: qf.h:234