QP/C  5.9.8
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 /****************************************************************************/
152 QEvt *QF_newX_(uint_fast16_t const evtSize,
153  uint_fast16_t const margin, enum_t const sig)
154 {
155  QEvt *e;
156  uint_fast8_t idx;
158 
159  /* find the pool index that fits the requested event size ... */
160  for (idx = (uint_fast8_t)0; idx < QF_maxPool_; ++idx) {
161  if (evtSize <= QF_EPOOL_EVENT_SIZE_(QF_pool_[idx])) {
162  break;
163  }
164  }
165  /* cannot run out of registered pools */
166  Q_ASSERT_ID(310, idx < QF_maxPool_);
167 
168  QS_BEGIN_(QS_QF_NEW, (void *)0, (void *)0)
169  QS_TIME_(); /* timestamp */
170  QS_EVS_(evtSize); /* the size of the event */
171  QS_SIG_((QSignal)sig); /* the signal of the event */
172  QS_END_()
173 
174  /* get e -- platform-dependent */
175  QF_EPOOL_GET_(QF_pool_[idx], e,
176  ((margin != QF_NO_MARGIN)
177  ? margin
178  : (uint_fast16_t)0));
179 
180  /* was e allocated correctly? */
181  if (e != (QEvt *)0) {
182  e->sig = (QSignal)sig; /* set signal for this event */
183  e->poolId_ = (uint8_t)(idx + (uint_fast8_t)1); /* store the pool ID */
184  e->refCtr_ = (uint8_t)0; /* set the reference counter to 0 */
185  }
186  /* event cannot be allocated */
187  else {
188  /* must tolerate bad alloc. */
189  Q_ASSERT_ID(320, margin != QF_NO_MARGIN);
190  }
191  return e; /* can't be NULL if we can't tolerate bad allocation */
192 }
193 
194 /****************************************************************************/
217 void QF_gc(QEvt const * const e) {
218 
219  /* is it a dynamic event? */
220  if (e->poolId_ != (uint8_t)0) {
222  QF_CRIT_ENTRY_();
223 
224  /* isn't this the last ref? */
225  if (e->refCtr_ > (uint8_t)1) {
226  QF_EVT_REF_CTR_DEC_(e); /* decrements the ref counter */
227 
228  QS_BEGIN_NOCRIT_(QS_QF_GC_ATTEMPT, (void *)0, (void *)0)
229  QS_TIME_(); /* timestamp */
230  QS_SIG_(e->sig); /* the signal of the event */
231  QS_2U8_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
233 
234  QF_CRIT_EXIT_();
235  }
236  /* this is the last reference to this event, recycle it */
237  else {
239 
240  QS_BEGIN_NOCRIT_(QS_QF_GC, (void *)0, (void *)0)
241  QS_TIME_(); /* timestamp */
242  QS_SIG_(e->sig); /* the signal of the event */
243  QS_2U8_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
245 
246  QF_CRIT_EXIT_();
247 
248  /* pool ID must be in range */
249  Q_ASSERT_ID(410, idx < QF_maxPool_);
250 
251  /* casting const away is legitimate, because it's a pool event */
252  QF_EPOOL_PUT_(QF_pool_[idx], (QEvt *)e);
253  }
254  }
255 }
256 
257 /****************************************************************************/
270 QEvt const *QF_newRef_(QEvt const * const e, QEvt const * const evtRef) {
272 
275  Q_REQUIRE_ID(500,
276  (e->poolId_ != (uint8_t)0)
277  && (evtRef == (QEvt const *)0));
278 
279  QF_CRIT_ENTRY_();
280  QF_EVT_REF_CTR_INC_(e); /* increments the ref counter */
281  QF_CRIT_EXIT_();
282 
283  return e;
284 }
285 
286 /****************************************************************************/
292  return QF_EPOOL_EVENT_SIZE_(QF_pool_[QF_maxPool_ - (uint_fast8_t)1]);
293 }
#define QS_2U8_(data1_, data2_)
Internal QS macro to output 2 unformatted uint8_t data elements.
Definition: qs.h:708
new event creation
Definition: qs.h:99
QSignal sig
signal of the event instance
Definition: qep.h:153
#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:686
#define Q_DEFINE_THIS_MODULE(name_)
Define the user-specified module name for assertions in this file.
Definition: qassert.h:101
unsigned char uint8_t
exact-width 8-bit unsigned int
Definition: stdint.h:28
#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:676
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:291
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:75
uint16_t QSignal
QSignal represents the signal of an event.
Definition: qep.h:129
unsigned long uint_fast32_t
fast at-least 32-bit unsigned int
Definition: stdint.h:39
Event structure.
Definition: qep.h:152
uint8_t volatile refCtr_
reference counter
Definition: qep.h:155
uint8_t poolId_
pool ID (0 for static event)
Definition: qep.h:154
#define Q_ASSERT_ID(id_, test_)
General purpose assertion with user-specified assertion-id.
Definition: qassert.h:136
#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:661
#define Q_REQUIRE_ID(id_, test_)
Assertion for checking preconditions with user-specified assertion-id.
Definition: qassert.h:254
#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:205
QEvt const * QF_newRef_(QEvt const *const e, QEvt const *const evtRef)
Internal QF implementation of the event reference creator.
Definition: qf_dyn.c:270
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:700
#define QF_NO_MARGIN
special value of margin that causes asserting failure in case event allocation or event posting fails...
Definition: qf.h:645
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:152
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:217
#define QS_CRIT_STAT_
This is an internal macro for defining the critical section status type.
Definition: qs.h:592
#define Q_DIM(array_)
Helper macro to calculate static dimension of a 1-dim array_.
Definition: qep.h:192
#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