QP/C  7.4.0-rc.2
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 6.1.1 <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 : 2024-12-31
14// License scope:
15//
16// Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
17//
18// Q u a n t u m L e a P s
19// ------------------------
20// Modern Embedded Software
21//
22// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
23//
24// This software is dual-licensed under the terms of the open source GNU
25// General Public License version 3 (or any later version), or alternatively,
26// under the terms of one of the closed source Quantum Leaps commercial
27// licenses.
28//
29// The terms of the open source GNU General Public License version 3
30// can be found at: <www.gnu.org/licenses/gpl-3.0>
31//
32// The terms of the closed source Quantum Leaps commercial licenses
33// can be found at: <www.state-machine.com/licensing>
34//
35// Redistributions in source code must retain this top-level comment block.
36// Plagiarizing this software to sidestep the license obligations is illegal.
37//
38// Contact information:
39// <www.state-machine.com/licensing>
40// <info@state-machine.com>
41//
42//$endhead${src::qf::qf_dyn.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43#define QP_IMPL // this is QP implementation
44#include "qp_port.h" // QP port
45#include "qp_pkg.h" // QP package-scope interface
46#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
47#ifdef Q_SPY // QS software tracing enabled?
48 #include "qs_port.h" // QS port
49 #include "qs_pkg.h" // QS facilities for pre-defined trace records
50#else
51 #include "qs_dummy.h" // disable the QS software tracing
52#endif // Q_SPY
53
54#if (QF_MAX_EPOOL > 0U) // mutable events configured?
55
56Q_DEFINE_THIS_MODULE("qf_dyn")
57
58//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
59// Check for the minimum required QP version
60#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
61#error qpc version 7.3.0 or higher required
62#endif
63//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
64
65//$define${QF::QF-dyn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
66
67//${QF::QF-dyn::poolInit} ....................................................
68//! @static @public @memberof QF
69void QF_poolInit(
70 void * const poolSto,
71 uint_fast32_t const poolSize,
72 uint_fast16_t const evtSize)
73{
74 uint_fast8_t const poolNum = QF_priv_.maxPool_;
75
76 // see precondition{qf_dyn,200} and precondition{qf_dyn,201}
79 QF_MEM_SYS();
80
81 Q_REQUIRE_INCRIT(200, poolNum < QF_MAX_EPOOL);
82 if (poolNum > 0U) {
84 QF_EPOOL_EVENT_SIZE_(QF_priv_.ePool_[poolNum - 1U]) < evtSize);
85 }
86 QF_priv_.maxPool_ = poolNum + 1U; // one more pool
87
88 QF_MEM_APP();
90
91 // perform the port-dependent initialization of the event-pool
92 QF_EPOOL_INIT_(QF_priv_.ePool_[poolNum], poolSto, poolSize, evtSize);
93
94 #ifdef Q_SPY
95 // generate the object-dictionary entry for the initialized pool
96 {
97 uint8_t obj_name[9] = "EvtPool?";
98 obj_name[7] = (uint8_t)((uint8_t)'0' + poolNum + 1U);
99 QS_obj_dict_pre_(&QF_priv_.ePool_[poolNum], (char const *)obj_name);
100 }
101 #endif // Q_SPY
102}
103
104//${QF::QF-dyn::poolGetMaxBlockSize} .........................................
105//! @static @public @memberof QF
106uint_fast16_t QF_poolGetMaxBlockSize(void) {
109 QF_MEM_SYS();
110 uint_fast16_t const max_size =
112 QF_MEM_APP();
113 QF_CRIT_EXIT();
114
115 return max_size;
116}
117
118//${QF::QF-dyn::getPoolMin} ..................................................
119//! @static @public @memberof QF
120uint_fast16_t QF_getPoolMin(uint_fast8_t const poolNum) {
123 QF_MEM_SYS();
124
125 Q_REQUIRE_INCRIT(400, (poolNum <= QF_MAX_EPOOL)
126 && (0U < poolNum) && (poolNum <= QF_priv_.maxPool_));
127
128 uint_fast16_t const min = (uint_fast16_t)QF_priv_.ePool_[poolNum - 1U].nMin;
129
130 QF_MEM_APP();
131 QF_CRIT_EXIT();
132
133 return min;
134}
135
136//${QF::QF-dyn::newX_} .......................................................
137//! @static @private @memberof QF
138QEvt * QF_newX_(
139 uint_fast16_t const evtSize,
140 uint_fast16_t const margin,
141 enum_t const sig)
142{
145 QF_MEM_SYS();
146
147 // find the pool id that fits the requested event size...
148 uint_fast8_t poolNum = 0U; // zero-based poolNum initially
149 for (; poolNum < QF_priv_.maxPool_; ++poolNum) {
150 if (evtSize <= QF_EPOOL_EVENT_SIZE_(QF_priv_.ePool_[poolNum])) {
151 break;
152 }
153 }
154
155 // precondition:
156 // - cannot run out of registered pools
157 Q_REQUIRE_INCRIT(300, poolNum < QF_priv_.maxPool_);
158
159 ++poolNum; // convert to 1-based poolNum
160
161 QF_MEM_APP();
162 QF_CRIT_EXIT();
163
164 // get event e (port-dependent)...
165 QEvt *e;
166 #ifdef Q_SPY
167 QF_EPOOL_GET_(QF_priv_.ePool_[poolNum - 1U], e,
168 ((margin != QF_NO_MARGIN) ? margin : 0U),
169 (uint_fast8_t)QS_EP_ID + poolNum);
170 #else
171 QF_EPOOL_GET_(QF_priv_.ePool_[poolNum - 1U], e,
172 ((margin != QF_NO_MARGIN) ? margin : 0U), 0U);
173 #endif
174
175 if (e != (QEvt *)0) { // was e allocated correctly?
176 e->sig = (QSignal)sig; // set the signal
177 e->refCtr_ = 0U; // initialize the reference counter to 0
178 e->evtTag_ = (uint8_t)(QEVT_MARKER | poolNum);
179
181 QS_MEM_SYS();
182 QS_BEGIN_PRE_(QS_QF_NEW,
183 (uint_fast8_t)QS_EP_ID + poolNum)
184 QS_TIME_PRE_(); // timestamp
185 QS_EVS_PRE_(evtSize); // the size of the event
186 QS_SIG_PRE_(sig); // the signal of the event
187 QS_END_PRE_()
188 QS_MEM_APP();
189 QS_CRIT_EXIT();
190 }
191 else { // event was not allocated
192
194 // This assertion means that the event allocation failed,
195 // and this failure cannot be tolerated. The most frequent
196 // reason is an event leak in the application.
197 Q_ASSERT_INCRIT(320, margin != QF_NO_MARGIN);
198
199 QS_MEM_SYS();
200 QS_BEGIN_PRE_(QS_QF_NEW_ATTEMPT,
201 (uint_fast8_t)QS_EP_ID + poolNum)
202 QS_TIME_PRE_(); // timestamp
203 QS_EVS_PRE_(evtSize); // the size of the event
204 QS_SIG_PRE_(sig); // the signal of the event
205 QS_END_PRE_()
206 QS_MEM_APP();
207
208 QF_CRIT_EXIT();
209 }
210
211 // the returned event e is guaranteed to be valid (not NULL)
212 // if we can't tolerate failed allocation
213 return e;
214}
215
216//${QF::QF-dyn::gc} ..........................................................
217//! @static @public @memberof QF
218void QF_gc(QEvt const * const e) {
221 Q_REQUIRE_INCRIT(400, QEvt_verify_(e));
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_); // poolNum & 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_); // poolNum & 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, QEvt_verify_(e));
287
288 uint_fast8_t const poolNum = QEvt_getPoolNum_(e);
289 Q_UNUSED_PAR(poolNum); // might be unused
290
291 Q_REQUIRE_INCRIT(501, (poolNum != 0U)
292 && (evtRef == (void *)0));
293
294 QEvt_refCtr_inc_(e); // increments the ref counter
295
296 QS_MEM_SYS();
297 QS_BEGIN_PRE_(QS_QF_NEW_REF,
298 (uint_fast8_t)QS_EP_ID + poolNum)
299 QS_TIME_PRE_(); // timestamp
300 QS_SIG_PRE_(e->sig); // the signal of the event
301 QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr
302 QS_END_PRE_()
303 QS_MEM_APP();
304
305 QF_CRIT_EXIT();
306
307 return e;
308}
309
310//${QF::QF-dyn::deleteRef_} ..................................................
311//! @static @private @memberof QF
312void QF_deleteRef_(void const * const evtRef) {
315
316 QEvt const * const e = (QEvt const *)evtRef;
317 Q_REQUIRE_INCRIT(600, QEvt_verify_(e));
318
319 #ifdef Q_SPY
320 uint_fast8_t const poolNum = QEvt_getPoolNum_(e);
321 #endif
322
323 QS_MEM_SYS();
324 QS_BEGIN_PRE_(QS_QF_DELETE_REF,
325 (uint_fast8_t)QS_EP_ID + poolNum)
326 QS_TIME_PRE_(); // timestamp
327 QS_SIG_PRE_(e->sig); // the signal of the event
328 QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr
329 QS_END_PRE_()
330 QS_MEM_APP();
331
332 QF_CRIT_EXIT();
333
334 #if (QF_MAX_EPOOL > 0U)
335 QF_gc(e); // recycle the referenced event
336 #endif
337}
338//$enddef${QF::QF-dyn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
339
340#endif // (QF_MAX_EPOOL > 0U) mutable events configured
QF_Attr QF_priv_
Definition qf_act.c:71
#define QF_EPOOL_EVENT_SIZE_(p_)
Definition qk.h:204
#define QF_EPOOL_PUT_(p_, e_, qsId_)
Definition qk.h:211
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_)
Definition qk.h:200
#define QF_EPOOL_GET_(p_, e_, m_, qsId_)
Definition qk.h:207
#define QF_MEM_APP()
Definition qp.h:1288
#define Q_UNUSED_PAR(par_)
Definition qp.h:536
#define QF_NO_MARGIN
Definition qp.h:1158
#define QEVT_MARKER
Definition qp.h:138
#define QF_MEM_SYS()
Definition qp.h:1283
int enum_t
Definition qp.h:107
uint16_t QSignal
Definition qp.h:129
#define QF_MAX_EPOOL
Maximum # event pools in the system (0..15)
Definition qp_config.h:122
Internal (package scope) QP/C interface.
Sample QP/C port.
@ QS_QF_DELETE_REF
an event reference is about to be deleted
Definition qs.h:133
#define QS_TIME_PRE_()
Definition qs.h:450
@ QS_QF_GC_ATTEMPT
garbage collection attempt
Definition qs.h:120
@ QS_QF_GC
garbage collection
Definition qs.h:121
#define QS_MEM_APP()
Definition qs.h:588
@ QS_EP_ID
offset for event-pool IDs
Definition qs.h:238
@ QS_QF_NEW_ATTEMPT
an attempt to allocate an event failed
Definition qs.h:110
@ QS_QF_NEW_REF
new event reference was created
Definition qs.h:118
@ QS_QF_NEW
new event was created
Definition qs.h:119
#define QS_CRIT_EXIT()
Definition qs.h:578
#define QS_MEM_SYS()
Definition qs.h:583
#define QS_CRIT_ENTRY()
Definition qs.h:573
QS/C package-scope interface.
Sample QS/C port.
QP Functional Safety (FuSa) Subsystem.
#define QF_CRIT_ENTRY()
Definition qsafe.h:58
#define Q_ASSERT_INCRIT(id_, expr_)
Definition qsafe.h:72
#define QF_CRIT_EXIT()
Definition qsafe.h:62
#define Q_REQUIRE_INCRIT(id_, expr_)
Definition qsafe.h:136
#define QF_CRIT_STAT
Definition qsafe.h:54
Event class.
Definition qp.h:145
QSignal sig
Definition qp.h:149
uint8_t evtTag_
Definition qp.h:157
uint8_t volatile refCtr_
Definition qp.h:154
uint_fast8_t maxPool_
Definition qp_pkg.h:60
QF_EPOOL_TYPE_ ePool_[QF_MAX_EPOOL]
Definition qp_pkg.h:55