QP/C  7.4.0-rc.3
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 6.2.0 <www.state-machine.com/qm>.
7// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
8//
9// This code is covered by the following QP license:
10// License # : LicenseRef-QL-dual
11// Issued to : Any user of the QP/C real-time embedded framework
12// Framework(s) : qpc
13// Support ends : 2025-12-31
14// License scope:
15//
16// Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
17//
18// Q u a n t u m L e a P s
19// ------------------------
20// Modern Embedded Software
21//
22// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
23//
24// This software is dual-licensed under the terms of the open source GNU
25// General Public License version 3 (or any later version), or alternatively,
26// under the terms of one of the closed source Quantum Leaps commercial
27// licenses.
28//
29// The terms of the open source GNU General Public License version 3
30// can be found at: <www.gnu.org/licenses/gpl-3.0>
31//
32// The terms of the closed source Quantum Leaps commercial licenses
33// can be found at: <www.state-machine.com/licensing>
34//
35// Redistributions in source code must retain this top-level comment block.
36// Plagiarizing this software to sidestep the license obligations is illegal.
37//
38// Contact information:
39// <www.state-machine.com/licensing>
40// <info@state-machine.com>
41//
42//$endhead${src::qf::qf_qeq.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43#define QP_IMPL // this is QP implementation
44#include "qp_port.h" // QP port
45#include "qp_pkg.h" // QP package-scope interface
46#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
47#ifdef Q_SPY // QS software tracing enabled?
48 #include "qs_port.h" // QS port
49 #include "qs_pkg.h" // QS facilities for pre-defined trace records
50#else
51 #include "qs_dummy.h" // disable the QS software tracing
52#endif // Q_SPY
53
54Q_DEFINE_THIS_MODULE("qf_qeq")
55
56//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
57// Check for the minimum required QP version
58#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
59#error qpc version 7.3.0 or higher required
60#endif
61//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62//$define${QF::QEQueue} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
63
64//${QF::QEQueue} .............................................................
66
67//${QF::QEQueue::init} .......................................................
68//! @public @memberof QEQueue
69void QEQueue_init(QEQueue * const me,
70 struct QEvt const ** const qSto,
71 uint_fast16_t const qLen)
72{
75 QF_MEM_SYS();
76
77 #if (QF_EQUEUE_CTR_SIZE == 1U)
78 Q_REQUIRE_INCRIT(100, qLen < 0xFFU);
79 #endif
80
81 me->frontEvt = (QEvt *)0; // no events in the queue
82 me->ring = qSto; // the beginning of the ring buffer
83 me->end = (QEQueueCtr)qLen;
84 if (qLen != 0U) {
85 me->head = 0U;
86 me->tail = 0U;
87 }
88 me->nFree = (QEQueueCtr)(qLen + 1U); // +1 for frontEvt
89 me->nMin = me->nFree;
90
91 QF_MEM_APP();
93}
94
95//${QF::QEQueue::post} .......................................................
96//! @public @memberof QEQueue
97bool QEQueue_post(QEQueue * const me,
98 struct QEvt const * const e,
99 uint_fast16_t const margin,
100 uint_fast8_t const qsId)
101{
102 #ifndef Q_SPY
103 Q_UNUSED_PAR(qsId);
104 #endif
105
108 QF_MEM_SYS();
109
110 Q_REQUIRE_INCRIT(200, QEvt_verify_(e));
111
112 QEQueueCtr nFree = me->nFree; // get volatile into temporary
113
114 // required margin available?
115 bool status;
116 if (((margin == QF_NO_MARGIN) && (nFree > 0U))
117 || (nFree > (QEQueueCtr)margin))
118 {
119 // is it a mutable event?
120 if (QEvt_getPoolNum_(e) != 0U) {
121 QEvt_refCtr_inc_(e); // increment the reference counter
122 }
123
124 --nFree; // one free entry just used up
125 me->nFree = nFree; // update the original
126 if (me->nMin > nFree) {
127 me->nMin = nFree; // update minimum so far
128 }
129
130 QS_BEGIN_PRE_(QS_QF_EQUEUE_POST, qsId)
131 QS_TIME_PRE_(); // timestamp
132 QS_SIG_PRE_(e->sig); // the signal of this event
133 QS_OBJ_PRE_(me); // this queue object
134 QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr
135 QS_EQC_PRE_(nFree); // # free entries
136 QS_EQC_PRE_(me->nMin); // min # free entries
137 QS_END_PRE_()
138
139 if (me->frontEvt == (QEvt *)0) { // was the queue empty?
140 me->frontEvt = e; // deliver event directly
141 }
142 else { // queue was not empty, insert event into the ring-buffer
143 // insert event into the ring buffer (FIFO)...
144 me->ring[me->head] = e; // insert e into buffer
145 // need to wrap the head?
146 if (me->head == 0U) {
147 me->head = me->end; // wrap around
148 }
149 --me->head;
150 }
151 status = true; // event posted successfully
152 }
153 else { // event cannot be posted
154 // dropping events must be acceptable
155 Q_ASSERT_INCRIT(210, margin != QF_NO_MARGIN);
156
157 QS_BEGIN_PRE_(QS_QF_EQUEUE_POST_ATTEMPT, qsId)
158 QS_TIME_PRE_(); // timestamp
159 QS_SIG_PRE_(e->sig); // the signal of this event
160 QS_OBJ_PRE_(me); // this queue object
161 QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr
162 QS_EQC_PRE_(nFree); // # free entries
163 QS_EQC_PRE_(margin); // margin requested
164 QS_END_PRE_()
165
166 status = false; // event not posted
167 }
168
169 QF_MEM_APP();
170 QF_CRIT_EXIT();
171
172 return status;
173}
174
175//${QF::QEQueue::postLIFO} ...................................................
176//! @public @memberof QEQueue
177void QEQueue_postLIFO(QEQueue * const me,
178 struct QEvt const * const e,
179 uint_fast8_t const qsId)
180{
181 #ifndef Q_SPY
182 Q_UNUSED_PAR(qsId);
183 #endif
184
187 QF_MEM_SYS();
188
189 Q_REQUIRE_INCRIT(300, QEvt_verify_(e));
190
191 QEQueueCtr nFree = me->nFree; // get volatile into temporary
192 Q_REQUIRE_INCRIT(301, nFree != 0U);
193
194 if (QEvt_getPoolNum_(e) != 0U) { // is it a mutable event?
195 QEvt_refCtr_inc_(e); // increment the reference counter
196 }
197
198 --nFree; // one free entry just used up
199 me->nFree = nFree; // update the original
200 if (me->nMin > nFree) {
201 me->nMin = nFree; // update minimum so far
202 }
203
204 QS_BEGIN_PRE_(QS_QF_EQUEUE_POST_LIFO, qsId)
205 QS_TIME_PRE_(); // timestamp
206 QS_SIG_PRE_(e->sig); // the signal of this event
207 QS_OBJ_PRE_(me); // this queue object
208 QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr
209 QS_EQC_PRE_(nFree); // # free entries
210 QS_EQC_PRE_(me->nMin); // min # free entries
211 QS_END_PRE_()
212
213 QEvt const * const frontEvt = me->frontEvt; // read into temporary
214 me->frontEvt = e; // deliver event directly to the front of the queue
215
216 if (frontEvt != (QEvt *)0) { // was the queue not empty?
217 ++me->tail;
218 if (me->tail == me->end) { // need to wrap the tail?
219 me->tail = 0U; // wrap around
220 }
221 me->ring[me->tail] = frontEvt; // save old front evt
222 }
223
224 QF_MEM_APP();
225 QF_CRIT_EXIT();
226}
227
228//${QF::QEQueue::get} ........................................................
229//! @public @memberof QEQueue
230struct QEvt const * QEQueue_get(QEQueue * const me,
231 uint_fast8_t const qsId)
232{
233 #ifndef Q_SPY
234 Q_UNUSED_PAR(qsId);
235 #endif
236
239 QF_MEM_SYS();
240
241 QEvt const * const e = me->frontEvt; // always remove evt from the front
242
243 if (e != (QEvt *)0) { // was the queue not empty?
245
246 // use a temporary variable to increment me->nFree
247 QEQueueCtr const nFree = me->nFree + 1U;
248 me->nFree = nFree; // update the # free
249
250 // any events in the ring buffer?
251 if (nFree <= me->end) {
252 me->frontEvt = me->ring[me->tail]; // get from tail
253 if (me->tail == 0U) { // need to wrap the tail?
254 me->tail = me->end; // wrap around
255 }
256 --me->tail;
257
258 QS_BEGIN_PRE_(QS_QF_EQUEUE_GET, qsId)
259 QS_TIME_PRE_(); // timestamp
260 QS_SIG_PRE_(e->sig); // the signal of this event
261 QS_OBJ_PRE_(me); // this queue object
262 QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr
263 QS_EQC_PRE_(nFree); // # free entries
264 QS_END_PRE_()
265 }
266 else {
267 me->frontEvt = (QEvt *)0; // queue becomes empty
268
269 // all entries in the queue must be free (+1 for fronEvt)
270 Q_INVARIANT_INCRIT(420, nFree == (me->end + 1U));
271
272 QS_BEGIN_PRE_(QS_QF_EQUEUE_GET_LAST, qsId)
273 QS_TIME_PRE_(); // timestamp
274 QS_SIG_PRE_(e->sig); // the signal of this event
275 QS_OBJ_PRE_(me); // this queue object
276 QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr
277 QS_END_PRE_()
278 }
279 }
280
281 QF_MEM_APP();
282 QF_CRIT_EXIT();
283
284 return e;
285}
286//$enddef${QF::QEQueue} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
QEQueue QEQueue_dummy
uint16_t QEQueueCtr
Definition qequeue.h:53
#define QF_MEM_APP()
Definition qp.h:1288
#define Q_UNUSED_PAR(par_)
Helper macro to clearly mark unused parameters of functions.
Definition qp.h:536
#define QF_NO_MARGIN
Special value of margin that causes asserting failure in case event allocation or event posting fails...
Definition qp.h:1158
#define QF_MEM_SYS()
Definition qp.h:1283
Internal (package scope) QP/C interface.
Sample QP/C port.
@ QS_QF_EQUEUE_GET_LAST
get the last event from the queue
Definition qs.h:107
#define QS_TIME_PRE_()
Definition qs.h:450
@ QS_QF_EQUEUE_POST_ATTEMPT
attempt to post evt to QEQueue failed
Definition qs.h:145
@ QS_QF_EQUEUE_POST_LIFO
an event was posted (LIFO) to a raw queue
Definition qs.h:105
@ QS_QF_EQUEUE_GET
get an event and queue still not empty
Definition qs.h:106
@ QS_QF_EQUEUE_POST
an event was posted (FIFO) to a raw queue
Definition qs.h:104
QS/C package-scope interface.
Sample QS/C port.
QP Functional Safety (FuSa) Subsystem.
#define QF_CRIT_ENTRY()
Definition qsafe.h:58
#define Q_ASSERT_INCRIT(id_, expr_)
Definition qsafe.h:72
#define Q_INVARIANT_INCRIT(id_, expr_)
Definition qsafe.h:154
#define QF_CRIT_EXIT()
Definition qsafe.h:62
#define Q_REQUIRE_INCRIT(id_, expr_)
Definition qsafe.h:136
#define QF_CRIT_STAT
Definition qsafe.h:54
Native QF Event Queue.
Definition qequeue.h:66
QEQueueCtr volatile tail
Offset of where next event will be extracted from the buffer.
Definition qequeue.h:82
QEQueueCtr volatile head
Offset to where next event will be inserted into the buffer.
Definition qequeue.h:79
QEQueueCtr end
Offset of the end of the ring buffer from the start of the buffer.
Definition qequeue.h:76
QEQueueCtr nMin
Minimum number of free events ever in the ring buffer.
Definition qequeue.h:88
QEQueueCtr volatile nFree
Number of free events in the ring buffer.
Definition qequeue.h:85
struct QEvt const ** ring
Pointer to the start of the ring buffer.
Definition qequeue.h:73
struct QEvt const *volatile frontEvt
Pointer to event at the front of the queue.
Definition qequeue.h:70
Event class.
Definition qp.h:145
QSignal sig
Signal of the event (see Event Signal)
Definition qp.h:149
uint8_t volatile refCtr_
Reference counter (for mutable events and 0 for immutable (static) events)
Definition qp.h:154
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:190
static bool QEvt_verify_(QEvt const *const me)
Internal function to verify the event pointer and the memory marker in the event (QP FuSa Subsystem)
Definition qp.h:184