QP/C  5.9.8
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 /****************************************************************************/
85 void QF_psInit(QSubscrList * const subscrSto, enum_t const maxSignal) {
86  QF_subscrList_ = subscrSto;
87  QF_maxPubSignal_ = maxSignal;
88 
89  /* zero the subscriber list, so that the framework can start correctly
90  * even if the startup code fails to clear the uninitialized data
91  * (as is required by the C Standard).
92  */
93  QF_bzero(subscrSto,
94  (uint_fast16_t)((uint_fast16_t)maxSignal
95  * (uint_fast16_t)sizeof(QSubscrList)));
96 }
97 
98 /****************************************************************************/
118 #ifndef Q_SPY
119 void QF_publish_(QEvt const * const e)
120 #else
121 void QF_publish_(QEvt const * const e, void const * const sender)
122 #endif
123 {
124  QPSet subscrList; /* local, modifiable copy of the subscriber list */
126 
129 
130  QF_CRIT_ENTRY_();
131 
132  QS_BEGIN_NOCRIT_(QS_QF_PUBLISH, (void *)0, (void *)0)
133  QS_TIME_(); /* the timestamp */
134  QS_OBJ_(sender); /* the sender object */
135  QS_SIG_(e->sig); /* the signal of the event */
136  QS_2U8_(e->poolId_, e->refCtr_);/* pool Id & ref Count of the event */
138 
139  /* is it a dynamic event? */
140  if (e->poolId_ != (uint8_t)0) {
141  /* NOTE: The reference counter of a dynamic event is incremented to
142  * prevent premature recycling of the event while the multicasting
143  * is still in progress. At the end of the function, the garbage
144  * collector step (QF_gc()) decrements the reference counter and
145  * recycles the event if the counter drops to zero. This covers the
146  * case when the event was published without any subscribers.
147  */
149  }
150 
151  /* make a local, modifiable copy of the subscriber list */
152  subscrList = QF_PTR_AT_(QF_subscrList_, e->sig);
153  QF_CRIT_EXIT_();
154 
155  if (QPSet_notEmpty(&subscrList)) { /* any subscribers? */
156  uint_fast8_t p;
158 
159  QPSet_findMax(&subscrList, p); /* the highest-prio subscriber */
160 
161  QF_SCHED_LOCK_(p); /* lock the scheduler up to prio 'p' */
162  do { /* loop over all subscribers */
163  /* the prio of the AO must be registered with the framework */
164  Q_ASSERT_ID(210, QF_active_[p] != (QActive *)0);
165 
166  /* QACTIVE_POST() asserts internally if the queue overflows */
167  QACTIVE_POST(QF_active_[p], e, sender);
168 
169  QPSet_remove(&subscrList, p); /* remove the handled subscriber */
170  if (QPSet_notEmpty(&subscrList)) { /* still more subscribers? */
171  QPSet_findMax(&subscrList, p); /* highest-prio subscriber */
172  }
173  else {
174  p = (uint_fast8_t)0; /* no more subscribers */
175  }
176  } while (p != (uint_fast8_t)0);
177  QF_SCHED_UNLOCK_(); /* unlock the scheduler */
178  }
179 
180  /* The following garbage collection step decrements the reference counter
181  * and recycles the event if the counter drops to zero. This covers both
182  * cases when the event was published with or without any subscribers.
183  */
184  QF_gc(e);
185 }
186 
187 /****************************************************************************/
205 void QActive_subscribe(QActive const * const me, enum_t const sig) {
206  uint_fast8_t p = me->prio;
208 
209  Q_REQUIRE_ID(300, ((enum_t)Q_USER_SIG <= sig)
210  && (sig < QF_maxPubSignal_)
211  && ((uint_fast8_t)0 < p) && (p <= (uint_fast8_t)QF_MAX_ACTIVE)
212  && (QF_active_[p] == me));
213 
214  QF_CRIT_ENTRY_();
215 
217  QS_TIME_(); /* timestamp */
218  QS_SIG_((QSignal)sig); /* the signal of this event */
219  QS_OBJ_(me); /* this active object */
221 
222  /* set the priority bit */
224 
225  QF_CRIT_EXIT_();
226 }
227 
228 /****************************************************************************/
250 void QActive_unsubscribe(QActive const * const me, enum_t const sig) {
251  uint_fast8_t p = me->prio;
253 
257  Q_REQUIRE_ID(400, ((enum_t)Q_USER_SIG <= sig)
258  && (sig < QF_maxPubSignal_)
259  && ((uint_fast8_t)0 < p) && (p <= (uint_fast8_t)QF_MAX_ACTIVE)
260  && (QF_active_[p] == me));
261 
262  QF_CRIT_ENTRY_();
263 
265  QS_TIME_(); /* timestamp */
266  QS_SIG_((QSignal)sig); /* the signal of this event */
267  QS_OBJ_(me); /* this active object */
269 
270  /* clear priority bit */
272 
273  QF_CRIT_EXIT_();
274 }
275 
276 /****************************************************************************/
297 void QActive_unsubscribeAll(QActive const * const me) {
298  uint_fast8_t p = me->prio;
299  enum_t sig;
300 
301  Q_REQUIRE_ID(500, ((uint_fast8_t)0 < p)
302  && (p <= (uint_fast8_t)QF_MAX_ACTIVE)
303  && (QF_active_[p] == me));
304 
305  for (sig = (enum_t)Q_USER_SIG; sig < QF_maxPubSignal_; ++sig) {
307  QF_CRIT_ENTRY_();
308  if (QPSet_hasElement(&QF_PTR_AT_(QF_subscrList_, sig), p)) {
310 
312  QS_priv_.locFilter[AO_OBJ], me)
313  QS_TIME_(); /* timestamp */
314  QS_SIG_((QSignal)sig); /* the signal of this event */
315  QS_OBJ_(me); /* this active object */
317  }
318  QF_CRIT_EXIT_();
319  }
320 }
#define QS_2U8_(data1_, data2_)
Internal QS macro to output 2 unformatted uint8_t data elements.
Definition: qs.h:708
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:121
QSignal sig
signal of the event instance
Definition: qep.h:153
#define QPSet_findMax(me_, n_)
Find the maximum element in the set, and assign it to n_.
Definition: qpset.h:84
#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:297
first signal that can be used for user signals
Definition: qep.h:609
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:250
#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
unsigned int uint_fast8_t
fast at-least 8-bit unsigned int
Definition: stdint.h:35
Internal (package scope) QF/C interface.
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
an event was published
Definition: qs.h:97
void QF_bzero(void *const start, uint_fast16_t len)
Clear a specified region of memory to zero.
Definition: qf_act.c:159
void QF_gc(QEvt const *const e)
Recycle a dynamic event.
Definition: qf_dyn.c:217
Event structure.
Definition: qep.h:152
#define QPSet_insert(me_, n_)
Insert element n_ into the set me_, n_= 1..32.
Definition: qpset.h:74
uint8_t volatile refCtr_
reference counter
Definition: qep.h:155
#define QPSet_notEmpty(me_)
Evaluates to TRUE if the priority set me_ is not empty.
Definition: qpset.h:67
QSubscrList * QF_subscrList_
the subscriber list array
Definition: qf_ps.c:54
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_SCHED_LOCK_(prio_)
Internal macro for selective scheduler locking.
Definition: qk.h:134
void const * locFilter[MAX_OBJ]
local QS filters
Definition: qs.h:1069
#define QF_SCHED_UNLOCK_()
Internal macro for selective scheduler unlocking.
Definition: qk.h:143
active object
Definition: qs.h:1058
#define QF_EVT_REF_CTR_INC_(e_)
increment the refCtr of an event e_ casting const away
Definition: qf_pkg.h:108
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:131
unsigned int uint_fast16_t
fast at-least 16-bit unsigned int
Definition: stdint.h:37
#define QF_MAX_ACTIVE
The maximum number of active objects in the application.
Definition: 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:254
Priority Set of up to 32 elements.
Definition: qpset.h:56
#define QS_OBJ_(obj_)
Internal macro to output an unformatted object pointer data element.
Definition: qs.h:744
#define QPSet_hasElement(me_, n_)
Evaluates to TRUE if the priority set me_ has element n_.
Definition: qpset.h:70
#define QF_PTR_AT_(base_, i_)
access element at index i_ from the base pointer base_
Definition: qf_pkg.h:114
#define QPSet_remove(me_, n_)
Remove element n_ from the set me_, n_= 1..32.
Definition: qpset.h:78
#define QS_TIME_()
Internal macro to output time stamp to a QS record.
Definition: qs.h:205
#define QS_END_NOCRIT_()
Internal QS macro to end a QS record without exiting critical section.
Definition: qs.h:700
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:205
Active Object (based on QHsm implementation)
Definition: qf.h:110
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:85
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:252
uint_fast8_t prio
QF priority (1..QF_MAX_ACTIVE) of this active object.
Definition: qf.h:153
#define QF_CRIT_EXIT_()
This is an internal macro for exiting a critical section.
Definition: qf_pkg.h:81