QP/C  7.3.4
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(402, 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(502, QEvt_verify_(e));
287
288 uint_fast8_t const poolNum = QEvt_getPoolNum_(e);
289
290 Q_REQUIRE_INCRIT(500, (poolNum != 0U)
291 && (evtRef == (void *)0));
292
293 QEvt_refCtr_inc_(e); // increments the ref counter
294
295 QS_MEM_SYS();
296 QS_BEGIN_PRE_(QS_QF_NEW_REF,
297 (uint_fast8_t)QS_EP_ID + poolNum)
298 QS_TIME_PRE_(); // timestamp
299 QS_SIG_PRE_(e->sig); // the signal of the event
300 QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr
301 QS_END_PRE_()
302 QS_MEM_APP();
303
304 QF_CRIT_EXIT();
305
306 return e;
307}
308
309//${QF::QF-dyn::deleteRef_} ..................................................
310//! @static @private @memberof QF
311void QF_deleteRef_(void const * const evtRef) {
312 QEvt const * const e = evtRef;
313
316 Q_REQUIRE_INCRIT(602, QEvt_verify_(e));
317
318 #ifdef Q_SPY
319 uint_fast8_t const poolNum = QEvt_getPoolNum_(e);
320 #endif
321
322 QS_MEM_SYS();
323 QS_BEGIN_PRE_(QS_QF_DELETE_REF,
324 (uint_fast8_t)QS_EP_ID + poolNum)
325 QS_TIME_PRE_(); // timestamp
326 QS_SIG_PRE_(e->sig); // the signal of the event
327 QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr
328 QS_END_PRE_()
329 QS_MEM_APP();
330
331 QF_CRIT_EXIT();
332
333 #if (QF_MAX_EPOOL > 0U)
334 QF_gc(e); // recycle the referenced event
335 #endif
336}
337//$enddef${QF::QF-dyn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
338
339#endif // (QF_MAX_EPOOL > 0U) mutable events configured
QF_Attr QF_priv_
Definition qf_act.c:70
#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:1284
uint16_t QSignal
Definition qp.h:131
#define Q_UNUSED_PAR(par_)
Definition qp.h:532
#define QF_NO_MARGIN
Definition qp.h:1154
#define QEVT_MARKER
Definition qp.h:140
#define QF_MEM_SYS()
Definition qp.h:1279
int enum_t
Definition qp.h:109
#define QF_MAX_EPOOL
Definition qp_config.h:121
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:147
uint8_t evtTag_
Definition qp.h:159
uint8_t volatile refCtr_
Definition qp.h:156
QSignal sig
Definition qp.h:151
QF_EPOOL_TYPE_ ePool_[QF_MAX_EPOOL]
Definition qp_pkg.h:55
uint_fast8_t maxPool_
Definition qp_pkg.h:60