QP/C  7.3.4
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qxk.c
Go to the documentation of this file.
1//$file${src::qxk::qxk.c} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpc.qm
4// File: ${src::qxk::qxk.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.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")
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::QXK-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
69
70//${QXK::QXK-base::priv_} ....................................................
71QXK_Attr QXK_priv_;
72
73//${QXK::QXK-base::schedLock} ................................................
74//! @static @public @memberof QXK
75QSchedStatus QXK_schedLock(uint_fast8_t const ceiling) {
78 QF_MEM_SYS();
79
81
82 QSchedStatus stat; // saved lock status to be returned
83
84 // is the lock ceiling being raised?
85 if (ceiling > QXK_priv_.lockCeil) {
86 QS_BEGIN_PRE_(QS_SCHED_LOCK, 0U)
87 QS_TIME_PRE_(); // timestamp
88 // the previous lock ceiling & new lock ceiling
89 QS_2U8_PRE_((uint8_t)QXK_priv_.lockCeil, (uint8_t)ceiling);
90 QS_END_PRE_()
91
92 // previous status of the lock
93 stat = (QSchedStatus)QXK_priv_.lockHolder;
94 stat |= (QSchedStatus)QXK_priv_.lockCeil << 8U;
95
96 // new status of the lock
97 QXK_priv_.lockHolder = (QXK_priv_.curr != (QActive *)0)
98 ? (uint_fast8_t)QXK_priv_.curr->prio
99 : 0U;
100 QXK_priv_.lockCeil = ceiling;
101 }
102 else {
103 stat = 0xFFU; // scheduler not locked
104 }
105 QF_MEM_APP();
106 QF_CRIT_EXIT();
107
108 return stat; // return the status to be saved in a stack variable
109}
110
111//${QXK::QXK-base::schedUnlock} ..............................................
112//! @static @public @memberof QXK
113void QXK_schedUnlock(QSchedStatus const stat) {
114 // has the scheduler been actually locked by the last QXK_schedLock()?
115 if (stat != 0xFFU) {
116 uint8_t const prevCeil = (uint8_t)(stat >> 8U);
119 QF_MEM_SYS();
120
122 Q_REQUIRE_INCRIT(201, QXK_priv_.lockCeil > prevCeil);
123
124 QS_BEGIN_PRE_(QS_SCHED_UNLOCK, 0U)
125 QS_TIME_PRE_(); // timestamp
126 // ceiling before unlocking & prio after unlocking
127 QS_2U8_PRE_((uint8_t)QXK_priv_.lockCeil, (uint8_t)prevCeil);
128 QS_END_PRE_()
129
130 // restore the previous lock ceiling and lock holder
131 QXK_priv_.lockCeil = prevCeil;
132 QXK_priv_.lockHolder = (stat & 0xFFU);
133
134 // find if any threads should be run after unlocking the scheduler
135 if (QXK_sched_() != 0U) { // activation needed?
136 QXK_activate_(); // synchronously activate basic-thread(s)
137 }
138
139 QF_MEM_APP();
140 QF_CRIT_EXIT();
141 }
142}
143
144//${QXK::QXK-base::current} ..................................................
145//! @static @public @memberof QXK
146QActive * QXK_current(void) {
149 QF_MEM_SYS();
150
151 Q_REQUIRE_INCRIT(600, QXK_priv_.lockCeil <= QF_MAX_ACTIVE);
152
153 struct QActive *curr = QXK_priv_.curr;
154 if (curr == (QActive *)0) { // basic thread?
155 curr = QActive_registry_[QXK_priv_.actPrio];
156 }
157
158 Q_ASSERT_INCRIT(690, curr != (QActive *)0);
159
160 QF_MEM_APP();
161 QF_CRIT_EXIT();
162
163 return curr;
164}
165
166//${QXK::QXK-base::sched_} ...................................................
167//! @static @private @memberof QXK
168uint_fast8_t QXK_sched_(void) {
169 Q_REQUIRE_INCRIT(402, QPSet_verify_(&QXK_priv_.readySet,
170 &QXK_priv_.readySet_dis));
171
172 QActive const * const curr = QXK_priv_.curr;
173 uint_fast8_t p;
174 if (QPSet_isEmpty(&QXK_priv_.readySet)) {
175 p = 0U; // no activation needed
176 }
177 else {
178 // find the highest-prio thread ready to run
179 p = QPSet_findMax(&QXK_priv_.readySet);
180 if (p <= QXK_priv_.lockCeil) {
181 p = (uint_fast8_t)QActive_registry_[QXK_priv_.lockHolder]->prio;
182 if (p != 0U) {
183 Q_ASSERT_INCRIT(410,
184 QPSet_hasElement(&QXK_priv_.readySet, p));
185 }
186 }
187 }
188 QActive * const next = QActive_registry_[p];
189
190 // is the current thread a basic-thread?
191 if (curr == (QActive *)0) {
192
193 // is the next prio. above the active prio.?
194 if (p > QXK_priv_.actPrio) {
195 QXK_priv_.next = next; // set the next AO to activate
196
197 if (next->osObject != (void *)0) { // is next extended?
199 p = 0U; // no activation needed
200 }
201 }
202 else { // below the active prio.
203 QXK_priv_.next = (QActive *)0;
204 p = 0U; // no activation needed
205 }
206 }
207 else { // currently executing an extended-thread
208 // is the current thread different from the next?
209 if (curr != next) {
210 QXK_priv_.next = next;
212 }
213 else { // current is the same as next
214 QXK_priv_.next = (QActive *)0; // no need to context-switch
215 }
216 p = 0U; // no activation needed
217 }
218 return p;
219}
220
221//${QXK::QXK-base::activate_} ................................................
222//! @static @private @memberof QXK
223void QXK_activate_(void) {
224 uint_fast8_t const prio_in = QXK_priv_.actPrio;
225 QActive *next = QXK_priv_.next; // the next AO (basic-thread) to run
226
227 Q_REQUIRE_INCRIT(500, (next != (QActive *)0)
228 && (prio_in <= QF_MAX_ACTIVE));
229
230 // QXK Context switch callback defined or QS tracing enabled?
231 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
232 QXK_contextSw_(next);
233 #endif // QF_ON_CONTEXT_SW || Q_SPY
234
235 QXK_priv_.next = (QActive *)0; // clear the next AO
236 QXK_priv_.curr = (QActive *)0; // current is basic-thread
237
238 // prio. of the next thread
239 uint_fast8_t p = (uint_fast8_t)next->prio;
240
241 // loop until no more ready-to-run AOs of higher prio than the initial
242 do {
243 QXK_priv_.actPrio = p; // next active prio
244
245 QF_INT_ENABLE(); // unconditionally enable interrupts
246
247 QEvt const * const e = QActive_get_(next);
248 // NOTE QActive_get_() performs QS_MEM_APP() before return
249
250 // dispatch event (virtual call)
251 (*next->super.vptr->dispatch)(&next->super, e, p);
252 #if (QF_MAX_EPOOL > 0U)
253 QF_gc(e);
254 #endif
255
256 QF_INT_DISABLE(); // unconditionally disable interrupts
257 QF_MEM_SYS();
258
259 // check internal integrity (duplicate inverse storage)
260 Q_ASSERT_INCRIT(502, QPSet_verify_(&QXK_priv_.readySet,
261 &QXK_priv_.readySet_dis));
262
263 if (next->eQueue.frontEvt == (QEvt *)0) { // empty queue?
264 QPSet_remove(&QXK_priv_.readySet, p);
265 #ifndef Q_UNSAFE
266 QPSet_update_(&QXK_priv_.readySet, &QXK_priv_.readySet_dis);
267 #endif
268 }
269
270 if (QPSet_isEmpty(&QXK_priv_.readySet)) {
271 QXK_priv_.next = (QActive *)0;
272 next = QActive_registry_[0];
273 p = 0U; // no activation needed
274 }
275 else {
276 // find next highest-prio below the lock ceiling
277 p = (uint8_t)QPSet_findMax(&QXK_priv_.readySet);
278 if (p <= QXK_priv_.lockCeil) {
279 p = QXK_priv_.lockHolder; // thread holding lock
280 if (p != 0U) {
281 Q_ASSERT_INCRIT(510,
282 QPSet_hasElement(&QXK_priv_.readySet, p));
283 }
284 }
285
286 // set the next thread and ensure that it is registered
287 next = QActive_registry_[p];
288 Q_ASSERT_INCRIT(520, next != (QActive *)0);
289
290 // is next a basic thread?
291 if (next->osObject == (void *)0) {
292 // is the next prio. above the initial prio.?
293 if (p > QActive_registry_[prio_in]->prio) {
294 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
295 if (p != QXK_priv_.actPrio) { // changing threads?
296 QXK_contextSw_(next);
297 }
298 #endif // QF_ON_CONTEXT_SW || Q_SPY
299 QXK_priv_.next = next;
300 }
301 else {
302 QXK_priv_.next = (QActive *)0;
303 p = 0U; // no activation needed
304 }
305 }
306 else { // next is the extended-thread
307 QXK_priv_.next = next;
309 p = 0U; // no activation needed
310 }
311 }
312 } while (p != 0U); // while activation needed
313
314 // restore the active prio.
315 QXK_priv_.actPrio = prio_in;
316
317 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
318 if (next->osObject == (void *)0) {
319 QXK_contextSw_((prio_in == 0U)
320 ? (QActive *)0
321 : QActive_registry_[prio_in]);
322 }
323 #endif // QF_ON_CONTEXT_SW || Q_SPY
324}
325
326//${QXK::QXK-base::contextSw_} ...............................................
327//! @static @public @memberof QXK
328void QXK_contextSw_(QActive * const next) {
329 #ifdef Q_SPY
330 uint8_t const prev_prio = (QXK_priv_.prev != (QActive *)0)
331 ? QXK_priv_.prev->prio
332 : 0U;
333 if (next != (QActive *)0) { // next is NOT idle?
334 QS_BEGIN_PRE_(QS_SCHED_NEXT, next->prio)
335 QS_TIME_PRE_(); // timestamp
336 QS_2U8_PRE_(next->prio, prev_prio);
337 QS_END_PRE_()
338 }
339 else { // going to idle
340 QS_BEGIN_PRE_(QS_SCHED_IDLE, prev_prio)
341 QS_TIME_PRE_(); // timestamp
342 QS_U8_PRE_(prev_prio);
343 QS_END_PRE_()
344 }
345 #endif // Q_SPY
346
347 #ifdef QF_ON_CONTEXT_SW
348 QF_onContextSw(QXK_priv_.prev, next);
349 #endif // QF_ON_CONTEXT_SW
350
351 QXK_priv_.prev = next; // update the previous thread
352}
353
354//${QXK::QXK-base::threadExit_} ..............................................
355//! @static @private @memberof QXK
356void QXK_threadExit_(void) {
359
360 QXThread const * const thr = QXTHREAD_CAST_(QXK_priv_.curr);
361
363 && (thr != (QXThread *)0)); // current thread must be extended
365 QXK_priv_.lockHolder != (uint_fast8_t)thr->super.prio);
366
367 uint_fast8_t const p = (uint_fast8_t)thr->super.prio;
368
369 QF_MEM_SYS();
370 QActive_registry_[p] = (QActive *)0;
371 QPSet_remove(&QXK_priv_.readySet, p);
372 #ifndef Q_UNSAFE
373 QPSet_update_(&QXK_priv_.readySet, &QXK_priv_.readySet_dis);
374 #endif
375
376 (void)QXK_sched_(); // schedule other threads
377
378 QF_MEM_APP();
379 QF_CRIT_EXIT();
380}
381//$enddef${QXK::QXK-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
382
383//$define${QXK::QF-cust} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
384
385//${QXK::QF-cust::init} ......................................................
386//! @static @public @memberof QF
387void QF_init(void) {
388 QF_bzero_(&QF_priv_, sizeof(QF_priv_));
389 QF_bzero_(&QXK_priv_, sizeof(QXK_priv_));
390 QF_bzero_(&QActive_registry_[0], sizeof(QActive_registry_));
391
392 // setup the QXK scheduler as initially locked and not running
393 QXK_priv_.lockCeil = (QF_MAX_ACTIVE + 1U); // scheduler locked
394
395 #ifndef Q_UNSAFE
396 QPSet_update_(&QXK_priv_.readySet, &QXK_priv_.readySet_dis);
397 #endif
398
399 for (uint_fast8_t tickRate = 0U;
400 tickRate < Q_DIM(QTimeEvt_timeEvtHead_);
401 ++tickRate)
402 {
403 QTimeEvt_ctorX(&QTimeEvt_timeEvtHead_[tickRate],
404 (QActive *)0, (enum_t)Q_USER_SIG, tickRate);
405 }
406
407 // QXK idle AO object (const in ROM)
408 static QActive const idle_ao = { (struct QAsmVtable const *)0 };
409
410 // register the idle AO object (cast 'const' away)
411 QActive_registry_[0] = QACTIVE_CAST_(&idle_ao);
412 QXK_priv_.prev = QActive_registry_[0];
413
414 #ifdef QXK_INIT
415 QXK_INIT(); // port-specific initialization of the QXK kernel
416 #endif
417}
418
419//${QXK::QF-cust::stop} ......................................................
420//! @static @public @memberof QF
421void QF_stop(void) {
422 QF_onCleanup(); // application-specific cleanup callback
423 // nothing else to do for the dual-mode QXK kernel
424}
425
426//${QXK::QF-cust::run} .......................................................
427//! @static @public @memberof QF
428int_t QF_run(void) {
429 #ifdef Q_SPY
432
433 // produce the QS_QF_RUN trace record
435 QF_MEM_SYS();
436 QS_beginRec_((uint_fast8_t)QS_QF_RUN);
437 QS_endRec_();
438 QF_MEM_APP();
440 #endif // Q_SPY
441
442 QF_onStartup(); // application-specific startup callback
443
445 QF_MEM_SYS();
446
447 #ifdef QXK_START
448 QXK_START(); // port-specific startup of the QXK kernel
449 #endif
450
451 QXK_priv_.lockCeil = 0U; // unlock the QXK scheduler
452
453 // activate AOs to process events posted so far
454 if (QXK_sched_() != 0U) {
455 QXK_activate_();
456 }
457
458 QF_MEM_APP();
460
461 for (;;) { // QXK idle loop...
462 QXK_onIdle(); // application-specific QXK idle callback
463 }
464
465 #ifdef __GNUC__ // GNU compiler?
466 return 0;
467 #endif
468}
469//$enddef${QXK::QF-cust} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
470
471//$define${QXK::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
472
473//${QXK::QActive} ............................................................
474
475//${QXK::QActive::start_} ....................................................
476//! @public @memberof QActive
477void QActive_start_(QActive * const me,
478 QPrioSpec const prioSpec,
479 QEvt const * * const qSto,
480 uint_fast16_t const qLen,
481 void * const stkSto,
482 uint_fast16_t const stkSize,
483 void const * const par)
484{
488 && ((prioSpec & 0xFF00U) == 0U));
489 QF_CRIT_EXIT();
490
491 me->prio = (uint8_t)(prioSpec & 0xFFU); // QF-prio. of the AO
492 me->pthre = 0U; // not used
493 QActive_register_(me); // make QF aware of this active object
494
495 if (stkSto == (void *)0) { // starting basic thread (AO)?
496
497 QEQueue_init(&me->eQueue, qSto, qLen); // init the built-in queue
498 me->osObject = (void *)0; // no private stack for AO
499
500 // top-most initial tran. (virtual call)
501 (*me->super.vptr->init)(&me->super, par, me->prio);
502 QS_FLUSH(); // flush the trace buffer to the host
503
504 // see if this AO needs to be scheduled if QXK is already running
506 QF_MEM_SYS();
507 if (QXK_priv_.lockCeil <= QF_MAX_ACTIVE) { // scheduler running?
508 if (QXK_sched_() != 0U) { // activation needed?
509 QXK_activate_(); // synchronously activate basic-thread(s)
510 }
511 }
512 QF_MEM_APP();
513 QF_CRIT_EXIT();
514 }
515 else { // starting QXThread
516
517 // is storage for the queue buffer provided?
518 if (qSto != (QEvt const **)0) {
519 QEQueue_init(&me->eQueue, qSto, qLen);
520 }
521
522 // extended thread constructor puts the thread handler in place of
523 // the top-most initial tran. 'me->super.temp.act'
524 QXThread_stackInit_(me, me->super.temp.thr, stkSto, stkSize);
525
526 // the new thread is not blocked on any object
527 me->super.temp.obj = (QMState *)0;
528
530 QF_MEM_SYS();
531
532 // extended-thread becomes ready immediately
533 QPSet_insert(&QXK_priv_.readySet, (uint_fast8_t)me->prio);
534 #ifndef Q_UNSAFE
535 QPSet_update_(&QXK_priv_.readySet, &QXK_priv_.readySet_dis);
536 #endif
537
538 // see if this thread needs to be scheduled in case QXK is running
539 if (QXK_priv_.lockCeil <= QF_MAX_ACTIVE) {
540 (void)QXK_sched_(); // schedule other threads
541 }
542 QF_MEM_APP();
543 QF_CRIT_EXIT();
544 }
545}
546//$enddef${QXK::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
QF_Attr QF_priv_
Definition qf_act.c:70
QActive * QActive_registry_[QF_MAX_ACTIVE+1U]
Definition qf_act.c:64
uint_fast8_t QSchedStatus
Definition qk.h:60
int int_t
Definition qp.h:106
#define QF_MEM_APP()
Definition qp.h:1284
@ Q_USER_SIG
offset for the user signals (QP Application)
Definition qp.h:260
#define QF_MEM_SYS()
Definition qp.h:1279
int enum_t
Definition qp.h:109
#define Q_DIM(array_)
Definition qp.h:535
uint16_t QPrioSpec
Definition qp.h:619
#define QF_MAX_ACTIVE
Definition qp_config.h:112
Internal (package scope) QP/C interface.
#define QACTIVE_CAST_(ptr_)
Definition qp_pkg.h:96
Sample QP/C port.
#define QXK_ISR_CONTEXT_()
Check if the code executes in the ISR context.
Definition qp_port.h:131
#define QXK_CONTEXT_SWITCH_()
Trigger context switch (used internally in QXK only)
Definition qp_port.h:134
#define QF_INT_DISABLE()
Disable interrupts.
Definition qp_port.h:37
#define QF_INT_ENABLE()
Enable interrupts.
Definition qp_port.h:40
@ QS_QF_RUN
QF_run() was entered.
Definition qs.h:179
#define QS_TIME_PRE_()
Definition qs.h:450
@ QS_SCHED_IDLE
scheduler restored the idle task
Definition qs.h:156
#define QS_SIG_DICTIONARY(sig_, obj_)
Definition qs.h:505
@ QS_SCHED_LOCK
scheduler was locked
Definition qs.h:153
@ QS_SCHED_UNLOCK
scheduler was unlocked
Definition qs.h:154
#define QS_FLUSH()
Definition qs.h:363
@ QS_SCHED_NEXT
scheduler started next task
Definition qs.h:155
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
int_t QF_run(void)
Definition qutest.c:191
void QF_init(void)
Definition qutest.c:172
void QF_stop(void)
Definition qutest.c:186
uint_fast16_t QSchedStatus
Definition qxk.h:60
#define QXTHREAD_CAST_(ptr_)
Definition qxk.h:366
@ QXK_TIMEOUT_SIG
Definition qxk.h:392
@ QXK_DELAY_SIG
Definition qxk.h:391
Active object class (based on the QHsm implementation strategy)
Definition qp.h:800
uint8_t prio
Definition qp.h:805
uint8_t pthre
Definition qp.h:808
QACTIVE_OS_OBJ_TYPE osObject
Definition qp.h:817
QACTIVE_EQUEUE_TYPE eQueue
Definition qp.h:822
QEvt const * QActive_get_(QActive *const me)
Definition qf_actq.c:301
QAsm super
Definition qp.h:802
struct QAsmVtable const * vptr
Definition qp.h:281
union QAsmAttr temp
Definition qp.h:289
Virtual table for the QAsm class.
Definition qp.h:298
void(* init)(QAsm *const me, void const *const e, uint_fast8_t const qsId)
Definition qp.h:299
void(* dispatch)(QAsm *const me, QEvt const *const e, uint_fast8_t const qsId)
Definition qp.h:301
Event class.
Definition qp.h:147
State object for the QMsm class (QM State Machine).
Definition qp.h:239
Private attributes of the QXK kernel.
Definition qxk.h:73
eXtended (blocking) thread of the QXK preemptive kernel
Definition qxk.h:145
QActive super
Definition qxk.h:147
QXThreadHandler thr
Definition qp.h:267
struct QMState const * obj
Definition qp.h:269