QP/C  8.0.2
Real-Time Event Framework
Loading...
Searching...
No Matches
qf_ps.c
Go to the documentation of this file.
1//============================================================================
2// QP/C Real-Time Event Framework (RTEF)
3//
4// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
5//
6// Q u a n t u m L e a P s
7// ------------------------
8// Modern Embedded Software
9//
10// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
11//
12// This software is dual-licensed under the terms of the open-source GNU
13// General Public License (GPL) or under the terms of one of the closed-
14// source Quantum Leaps commercial licenses.
15//
16// Redistributions in source code must retain this top-level comment block.
17// Plagiarizing this software to sidestep the license obligations is illegal.
18//
19// NOTE:
20// The GPL does NOT permit the incorporation of this code into proprietary
21// programs. Please contact Quantum Leaps for commercial licensing options,
22// which expressly supersede the GPL and are designed explicitly for
23// closed-source distribution.
24//
25// Quantum Leaps contact information:
26// <www.state-machine.com/licensing>
27// <info@state-machine.com>
28//============================================================================
29#define QP_IMPL // this is QP implementation
30#include "qp_port.h" // QP port
31#include "qp_pkg.h" // QP package-scope interface
32#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
33#ifdef Q_SPY // QS software tracing enabled?
34 #include "qs_port.h" // QS port
35 #include "qs_pkg.h" // QS facilities for pre-defined trace records
36#else
37 #include "qs_dummy.h" // disable the QS software tracing
38#endif // Q_SPY
39
40Q_DEFINE_THIS_MODULE("qf_ps")
41
42QSubscrList * QActive_subscrList_;
43enum_t QActive_maxPubSignal_;
44
45//............................................................................
46//! @static @public @memberof QActive
47void QActive_psInit(
48 QSubscrList * const subscrSto,
49 enum_t const maxSignal)
50{
51 QActive_subscrList_ = subscrSto;
52 QActive_maxPubSignal_ = maxSignal;
53
54 // initialize the subscriber list
55 for (enum_t sig = 0; sig < maxSignal; ++sig) {
56 QPSet_setEmpty(&subscrSto[sig].set);
57 }
58}
59
60//............................................................................
61//! @static @private @memberof QActive
63 QEvt const * const e,
64 void const * const sender,
65 uint_fast8_t const qsId)
66{
67#ifndef Q_SPY
68 Q_UNUSED_PAR(sender);
69 Q_UNUSED_PAR(qsId);
70#endif
71
72 QSignal const sig = e->sig;
73
76
78
79 QS_BEGIN_PRE(QS_QF_PUBLISH, qsId)
80 QS_TIME_PRE(); // the timestamp
81 QS_OBJ_PRE(sender); // the sender object
82 QS_SIG_PRE(sig); // the signal of the event
85
86 // is it a mutable event?
87 if (e->poolNum_ != 0U) {
88 // NOTE: The reference counter of a mutable event is incremented to
89 // prevent premature recycling of the event while the multicasting
90 // is still in progress. At the end of the function, the garbage
91 // collector step (QF_gc()) decrements the reference counter and
92 // recycles the event if the counter drops to zero. This covers the
93 // case when the event was published without any subscribers.
94 Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE));
95 QEvt_refCtr_inc_(e);
96 }
97
98 // make a local, modifiable copy of the subscriber set
99 QPSet subscrSet = QActive_subscrList_[sig].set;
100
101 QF_CRIT_EXIT();
102
103 if (QPSet_notEmpty(&subscrSet)) { // any subscribers?
104 // highest-prio subscriber
105 uint_fast8_t p = QPSet_findMax(&subscrSet);
106
108
110 // the AO must be registered with the framework
111 Q_ASSERT_INCRIT(210, a != (QActive *)0);
112
113 QF_CRIT_EXIT();
114
116 QF_SCHED_LOCK_(p); // lock the scheduler up to AO's prio
117 do { // loop over all subscribers
118 // QACTIVE_POST() asserts internally if the queue overflows
119 QACTIVE_POST(a, e, sender);
120
121 QPSet_remove(&subscrSet, p); // remove the handled subscriber
122 if (QPSet_notEmpty(&subscrSet)) { // still more subscribers?
123 p = QPSet_findMax(&subscrSet); // highest-prio subscriber
124
126
127 a = QActive_registry_[p];
128 // the AO must be registered with the framework
129 Q_ASSERT_INCRIT(220, a != (QActive *)0);
130
131 QF_CRIT_EXIT();
132 }
133 else {
134 p = 0U; // no more subscribers
135 }
136 } while (p != 0U);
137
139 Q_ASSERT_INCRIT(290, p == 0U); // all subscribers processed
140 QF_CRIT_EXIT();
141
142 QF_SCHED_UNLOCK_(); // unlock the scheduler
143 }
144
145#if (QF_MAX_EPOOL > 0U)
146 // The following garbage collection step decrements the reference counter
147 // and recycles the event if the counter drops to zero. This covers both
148 // cases when the event was published with or without any subscribers.
149 QF_gc(e); // recycle the event to avoid a leak
150#endif
151}
152
153//............................................................................
154//! @protected @memberof QActive
155void QActive_subscribe(QActive const * const me,
156 enum_t const sig)
157{
158 uint_fast8_t const p = (uint_fast8_t)me->prio;
159
162
163 Q_REQUIRE_INCRIT(300, (Q_USER_SIG <= sig)
164 && (sig < QActive_maxPubSignal_)
165 && (0U < p) && (p <= QF_MAX_ACTIVE)
166 && (QActive_registry_[p] == me));
167
168 QS_BEGIN_PRE(QS_QF_ACTIVE_SUBSCRIBE, p)
169 QS_TIME_PRE(); // timestamp
170 QS_SIG_PRE(sig); // the signal of this event
171 QS_OBJ_PRE(me); // this active object
172 QS_END_PRE()
173
174 // insert the prio. into the subscriber set
175 QPSet_insert(&QActive_subscrList_[sig].set, p);
176
177 QF_CRIT_EXIT();
178}
179
180//............................................................................
181//! @protected @memberof QActive
182void QActive_unsubscribe(QActive const * const me,
183 enum_t const sig)
184{
185 uint_fast8_t const p = (uint_fast8_t)me->prio;
186
189
190 Q_REQUIRE_INCRIT(400, (Q_USER_SIG <= sig)
191 && (sig < QActive_maxPubSignal_)
192 && (0U < p) && (p <= QF_MAX_ACTIVE)
193 && (QActive_registry_[p] == me));
194
195 QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, p)
196 QS_TIME_PRE(); // timestamp
197 QS_SIG_PRE(sig); // the signal of this event
198 QS_OBJ_PRE(me); // this active object
199 QS_END_PRE()
200
201 // remove the prio. from the subscriber set
202 QPSet_remove(&QActive_subscrList_[sig].set, p);
203
204 QF_CRIT_EXIT();
205}
206
207//............................................................................
208//! @protected @memberof QActive
209void QActive_unsubscribeAll(QActive const * const me) {
212
213 uint_fast8_t const p = (uint_fast8_t)me->prio;
214
215 Q_REQUIRE_INCRIT(500, (0U < p) && (p <= QF_MAX_ACTIVE)
216 && (QActive_registry_[p] == me));
217 enum_t const maxPubSig = QActive_maxPubSignal_;
218
219 QF_CRIT_EXIT();
220
221 for (enum_t sig = Q_USER_SIG; sig < maxPubSig; ++sig) {
223
224 if (QPSet_hasElement(&QActive_subscrList_[sig].set, p)) {
225 QPSet_remove(&QActive_subscrList_[sig].set, p);
226
227 QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, p)
228 QS_TIME_PRE(); // timestamp
229 QS_SIG_PRE(sig); // the signal of this event
230 QS_OBJ_PRE(me); // this active object
231 QS_END_PRE()
232 }
233 QF_CRIT_EXIT();
234
235 QF_CRIT_EXIT_NOP(); // prevent merging critical sections
236 }
237}
#define QF_SCHED_LOCK_(ceil_)
Definition qk.h:82
#define QF_SCHED_UNLOCK_()
Definition qk.h:90
#define QF_SCHED_STAT_
Definition qk.h:81
#define Q_UNUSED_PAR(par_)
Helper macro to clearly mark unused parameters of functions.
Definition qp.h:96
#define Q_USER_SIG
offset for the user signals (QP Application))
Definition qp.h:214
#define QACTIVE_POST(me_, e_, sender_)
Invoke the direct event posting facility QActive_post_().
Definition qp.h:808
int enum_t
Definition qp.h:92
#define QF_CRIT_EXIT_NOP()
No-operation for exiting a critical section.
Definition qp.h:830
uint16_t QSignal
The signal of event QEvt.
Definition qp.h:107
#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:149
#define QS_SIG_PRE(sig_)
Definition qs_dummy.h:147
#define QS_TIME_PRE()
Definition qs_dummy.h:146
#define QS_2U8_PRE(data1_, data2_)
Definition qs_dummy.h:143
#define QS_END_PRE()
Definition qs_dummy.h:141
#define QS_BEGIN_PRE(rec_, qsId_)
Definition qs_dummy.h:140
Sample QS/C port.
QP Functional Safety (FuSa) Subsystem.
#define QF_CRIT_ENTRY()
Definition qsafe.h:39
#define Q_ASSERT_INCRIT(id_, expr_)
General-purpose assertion with user-specified ID number (in critical section)
Definition qsafe.h:49
#define QF_CRIT_EXIT()
Definition qsafe.h:43
#define Q_REQUIRE_INCRIT(id_, expr_)
Assertion for checking a precondition (in critical section)
Definition qsafe.h:86
#define QF_CRIT_STAT
Definition qsafe.h:35
Active object class (based on the QHsm implementation strategy)
Definition qp.h:506
QSubscrList * QActive_subscrList_
Static (one per-class) pointer to all subscriber AOs for a given event signal.
Definition qp.h:528
void QActive_unsubscribe(QActive const *const me, enum_t const sig)
Unsubscribes from the delivery of signal sig to the active object.
Definition qf_ps.c:182
enum_t QActive_maxPubSignal_
Static (one per-class) maximum published signal (the size of the subscrList_ array)
Definition qp.h:531
void QActive_publish_(QEvt const *const e, void const *const sender, uint_fast8_t const qsId)
Publish event to all subscribers of a given signal e->sig
Definition qf_ps.c:62
QActive * QActive_registry_[QF_MAX_ACTIVE+1U]
Static (one per-class) array of registered active objects.
Definition qp.h:525
uint8_t prio
QF-priority [1..QF_MAX_ACTIVE] of this AO.
Definition qp.h:508
void QActive_subscribe(QActive const *const me, enum_t const sig)
Subscribes for delivery of signal sig to the active object.
Definition qf_ps.c:155
void QActive_unsubscribeAll(QActive const *const me)
Unsubscribes from the delivery of all signals to the active object.
Definition qf_ps.c:209
Event class.
Definition qp.h:114
QSignal sig
Signal of the event (see Event Signal)
Definition qp.h:115
uint8_t volatile refCtr_
Event reference counter.
Definition qp.h:117
uint8_t poolNum_
Event pool number of this event.
Definition qp.h:116
Set of Active Objects of up to QF_MAX_ACTIVE elements.
Definition qp.h:408
Subscriber List (for publish-subscribe)
Definition qp.h:497