QP/C  8.0.2
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qf_dyn.c
Go to the documentation of this file.
1//============================================================================
2// QP/C Real-Time Embedded Framework (RTEF)
3// Version 8.0.2
4//
5// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
6//
7// Q u a n t u m L e a P s
8// ------------------------
9// Modern Embedded Software
10//
11// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
12//
13// This software is dual-licensed under the terms of the open-source GNU
14// General Public License (GPL) or under the terms of one of the closed-
15// source Quantum Leaps commercial licenses.
16//
17// Redistributions in source code must retain this top-level comment block.
18// Plagiarizing this software to sidestep the license obligations is illegal.
19//
20// NOTE:
21// The GPL does NOT permit the incorporation of this code into proprietary
22// programs. Please contact Quantum Leaps for commercial licensing options,
23// which expressly supersede the GPL and are designed explicitly for
24// closed-source distribution.
25//
26// Quantum Leaps contact information:
27// <www.state-machine.com/licensing>
28// <info@state-machine.com>
29//============================================================================
30#define QP_IMPL // this is QP implementation
31#include "qp_port.h" // QP port
32#include "qp_pkg.h" // QP package-scope interface
33#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
34#ifdef Q_SPY // QS software tracing enabled?
35 #include "qs_port.h" // QS port
36 #include "qs_pkg.h" // QS facilities for pre-defined trace records
37#else
38 #include "qs_dummy.h" // disable the QS software tracing
39#endif // Q_SPY
40
41#if (QF_MAX_EPOOL > 0U) // mutable events configured?
42
43Q_DEFINE_THIS_MODULE("qf_dyn")
44
45//............................................................................
46//! @static @public @memberof QF
47void QF_poolInit(
48 void * const poolSto,
49 uint_fast32_t const poolSize,
50 uint_fast16_t const evtSize)
51{
52 uint_fast8_t const poolNum = QF_priv_.maxPool_;
53
54 // see precondition{qf_dyn,200} and precondition{qf_dyn,201}
57
58 Q_REQUIRE_INCRIT(100, poolNum < QF_MAX_EPOOL);
59 if (poolNum > 0U) {
61 QF_EPOOL_EVENT_SIZE_(QF_priv_.ePool_[poolNum - 1U]) < evtSize);
62 }
63 QF_priv_.maxPool_ = poolNum + 1U; // one more pool
64
66
67 // perform the port-dependent initialization of the event-pool
68 QF_EPOOL_INIT_(QF_priv_.ePool_[poolNum], poolSto, poolSize, evtSize);
69
70#ifdef Q_SPY
71 // generate the object-dictionary entry for the initialized pool
72 {
73 uint8_t obj_name[9] = "EvtPool?";
74 obj_name[7] = (uint8_t)((uint8_t)'0' + poolNum + 1U);
75 QS_obj_dict_pre_(&QF_priv_.ePool_[poolNum], (char const *)obj_name);
76 }
77#endif // Q_SPY
78}
79
80//............................................................................
81//! @static @public @memberof QF
82uint_fast16_t QF_poolGetMaxBlockSize(void) {
85 uint_fast16_t const max_size =
86 QF_EPOOL_EVENT_SIZE_(QF_priv_.ePool_[QF_priv_.maxPool_ - 1U]);
88
89 return max_size;
90}
91
92//............................................................................
93//! @static @public @memberof QF
94uint_fast16_t QF_getPoolMin(uint_fast8_t const poolNum) {
97
98 Q_REQUIRE_INCRIT(300, (poolNum <= QF_MAX_EPOOL)
99 && (0U < poolNum) && (poolNum <= QF_priv_.maxPool_));
100
101 uint_fast16_t const min = (uint_fast16_t)QF_priv_.ePool_[poolNum - 1U].nMin;
102
103 QF_CRIT_EXIT();
104
105 return min;
106}
107
108//............................................................................
109//! @static @private @memberof QF
111 uint_fast16_t const evtSize,
112 uint_fast16_t const margin,
113 enum_t const sig)
114{
115 // find the pool id that fits the requested event size...
116 uint8_t poolNum = 0U; // zero-based poolNum initially
117 for (; poolNum < QF_priv_.maxPool_; ++poolNum) {
118 if (evtSize <= QF_EPOOL_EVENT_SIZE_(QF_priv_.ePool_[poolNum])) {
119 break;
120 }
121 }
122
125
126 // precondition:
127 // - cannot run out of registered pools
128 Q_REQUIRE_INCRIT(400, poolNum < QF_priv_.maxPool_);
129
130 ++poolNum; // convert to 1-based poolNum
131
132 QF_CRIT_EXIT();
133
134 // get event e (port-dependent)...
135 QEvt *e;
136#ifdef Q_SPY
137 QF_EPOOL_GET_(QF_priv_.ePool_[poolNum - 1U], e,
138 ((margin != QF_NO_MARGIN) ? margin : 0U),
139 (uint_fast8_t)QS_EP_ID + poolNum);
140#else
141 QF_EPOOL_GET_(QF_priv_.ePool_[poolNum - 1U], e,
142 ((margin != QF_NO_MARGIN) ? margin : 0U), 0U);
143#endif
144
145 if (e != (QEvt *)0) { // was e allocated correctly?
146 e->sig = (QSignal)sig; // set the signal
147 e->poolNum_ = poolNum;
148 e->refCtr_ = 0U;
149
151 QS_BEGIN_PRE(QS_QF_NEW, (uint_fast8_t)QS_EP_ID + poolNum)
152 QS_TIME_PRE(); // timestamp
153 QS_EVS_PRE(evtSize); // the size of the event
154 QS_SIG_PRE(sig); // the signal of the event
155 QS_END_PRE()
156 QS_CRIT_EXIT();
157 }
158 else { // event was not allocated
159
161 // This assertion means that the event allocation failed,
162 // and this failure cannot be tolerated. The most frequent
163 // reason is an event leak in the application.
164 Q_ASSERT_INCRIT(420, margin != QF_NO_MARGIN);
165
166 QS_BEGIN_PRE(QS_QF_NEW_ATTEMPT,
167 (uint_fast8_t)QS_EP_ID + poolNum)
168 QS_TIME_PRE(); // timestamp
169 QS_EVS_PRE(evtSize); // the size of the event
170 QS_SIG_PRE(sig); // the signal of the event
171 QS_END_PRE()
172
173 QF_CRIT_EXIT();
174 }
175
176 // the returned event e is guaranteed to be valid (not NULL)
177 // if we can't tolerate failed allocation
178 return e;
179}
180
181//............................................................................
182//! @static @public @memberof QF
183void QF_gc(QEvt const * const e) {
186
187 Q_REQUIRE_INCRIT(500, e != (QEvt *)0);
188
189 uint8_t const poolNum = e->poolNum_;
190
191 if (poolNum != 0U) { // is it a pool event (mutable)?
192
193 if (e->refCtr_ > 1U) { // isn't this the last reference?
194
195 QS_BEGIN_PRE(QS_QF_GC_ATTEMPT,
196 (uint_fast8_t)QS_EP_ID + poolNum)
197 QS_TIME_PRE(); // timestamp
198 QS_SIG_PRE(e->sig); // the signal of the event
199 QS_2U8_PRE(poolNum, e->refCtr_);
200 QS_END_PRE()
201
202 Q_ASSERT_INCRIT(505, e->refCtr_ > 0U);
203 QEvt_refCtr_dec_(e); // decrement the ref counter
204
205 QF_CRIT_EXIT();
206 }
207 else { // this is the last reference to this event, recycle it
208
209 QS_BEGIN_PRE(QS_QF_GC,
210 (uint_fast8_t)QS_EP_ID + poolNum)
211 QS_TIME_PRE(); // timestamp
212 QS_SIG_PRE(e->sig); // the signal of the event
213 QS_2U8_PRE(poolNum, e->refCtr_);
214 QS_END_PRE()
215
216 // pool number must be in range
217 Q_ASSERT_INCRIT(510, (poolNum <= QF_priv_.maxPool_)
218 && (poolNum <= QF_MAX_EPOOL));
219 QF_CRIT_EXIT();
220
221 // NOTE: casting 'const' away is legit because 'e' is a pool event
222#ifdef Q_SPY
223 QF_EPOOL_PUT_(QF_priv_.ePool_[poolNum - 1U], (QEvt *)e,
224 (uint_fast8_t)QS_EP_ID + poolNum);
225#else
226 QF_EPOOL_PUT_(QF_priv_.ePool_[poolNum - 1U], (QEvt *)e,
227 0U);
228#endif
229 }
230 }
231 else {
232 QF_CRIT_EXIT();
233 }
234}
235
236//............................................................................
237//! @static @private @memberof QF
239 QEvt const * const e,
240 void const * const evtRef)
241{
242#ifdef Q_UNSAFE
243 Q_UNUSED_PAR(evtRef);
244#endif
245
248
249 Q_REQUIRE_INCRIT(600, e != (QEvt *)0);
250
251 uint_fast8_t const poolNum = e->poolNum_;
252 Q_UNUSED_PAR(poolNum); // might be unused
253
254 Q_REQUIRE_INCRIT(610, (poolNum != 0U)
255 && (evtRef == (void *)0));
256
257 Q_ASSERT_INCRIT(605, e->refCtr_ < (2U * QF_MAX_ACTIVE));
258 QEvt_refCtr_inc_(e); // increments the ref counter
259
260 QS_BEGIN_PRE(QS_QF_NEW_REF,
261 (uint_fast8_t)QS_EP_ID + poolNum)
262 QS_TIME_PRE(); // timestamp
263 QS_SIG_PRE(e->sig); // the signal of the event
264 QS_2U8_PRE(poolNum, e->refCtr_);
265 QS_END_PRE()
266
267 QF_CRIT_EXIT();
268
269 return e;
270}
271
272//............................................................................
273//! @static @private @memberof QF
274void QF_deleteRef_(void const * const evtRef) {
277
278 QEvt const * const e = (QEvt const *)evtRef;
279 Q_REQUIRE_INCRIT(700, e != (QEvt *)0);
280
281#ifdef Q_SPY
282 uint_fast8_t const poolNum = e->poolNum_;
283 QS_BEGIN_PRE(QS_QF_DELETE_REF,
284 (uint_fast8_t)QS_EP_ID + poolNum)
285 QS_TIME_PRE(); // timestamp
286 QS_SIG_PRE(e->sig); // the signal of the event
287 QS_2U8_PRE(poolNum, e->refCtr_);
288 QS_END_PRE()
289#endif // def Q_SPY
290
291 QF_CRIT_EXIT();
292
293#if (QF_MAX_EPOOL > 0U)
294 QF_gc(e); // recycle the referenced event
295#endif
296}
297
298#endif // (QF_MAX_EPOOL > 0U) mutable events configured
QF_Attr QF_priv_
Definition qp_pkg.h:47
void QF_gc(QEvt const *const e)
Definition qf_dyn.c:183
uint_fast16_t QF_poolGetMaxBlockSize(void)
Definition qf_dyn.c:82
uint_fast16_t QF_getPoolMin(uint_fast8_t const poolNum)
Definition qf_dyn.c:94
QEvt * QF_newX_(uint_fast16_t const evtSize, uint_fast16_t const margin, enum_t const sig)
Definition qf_dyn.c:110
void QF_deleteRef_(void const *const evtRef)
Definition qf_dyn.c:274
QEvt const * QF_newRef_(QEvt const *const e, void const *const evtRef)
Definition qf_dyn.c:238
QF_Attr QF_priv_
Definition qf_act.c:46
#define QF_EPOOL_EVENT_SIZE_(p_)
Definition qk.h:112
#define QF_EPOOL_PUT_(p_, e_, qsId_)
Definition qk.h:115
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_)
Definition qk.h:110
#define QF_EPOOL_GET_(p_, e_, m_, qsId_)
Definition qk.h:113
#define Q_UNUSED_PAR(par_)
Helper macro to clearly mark unused parameters of functions.
Definition qp.h:97
#define QF_NO_MARGIN
Special value of margin that causes asserting failure in case event allocation or event posting fails...
Definition qp.h:748
int enum_t
Definition qp.h:93
uint16_t QSignal
The signal of event QEvt.
Definition qp.h:108
#define QF_MAX_ACTIVE
Maximum # Active Objects in the system (1..64)
Definition qp_config.h:123
#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 QF_CRIT_ENTRY()
Definition qp_port.h:64
#define QF_CRIT_EXIT()
Definition qp_port.h:72
#define QF_CRIT_STAT
Definition qp_port.h:55
#define QS_SIG_PRE(sig_)
Definition qs_dummy.h:148
#define QS_TIME_PRE()
Definition qs_dummy.h:147
#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_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.
#define Q_ASSERT_INCRIT(id_, expr_)
Definition qsafe.h:50
#define Q_REQUIRE_INCRIT(id_, expr_)
Definition qsafe.h:87
Event class.
Definition qp.h:115
QSignal sig
Signal of the event (see Event Signal)
Definition qp.h:116
uint8_t volatile refCtr_
Event reference counter.
Definition qp.h:118
uint8_t poolNum_
Definition qp.h:117