QP/C  7.0.0
Real-Time Embedded Framework
qf_dyn.c
Go to the documentation of this file.
1/*============================================================================
2* QP/C Real-Time Embedded Framework (RTEF)
3* Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
4*
5* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
6*
7* This software is dual-licensed under the terms of the open source GNU
8* General Public License version 3 (or any later version), or alternatively,
9* under the terms of one of the closed source Quantum Leaps commercial
10* licenses.
11*
12* The terms of the open source GNU General Public License version 3
13* can be found at: <www.gnu.org/licenses/gpl-3.0>
14*
15* The terms of the closed source Quantum Leaps commercial licenses
16* can be found at: <www.state-machine.com/licensing>
17*
18* Redistributions in source code must retain this top-level comment block.
19* Plagiarizing this software to sidestep the license obligations is illegal.
20*
21* Contact information:
22* <www.state-machine.com>
23* <info@state-machine.com>
24============================================================================*/
32#define QP_IMPL /* this is QP implementation */
33#include "qf_port.h" /* QF port */
34#include "qf_pkg.h" /* QF package-scope interface */
35#include "qassert.h" /* QP embedded systems-friendly assertions */
36#ifdef Q_SPY /* QS software tracing enabled? */
37 #include "qs_port.h" /* QS port */
38 #include "qs_pkg.h" /* QS facilities for pre-defined trace records */
39#else
40 #include "qs_dummy.h" /* disable the QS software tracing */
41#endif /* Q_SPY */
42
44
45
46/* Package-scope objects ****************************************************/
47QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL]; /* allocate the event pools */
48uint_fast8_t QF_maxPool_; /* number of initialized event pools */
49
50/*==========================================================================*/
51#ifdef Q_EVT_CTOR /* Provide the constructor for the ::QEvt class? */
52
62QEvt *QEvt_ctor(QEvt * const me, enum_t const sig) {
64 Q_REQUIRE_ID(100, me != (QEvt *)0);
65 me->sig = (QSignal)sig;
66 return me;
67}
68
69#endif /* Q_EVT_CTOR */
70
71
72/*==========================================================================*/
107void QF_poolInit(void * const poolSto, uint_fast32_t const poolSize,
108 uint_fast16_t const evtSize)
109{
111 Q_REQUIRE_ID(200, QF_maxPool_ < QF_MAX_EPOOL);
112
114 Q_REQUIRE_ID(201, (QF_maxPool_ == 0U)
116 < evtSize));
117
118 /* perform the platform-dependent initialization of the pool */
119 QF_EPOOL_INIT_(QF_pool_[QF_maxPool_], poolSto, poolSize, evtSize);
120 ++QF_maxPool_; /* one more pool */
121
122#ifdef Q_SPY
123 /* generate the object-dictionary entry for the initialized pool */
124 {
125 uint8_t obj_name[9] = "EvtPool?";
126 obj_name[7] = (uint8_t)(((uint8_t)'0' + QF_maxPool_) & 0x7FU);
127 QS_obj_dict_pre_(&QF_pool_[QF_maxPool_ - 1U], (char const *)obj_name);
128 }
129#endif /* Q_SPY*/
130}
131
132/*==========================================================================*/
160QEvt *QF_newX_(uint_fast16_t const evtSize,
161 uint_fast16_t const margin, enum_t const sig)
162{
163 uint_fast8_t idx;
164
165 /* find the pool index that fits the requested event size ... */
166 for (idx = 0U; idx < QF_maxPool_; ++idx) {
167 if (evtSize <= QF_EPOOL_EVENT_SIZE_(QF_pool_[idx])) {
168 break;
169 }
170 }
171 /* cannot run out of registered pools */
172 Q_ASSERT_ID(310, idx < QF_maxPool_);
173
174 /* get e -- platform-dependent */
175 QEvt *e;
176
177#ifdef Q_SPY
178 QF_EPOOL_GET_(QF_pool_[idx], e,
179 ((margin != QF_NO_MARGIN) ? margin : 0U),
180 (uint_fast8_t)QS_EP_ID + idx + 1U);
181#else
182 QF_EPOOL_GET_(QF_pool_[idx], e,
183 ((margin != QF_NO_MARGIN) ? margin : 0U), 0U);
184#endif
185
186 /* was e allocated correctly? */
188 if (e != (QEvt *)0) {
189 e->sig = (QSignal)sig; /* set signal for this event */
190 e->poolId_ = (uint8_t)(idx + 1U); /* store the pool ID */
191 e->refCtr_ = 0U; /* set the reference counter to 0 */
192
193 QS_BEGIN_PRE_(QS_QF_NEW, (uint_fast8_t)QS_EP_ID + e->poolId_)
194 QS_TIME_PRE_(); /* timestamp */
195 QS_EVS_PRE_(evtSize); /* the size of the event */
196 QS_SIG_PRE_(sig); /* the signal of the event */
198 }
199 /* event cannot be allocated */
200 else {
201 /* This assertion means that the event allocation failed,
202 * and this failure cannot be tolerated. The most frequent
203 * reason is an event leak in the application.
204 */
205 Q_ASSERT_ID(320, margin != QF_NO_MARGIN);
206
207 QS_BEGIN_PRE_(QS_QF_NEW_ATTEMPT, (uint_fast8_t)QS_EP_ID + idx + 1U)
208 QS_TIME_PRE_(); /* timestamp */
209 QS_EVS_PRE_(evtSize); /* the size of the event */
210 QS_SIG_PRE_(sig); /* the signal of the event */
212 }
213 return e; /* can't be NULL if we can't tolerate failed allocation */
214}
215
216/*==========================================================================*/
241void QF_gc(QEvt const * const e) {
242
243 /* is it a dynamic event? */
244 if (e->poolId_ != 0U) {
246 QF_CRIT_E_();
247
248 /* isn't this the last reference? */
249 if (e->refCtr_ > 1U) {
250
252 (uint_fast8_t)QS_EP_ID + e->poolId_)
253 QS_TIME_PRE_(); /* timestamp */
254 QS_SIG_PRE_(e->sig); /* the signal of the event */
255 QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
257
258 QF_EVT_REF_CTR_DEC_(e); /* decrement the ref counter */
259
260 QF_CRIT_X_();
261 }
262 /* this is the last reference to this event, recycle it */
263 else {
264 uint_fast8_t const idx = (uint_fast8_t)e->poolId_ - 1U;
265
267 (uint_fast8_t)QS_EP_ID + e->poolId_)
268 QS_TIME_PRE_(); /* timestamp */
269 QS_SIG_PRE_(e->sig); /* the signal of the event */
270 QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
272
273 QF_CRIT_X_();
274
275 /* pool ID must be in range */
276 Q_ASSERT_ID(410, idx < QF_maxPool_);
277
278 /* cast 'const' away, which is OK, because it's a pool event */
279#ifdef Q_SPY
281 (uint_fast8_t)QS_EP_ID + e->poolId_);
282#else
284#endif
285 }
286 }
287}
288
289/*==========================================================================*/
305QEvt const *QF_newRef_(QEvt const * const e, void const * const evtRef) {
306
309 Q_REQUIRE_ID(500,
310 (e->poolId_ != 0U)
311 && (evtRef == (void *)0));
312
314 QF_CRIT_E_();
315
316 QF_EVT_REF_CTR_INC_(e); /* increments the ref counter */
317
319 (uint_fast8_t)QS_EP_ID + e->poolId_)
320 QS_TIME_PRE_(); /* timestamp */
321 QS_SIG_PRE_(e->sig); /* the signal of the event */
322 QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
324
325 QF_CRIT_X_();
326
327 return e;
328}
329
330/*==========================================================================*/
342void QF_deleteRef_(void const * const evtRef) {
344 QEvt const * const e = (QEvt const *)evtRef;
345
347 (uint_fast8_t)QS_EP_ID + e->poolId_)
348 QS_TIME_PRE_(); /* timestamp */
349 QS_SIG_PRE_(e->sig); /* the signal of the event */
350 QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
352
353 QF_gc(e);
354}
355
356/*==========================================================================*/
362uint_fast16_t QF_poolGetMaxBlockSize(void) {
364}
#define QF_EPOOL_PUT_(p_, e_, qs_id_)
Definition: macros.h:164
#define QF_EPOOL_GET_(p_, e_, m_, qs_id_)
Definition: macros.h:153
#define QF_EPOOL_EVENT_SIZE_(p_)
Definition: macros.h:143
#define QF_EPOOL_TYPE_
Definition: macros.h:116
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_)
Definition: macros.h:133
Customizable and memory-efficient assertions for embedded systems.
#define Q_DEFINE_THIS_MODULE(name_)
Definition: qassert.h:102
#define Q_ASSERT_ID(id_, test_)
Definition: qassert.h:135
#define Q_REQUIRE_ID(id_, test_)
Definition: qassert.h:252
uint16_t QSignal
Definition: qep.h:97
signed int enum_t
Definition: qep.h:60
#define QF_NO_MARGIN
Definition: qf.h:687
uint_fast8_t QF_maxPool_
Definition: qf_dyn.c:48
QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL]
Definition: qf_dyn.c:47
Internal (package scope) QF/C interface.
#define QF_CRIT_STAT_
Definition: qf_pkg.h:54
#define QF_EVT_REF_CTR_DEC_(e_)
Definition: qf_pkg.h:180
#define QF_EVT_CONST_CAST_(e_)
Definition: qf_pkg.h:174
#define QF_CRIT_X_()
Definition: qf_pkg.h:78
#define QF_EVT_REF_CTR_INC_(e_)
Definition: qf_pkg.h:177
#define QF_CRIT_E_()
Definition: qf_pkg.h:66
#define QS_CRIT_STAT_
Definition: qs.h:509
#define QS_TIME_PRE_()
Definition: qs.h:220
@ QS_EP_ID
Definition: qs.h:189
@ QS_QF_DELETE_REF
Definition: qs.h:109
@ QS_QF_GC_ATTEMPT
Definition: qs.h:96
@ QS_QF_GC
Definition: qs.h:97
@ QS_QF_NEW_ATTEMPT
Definition: qs.h:86
@ QS_QF_NEW_REF
Definition: qs.h:94
@ QS_QF_NEW
Definition: qs.h:95
Internal (package scope) QS/C interface.
#define QS_BEGIN_PRE_(rec_, qs_id_)
Definition: qs_pkg.h:114
#define QS_BEGIN_NOCRIT_PRE_(rec_, qs_id_)
Definition: qs_pkg.h:138
#define QS_END_NOCRIT_PRE_()
Definition: qs_pkg.h:148
#define QS_2U8_PRE_(data1_, data2_)
Definition: qs_pkg.h:154
#define QS_EVS_PRE_(size_)
Definition: qs_pkg.h:220
#define QS_SIG_PRE_(sig_)
Definition: qs_pkg.h:172
#define QS_END_PRE_()
Definition: qs_pkg.h:126
Definition: qep.h:119
QSignal sig
Definition: qep.h:123
uint8_t poolId_
Definition: qep.h:128
uint8_t volatile refCtr_
Definition: qep.h:133
void QF_poolInit(void *const poolSto, uint_fast32_t const poolSize, uint_fast16_t const evtSize)
Definition: qf_dyn.c:107
void QF_gc(QEvt const *const e)
Definition: qf_dyn.c:241
uint_fast16_t QF_poolGetMaxBlockSize(void)
Definition: qf_dyn.c:362
QEvt * QF_newX_(uint_fast16_t const evtSize, uint_fast16_t const margin, enum_t const sig)
Definition: qf_dyn.c:160
void QF_deleteRef_(void const *const evtRef)
Definition: qf_dyn.c:342
QEvt const * QF_newRef_(QEvt const *const e, void const *const evtRef)
Definition: qf_dyn.c:305
void QS_obj_dict_pre_(void const *const obj, char const *name)
Definition: qs.c:856