QP/C  5.8.2
qf_dyn.c
Go to the documentation of this file.
1 
40 #define QP_IMPL /* this is QP implementation */
41 #include "qf_port.h" /* QF port */
42 #include "qf_pkg.h" /* QF package-scope interface */
43 #include "qassert.h" /* QP embedded systems-friendly assertions */
44 #ifdef Q_SPY /* QS software tracing enabled? */
45  #include "qs_port.h" /* include QS port */
46 #else
47  #include "qs_dummy.h" /* disable the QS software tracing */
48 #endif /* Q_SPY */
49 
50 Q_DEFINE_THIS_MODULE("qf_dyn")
51 
52 
53 /* Package-scope objects ****************************************************/
54 QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL]; /* allocate the event pools */
55 uint_fast8_t QF_maxPool_; /* number of initialized event pools */
56 
57 /****************************************************************************/
58 #ifdef Q_EVT_CTOR /* Provide the constructor for the ::QEvt class? */
59 
68 QEvt *QEvt_ctor(QEvt * const me, enum_t const sig) {
70  Q_REQUIRE_ID(100, me != (QEvt *)0);
71  me->sig = (QSignal)sig;
72  return me;
73 }
74 
75 #endif /* Q_EVT_CTOR */
76 
77 
78 /****************************************************************************/
112 void QF_poolInit(void * const poolSto, uint_fast32_t const poolSize,
113  uint_fast16_t const evtSize)
114 {
116  Q_REQUIRE_ID(200, QF_maxPool_ < (uint_fast8_t)Q_DIM(QF_pool_));
118  Q_REQUIRE_ID(201, (QF_maxPool_ == (uint_fast8_t)0)
119  || (QF_EPOOL_EVENT_SIZE_(QF_pool_[QF_maxPool_ - (uint_fast8_t)1])
120  < evtSize));
121 
122  /* perform the platform-dependent initialization of the pool */
123  QF_EPOOL_INIT_(QF_pool_[QF_maxPool_],
124  poolSto, poolSize, evtSize);
125  ++QF_maxPool_; /* one more pool */
126 }
127 
128 /****************************************************************************/
150 QEvt *QF_newX_(uint_fast16_t const evtSize,
151  uint_fast16_t const margin, enum_t const sig)
152 {
153  QEvt *e;
154  uint_fast8_t idx;
156 
157  /* find the pool index that fits the requested event size ... */
158  for (idx = (uint_fast8_t)0; idx < QF_maxPool_; ++idx) {
159  if (evtSize <= QF_EPOOL_EVENT_SIZE_(QF_pool_[idx])) {
160  break;
161  }
162  }
163  /* cannot run out of registered pools */
164  Q_ASSERT_ID(310, idx < QF_maxPool_);
165 
166  QS_BEGIN_(QS_QF_NEW, (void *)0, (void *)0)
167  QS_TIME_(); /* timestamp */
168  QS_EVS_(evtSize); /* the size of the event */
169  QS_SIG_((QSignal)sig); /* the signal of the event */
170  QS_END_()
171 
172  QF_EPOOL_GET_(QF_pool_[idx], e, margin); /* get e -- platform-dependent */
173 
174  /* was e allocated correctly? */
175  if (e != (QEvt *)0) {
176  e->sig = (QSignal)sig; /* set signal for this event */
177  e->poolId_ = (uint8_t)(idx + (uint_fast8_t)1); /* store the pool ID */
178  e->refCtr_ = (uint8_t)0; /* set the reference counter to 0 */
179  }
180  /* event cannot be allocated */
181  else {
182  /* must tolerate bad alloc. */
183  Q_ASSERT_ID(320, margin != (uint_fast16_t)0);
184  }
185  return e; /* can't be NULL if we can't tolerate bad allocation */
186 }
187 
188 /****************************************************************************/
211 void QF_gc(QEvt const * const e) {
212 
213  /* is it a dynamic event? */
214  if (e->poolId_ != (uint8_t)0) {
216  QF_CRIT_ENTRY_();
217 
218  /* isn't this the last ref? */
219  if (e->refCtr_ > (uint8_t)1) {
220  QF_EVT_REF_CTR_DEC_(e); /* decrements the ref counter */
221 
222  QS_BEGIN_NOCRIT_(QS_QF_GC_ATTEMPT, (void *)0, (void *)0)
223  QS_TIME_(); /* timestamp */
224  QS_SIG_(e->sig); /* the signal of the event */
225  QS_2U8_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
227 
228  QF_CRIT_EXIT_();
229  }
230  /* this is the last reference to this event, recycle it */
231  else {
233 
234  QS_BEGIN_NOCRIT_(QS_QF_GC, (void *)0, (void *)0)
235  QS_TIME_(); /* timestamp */
236  QS_SIG_(e->sig); /* the signal of the event */
237  QS_2U8_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
239 
240  QF_CRIT_EXIT_();
241 
242  /* pool ID must be in range */
243  Q_ASSERT_ID(410, idx < QF_maxPool_);
244 
245  /* casting const away is legitimate, because it's a pool event */
246  QF_EPOOL_PUT_(QF_pool_[idx], (QEvt *)e);
247  }
248  }
249 }
250 
251 /****************************************************************************/
264 QEvt const *QF_newRef_(QEvt const * const e, QEvt const * const evtRef) {
266 
267  /* the provided event reference must not be in use */
268  Q_REQUIRE_ID(500, evtRef == (QEvt const *)0);
269 
270  QF_CRIT_ENTRY_();
271  /* is the current event dynamic? */
272  if (e->poolId_ != (uint8_t)0) {
273  QF_EVT_REF_CTR_INC_(e); /* increments the ref counter */
274  }
275  QF_CRIT_EXIT_();
276 
277  return e;
278 }
279 
280 /****************************************************************************/
286  return QF_EPOOL_EVENT_SIZE_(QF_pool_[QF_maxPool_ - (uint_fast8_t)1]);
287 }
#define QS_2U8_(data1_, data2_)
Internal QS macro to output 2 unformatted uint8_t data elements.
Definition: qs.h:682
new event creation
Definition: qs.h:99
#define QF_CRIT_ENTRY_()
This is an internal macro for entering a critical section.
Definition: qf_pkg.h:69
#define QF_EPOOL_TYPE_
This macro defines the type of the event pool used in the QK kernel.
Definition: macros.h:101
#define QF_EPOOL_GET_(p_, e_, m_)
Platform-dependent macro defining how QF should obtain an event e_ from the event pool p_ with the fr...
Definition: macros.h:128
#define QF_CRIT_STAT_
This is an internal macro for defining the critical section status type.
Definition: qf_pkg.h:57
#define QS_BEGIN_NOCRIT_(rec_, objFilter_, obj_)
Internal macro to begin a QS record without entering critical section.
Definition: qs.h:660
#define Q_DEFINE_THIS_MODULE(name_)
Define the user-specified module name for assertions in this file.
Definition: qassert.h:95
unsigned char uint8_t
exact-width 8-bit unsigned int
Definition: stdint.h:28
QSignal sig
signal of the event instance
Definition: qep.h:154
#define QF_EPOOL_PUT_(p_, e_)
Platform-dependent macro defining how QF should return an event e_ to the event pool p_...
Definition: macros.h:137
#define QS_END_()
Internal QS macro to end a QS record with exiting critical section.
Definition: qs.h:650
unsigned int uint_fast8_t
fast at-least 8-bit unsigned int
Definition: stdint.h:35
uint_fast16_t QF_poolGetMaxBlockSize(void)
Obtain the block size of any registered event pools.
Definition: qf_dyn.c:285
Internal (package scope) QF/C interface.
#define QF_EPOOL_EVENT_SIZE_(p_)
Platform-dependent macro defining how QF should obtain the event pool block-size. ...
Definition: macros.h:119
int enum_t
typedef for enumerations used for event signals
Definition: qep.h:76
uint16_t QSignal
QSignal represents the signal of an event.
Definition: qep.h:130
unsigned long uint_fast32_t
fast at-least 32-bit unsigned int
Definition: stdint.h:39
Event structure.
Definition: qep.h:153
#define Q_ASSERT_ID(id_, test_)
General purpose assertion with user-specified assertion-id.
Definition: qassert.h:130
#define QF_EVT_REF_CTR_INC_(e_)
increment the refCtr of an event e_ casting const away
Definition: qf_pkg.h:108
unsigned int uint_fast16_t
fast at-least 16-bit unsigned int
Definition: stdint.h:37
uint_fast8_t QF_maxPool_
of initialized event pools
Definition: qf_dyn.c:55
Customizable and memory-efficient assertions for embedded systems.
#define QS_BEGIN_(rec_, objFilter_, obj_)
Internal QS macro to begin a QS record with entering critical section.
Definition: qs.h:635
#define Q_REQUIRE_ID(id_, test_)
Assertion for checking preconditions with user-specified assertion-id.
Definition: qassert.h:248
#define QF_EVT_REF_CTR_DEC_(e_)
decrement the refCtr of an event e_ casting const away
Definition: qf_pkg.h:111
garbage collection attempt
Definition: qs.h:100
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_)
Platform-dependent macro defining the event pool initialization.
Definition: macros.h:109
#define QF_MAX_EPOOL
Default value of the macro configurable value in qf_port.h.
Definition: qf.h:70
#define QS_TIME_()
Internal macro to output time stamp to a QS record.
Definition: qs.h:182
QEvt const * QF_newRef_(QEvt const *const e, QEvt const *const evtRef)
Internal QF implementation of the event reference creator.
Definition: qf_dyn.c:264
garbage collection
Definition: qs.h:101
#define QS_END_NOCRIT_()
Internal QS macro to end a QS record without exiting critical section.
Definition: qs.h:674
QEvt * QF_newX_(uint_fast16_t const evtSize, uint_fast16_t const margin, enum_t const sig)
Internal QF implementation of the dynamic event allocator.
Definition: qf_dyn.c:150
QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL]
allocate event pools
Definition: qf_dyn.c:54
void QF_gc(QEvt const *const e)
Recycle a dynamic event.
Definition: qf_dyn.c:211
uint8_t poolId_
pool ID (0 for static event)
Definition: qep.h:155
#define QS_CRIT_STAT_
This is an internal macro for defining the critical section status type.
Definition: qs.h:565
uint8_t volatile refCtr_
reference counter
Definition: qep.h:156
#define Q_DIM(array_)
Helper macro to calculate static dimension of a 1-dim array_.
Definition: qep.h:193
#define QF_CRIT_EXIT_()
This is an internal macro for exiting a critical section.
Definition: qf_pkg.h:81
void QF_poolInit(void *const poolSto, uint_fast32_t const poolSize, uint_fast16_t const evtSize)
Event pool initialization for dynamic allocation of events.
Definition: qf_dyn.c:112