QP/C  7.3.4
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.1.1 <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 : 2024-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) % 0x3E8U))
59#error qpc version 7.3.0 or higher required
60#endif
61//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62
63//$define${QF::QEQueue} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
64
65//${QF::QEQueue} .............................................................
67
68//${QF::QEQueue::init} .......................................................
69//! @public @memberof QEQueue
70void QEQueue_init(QEQueue * const me,
71 struct QEvt const ** const qSto,
72 uint_fast16_t const qLen)
73{
74 me->frontEvt = (QEvt *)0; // no events in the queue
75 me->ring = qSto; // the beginning of the ring buffer
76 me->end = (QEQueueCtr)qLen;
77 if (qLen != 0U) {
78 me->head = 0U;
79 me->tail = 0U;
80 }
81 me->nFree = (QEQueueCtr)(qLen + 1U); // +1 for frontEvt
82 me->nMin = me->nFree;
83}
84
85//${QF::QEQueue::post} .......................................................
86//! @public @memberof QEQueue
87bool QEQueue_post(QEQueue * const me,
88 struct QEvt const * const e,
89 uint_fast16_t const margin,
90 uint_fast8_t const qsId)
91{
92 #ifndef Q_SPY
93 Q_UNUSED_PAR(qsId);
94 #endif
95
98 QF_MEM_SYS();
99
100 Q_REQUIRE_INCRIT(200, e != (QEvt *)0);
101
102 QEQueueCtr nFree = me->nFree; // get volatile into temporary
103
104 // required margin available?
105 bool status;
106 if (((margin == QF_NO_MARGIN) && (nFree > 0U))
107 || (nFree > (QEQueueCtr)margin))
108 {
109 // is it a mutable event?
110 if (QEvt_getPoolNum_(e) != 0U) {
111 QEvt_refCtr_inc_(e); // increment the reference counter
112 }
113
114 --nFree; // one free entry just used up
115 me->nFree = nFree; // update the original
116 if (me->nMin > nFree) {
117 me->nMin = nFree; // update minimum so far
118 }
119
120 QS_BEGIN_PRE_(QS_QF_EQUEUE_POST, qsId)
121 QS_TIME_PRE_(); // timestamp
122 QS_SIG_PRE_(e->sig); // the signal of this event
123 QS_OBJ_PRE_(me); // this queue object
124 QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr
125 QS_EQC_PRE_(nFree); // # free entries
126 QS_EQC_PRE_(me->nMin); // min # free entries
127 QS_END_PRE_()
128
129 if (me->frontEvt == (QEvt *)0) { // was the queue empty?
130 me->frontEvt = e; // deliver event directly
131 }
132 else { // queue was not empty, insert event into the ring-buffer
133 // insert event into the ring buffer (FIFO)...
134 me->ring[me->head] = e; // insert e into buffer
135 // need to wrap the head?
136 if (me->head == 0U) {
137 me->head = me->end; // wrap around
138 }
139 --me->head;
140 }
141 status = true; // event posted successfully
142 }
143 else { // event cannot be posted
144 // dropping events must be acceptable
145 Q_ASSERT_INCRIT(210, margin != QF_NO_MARGIN);
146
147 QS_BEGIN_PRE_(QS_QF_EQUEUE_POST_ATTEMPT, qsId)
148 QS_TIME_PRE_(); // timestamp
149 QS_SIG_PRE_(e->sig); // the signal of this event
150 QS_OBJ_PRE_(me); // this queue object
151 QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr
152 QS_EQC_PRE_(nFree); // # free entries
153 QS_EQC_PRE_(margin); // margin requested
154 QS_END_PRE_()
155
156 status = false; // event not posted
157 }
158
159 QF_MEM_APP();
160 QF_CRIT_EXIT();
161
162 return status;
163}
164
165//${QF::QEQueue::postLIFO} ...................................................
166//! @public @memberof QEQueue
167void QEQueue_postLIFO(QEQueue * const me,
168 struct QEvt const * const e,
169 uint_fast8_t const qsId)
170{
171 #ifndef Q_SPY
172 Q_UNUSED_PAR(qsId);
173 #endif
174
177 QF_MEM_SYS();
178
179 QEQueueCtr nFree = me->nFree; // get volatile into temporary
180
181 Q_REQUIRE_INCRIT(300, nFree != 0U);
182
183 if (QEvt_getPoolNum_(e) != 0U) { // is it a mutable event?
184 QEvt_refCtr_inc_(e); // increment the reference counter
185 }
186
187 --nFree; // one free entry just used up
188 me->nFree = nFree; // update the original
189 if (me->nMin > nFree) {
190 me->nMin = nFree; // update minimum so far
191 }
192
193 QS_BEGIN_PRE_(QS_QF_EQUEUE_POST_LIFO, qsId)
194 QS_TIME_PRE_(); // timestamp
195 QS_SIG_PRE_(e->sig); // the signal of this event
196 QS_OBJ_PRE_(me); // this queue object
197 QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr
198 QS_EQC_PRE_(nFree); // # free entries
199 QS_EQC_PRE_(me->nMin); // min # free entries
200 QS_END_PRE_()
201
202 QEvt const * const frontEvt = me->frontEvt; // read into temporary
203 me->frontEvt = e; // deliver event directly to the front of the queue
204
205 if (frontEvt != (QEvt *)0) { // was the queue not empty?
206 ++me->tail;
207 if (me->tail == me->end) { // need to wrap the tail?
208 me->tail = 0U; // wrap around
209 }
210 me->ring[me->tail] = frontEvt; // save old front evt
211 }
212
213 QF_MEM_APP();
214 QF_CRIT_EXIT();
215}
216
217//${QF::QEQueue::get} ........................................................
218//! @public @memberof QEQueue
219struct QEvt const * QEQueue_get(QEQueue * const me,
220 uint_fast8_t const qsId)
221{
222 #ifndef Q_SPY
223 Q_UNUSED_PAR(qsId);
224 #endif
225
228 QF_MEM_SYS();
229
230 QEvt const * const e = me->frontEvt; // always remove evt from the front
231
232 if (e != (QEvt *)0) { // was the queue not empty?
233 // use a temporary variable to increment me->nFree
234 QEQueueCtr const nFree = me->nFree + 1U;
235 me->nFree = nFree; // update the # free
236
237 // any events in the ring buffer?
238 if (nFree <= me->end) {
239 me->frontEvt = me->ring[me->tail]; // get from tail
240 if (me->tail == 0U) { // need to wrap the tail?
241 me->tail = me->end; // wrap around
242 }
243 --me->tail;
244
245 QS_BEGIN_PRE_(QS_QF_EQUEUE_GET, qsId)
246 QS_TIME_PRE_(); // timestamp
247 QS_SIG_PRE_(e->sig); // the signal of this event
248 QS_OBJ_PRE_(me); // this queue object
249 QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr
250 QS_EQC_PRE_(nFree); // # free entries
251 QS_END_PRE_()
252 }
253 else {
254 me->frontEvt = (QEvt *)0; // queue becomes empty
255
256 // all entries in the queue must be free (+1 for fronEvt)
257 Q_ASSERT_INCRIT(410, nFree == (me->end + 1U));
258
259 QS_BEGIN_PRE_(QS_QF_EQUEUE_GET_LAST, qsId)
260 QS_TIME_PRE_(); // timestamp
261 QS_SIG_PRE_(e->sig); // the signal of this event
262 QS_OBJ_PRE_(me); // this queue object
263 QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr
264 QS_END_PRE_()
265 }
266 }
267
268 QF_MEM_APP();
269 QF_CRIT_EXIT();
270
271 return e;
272}
273//$enddef${QF::QEQueue} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
uint16_t QEQueueCtr
Definition qequeue.h:53
QEQueue QEQueue_dummy
#define QF_MEM_APP()
Definition qp.h:1284
#define Q_UNUSED_PAR(par_)
Definition qp.h:532
#define QF_NO_MARGIN
Definition qp.h:1154
#define QF_MEM_SYS()
Definition qp.h:1279
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 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
struct QEvt const ** ring
Definition qequeue.h:73
QEQueueCtr nMin
Definition qequeue.h:88
QEQueueCtr volatile nFree
Definition qequeue.h:85
QEQueueCtr end
Definition qequeue.h:76
QEQueueCtr volatile head
Definition qequeue.h:79
struct QEvt const *volatile frontEvt
Definition qequeue.h:70
QEQueueCtr volatile tail
Definition qequeue.h:82
Event class.
Definition qp.h:147
static uint_fast8_t QEvt_getPoolNum_(QEvt const *const me)
Definition qp.h:187
uint8_t volatile refCtr_
Definition qp.h:156
QSignal sig
Definition qp.h:151