QP/C  7.2.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} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
2/*
3* Model: qpc.qm
4* File: ${src::qf::qf_dyn.c}
5*
6* This code has been generated by QM 5.2.5 <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 : 2023-12-31
14* License scope:
15*
16* Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
17*
18* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
19*
20* This software is dual-licensed under the terms of the open source GNU
21* General Public License version 3 (or any later version), or alternatively,
22* under the terms of one of the closed source Quantum Leaps commercial
23* licenses.
24*
25* The terms of the open source GNU General Public License version 3
26* can be found at: <www.gnu.org/licenses/gpl-3.0>
27*
28* The terms of the closed source Quantum Leaps commercial licenses
29* can be found at: <www.state-machine.com/licensing>
30*
31* Redistributions in source code must retain this top-level comment block.
32* Plagiarizing this software to sidestep the license obligations is illegal.
33*
34* Contact information:
35* <www.state-machine.com/licensing>
36* <info@state-machine.com>
37*/
38/*$endhead${src::qf::qf_dyn.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
39/*! @file
40* @brief QF/C dynamic event management
41*/
42#define QP_IMPL /* this is QP implementation */
43#include "qf_port.h" /* QF port */
44#include "qf_pkg.h" /* QF package-scope interface */
45#include "qassert.h" /* QP embedded systems-friendly assertions */
46#ifdef Q_SPY /* QS software tracing enabled? */
47 #include "qs_port.h" /* QS port */
48 #include "qs_pkg.h" /* QS facilities for pre-defined trace records */
49#else
50 #include "qs_dummy.h" /* disable the QS software tracing */
51#endif /* Q_SPY */
52
53#if (QF_MAX_EPOOL > 0U) /* dynamic events configured? */
54
55Q_DEFINE_THIS_MODULE("qf_dyn")
56
57//============================================================================
58/*$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
59/* Check for the minimum required QP version */
60#if (QP_VERSION < 700U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
61#error qpc version 7.0.0 or higher required
62#endif
63/*$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
64
65/*$define${QF::QF-pkg::maxPool_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
66
67/*${QF::QF-pkg::maxPool_} ..................................................*/
68uint_fast8_t QF_maxPool_;
69/*$enddef${QF::QF-pkg::maxPool_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
70/*$define${QF::QF-pkg::ePool_[QF_MAX_EPOOL]} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
71
72/*${QF::QF-pkg::ePool_[QF_MAX_EPOOL]} ......................................*/
73#if (QF_MAX_EPOOL > 0U)
75#endif /* (QF_MAX_EPOOL > 0U) */
76/*$enddef${QF::QF-pkg::ePool_[QF_MAX_EPOOL]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
77//============================================================================
78/*$define${QEP::QEvt} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
79
80/*${QEP::QEvt} .............................................................*/
81/*$enddef${QEP::QEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
82//============================================================================
83/*$define${QF::QF-dyn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
84
85/*${QF::QF-dyn::poolInit} ..................................................*/
86/*! @static @public @memberof QF */
87void QF_poolInit(
88 void * const poolSto,
89 uint_fast32_t const poolSize,
90 uint_fast16_t const evtSize)
91{
92 /*! @pre cannot exceed the number of available memory pools */
94
95 /*! @pre please initialize event pools in ascending order of evtSize: */
96 Q_REQUIRE_ID(201, (QF_maxPool_ == 0U)
98 < evtSize));
99
100 /* perform the platform-dependent initialization of the pool */
101 QF_EPOOL_INIT_(QF_ePool_[QF_maxPool_], poolSto, poolSize, evtSize);
102 ++QF_maxPool_; /* one more pool */
103
104 #ifdef Q_SPY
105 /* generate the object-dictionary entry for the initialized pool */
106 {
107 uint8_t obj_name[9] = "EvtPool?";
108 obj_name[7] = (uint8_t)(((uint8_t)'0' + QF_maxPool_) & 0x7FU);
109 QS_obj_dict_pre_(&QF_ePool_[QF_maxPool_ - 1U], (char const *)obj_name);
110 }
111 #endif /* Q_SPY*/
112}
113
114/*${QF::QF-dyn::poolGetMaxBlockSize} .......................................*/
115/*! @static @public @memberof QF */
116uint_fast16_t QF_poolGetMaxBlockSize(void) {
118}
119
120/*${QF::QF-dyn::getPoolMin} ................................................*/
121/*! @static @public @memberof QF */
122uint_fast16_t QF_getPoolMin(uint_fast8_t const poolId) {
123 /*! @pre the poolId must be in range */
124 Q_REQUIRE_ID(400, (poolId <= QF_MAX_EPOOL)
125 && (0U < poolId) && (poolId <= QF_maxPool_));
126
128 QF_CRIT_E_();
129 uint_fast16_t const min = (uint_fast16_t)QF_ePool_[poolId - 1U].nMin;
130 QF_CRIT_X_();
131
132 return min;
133}
134
135/*${QF::QF-dyn::newX_} .....................................................*/
136/*! @static @private @memberof QF */
137QEvt * QF_newX_(
138 uint_fast16_t const evtSize,
139 uint_fast16_t const margin,
140 enum_t const sig)
141{
142 uint_fast8_t idx;
143
144 /* find the pool index that fits the requested event size ... */
145 for (idx = 0U; idx < QF_maxPool_; ++idx) {
146 if (evtSize <= QF_EPOOL_EVENT_SIZE_(QF_ePool_[idx])) {
147 break;
148 }
149 }
150 /* cannot run out of registered pools */
151 Q_ASSERT_ID(310, idx < QF_maxPool_);
152
153 /* get e -- platform-dependent */
154 QEvt *e;
155
156 #ifdef Q_SPY
157 QF_EPOOL_GET_(QF_ePool_[idx], e,
158 ((margin != QF_NO_MARGIN) ? margin : 0U),
159 (uint_fast8_t)QS_EP_ID + idx + 1U);
160 #else
161 QF_EPOOL_GET_(QF_ePool_[idx], e,
162 ((margin != QF_NO_MARGIN) ? margin : 0U), 0U);
163 #endif
164
165 /* was e allocated correctly? */
167 if (e != (QEvt *)0) {
168 e->sig = (QSignal)sig; /* set signal for this event */
169 e->poolId_ = (uint8_t)(idx + 1U); /* store the pool ID */
170 e->refCtr_ = 0U; /* set the reference counter to 0 */
171
172 QS_BEGIN_PRE_(QS_QF_NEW, (uint_fast8_t)QS_EP_ID + e->poolId_)
173 QS_TIME_PRE_(); /* timestamp */
174 QS_EVS_PRE_(evtSize); /* the size of the event */
175 QS_SIG_PRE_(sig); /* the signal of the event */
177 }
178 /* event cannot be allocated */
179 else {
180 /* This assertion means that the event allocation failed,
181 * and this failure cannot be tolerated. The most frequent
182 * reason is an event leak in the application.
183 */
184 Q_ASSERT_ID(320, margin != QF_NO_MARGIN);
185
186 QS_BEGIN_PRE_(QS_QF_NEW_ATTEMPT, (uint_fast8_t)QS_EP_ID + idx + 1U)
187 QS_TIME_PRE_(); /* timestamp */
188 QS_EVS_PRE_(evtSize); /* the size of the event */
189 QS_SIG_PRE_(sig); /* the signal of the event */
191 }
192 return e; /* can't be NULL if we can't tolerate failed allocation */
193}
194
195/*${QF::QF-dyn::gc} ........................................................*/
196/*! @static @public @memberof QF */
197void QF_gc(QEvt const * const e) {
198 /* is it a dynamic event? */
199 if (e->poolId_ != 0U) {
201 QF_CRIT_E_();
202
203 /* isn't this the last reference? */
204 if (e->refCtr_ > 1U) {
205
207 (uint_fast8_t)QS_EP_ID + e->poolId_)
208 QS_TIME_PRE_(); /* timestamp */
209 QS_SIG_PRE_(e->sig); /* the signal of the event */
210 QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
212
213 QEvt_refCtr_dec_(e); /* decrement the ref counter */
214
215 QF_CRIT_X_();
216 }
217 /* this is the last reference to this event, recycle it */
218 else {
219 uint_fast8_t const idx = (uint_fast8_t)e->poolId_ - 1U;
220
222 (uint_fast8_t)QS_EP_ID + e->poolId_)
223 QS_TIME_PRE_(); /* timestamp */
224 QS_SIG_PRE_(e->sig); /* the signal of the event */
225 QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
227
228 QF_CRIT_X_();
229
230 /* pool ID must be in range */
231 Q_ASSERT_ID(410, idx < QF_maxPool_);
232
233 /* cast 'const' away, which is OK, because it's a pool event */
234 #ifdef Q_SPY
235 QF_EPOOL_PUT_(QF_ePool_[idx], (QEvt *)e,
236 (uint_fast8_t)QS_EP_ID + e->poolId_);
237 #else
238 QF_EPOOL_PUT_(QF_ePool_[idx], (QEvt *)e, 0U);
239 #endif
240 }
241 }
242}
243
244/*${QF::QF-dyn::newRef_} ...................................................*/
245/*! @static @private @memberof QF */
246QEvt const * QF_newRef_(
247 QEvt const * const e,
248 void const * const evtRef)
249{
250 #ifdef QP_NSSM
251 Q_UNUSED_PAR(evtRef);
252 #endif
253
254 /*! @pre the event must be dynamic and the provided event reference
255 * must not be already in use */
256 Q_REQUIRE_ID(500,
257 (e->poolId_ != 0U)
258 && (evtRef == (void *)0));
259
261 QF_CRIT_E_();
262
263 QEvt_refCtr_inc_(e); /* increments the ref counter */
264
266 (uint_fast8_t)QS_EP_ID + e->poolId_)
267 QS_TIME_PRE_(); /* timestamp */
268 QS_SIG_PRE_(e->sig); /* the signal of the event */
269 QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
271
272 QF_CRIT_X_();
273
274 return e;
275}
276
277/*${QF::QF-dyn::deleteRef_} ................................................*/
278/*! @static @private @memberof QF */
279void QF_deleteRef_(void const * const evtRef) {
281 QEvt const * const e = (QEvt const *)evtRef;
282
284 (uint_fast8_t)QS_EP_ID + e->poolId_)
285 QS_TIME_PRE_(); /* timestamp */
286 QS_SIG_PRE_(e->sig); /* the signal of the event */
287 QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
289
290 #if (QF_MAX_EPOOL > 0U)
291 QF_gc(e);
292 #endif
293}
294/*$enddef${QF::QF-dyn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
295
296#endif /* (QF_MAX_EPOOL > 0U) dynamic events configured */
Customizable and memory-efficient Design by Contract (DbC) for embedded systems.
#define Q_REQUIRE_ID(id_, expr_)
Definition: qassert.h:240
#define Q_ASSERT_ID(id_, expr_)
Definition: qassert.h:103
#define Q_UNUSED_PAR(par_)
Definition: qep.h:1108
int enum_t
Definition: qep.h:79
uint16_t QSignal
Definition: qep.h:140
#define QF_NO_MARGIN
Definition: qf.h:1834
Internal (package scope) QF/C interface.
#define QF_CRIT_STAT_
Definition: qf_pkg.h:113
#define QF_CRIT_X_()
Definition: qf_pkg.h:143
QF_EPOOL_TYPE_ QF_ePool_[QF_MAX_EPOOL]
uint_fast8_t QF_maxPool_
#define QF_CRIT_E_()
Definition: qf_pkg.h:128
QF/C sample port with all configurable options.
#define QF_MAX_EPOOL
Definition: qf_port.h:111
#define QF_EPOOL_PUT_(p_, e_, qs_id_)
Definition: qk.h:310
#define QF_EPOOL_GET_(p_, e_, m_, qs_id_)
Definition: qk.h:306
#define QF_EPOOL_EVENT_SIZE_(p_)
Definition: qk.h:298
#define QF_EPOOL_TYPE_
Definition: qk.h:286
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_)
Definition: qk.h:289
@ QS_QF_DELETE_REF
Definition: qs.h:215
#define QS_CRIT_STAT_
Definition: qs.h:1628
#define QS_TIME_PRE_()
Definition: qs.h:1313
@ QS_QF_GC_ATTEMPT
Definition: qs.h:202
@ QS_QF_GC
Definition: qs.h:203
@ QS_EP_ID
Definition: qs.h:323
@ QS_QF_NEW_ATTEMPT
Definition: qs.h:192
@ QS_QF_NEW_REF
Definition: qs.h:200
@ QS_QF_NEW
Definition: qs.h:201
Internal (package scope) QS/C interface.
#define QS_BEGIN_PRE_(rec_, qs_id_)
Definition: qs_pkg.h:103
#define QS_BEGIN_NOCRIT_PRE_(rec_, qs_id_)
Definition: qs_pkg.h:136
#define QS_END_NOCRIT_PRE_()
Definition: qs_pkg.h:149
#define QS_2U8_PRE_(data1_, data2_)
Definition: qs_pkg.h:163
#define QS_EVS_PRE_(size_)
Definition: qs_pkg.h:262
#define QS_SIG_PRE_(sig_)
Definition: qs_pkg.h:195
#define QS_END_PRE_()
Definition: qs_pkg.h:118
QS/C sample port with all configurable options.
Event class.
Definition: qep.h:171
QSignal sig
Definition: qep.h:180
uint8_t poolId_
Definition: qep.h:190
uint8_t volatile refCtr_
Definition: qep.h:198