QP/C  7.0.0
Real-Time Embedded Framework
qf_ps.c
Go to the documentation of this file.
1/*============================================================================
2* QP/C Real-Time Embedded Framework (RTEF)
3* Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
4*
5* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
6*
7* This software is dual-licensed under the terms of the open source GNU
8* General Public License version 3 (or any later version), or alternatively,
9* under the terms of one of the closed source Quantum Leaps commercial
10* licenses.
11*
12* The terms of the open source GNU General Public License version 3
13* can be found at: <www.gnu.org/licenses/gpl-3.0>
14*
15* The terms of the closed source Quantum Leaps commercial licenses
16* can be found at: <www.state-machine.com/licensing>
17*
18* Redistributions in source code must retain this top-level comment block.
19* Plagiarizing this software to sidestep the license obligations is illegal.
20*
21* Contact information:
22* <www.state-machine.com>
23* <info@state-machine.com>
24============================================================================*/
32#define QP_IMPL /* this is QP implementation */
33#include "qf_port.h" /* QF port */
34#include "qf_pkg.h" /* QF package-scope interface */
35#include "qassert.h" /* QP embedded systems-friendly assertions */
36#ifdef Q_SPY /* QS software tracing enabled? */
37 #include "qs_port.h" /* QS port */
38 #include "qs_pkg.h" /* QS facilities for pre-defined trace records */
39#else
40 #include "qs_dummy.h" /* disable the QS software tracing */
41#endif /* Q_SPY */
42
44
45
46/*==========================================================================*/
47/* Package-scope objects */
50
53
54/*==========================================================================*/
84void QF_psInit(QSubscrList * const subscrSto, enum_t const maxSignal) {
85 QF_subscrList_ = subscrSto;
86 QF_maxPubSignal_ = maxSignal;
87
88 /* zero the subscriber list, so that the framework can start correctly
89 * even if the startup code fails to clear the uninitialized data
90 * (as is required by the C Standard).
91 */
92 QF_bzero(subscrSto, (uint_fast16_t)maxSignal * sizeof(QSubscrList));
93}
94
95/*==========================================================================*/
116#ifndef Q_SPY
117void QF_publish_(QEvt const * const e)
118#else
119void QF_publish_(QEvt const * const e,
120 void const * const sender, uint_fast8_t const qs_id)
121#endif
122{
125
127 QF_CRIT_E_();
128
130 QS_TIME_PRE_(); /* the timestamp */
131 QS_OBJ_PRE_(sender); /* the sender object */
132 QS_SIG_PRE_(e->sig); /* the signal of the event */
133 QS_2U8_PRE_(e->poolId_, e->refCtr_);/* pool Id & ref Count */
135
136 /* is it a dynamic event? */
137 if (e->poolId_ != 0U) {
138 /* NOTE: The reference counter of a dynamic event is incremented to
139 * prevent premature recycling of the event while the multicasting
140 * is still in progress. At the end of the function, the garbage
141 * collector step (QF_gc()) decrements the reference counter and
142 * recycles the event if the counter drops to zero. This covers the
143 * case when the event was published without any subscribers.
144 */
146 }
147
148 /* make a local, modifiable copy of the subscriber list */
149 QPSet subscrList = QF_PTR_AT_(QF_subscrList_, e->sig);
150 QF_CRIT_X_();
151
152 if (QPSet_notEmpty(&subscrList)) { /* any subscribers? */
153 /* the highest-prio subscriber */;
154 uint_fast8_t p = QPSet_findMax(&subscrList);
156
157 QF_SCHED_LOCK_(p); /* lock the scheduler up to prio 'p' */
158 do { /* loop over all subscribers */
159 /* the prio of the AO must be registered with the framework */
160 Q_ASSERT_ID(210, QF_active_[p] != (QActive *)0);
161
162 /* QACTIVE_POST() asserts internally if the queue overflows */
163 QACTIVE_POST(QF_active_[p], e, sender);
164
165 QPSet_remove(&subscrList, p); /* remove the handled subscriber */
166 if (QPSet_notEmpty(&subscrList)) { /* still more subscribers? */
167 /* highest-prio subscriber */
168 p = QPSet_findMax(&subscrList);
169 }
170 else {
171 p = 0U; /* no more subscribers */
172 }
173 } while (p != 0U);
174 QF_SCHED_UNLOCK_(); /* unlock the scheduler */
175 }
176
177 /* The following garbage collection step decrements the reference counter
178 * and recycles the event if the counter drops to zero. This covers both
179 * cases when the event was published with or without any subscribers.
180 */
181 QF_gc(e);
182}
183
184/*==========================================================================*/
204void QActive_subscribe(QActive const * const me, enum_t const sig) {
205 uint_fast8_t const p = (uint_fast8_t)me->prio;
206
207 Q_REQUIRE_ID(300, ((enum_t)Q_USER_SIG <= sig)
208 && (sig < QF_maxPubSignal_)
209 && (0U < p) && (p <= QF_MAX_ACTIVE)
210 && (QF_active_[p] == me));
211
213 QF_CRIT_E_();
214
216 QS_TIME_PRE_(); /* timestamp */
217 QS_SIG_PRE_(sig); /* the signal of this event */
218 QS_OBJ_PRE_(me); /* this active object */
220
221 /* set the priority bit */
223
224 QF_CRIT_X_();
225}
226
227/*==========================================================================*/
253void QActive_unsubscribe(QActive const * const me, enum_t const sig) {
254 uint_fast8_t const p = (uint_fast8_t)me->prio;
255
259 Q_REQUIRE_ID(400, ((enum_t)Q_USER_SIG <= sig)
260 && (sig < QF_maxPubSignal_)
261 && (0U < p) && (p <= QF_MAX_ACTIVE)
262 && (QF_active_[p] == me));
263
265 QF_CRIT_E_();
266
268 QS_TIME_PRE_(); /* timestamp */
269 QS_SIG_PRE_(sig); /* the signal of this event */
270 QS_OBJ_PRE_(me); /* this active object */
272
273 /* clear priority bit */
275
276 QF_CRIT_X_();
277}
278
279/*==========================================================================*/
303void QActive_unsubscribeAll(QActive const * const me) {
304 uint_fast8_t const p = (uint_fast8_t)me->prio;
305
306 Q_REQUIRE_ID(500, (0U < p) && (p <= QF_MAX_ACTIVE)
307 && (QF_active_[p] == me));
308
309 for (enum_t sig = (enum_t)Q_USER_SIG; sig < QF_maxPubSignal_; ++sig) {
311 QF_CRIT_E_();
314
316 QS_TIME_PRE_(); /* timestamp */
317 QS_SIG_PRE_(sig); /* the signal of this event */
318 QS_OBJ_PRE_(me); /* this active object */
320 }
321 QF_CRIT_X_();
322
323 /* prevent merging critical sections */
325 }
326}
Customizable and memory-efficient assertions for embedded systems.
#define Q_DEFINE_THIS_MODULE(name_)
Definition: qassert.h:102
#define Q_ASSERT_ID(id_, test_)
Definition: qassert.h:135
#define Q_REQUIRE_ID(id_, test_)
Definition: qassert.h:252
@ Q_USER_SIG
Definition: qep.h:691
uint16_t QSignal
Definition: qep.h:97
signed int enum_t
Definition: qep.h:60
#define QACTIVE_POST(me_, e_, sender_)
Definition: qf.h:238
#define QF_CRIT_EXIT_NOP()
Definition: qf.h:871
Internal (package scope) QF/C interface.
#define QF_CRIT_STAT_
Definition: qf_pkg.h:54
#define QF_PTR_AT_(base_, i_)
Definition: qf_pkg.h:183
#define QF_CRIT_X_()
Definition: qf_pkg.h:78
#define QF_EVT_REF_CTR_INC_(e_)
Definition: qf_pkg.h:177
#define QF_CRIT_E_()
Definition: qf_pkg.h:66
static bool QPSet_notEmpty(QPSet *const me)
Definition: qpset.h:80
static uint_fast8_t QPSet_findMax(QPSet *const me)
Definition: qpset.h:102
static void QPSet_insert(QPSet *const me, uint_fast8_t const n)
Definition: qpset.h:90
static void QPSet_remove(QPSet *const me, uint_fast8_t const n)
Definition: qpset.h:95
static bool QPSet_hasElement(QPSet *const me, uint_fast8_t const n)
Definition: qpset.h:85
Definition: qpset.h:65
#define QS_TIME_PRE_()
Definition: qs.h:220
@ QS_QF_PUBLISH
Definition: qs.h:93
@ QS_QF_ACTIVE_UNSUBSCRIBE
Definition: qs.h:72
@ QS_QF_ACTIVE_SUBSCRIBE
Definition: qs.h:71
Internal (package scope) QS/C interface.
#define QS_BEGIN_NOCRIT_PRE_(rec_, qs_id_)
Definition: qs_pkg.h:138
#define QS_OBJ_PRE_(obj_)
Definition: qs_pkg.h:179
#define QS_END_NOCRIT_PRE_()
Definition: qs_pkg.h:148
#define QS_2U8_PRE_(data1_, data2_)
Definition: qs_pkg.h:154
#define QS_SIG_PRE_(sig_)
Definition: qs_pkg.h:172
#define QF_MAX_ACTIVE
#define QF_SCHED_UNLOCK_(dummy)
Definition: qv.h:76
#define QF_SCHED_LOCK_(dummy)
Definition: qv.h:75
#define QF_SCHED_STAT_
Definition: qv.h:74
Definition: qf.h:107
void QActive_unsubscribe(QActive const *const me, enum_t const sig)
Definition: qf_ps.c:253
uint8_t prio
Definition: qf.h:152
void QActive_subscribe(QActive const *const me, enum_t const sig)
Definition: qf_ps.c:204
void QActive_unsubscribeAll(QActive const *const me)
Definition: qf_ps.c:303
Definition: qep.h:119
QSignal sig
Definition: qep.h:123
uint8_t poolId_
Definition: qep.h:128
uint8_t volatile refCtr_
Definition: qep.h:133
void QF_bzero(void *const start, uint_fast16_t len)
Definition: qf_act.c:129
void QF_psInit(QSubscrList *const subscrSto, enum_t const maxSignal)
Definition: qf_ps.c:84
enum_t QF_maxPubSignal_
Definition: qf_ps.c:52
QActive * QF_active_[QF_MAX_ACTIVE+1U]
Definition: qf_act.c:48
void QF_publish_(QEvt const *const e, void const *const sender, uint_fast8_t const qs_id)
Definition: qf_ps.c:119
void QF_gc(QEvt const *const e)
Definition: qf_dyn.c:241
QSubscrList * QF_subscrList_
Definition: qf_ps.c:49