QP/C  8.0.0
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qf_qeq.c
Go to the documentation of this file.
1//$file${src::qf::qf_qeq.c} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpc.qm
4// File: ${src::qf::qf_qeq.c}
5//
6// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
7// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
8//
9// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
10//
11// Q u a n t u m L e a P s
12// ------------------------
13// Modern Embedded Software
14//
15// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
16//
17// The QP/C software is dual-licensed under the terms of the open-source GNU
18// General Public License (GPL) or under the terms of one of the closed-
19// source Quantum Leaps commercial licenses.
20//
21// Redistributions in source code must retain this top-level comment block.
22// Plagiarizing this software to sidestep the license obligations is illegal.
23//
24// NOTE:
25// The GPL does NOT permit the incorporation of this code into proprietary
26// programs. Please contact Quantum Leaps for commercial licensing options,
27// which expressly supersede the GPL and are designed explicitly for
28// closed-source distribution.
29//
30// Quantum Leaps contact information:
31// <www.state-machine.com/licensing>
32// <info@state-machine.com>
33//
34//$endhead${src::qf::qf_qeq.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35#define QP_IMPL // this is QP implementation
36#include "qp_port.h" // QP port
37#include "qp_pkg.h" // QP package-scope interface
38#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
39#ifdef Q_SPY // QS software tracing enabled?
40 #include "qs_port.h" // QS port
41 #include "qs_pkg.h" // QS facilities for pre-defined trace records
42#else
43 #include "qs_dummy.h" // disable the QS software tracing
44#endif // Q_SPY
45
46Q_DEFINE_THIS_MODULE("qf_qeq")
47
48//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
49// Check for the minimum required QP version
50#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
51#error qpc version 7.3.0 or higher required
52#endif
53//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
54//$define${QF::QEQueue} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
55
56//${QF::QEQueue} .............................................................
57
58//${QF::QEQueue::init} .......................................................
59//! @public @memberof QEQueue
60void QEQueue_init(QEQueue * const me,
61 struct QEvt const * * const qSto,
62 uint_fast16_t const qLen)
63{
66 QF_MEM_SYS();
67
68 #if (QF_EQUEUE_CTR_SIZE == 1U)
69 Q_REQUIRE_INCRIT(100, qLen < 0xFFU);
70 #endif
71
72 me->frontEvt = (QEvt *)0; // no events in the queue
73 me->ring = qSto; // the beginning of the ring buffer
74 me->end = (QEQueueCtr)qLen;
75 if (qLen > 0U) {
76 me->head = 0U;
77 me->tail = 0U;
78 }
79 me->nFree = (QEQueueCtr)(qLen + 1U); // +1 for frontEvt
80
81 #ifndef Q_UNSAFE
82 me->frontEvt_dis = (uintptr_t)~Q_PTR2UINT_CAST_(me->frontEvt);
83 me->head_dis = (QEQueueCtr)~me->head;
84 me->tail_dis = (QEQueueCtr)~me->tail;
85 me->nFree_dis = (QEQueueCtr)~me->nFree;
86 me->nMin = me->nFree;
87 #endif
88
89 QF_MEM_APP();
91}
92
93//${QF::QEQueue::post} .......................................................
94//! @public @memberof QEQueue
95bool QEQueue_post(QEQueue * const me,
96 struct QEvt const * const e,
97 uint_fast16_t const margin,
98 uint_fast8_t const qsId)
99{
100 #ifndef Q_SPY
101 Q_UNUSED_PAR(qsId);
102 #endif
103
106 QF_MEM_SYS();
107
108 Q_REQUIRE_INCRIT(200, e != (QEvt *)0);
109
110 QEQueueCtr tmp = me->nFree; // get volatile into temporary
111
112 #ifndef Q_UNSAFE
113 Q_INVARIANT_INCRIT(201, QEvt_verify_(e));
114 QEQueueCtr dis = (QEQueueCtr)~me->nFree_dis;
115 Q_INVARIANT_INCRIT(202, tmp == dis);
116 #endif // ndef Q_UNSAFE
117
118 // test-probe#1 for faking queue overflow
119 QS_TEST_PROBE_DEF(&QEQueue_post)
121 tmp = 0U; // fake no free events
122 )
123
124 // required margin available?
125 bool status;
126 if (((margin == QF_NO_MARGIN) && (tmp > 0U))
127 || (tmp > (QEQueueCtr)margin))
128 {
129 // is it a mutable event?
130 if (QEvt_getPoolNum_(e) != 0U) {
131 QEvt_refCtr_inc_(e); // increment the reference counter
132 }
133
134 --tmp; // one free entry just used up
135
136 me->nFree = tmp; // update the original
137 #ifndef Q_UNSAFE
138 me->nFree_dis = (QEQueueCtr)~tmp;
139
140 if (me->nMin > tmp) {
141 me->nMin = tmp; // update minimum so far
142 }
143 #endif // ndef Q_UNSAFE
144
145 QS_BEGIN_PRE(QS_QF_EQUEUE_POST, qsId)
146 QS_TIME_PRE(); // timestamp
147 QS_SIG_PRE(e->sig); // the signal of the event
148 QS_OBJ_PRE(me); // this queue object
149 QS_2U8_PRE(QEvt_getPoolNum_(e), e->refCtr_);
150 QS_EQC_PRE(tmp); // # free entries
151 #ifndef Q_UNSAFE
152 QS_EQC_PRE(me->nMin); // min # free entries
153 #else
154 QS_EQC_PRE(0U); // min # free entries
155 #endif
156 QS_END_PRE()
157
158 if (me->frontEvt == (QEvt *)0) { // is the queue empty?
159 me->frontEvt = e; // deliver event directly
160 #ifndef Q_UNSAFE
162 == (uintptr_t)~Q_PTR2UINT_CAST_((QEvt *)0));
163 me->frontEvt_dis = (uintptr_t)~Q_PTR2UINT_CAST_(e);
164 #endif // ndef Q_UNSAFE
165 }
166 else { // queue was not empty, insert event into the ring-buffer
167 tmp = me->head; // get volatile into temporary
168 #ifndef Q_UNSAFE
169 dis = (QEQueueCtr)~me->head_dis;
170 Q_INVARIANT_INCRIT(212, tmp == dis);
171 #endif // ndef Q_UNSAFE
172 me->ring[tmp] = e; // insert e into buffer
173
174 if (tmp == 0U) { // need to wrap the head?
175 tmp = me->end;
176 }
177 --tmp; // advance head (counter-clockwise)
178
179 me->head = tmp; // update the original
180 #ifndef Q_UNSAFE
181 me->head_dis = (QEQueueCtr)~tmp;
182 #endif // ndef Q_UNSAFE
183 }
184 status = true; // event posted successfully
185 }
186 else { // event cannot be posted
187 // dropping events must be acceptable
188 Q_ASSERT_INCRIT(210, margin != QF_NO_MARGIN);
189
190 QS_BEGIN_PRE(QS_QF_EQUEUE_POST_ATTEMPT, qsId)
191 QS_TIME_PRE(); // timestamp
192 QS_SIG_PRE(e->sig); // the signal of this event
193 QS_OBJ_PRE(me); // this queue object
194 QS_2U8_PRE(QEvt_getPoolNum_(e), e->refCtr_);
195 QS_EQC_PRE(tmp); // # free entries
196 QS_EQC_PRE(margin); // margin requested
197 QS_END_PRE()
198
199 status = false; // event not posted
200 }
201
202 QF_MEM_APP();
203 QF_CRIT_EXIT();
204
205 return status;
206}
207
208//${QF::QEQueue::postLIFO} ...................................................
209//! @public @memberof QEQueue
210void QEQueue_postLIFO(QEQueue * const me,
211 struct QEvt const * const e,
212 uint_fast8_t const qsId)
213{
214 #ifndef Q_SPY
215 Q_UNUSED_PAR(qsId);
216 #endif
217
220 QF_MEM_SYS();
221
222 Q_REQUIRE_INCRIT(300, e != (QEvt *)0);
223
224 QEQueueCtr tmp = me->nFree; // get volatile into temporary
225
226 #ifndef Q_UNSAFE
227 Q_INVARIANT_INCRIT(301, QEvt_verify_(e));
228 QEQueueCtr dis = (QEQueueCtr)~me->nFree_dis;
229 Q_INVARIANT_INCRIT(302, tmp == dis);
230 #endif // ndef Q_UNSAFE
231
232 // test-probe#1 for faking queue overflow
233 QS_TEST_PROBE_DEF(&QEQueue_postLIFO)
235 tmp = 0U; // fake no free events
236 )
237
238 // must be able to LIFO-post the event
239 Q_REQUIRE_INCRIT(310, tmp != 0U);
240
241 if (QEvt_getPoolNum_(e) != 0U) { // is it a mutable event?
242 QEvt_refCtr_inc_(e); // increment the reference counter
243 }
244
245 --tmp; // one free entry just used up
246
247 me->nFree = tmp; // update the original
248 #ifndef Q_UNSAFE
249 me->nFree_dis = (QEQueueCtr)~tmp;
250
251 if (me->nMin > tmp) {
252 me->nMin = tmp; // update minimum so far
253 }
254 #endif // ndef Q_UNSAFE
255
256 QS_BEGIN_PRE(QS_QF_EQUEUE_POST_LIFO, qsId)
257 QS_TIME_PRE(); // timestamp
258 QS_SIG_PRE(e->sig); // the signal of this event
259 QS_OBJ_PRE(me); // this queue object
260 QS_2U8_PRE(QEvt_getPoolNum_(e), e->refCtr_);
261 QS_EQC_PRE(tmp); // # free entries
262 #ifndef Q_UNSAFE
263 QS_EQC_PRE(me->nMin); // min # free entries
264 #else
265 QS_EQC_PRE(0U); // min # free entries
266 #endif
267 QS_END_PRE()
268
269 QEvt const * const frontEvt = me->frontEvt;
270 me->frontEvt = e; // deliver the event directly to the front
271 #ifndef Q_UNSAFE
272 me->frontEvt_dis = (uintptr_t)~Q_PTR2UINT_CAST_(e);
273 #endif // ndef Q_UNSAFE
274
275 if (frontEvt != (QEvt *)0) { // was the queue NOT empty?
276 tmp = me->tail; // get volatile into temporary;
277 #ifndef Q_UNSAFE
278 dis = (QEQueueCtr)~me->tail_dis;
279 Q_INVARIANT_INCRIT(311, tmp == dis);
280 #endif // ndef Q_UNSAFE
281 ++tmp;
282 if (tmp == me->end) { // need to wrap the tail?
283 tmp = 0U; // wrap around
284 }
285 me->tail = tmp;
286 #ifndef Q_UNSAFE
287 me->tail_dis = (QEQueueCtr)~tmp;
288 #endif
289 me->ring[tmp] = frontEvt;
290 }
291
292 QF_MEM_APP();
293 QF_CRIT_EXIT();
294}
295
296//${QF::QEQueue::get} ........................................................
297//! @public @memberof QEQueue
298struct QEvt const * QEQueue_get(QEQueue * const me,
299 uint_fast8_t const qsId)
300{
301 #ifndef Q_SPY
302 Q_UNUSED_PAR(qsId);
303 #endif
304
307 QF_MEM_SYS();
308
309 QEvt const * const e = me->frontEvt; // always remove evt from the front
310 #ifndef Q_UNSAFE
312 == (uintptr_t)~me->frontEvt_dis);
313 #endif // ndef Q_UNSAFE
314
315 if (e != (QEvt *)0) { // was the queue not empty?
316 QEQueueCtr tmp = me->nFree; // get volatile into temporary
317 #ifndef Q_UNSAFE
318 QEQueueCtr const dis = (QEQueueCtr)~me->nFree_dis;
319 Q_INVARIANT_INCRIT(412, tmp == dis);
320 #endif // ndef Q_UNSAFE
321
322 ++tmp; // one more free event in the queue
323
324 me->nFree = tmp; // update the # free
325 #ifndef Q_UNSAFE
326 me->nFree_dis = (QEQueueCtr)~tmp;
327 #endif // ndef Q_UNSAFE
328
329 // any events in the ring buffer?
330 if (tmp <= me->end) {
331
332 QS_BEGIN_PRE(QS_QF_EQUEUE_GET, qsId)
333 QS_TIME_PRE(); // timestamp
334 QS_SIG_PRE(e->sig); // the signal of this event
335 QS_OBJ_PRE(me); // this queue object
337 QS_EQC_PRE(tmp); // # free entries
338 QS_END_PRE()
339
340 tmp = me->tail; // get volatile into temporary
341 QEvt const * const frontEvt = me->ring[tmp];
342 #ifndef Q_UNSAFE
343 Q_ASSERT_INCRIT(421, frontEvt != (QEvt *)0);
344 me->frontEvt_dis = (uintptr_t)~Q_PTR2UINT_CAST_(frontEvt);
345 #endif // ndef Q_UNSAFE
346 me->frontEvt = frontEvt; // update the original
347
348 if (tmp == 0U) { // need to wrap the tail?
349 tmp = me->end;
350 }
351 --tmp; // advance the tail (counter-clockwise)
352 me->tail = tmp; // update the original
353 #ifndef Q_UNSAFE
354 me->tail_dis = (QEQueueCtr)~tmp;
355 #endif // ndef Q_UNSAFE
356 }
357 else {
358 me->frontEvt = (QEvt *)0; // queue becomes empty
359 #ifndef Q_UNSAFE
360 me->frontEvt_dis = (uintptr_t)~Q_PTR2UINT_CAST_((QEvt *)0);
361 #endif // ndef Q_UNSAFE
362
363 // all entries in the queue must be free (+1 for frontEvt)
364 Q_INVARIANT_INCRIT(440, tmp == (me->end + 1U));
365
366 QS_BEGIN_PRE(QS_QF_EQUEUE_GET_LAST, qsId)
367 QS_TIME_PRE(); // timestamp
368 QS_SIG_PRE(e->sig); // the signal of this event
369 QS_OBJ_PRE(me); // this queue object
371 QS_END_PRE()
372 }
373 }
374
375 QF_MEM_APP();
376 QF_CRIT_EXIT();
377
378 return e;
379}
380//$enddef${QF::QEQueue} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
uint16_t QEQueueCtr
Definition qequeue.h:45
#define QF_MEM_APP()
Definition qp.h:1276
#define Q_UNUSED_PAR(par_)
Helper macro to clearly mark unused parameters of functions.
Definition qp.h:521
#define QF_NO_MARGIN
Special value of margin that causes asserting failure in case event allocation or event posting fails...
Definition qp.h:1151
#define QF_MEM_SYS()
Definition qp.h:1271
Internal (package scope) QP/C interface.
#define Q_PTR2UINT_CAST_(ptr_)
Definition qp_pkg.h:95
Sample QP/C port.
#define QS_OBJ_PRE(obj_)
Definition qs_dummy.h:150
#define QS_EQC_PRE(ctr_)
Definition qs_dummy.h:152
#define QS_SIG_PRE(sig_)
Definition qs_dummy.h:148
#define QS_TIME_PRE()
Definition qs_dummy.h:147
#define QS_2U8_PRE(data1_, data2_)
Definition qs_dummy.h:144
#define QS_TEST_PROBE_DEF(fun_)
Definition qs_dummy.h:78
#define QS_TEST_PROBE_ID(id_, code_)
Definition qs_dummy.h:80
#define QS_END_PRE()
Definition qs_dummy.h:142
#define QS_BEGIN_PRE(rec_, qsId_)
Definition qs_dummy.h:141
Sample QS/C port.
QP Functional Safety (FuSa) Subsystem.
#define QF_CRIT_ENTRY()
Definition qsafe.h:50
#define Q_ASSERT_INCRIT(id_, expr_)
Definition qsafe.h:64
#define Q_INVARIANT_INCRIT(id_, expr_)
Definition qsafe.h:146
#define QF_CRIT_EXIT()
Definition qsafe.h:54
#define Q_REQUIRE_INCRIT(id_, expr_)
Definition qsafe.h:128
#define QF_CRIT_STAT
Definition qsafe.h:46
Native QF Event Queue.
Definition qequeue.h:56
QEQueueCtr tail_dis
Definition qequeue.h:89
QEQueueCtr volatile tail
Offset of where next event will be extracted from the buffer.
Definition qequeue.h:72
QEQueueCtr nFree_dis
Definition qequeue.h:94
QEQueueCtr volatile head
Offset to where next event will be inserted into the buffer.
Definition qequeue.h:69
QEQueueCtr end
Offset of the end of the ring buffer from the start of the buffer.
Definition qequeue.h:66
QEQueueCtr nMin
Minimum number of free events ever in the ring buffer.
Definition qequeue.h:99
QEQueueCtr volatile nFree
Number of free events in the ring buffer.
Definition qequeue.h:75
struct QEvt const ** ring
Pointer to the start of the ring buffer.
Definition qequeue.h:63
QEQueueCtr head_dis
Definition qequeue.h:84
uintptr_t frontEvt_dis
Definition qequeue.h:79
struct QEvt const *volatile frontEvt
Pointer to event at the front of the queue.
Definition qequeue.h:60
Event class.
Definition qp.h:131
QSignal sig
Signal of the event (see Event Signal)
Definition qp.h:135
uint8_t volatile refCtr_
Event reference counter.
Definition qp.h:143
static uint_fast8_t QEvt_getPoolNum_(QEvt const *const me)
Internal function to get the event pool-number of the given event.
Definition qp.h:179