QP/C  6.5.1
qf_ps.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_ps")
51 
52 
53 /* Package-scope objects ****************************************************/
56 
57 /****************************************************************************/
86 void QF_psInit(QSubscrList * const subscrSto, enum_t const maxSignal) {
87  QF_subscrList_ = subscrSto;
88  QF_maxPubSignal_ = maxSignal;
89 
90  /* zero the subscriber list, so that the framework can start correctly
91  * even if the startup code fails to clear the uninitialized data
92  * (as is required by the C Standard).
93  */
94  QF_bzero(subscrSto,
95  (uint_fast16_t)((uint_fast16_t)maxSignal
96  * (uint_fast16_t)sizeof(QSubscrList)));
97 }
98 
99 /****************************************************************************/
119 #ifndef Q_SPY
120 void QF_publish_(QEvt const * const e)
121 #else
122 void QF_publish_(QEvt const * const e, void const * const sender)
123 #endif
124 {
125  QPSet subscrList; /* local, modifiable copy of the subscriber list */
127 
130 
131  QF_CRIT_ENTRY_();
132 
133  QS_BEGIN_NOCRIT_(QS_QF_PUBLISH, (void *)0, (void *)0)
134  QS_TIME_(); /* the timestamp */
135  QS_OBJ_(sender); /* the sender object */
136  QS_SIG_(e->sig); /* the signal of the event */
137  QS_2U8_(e->poolId_, e->refCtr_);/* pool Id & ref Count of the event */
139 
140  /* is it a dynamic event? */
141  if (e->poolId_ != (uint8_t)0) {
142  /* NOTE: The reference counter of a dynamic event is incremented to
143  * prevent premature recycling of the event while the multicasting
144  * is still in progress. At the end of the function, the garbage
145  * collector step (QF_gc()) decrements the reference counter and
146  * recycles the event if the counter drops to zero. This covers the
147  * case when the event was published without any subscribers.
148  */
150  }
151 
152  /* make a local, modifiable copy of the subscriber list */
153  subscrList = QF_PTR_AT_(QF_subscrList_, e->sig);
154  QF_CRIT_EXIT_();
155 
156  if (QPSet_notEmpty(&subscrList)) { /* any subscribers? */
157  uint_fast8_t p;
159 
160  QPSet_findMax(&subscrList, p); /* the highest-prio subscriber */
161 
162  QF_SCHED_LOCK_(p); /* lock the scheduler up to prio 'p' */
163  do { /* loop over all subscribers */
164  /* the prio of the AO must be registered with the framework */
165  Q_ASSERT_ID(210, QF_active_[p] != (QActive *)0);
166 
167  /* QACTIVE_POST() asserts internally if the queue overflows */
168  QACTIVE_POST(QF_active_[p], e, sender);
169 
170  QPSet_remove(&subscrList, p); /* remove the handled subscriber */
171  if (QPSet_notEmpty(&subscrList)) { /* still more subscribers? */
172  QPSet_findMax(&subscrList, p); /* highest-prio subscriber */
173  }
174  else {
175  p = (uint_fast8_t)0; /* no more subscribers */
176  }
177  } while (p != (uint_fast8_t)0);
178  QF_SCHED_UNLOCK_(); /* unlock the scheduler */
179  }
180 
181  /* The following garbage collection step decrements the reference counter
182  * and recycles the event if the counter drops to zero. This covers both
183  * cases when the event was published with or without any subscribers.
184  */
185  QF_gc(e);
186 }
187 
188 /****************************************************************************/
207 void QActive_subscribe(QActive const * const me, enum_t const sig) {
208  uint_fast8_t p = (uint_fast8_t)me->prio;
210 
211  Q_REQUIRE_ID(300, ((enum_t)Q_USER_SIG <= sig)
212  && (sig < QF_maxPubSignal_)
213  && ((uint_fast8_t)0 < p) && (p <= (uint_fast8_t)QF_MAX_ACTIVE)
214  && (QF_active_[p] == me));
215 
216  QF_CRIT_ENTRY_();
217 
219  QS_TIME_(); /* timestamp */
220  QS_SIG_((QSignal)sig); /* the signal of this event */
221  QS_OBJ_(me); /* this active object */
223 
224  /* set the priority bit */
226 
227  QF_CRIT_EXIT_();
228 }
229 
230 /****************************************************************************/
255 void QActive_unsubscribe(QActive const * const me, enum_t const sig) {
256  uint_fast8_t p = (uint_fast8_t)me->prio;
258 
262  Q_REQUIRE_ID(400, ((enum_t)Q_USER_SIG <= sig)
263  && (sig < QF_maxPubSignal_)
264  && ((uint_fast8_t)0 < p) && (p <= (uint_fast8_t)QF_MAX_ACTIVE)
265  && (QF_active_[p] == me));
266 
267  QF_CRIT_ENTRY_();
268 
270  QS_TIME_(); /* timestamp */
271  QS_SIG_((QSignal)sig); /* the signal of this event */
272  QS_OBJ_(me); /* this active object */
274 
275  /* clear priority bit */
277 
278  QF_CRIT_EXIT_();
279 }
280 
281 /****************************************************************************/
304 void QActive_unsubscribeAll(QActive const * const me) {
305  uint_fast8_t p = (uint_fast8_t)me->prio;
306  enum_t sig;
307 
308  Q_REQUIRE_ID(500, ((uint_fast8_t)0 < p)
309  && (p <= (uint_fast8_t)QF_MAX_ACTIVE)
310  && (QF_active_[p] == me));
311 
312  for (sig = (enum_t)Q_USER_SIG; sig < QF_maxPubSignal_; ++sig) {
314  QF_CRIT_ENTRY_();
315  if (QPSet_hasElement(&QF_PTR_AT_(QF_subscrList_, sig), p)) {
317 
320  QS_TIME_(); /* timestamp */
321  QS_SIG_((QSignal)sig); /* the signal of this event */
322  QS_OBJ_(me); /* this active object */
324  }
325  QF_CRIT_EXIT_();
326 
327  /* prevent merging critical sections */
329  }
330 }
331 
#define QS_2U8_(data1_, data2_)
Internal QS macro to output 2 unformatted uint8_t data elements.
Definition: qs.h:727
#define QF_CRIT_EXIT_NOP()
No-operation for exiting a critical section.
Definition: qf.h:802
uint8_t prio
QF priority (1..QF_MAX_ACTIVE) of this active object.
Definition: qf.h:157
an AO subscribed to an event
Definition: qs.h:83
void QF_publish_(QEvt const *const e, void const *const sender)
Publish event to the framework.
Definition: qf_ps.c:122
QSignal sig
signal of the event instance
Definition: qep.h:154
#define QPSet_findMax(me_, n_)
Find the maximum element in the set, and assign it to n_.
Definition: qpset.h:91
#define QF_CRIT_ENTRY_()
This is an internal macro for entering a critical section.
Definition: qf_pkg.h:69
void QActive_unsubscribeAll(QActive const *const me)
Un-subscribes from the delivery of all signals to the AO me.
Definition: qf_ps.c:304
first signal that can be used for user signals
Definition: qep.h:622
void QActive_unsubscribe(QActive const *const me, enum_t const sig)
Un-subscribes from the delivery of signal sig to the AO me.
Definition: qf_ps.c:255
#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:705
#define Q_DEFINE_THIS_MODULE(name_)
Define the user-specified module name for assertions in this file.
Definition: qassert.h:120
unsigned char uint8_t
exact-width 8-bit unsigned int
Definition: stdint.h:29
QF_SCHED_UNLOCK_
Definition: options.lnt:138
QSPriv QS_priv_
Definition: qs.c:53
unsigned int uint_fast8_t
fast at-least 8-bit unsigned int
Definition: stdint.h:36
Internal (package scope) QF/C interface.
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
an event was published
Definition: qs.h:104
void QF_bzero(void *const start, uint_fast16_t len)
Clear a specified region of memory to zero.
Definition: qf_act.c:144
void QF_gc(QEvt const *const e)
Recycle a dynamic event.
Definition: qf_dyn.c:229
Event structure.
Definition: qep.h:153
#define QPSet_insert(me_, n_)
Insert element n_ into the set me_, n_= 1..32.
Definition: qpset.h:81
uint8_t volatile refCtr_
reference counter
Definition: qep.h:156
#define QPSet_notEmpty(me_)
Evaluates to TRUE if the priority set me_ is not empty.
Definition: qpset.h:74
QSubscrList * QF_subscrList_
the subscriber list array
Definition: qf_ps.c:54
uint8_t poolId_
pool ID (0 for static event)
Definition: qep.h:155
#define Q_ASSERT_ID(id_, test_)
General purpose assertion with user-specified assertion-id.
Definition: qassert.h:155
void const * locFilter[MAX_OBJ]
local QS filters
Definition: qs.h:1096
active object
Definition: qs.h:1081
#define QF_EVT_REF_CTR_INC_(e_)
increment the refCtr of an event e_ casting const away
Definition: qf_pkg.h:169
enum_t QF_maxPubSignal_
the maximum published signal
Definition: qf_ps.c:55
#define QF_SCHED_STAT_
Internal macro to represent the scheduler lock status that needs to be preserved to allow nesting of ...
Definition: qk.h:167
unsigned int uint_fast16_t
fast at-least 16-bit unsigned int
Definition: stdint.h:38
#define QF_MAX_ACTIVE
The maximum number of active objects in the application.
Definition: qk/qf_port.h:58
Customizable and memory-efficient assertions for embedded systems.
#define Q_REQUIRE_ID(id_, test_)
Assertion for checking preconditions with user-specified assertion-id.
Definition: qassert.h:273
Priority Set of up to 32 elements.
Definition: qpset.h:63
#define QS_OBJ_(obj_)
Internal macro to output an unformatted object pointer data element.
Definition: qs.h:766
#define QPSet_hasElement(me_, n_)
Evaluates to TRUE if the priority set me_ has element n_.
Definition: qpset.h:77
#define QF_PTR_AT_(base_, i_)
access element at index i_ from the base pointer base_
Definition: qf_pkg.h:175
QF_SCHED_LOCK_
Definition: options.lnt:138
#define QPSet_remove(me_, n_)
Remove element n_ from the set me_, n_= 1..32.
Definition: qpset.h:85
#define QS_TIME_()
Internal macro to output time stamp to a QS record.
Definition: qs.h:223
#define QS_END_NOCRIT_()
Internal QS macro to end a QS record without exiting critical section.
Definition: qs.h:719
void QActive_subscribe(QActive const *const me, enum_t const sig)
Subscribes for delivery of signal sig to the active object me.
Definition: qf_ps.c:207
Active Object (based on QHsm implementation)
Definition: qf.h:114
QActive * QF_active_[QF_MAX_ACTIVE+1]
array of registered active objects
Definition: qf_act.c:53
void QF_psInit(QSubscrList *const subscrSto, enum_t const maxSignal)
Publish-subscribe initialization.
Definition: qf_ps.c:86
an AO unsubscribed to an event
Definition: qs.h:84
#define QACTIVE_POST(me_, e_, sender_)
Polymorphically posts an event to an active object (FIFO) with delivery guarantee.
Definition: qf.h:247
#define QF_CRIT_EXIT_()
This is an internal macro for exiting a critical section.
Definition: qf_pkg.h:81