QP/C  8.0.0
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qf_dyn.c
Go to the documentation of this file.
1//$file${src::qf::qf_dyn.c} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpc.qm
4// File: ${src::qf::qf_dyn.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_dyn.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
46#if (QF_MAX_EPOOL > 0U) // mutable events configured?
47
48Q_DEFINE_THIS_MODULE("qf_dyn")
49
50//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
51// Check for the minimum required QP version
52#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
53#error qpc version 7.3.0 or higher required
54#endif
55//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
56//$define${QF::QF-dyn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
57
58//${QF::QF-dyn::poolInit} ....................................................
59//! @static @public @memberof QF
60void QF_poolInit(
61 void * const poolSto,
62 uint_fast32_t const poolSize,
63 uint_fast16_t const evtSize)
64{
65 uint_fast8_t const poolNum = QF_priv_.maxPool_;
66
67 // see precondition{qf_dyn,200} and precondition{qf_dyn,201}
70 QF_MEM_SYS();
71
72 Q_REQUIRE_INCRIT(200, poolNum < QF_MAX_EPOOL);
73 if (poolNum > 0U) {
75 QF_EPOOL_EVENT_SIZE_(QF_priv_.ePool_[poolNum - 1U]) < evtSize);
76 }
77 QF_priv_.maxPool_ = poolNum + 1U; // one more pool
78
79 QF_MEM_APP();
81
82 // perform the port-dependent initialization of the event-pool
83 QF_EPOOL_INIT_(QF_priv_.ePool_[poolNum], poolSto, poolSize, evtSize);
84
85 #ifdef Q_SPY
86 // generate the object-dictionary entry for the initialized pool
87 {
88 uint8_t obj_name[9] = "EvtPool?";
89 obj_name[7] = (uint8_t)((uint8_t)'0' + poolNum + 1U);
90 QS_obj_dict_pre_(&QF_priv_.ePool_[poolNum], (char const *)obj_name);
91 }
92 #endif // Q_SPY
93}
94
95//${QF::QF-dyn::poolGetMaxBlockSize} .........................................
96//! @static @public @memberof QF
97uint_fast16_t QF_poolGetMaxBlockSize(void) {
100 QF_MEM_SYS();
101 uint_fast16_t const max_size =
103 QF_MEM_APP();
104 QF_CRIT_EXIT();
105
106 return max_size;
107}
108
109//${QF::QF-dyn::getPoolMin} ..................................................
110//! @static @public @memberof QF
111uint_fast16_t QF_getPoolMin(uint_fast8_t const poolNum) {
114 QF_MEM_SYS();
115
116 Q_REQUIRE_INCRIT(400, (poolNum <= QF_MAX_EPOOL)
117 && (0U < poolNum) && (poolNum <= QF_priv_.maxPool_));
118
119 #ifndef Q_UNSAFE
120 uint_fast16_t const min = (uint_fast16_t)QF_priv_.ePool_[poolNum - 1U].nMin;
121 #else
122 uint_fast16_t const min = 0U;
123 #endif
124
125 QF_MEM_APP();
126 QF_CRIT_EXIT();
127
128 return min;
129}
130
131//${QF::QF-dyn::newX_} .......................................................
132//! @static @private @memberof QF
133QEvt * QF_newX_(
134 uint_fast16_t const evtSize,
135 uint_fast16_t const margin,
136 enum_t const sig)
137{
140 QF_MEM_SYS();
141
142 // find the pool id that fits the requested event size...
143 uint_fast8_t poolNum = 0U; // zero-based poolNum initially
144 for (; poolNum < QF_priv_.maxPool_; ++poolNum) {
145 if (evtSize <= QF_EPOOL_EVENT_SIZE_(QF_priv_.ePool_[poolNum])) {
146 break;
147 }
148 }
149
150 // precondition:
151 // - cannot run out of registered pools
152 Q_REQUIRE_INCRIT(300, poolNum < QF_priv_.maxPool_);
153
154 ++poolNum; // convert to 1-based poolNum
155
156 QF_MEM_APP();
157 QF_CRIT_EXIT();
158
159 // get event e (port-dependent)...
160 QEvt *e;
161 #ifdef Q_SPY
162 QF_EPOOL_GET_(QF_priv_.ePool_[poolNum - 1U], e,
163 ((margin != QF_NO_MARGIN) ? margin : 0U),
164 (uint_fast8_t)QS_EP_ID + poolNum);
165 #else
166 QF_EPOOL_GET_(QF_priv_.ePool_[poolNum - 1U], e,
167 ((margin != QF_NO_MARGIN) ? margin : 0U), 0U);
168 #endif
169
170 if (e != (QEvt *)0) { // was e allocated correctly?
171 e->sig = (QSignal)sig; // set the signal
172 e->refCtr_ = 0U; // initialize the reference counter to 0
173 e->evtTag_ = (uint8_t)((poolNum << 4U) | 0x0FU);
174
176 QS_MEM_SYS();
177 QS_BEGIN_PRE(QS_QF_NEW,
178 (uint_fast8_t)QS_EP_ID + poolNum)
179 QS_TIME_PRE(); // timestamp
180 QS_EVS_PRE(evtSize); // the size of the event
181 QS_SIG_PRE(sig); // the signal of the event
182 QS_END_PRE()
183 QS_MEM_APP();
184 QS_CRIT_EXIT();
185 }
186 else { // event was not allocated
187
189 // This assertion means that the event allocation failed,
190 // and this failure cannot be tolerated. The most frequent
191 // reason is an event leak in the application.
192 Q_ASSERT_INCRIT(320, margin != QF_NO_MARGIN);
193
194 QS_MEM_SYS();
195 QS_BEGIN_PRE(QS_QF_NEW_ATTEMPT,
196 (uint_fast8_t)QS_EP_ID + poolNum)
197 QS_TIME_PRE(); // timestamp
198 QS_EVS_PRE(evtSize); // the size of the event
199 QS_SIG_PRE(sig); // the signal of the event
200 QS_END_PRE()
201 QS_MEM_APP();
202
203 QF_CRIT_EXIT();
204 }
205
206 // the returned event e is guaranteed to be valid (not NULL)
207 // if we can't tolerate failed allocation
208 return e;
209}
210
211//${QF::QF-dyn::gc} ..........................................................
212//! @static @public @memberof QF
213void QF_gc(QEvt const * const e) {
216
217 Q_REQUIRE_INCRIT(400, e != (QEvt *)0);
218
219 #ifndef Q_UNSAFE
220 Q_INVARIANT_INCRIT(401, QEvt_verify_(e));
221 #endif
222
223 uint_fast8_t const poolNum = QEvt_getPoolNum_(e);
224
225 if (poolNum != 0U) { // is it a pool event (mutable)?
226 QF_MEM_SYS();
227
228 if (e->refCtr_ > 1U) { // isn't this the last reference?
229
230 QS_BEGIN_PRE(QS_QF_GC_ATTEMPT,
231 (uint_fast8_t)QS_EP_ID + poolNum)
232 QS_TIME_PRE(); // timestamp
233 QS_SIG_PRE(e->sig); // the signal of the event
234 QS_2U8_PRE(poolNum, e->refCtr_);
235 QS_END_PRE()
236
237 QEvt_refCtr_dec_(e); // decrement the ref counter
238
239 QF_MEM_APP();
240 QF_CRIT_EXIT();
241 }
242 else { // this is the last reference to this event, recycle it
243
244 QS_BEGIN_PRE(QS_QF_GC,
245 (uint_fast8_t)QS_EP_ID + poolNum)
246 QS_TIME_PRE(); // timestamp
247 QS_SIG_PRE(e->sig); // the signal of the event
248 QS_2U8_PRE(poolNum, e->refCtr_);
249 QS_END_PRE()
250
251 // pool number must be in range
252 Q_ASSERT_INCRIT(410, (poolNum <= QF_priv_.maxPool_)
253 && (poolNum <= QF_MAX_EPOOL));
254 QF_MEM_APP();
255 QF_CRIT_EXIT();
256
257 // NOTE: casting 'const' away is legit because it's a pool event
258 #ifdef Q_SPY
259 QF_EPOOL_PUT_(QF_priv_.ePool_[poolNum - 1U],
260 (QEvt *)e,
261 (uint_fast8_t)QS_EP_ID + poolNum);
262 #else
263 QF_EPOOL_PUT_(QF_priv_.ePool_[poolNum - 1U],
264 (QEvt *)e, 0U);
265 #endif
266 }
267 }
268 else {
269 QF_CRIT_EXIT();
270 }
271}
272
273//${QF::QF-dyn::newRef_} .....................................................
274//! @static @private @memberof QF
275QEvt const * QF_newRef_(
276 QEvt const * const e,
277 void const * const evtRef)
278{
279 #ifdef Q_UNSAFE
280 Q_UNUSED_PAR(evtRef);
281 #endif
282
285
286 Q_REQUIRE_INCRIT(500, e != (QEvt *)0);
287 #ifndef Q_UNSAFE
288 Q_INVARIANT_INCRIT(501, QEvt_verify_(e));
289 #endif
290
291 uint_fast8_t const poolNum = QEvt_getPoolNum_(e);
292 Q_UNUSED_PAR(poolNum); // might be unused
293
294 Q_REQUIRE_INCRIT(510, (poolNum != 0U)
295 && (evtRef == (void *)0));
296
297 QEvt_refCtr_inc_(e); // increments the ref counter
298
299 QS_MEM_SYS();
300 QS_BEGIN_PRE(QS_QF_NEW_REF,
301 (uint_fast8_t)QS_EP_ID + poolNum)
302 QS_TIME_PRE(); // timestamp
303 QS_SIG_PRE(e->sig); // the signal of the event
304 QS_2U8_PRE(poolNum, e->refCtr_);
305 QS_END_PRE()
306 QS_MEM_APP();
307
308 QF_CRIT_EXIT();
309
310 return e;
311}
312
313//${QF::QF-dyn::deleteRef_} ..................................................
314//! @static @private @memberof QF
315void QF_deleteRef_(void const * const evtRef) {
318
319 QEvt const * const e = (QEvt const *)evtRef;
320 Q_REQUIRE_INCRIT(600, e != (QEvt *)0);
321 #ifndef Q_UNSAFE
322 Q_INVARIANT_INCRIT(601, QEvt_verify_(e));
323 #endif // ndef Q_UNSAFE
324
325 #ifdef Q_SPY
326 uint_fast8_t const poolNum = QEvt_getPoolNum_(e);
327 QS_MEM_SYS();
328 QS_BEGIN_PRE(QS_QF_DELETE_REF,
329 (uint_fast8_t)QS_EP_ID + poolNum)
330 QS_TIME_PRE(); // timestamp
331 QS_SIG_PRE(e->sig); // the signal of the event
332 QS_2U8_PRE(poolNum, e->refCtr_);
333 QS_END_PRE()
334 QS_MEM_APP();
335 #endif // def Q_SPY
336
337 QF_CRIT_EXIT();
338
339 #if (QF_MAX_EPOOL > 0U)
340 QF_gc(e); // recycle the referenced event
341 #endif
342}
343//$enddef${QF::QF-dyn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
344
345#endif // (QF_MAX_EPOOL > 0U) mutable events configured
QF_Attr QF_priv_
Definition qf_act.c:62
#define QF_EPOOL_EVENT_SIZE_(p_)
Definition qk.h:195
#define QF_EPOOL_PUT_(p_, e_, qsId_)
Definition qk.h:202
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_)
Definition qk.h:191
#define QF_EPOOL_GET_(p_, e_, m_, qsId_)
Definition qk.h:198
#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 QF_NO_MARGIN
Special value of margin that causes asserting failure in case event allocation or event posting fails...
Definition qp.h:1151
#define QF_MEM_SYS()
Definition qp.h:1271
int enum_t
Definition qp.h:99
uint16_t QSignal
The signal of event QEvt.
Definition qp.h:121
#define QF_MAX_EPOOL
Maximum # event pools in the system (0..15)
Definition qp_config.h:133
Internal (package scope) QP/C interface.
Sample QP/C port.
#define QS_SIG_PRE(sig_)
Definition qs_dummy.h:148
#define QS_TIME_PRE()
Definition qs_dummy.h:147
#define QS_MEM_APP()
Definition qs_dummy.h:162
#define QS_2U8_PRE(data1_, data2_)
Definition qs_dummy.h:144
#define QS_EVS_PRE(size_)
Definition qs_dummy.h:149
#define QS_CRIT_EXIT()
Definition qs_dummy.h:159
#define QS_MEM_SYS()
Definition qs_dummy.h:161
#define QS_END_PRE()
Definition qs_dummy.h:142
#define QS_CRIT_ENTRY()
Definition qs_dummy.h:158
#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 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
Event class.
Definition qp.h:131
QSignal sig
Signal of the event (see Event Signal)
Definition qp.h:135
uint8_t evtTag_
Event "tag" contains pool-ID plus the Duplicate Inverted Storage of the QEvt::refCtr_.
Definition qp.h:140
uint8_t volatile refCtr_
Event reference counter.
Definition qp.h:143
uint_fast8_t maxPool_
Definition qp_pkg.h:52
QF_EPOOL_TYPE_ ePool_[QF_MAX_EPOOL]
Definition qp_pkg.h:47