QP/C  7.3.3
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qxk_sema.c
Go to the documentation of this file.
1//$file${src::qxk::qxk_sema.c} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpc.qm
4// File: ${src::qxk::qxk_sema.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::qxk::qxk_sema.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
54// protection against including this source file in a wrong project
55#ifndef QXK_H_
56 #error "Source file included in a project NOT based on the QXK kernel"
57#endif // QXK_H_
58
59Q_DEFINE_THIS_MODULE("qxk_sema")
60
61//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
62// Check for the minimum required QP version
63#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
64#error qpc version 7.3.0 or higher required
65#endif
66//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
67
68//$define${QXK::QXSemaphore} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
69
70//${QXK::QXSemaphore} ........................................................
71
72//${QXK::QXSemaphore::init} ..................................................
73//! @public @memberof QXSemaphore
74void QXSemaphore_init(QXSemaphore * const me,
75 uint_fast8_t const count,
76 uint_fast8_t const max_count)
77{
80 QF_MEM_SYS();
81
82 Q_REQUIRE_INCRIT(100, (count <= max_count)
83 && (0U < max_count) && (max_count <= 0xFFU));
84
85 me->count = (uint8_t)count;
86 me->max_count = (uint8_t)max_count;
87 QPSet_setEmpty(&me->waitSet);
88
89 QF_MEM_APP();
91}
92
93//${QXK::QXSemaphore::wait} ..................................................
94//! @public @memberof QXSemaphore
95bool QXSemaphore_wait(QXSemaphore * const me,
96 QTimeEvtCtr const nTicks)
97{
100 QF_MEM_SYS();
101
102 QXThread * const curr = QXK_PTR_CAST_(QXThread*, QXK_priv_.curr);
103
104 // precondition, this function:
105 // - must NOT be called from an ISR;
106 // - the semaphore must be initialized
107 // - be called from an extended thread;
108 // - the thread must NOT be already blocked on any object.
110 && (me->max_count > 0U)
111 && (curr != (QXThread *)0)
112 && (curr->super.super.temp.obj == (QMState *)0));
113 // - the thread must NOT be holding a scheduler lock.
115 QXK_priv_.lockHolder != (uint_fast8_t)curr->super.prio);
116
117 bool taken = true; // assume that the semaphore will be signaled
118 if (me->count > 0U) {
119 --me->count; // semaphore taken: decrement the count
120
121 QS_BEGIN_PRE_(QS_SEM_TAKE, curr->super.prio)
122 QS_TIME_PRE_(); // timestamp
123 QS_OBJ_PRE_(me); // this semaphore
124 QS_2U8_PRE_(curr->super.prio, me->count);
125 QS_END_PRE_()
126 }
127 else { // semaphore not available -- BLOCK the thread
128 uint_fast8_t const p = (uint_fast8_t)curr->super.prio;
129 // remove the curr prio from the ready set (will block)
130 // and insert to the waiting set on this semaphore
131 QPSet_remove(&QXK_priv_.readySet, p);
132 #ifndef Q_UNSAFE
133 QPSet_update_(&QXK_priv_.readySet, &QXK_priv_.readySet_dis);
134 #endif
135 QPSet_insert(&me->waitSet, p);
136
137 // remember the blocking object (this semaphore)
138 curr->super.super.temp.obj = QXK_PTR_CAST_(QMState*, me);
139 QXThread_teArm_(curr, (enum_t)QXK_TIMEOUT_SIG, nTicks);
140
141 QS_BEGIN_PRE_(QS_SEM_BLOCK, curr->super.prio)
142 QS_TIME_PRE_(); // timestamp
143 QS_OBJ_PRE_(me); // this semaphore
144 QS_2U8_PRE_(curr->super.prio, me->count);
145 QS_END_PRE_()
146
147 // schedule the next thread if multitasking started
148 (void)QXK_sched_(); // schedule other threads
149
150 QF_MEM_APP();
151 QF_CRIT_EXIT();
152 QF_CRIT_EXIT_NOP(); // BLOCK here !!!
153
154 QF_CRIT_ENTRY(); // AFTER unblocking...
155 QF_MEM_SYS();
156
157 // the blocking object must be this semaphore
159 == QXK_PTR_CAST_(QMState*, me));
160
161 // did the blocking time-out? (signal of zero means that it did)
162 if (curr->timeEvt.super.sig == 0U) {
163 if (QPSet_hasElement(&me->waitSet, p)) { // still waiting?
164 QPSet_remove(&me->waitSet, p); // remove unblocked thread
165 taken = false; // the semaphore was NOT taken
166 }
167 }
168 else { // blocking did NOT time out
169 // the thread must NOT be waiting on this semaphore
170 Q_ASSERT_INCRIT(250, !QPSet_hasElement(&me->waitSet, p));
171 }
172 curr->super.super.temp.obj = (QMState *)0; // clear blocking obj.
173 }
174 QF_MEM_APP();
175 QF_CRIT_EXIT();
176
177 return taken;
178}
179
180//${QXK::QXSemaphore::tryWait} ...............................................
181//! @public @memberof QXSemaphore
182bool QXSemaphore_tryWait(QXSemaphore * const me) {
185 QF_MEM_SYS();
186
187 // precondition:
188 // - the semaphore must be initialized
189 Q_REQUIRE_INCRIT(300, me->max_count > 0U);
190
191 #ifdef Q_SPY
192 QActive const * const curr = QXK_PTR_CAST_(QActive*, QXK_priv_.curr);
193 #endif // Q_SPY
194
195 bool taken;
196 // is the semaphore available?
197 if (me->count > 0U) {
198 --me->count;
199 taken = true;
200
201 QS_BEGIN_PRE_(QS_SEM_TAKE, curr->prio)
202 QS_TIME_PRE_(); // timestamp
203 QS_OBJ_PRE_(me); // this semaphore
204 QS_2U8_PRE_(curr->prio, me->count);
205 QS_END_PRE_()
206 }
207 else { // the semaphore is NOT available (would block)
208 taken = false;
209
210 QS_BEGIN_PRE_(QS_SEM_BLOCK_ATTEMPT, curr->prio)
211 QS_TIME_PRE_(); // timestamp
212 QS_OBJ_PRE_(me); // this semaphore
213 QS_2U8_PRE_(curr->prio, me->count);
214 QS_END_PRE_()
215 }
216 QF_MEM_APP();
217 QF_CRIT_EXIT();
218
219 return taken;
220}
221
222//${QXK::QXSemaphore::signal} ................................................
223//! @public @memberof QXSemaphore
224bool QXSemaphore_signal(QXSemaphore * const me) {
225 bool signaled = true; // assume that the semaphore will be signaled
226
229 QF_MEM_SYS();
230
231 // precondition:
232 // - the semaphore must be initialized
233 Q_REQUIRE_INCRIT(400, me->max_count > 0U);
234
235 // any threads blocked on this semaphore?
236 if (QPSet_notEmpty(&me->waitSet)) {
237 // find the highest-prio. thread waiting on this semaphore
238 uint_fast8_t const p = QPSet_findMax(&me->waitSet);
239 QXThread * const thr =
241
242 // assert that the thread:
243 // - must be registered in QF;
244 // - must be extended; and
245 // - must be blocked on this semaphore;
246 Q_ASSERT_INCRIT(410, (thr != (QXThread *)0)
247 && (thr->super.osObject != (void *)0)
248 && (thr->super.super.temp.obj
249 == QXK_PTR_CAST_(QMState*, me)));
250
251 // disarm the internal time event
252 (void)QXThread_teDisarm_(thr);
253
254 // make the thread ready to run and remove from the wait-list
255 QPSet_insert(&QXK_priv_.readySet, p);
256 #ifndef Q_UNSAFE
257 QPSet_update_(&QXK_priv_.readySet, &QXK_priv_.readySet_dis);
258 #endif
259 QPSet_remove(&me->waitSet, p);
260
261 QS_BEGIN_PRE_(QS_SEM_TAKE, thr->super.prio)
262 QS_TIME_PRE_(); // timestamp
263 QS_OBJ_PRE_(me); // this semaphore
264 QS_2U8_PRE_(thr->super.prio, me->count);
265 QS_END_PRE_()
266
267 if (!QXK_ISR_CONTEXT_()) { // not inside ISR?
268 (void)QXK_sched_(); // schedule other threads
269 }
270 }
271 else if (me->count < me->max_count) {
272 ++me->count; // increment the semaphore count
273
274 QS_BEGIN_PRE_(QS_SEM_SIGNAL, 0U)
275 QS_TIME_PRE_(); // timestamp
276 QS_OBJ_PRE_(me); // this semaphore
277 QS_2U8_PRE_(0U, me->count);
278 QS_END_PRE_()
279 }
280 else {
281 signaled = false; // semaphore NOT signaled
282 }
283 QF_MEM_APP();
284 QF_CRIT_EXIT();
285
286 return signaled;
287}
288//$enddef${QXK::QXSemaphore} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
QActive * QActive_registry_[QF_MAX_ACTIVE+1U]
Definition qf_act.c:64
#define QF_MEM_APP()
Definition qp.h:1284
uint32_t QTimeEvtCtr
Definition qp.h:633
#define QF_MEM_SYS()
Definition qp.h:1279
int enum_t
Definition qp.h:109
#define QF_CRIT_EXIT_NOP()
Definition qp.h:1265
Internal (package scope) QP/C interface.
Sample QP/C port.
#define QXK_ISR_CONTEXT_()
Check if the code executes in the ISR context.
Definition qp_port.h:131
@ QS_SEM_BLOCK
a semaphore blocked a thread
Definition qs.h:183
#define QS_TIME_PRE_()
Definition qs.h:450
@ QS_SEM_BLOCK_ATTEMPT
a semaphore blocked was attempted
Definition qs.h:185
@ QS_SEM_TAKE
a semaphore was taken by a thread
Definition qs.h:182
@ QS_SEM_SIGNAL
a semaphore was signaled
Definition qs.h:184
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
#define QXK_PTR_CAST_(type_, ptr_)
Definition qxk.h:363
@ QXK_TIMEOUT_SIG
Definition qxk.h:392
Active object class (based on the QHsm implementation strategy)
Definition qp.h:800
uint8_t prio
Definition qp.h:805
QACTIVE_OS_OBJ_TYPE osObject
Definition qp.h:817
QAsm super
Definition qp.h:802
union QAsmAttr temp
Definition qp.h:289
QSignal sig
Definition qp.h:151
State object for the QMsm class (QM State Machine).
Definition qp.h:239
QEvt super
Definition qp.h:971
Counting Semaphore of the QXK preemptive kernel.
Definition qxk.h:208
uint8_t max_count
Definition qxk.h:218
QPSet waitSet
Definition qxk.h:212
uint8_t volatile count
Definition qxk.h:215
eXtended (blocking) thread of the QXK preemptive kernel
Definition qxk.h:145
QActive super
Definition qxk.h:147
QTimeEvt timeEvt
Definition qxk.h:152
struct QMState const * obj
Definition qp.h:269