QP/C  7.0.0
Real-Time Embedded Framework
qf_qeq.c
Go to the documentation of this file.
1/*============================================================================
2* QP/C Real-Time Embedded Framework (RTEF)
3* Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
4*
5* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
6*
7* This software is dual-licensed under the terms of the open source GNU
8* General Public License version 3 (or any later version), or alternatively,
9* under the terms of one of the closed source Quantum Leaps commercial
10* licenses.
11*
12* The terms of the open source GNU General Public License version 3
13* can be found at: <www.gnu.org/licenses/gpl-3.0>
14*
15* The terms of the closed source Quantum Leaps commercial licenses
16* can be found at: <www.state-machine.com/licensing>
17*
18* Redistributions in source code must retain this top-level comment block.
19* Plagiarizing this software to sidestep the license obligations is illegal.
20*
21* Contact information:
22* <www.state-machine.com>
23* <info@state-machine.com>
24============================================================================*/
32#define QP_IMPL /* this is QP implementation */
33#include "qf_port.h" /* QF port */
34#include "qf_pkg.h" /* QF package-scope interface */
35#include "qassert.h" /* QP embedded systems-friendly assertions */
36#ifdef Q_SPY /* QS software tracing enabled? */
37 #include "qs_port.h" /* QS port */
38 #include "qs_pkg.h" /* QS facilities for pre-defined trace records */
39#else
40 #include "qs_dummy.h" /* disable the QS software tracing */
41#endif /* Q_SPY */
42
44
45/*==========================================================================*/
64void QEQueue_init(QEQueue * const me, QEvt const * * const qSto,
65 uint_fast16_t const qLen)
66{
67 me->frontEvt = (QEvt *)0; /* no events in the queue */
68 me->ring = qSto; /* the beginning of the ring buffer */
69 me->end = (QEQueueCtr)qLen;
70 if (qLen != 0U) {
71 me->head = 0U;
72 me->tail = 0U;
73 }
74 me->nFree = (QEQueueCtr)(qLen + 1U); /* +1 for frontEvt */
75 me->nMin = me->nFree;
76}
77
78/*==========================================================================*/
103bool QEQueue_post(QEQueue * const me, QEvt const * const e,
104 uint_fast16_t const margin, uint_fast8_t const qs_id)
105{
106 /* @pre event must be valid */
107 Q_REQUIRE_ID(200, e != (QEvt *)0);
108
109 (void)qs_id; /* unused parameter (outside Q_SPY build configuration) */
110
112 QF_CRIT_E_();
113 QEQueueCtr nFree = me->nFree; /* get volatile into the temporary */
114
115 /* required margin available? */
116 bool status;
117 if (((margin == QF_NO_MARGIN) && (nFree > 0U))
118 || (nFree > (QEQueueCtr)margin))
119 {
120 /* is it a dynamic event? */
121 if (e->poolId_ != 0U) {
122 QF_EVT_REF_CTR_INC_(e); /* increment the reference counter */
123 }
124
125 --nFree; /* one free entry just used up */
126 me->nFree = nFree; /* update the volatile */
127 if (me->nMin > nFree) {
128 me->nMin = nFree; /* update minimum so far */
129 }
130
132 QS_TIME_PRE_(); /* timestamp */
133 QS_SIG_PRE_(e->sig); /* the signal of this event */
134 QS_OBJ_PRE_(me); /* this queue object */
135 QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
136 QS_EQC_PRE_(nFree); /* number of free entries */
137 QS_EQC_PRE_(me->nMin); /* min number of free entries */
139
140 /* was the queue empty? */
141 if (me->frontEvt == (QEvt *)0) {
142 me->frontEvt = e; /* deliver event directly */
143 }
144 /* queue was not empty, insert event into the ring-buffer */
145 else {
146 /* insert event into the ring buffer (FIFO)... */
147 QF_PTR_AT_(me->ring, me->head) = e; /* insert e into buffer */
148 /* need to wrap the head? */
149 if (me->head == 0U) {
150 me->head = me->end; /* wrap around */
151 }
152 --me->head;
153 }
154 status = true; /* event posted successfully */
155 }
156 else {
160 Q_ASSERT_CRIT_(210, margin != QF_NO_MARGIN);
161
163 QS_TIME_PRE_(); /* timestamp */
164 QS_SIG_PRE_(e->sig); /* the signal of this event */
165 QS_OBJ_PRE_(me); /* this queue object */
166 QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
167 QS_EQC_PRE_(nFree); /* number of free entries */
168 QS_EQC_PRE_(margin); /* margin requested */
170
171 status = false;
172 }
173 QF_CRIT_X_();
174
175 return status;
176}
177
178/*==========================================================================*/
202void QEQueue_postLIFO(QEQueue * const me, QEvt const * const e,
203 uint_fast8_t const qs_id)
204{
205 (void)qs_id; /* unused parameter, if Q_SPY not defined */
206
208 QF_CRIT_E_();
209 QEQueueCtr nFree = me->nFree; /* get volatile into the temporary */
210
212 Q_REQUIRE_CRIT_(300, nFree != 0U);
213
214 /* is it a dynamic event? */
215 if (e->poolId_ != 0U) {
216 QF_EVT_REF_CTR_INC_(e); /* increment the reference counter */
217 }
218
219 --nFree; /* one free entry just used up */
220 me->nFree = nFree; /* update the volatile */
221 if (me->nMin > nFree) {
222 me->nMin = nFree; /* update minimum so far */
223 }
224
226 QS_TIME_PRE_(); /* timestamp */
227 QS_SIG_PRE_(e->sig); /* the signal of this event */
228 QS_OBJ_PRE_(me); /* this queue object */
229 QS_2U8_PRE_(e->poolId_, e->refCtr_);/* pool Id & ref Count of event */
230 QS_EQC_PRE_(nFree); /* number of free entries */
231 QS_EQC_PRE_(me->nMin); /* min number of free entries */
233
234 QEvt const * const frontEvt = me->frontEvt; /* read volatile into temp */
235 me->frontEvt = e; /* deliver event directly to the front of the queue */
236
237 /* was the queue not empty? */
238 if (frontEvt != (QEvt *)0) {
239 ++me->tail;
240 if (me->tail == me->end) { /* need to wrap the tail? */
241 me->tail = 0U; /* wrap around */
242 }
243 QF_PTR_AT_(me->ring, me->tail) = frontEvt; /* save old front evt */
244 }
245 QF_CRIT_X_();
246}
247
248/*==========================================================================*/
268QEvt const *QEQueue_get(QEQueue * const me, uint_fast8_t const qs_id) {
269 (void)qs_id; /* unused parameter (outside Q_SPY build configuration) */
270
272 QF_CRIT_E_();
273 QEvt const * const e = me->frontEvt; /* remove event from the front */
274
275 /* was the queue not empty? */
276 if (e != (QEvt *)0) {
277 /* use a temporary variable to increment volatile me->nFree */
278 QEQueueCtr const nFree = me->nFree + 1U;
279 me->nFree = nFree; /* update the number of free */
280
281 /* any events in the ring buffer? */
282 if (nFree <= me->end) {
283 me->frontEvt = QF_PTR_AT_(me->ring, me->tail); /* get from tail */
284 if (me->tail == 0U) { /* need to wrap the tail? */
285 me->tail = me->end; /* wrap around */
286 }
287 --me->tail;
288
290 QS_TIME_PRE_(); /* timestamp */
291 QS_SIG_PRE_(e->sig); /* the signal of this event */
292 QS_OBJ_PRE_(me); /* this queue object */
293 QS_2U8_PRE_(e->poolId_, e->refCtr_);/* pool Id & ref Count */
294 QS_EQC_PRE_(nFree); /* number of free entries */
296 }
297 else {
298 me->frontEvt = (QEvt *)0; /* queue becomes empty */
299
300 /* all entries in the queue must be free (+1 for fronEvt) */
301 Q_ASSERT_CRIT_(410, nFree == (me->end + 1U));
302
304 QS_TIME_PRE_(); /* timestamp */
305 QS_SIG_PRE_(e->sig); /* the signal of this event */
306 QS_OBJ_PRE_(me); /* this queue object */
307 QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
309 }
310 }
311 QF_CRIT_X_();
312 return e;
313}
Customizable and memory-efficient assertions for embedded systems.
#define Q_DEFINE_THIS_MODULE(name_)
Definition: qassert.h:102
#define Q_REQUIRE_ID(id_, test_)
Definition: qassert.h:252
uint8_t QEQueueCtr
Definition: qequeue.h:63
#define QF_NO_MARGIN
Definition: qf.h:687
Internal (package scope) QF/C interface.
#define QF_CRIT_STAT_
Definition: qf_pkg.h:54
#define QF_PTR_AT_(base_, i_)
Definition: qf_pkg.h:183
#define Q_ASSERT_CRIT_(id_, test_)
Definition: qf_pkg.h:97
#define QF_CRIT_X_()
Definition: qf_pkg.h:78
#define QF_EVT_REF_CTR_INC_(e_)
Definition: qf_pkg.h:177
#define Q_REQUIRE_CRIT_(id_, test_)
Definition: qf_pkg.h:104
#define QF_CRIT_E_()
Definition: qf_pkg.h:66
#define QS_TIME_PRE_()
Definition: qs.h:220
@ QS_QF_EQUEUE_GET_LAST
Definition: qs.h:83
@ QS_QF_EQUEUE_POST_ATTEMPT
Definition: qs.h:121
@ QS_QF_EQUEUE_POST_LIFO
Definition: qs.h:81
@ QS_QF_EQUEUE_GET
Definition: qs.h:82
@ QS_QF_EQUEUE_POST
Definition: qs.h:80
Internal (package scope) QS/C interface.
#define QS_BEGIN_NOCRIT_PRE_(rec_, qs_id_)
Definition: qs_pkg.h:138
#define QS_OBJ_PRE_(obj_)
Definition: qs_pkg.h:179
#define QS_END_NOCRIT_PRE_()
Definition: qs_pkg.h:148
#define QS_2U8_PRE_(data1_, data2_)
Definition: qs_pkg.h:154
#define QS_SIG_PRE_(sig_)
Definition: qs_pkg.h:172
#define QS_EQC_PRE_(ctr_)
Definition: qs_pkg.h:205
QEQueueCtr volatile tail
Definition: qequeue.h:141
QEvt const *volatile frontEvt
Definition: qequeue.h:129
QEvt const * QEQueue_get(QEQueue *const me, uint_fast8_t const qs_id)
Definition: qf_qeq.c:268
QEQueueCtr volatile head
Definition: qequeue.h:138
QEQueueCtr end
Definition: qequeue.h:135
QEvt const ** ring
Definition: qequeue.h:132
QEQueueCtr nMin
Definition: qequeue.h:152
QEQueueCtr volatile nFree
Definition: qequeue.h:144
bool QEQueue_post(QEQueue *const me, QEvt const *const e, uint_fast16_t const margin, uint_fast8_t const qs_id)
Definition: qf_qeq.c:103
void QEQueue_postLIFO(QEQueue *const me, QEvt const *const e, uint_fast8_t const qs_id)
Definition: qf_qeq.c:202
void QEQueue_init(QEQueue *const me, QEvt const **const qSto, uint_fast16_t const qLen)
Definition: qf_qeq.c:64
Definition: qep.h:119
QSignal sig
Definition: qep.h:123
uint8_t poolId_
Definition: qep.h:128
uint8_t volatile refCtr_
Definition: qep.h:133