QP/C++  7.0.1
Real-Time Embedded Framework
qxk_xthr.cpp
Go to the documentation of this file.
1//============================================================================
2// QP/C++ Real-Time Embedded Framework (RTEF)
3// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
4//
5// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
6//
7// This software is dual-licensed under the terms of the open source GNU
8// General Public License version 3 (or any later version), or alternatively,
9// under the terms of one of the closed source Quantum Leaps commercial
10// licenses.
11//
12// The terms of the open source GNU General Public License version 3
13// can be found at: <www.gnu.org/licenses/gpl-3.0>
14//
15// The terms of the closed source Quantum Leaps commercial licenses
16// can be found at: <www.state-machine.com/licensing>
17//
18// Redistributions in source code must retain this top-level comment block.
19// Plagiarizing this software to sidestep the license obligations is illegal.
20//
21// Contact information:
22// <www.state-machine.com>
23// <info@state-machine.com>
24//============================================================================
30
31#define QP_IMPL // this is QP implementation
32#include "qf_port.hpp" // QF port
33#include "qxk_pkg.hpp" // QXK package-scope internal interface
34#include "qassert.h" // QP embedded systems-friendly assertions
35#ifdef Q_SPY // QS software tracing enabled?
36 #include "qs_port.hpp" // QS port
37 #include "qs_pkg.hpp" // QS facilities for pre-defined trace records
38#else
39 #include "qs_dummy.hpp" // disable the QS software tracing
40#endif // Q_SPY
41
42// protection against including this source file in a wrong project
43#ifndef QXK_HPP
44 #error "Source file included in a project NOT based on the QXK kernel"
45#endif // QXK_HPP
46
47extern "C" {
48
49Q_DEFINE_THIS_MODULE("qxk_xthr")
50
51} // extern "C"
52
64#define QXTHREAD_CAST_(ptr_) (static_cast<QP::QXThread *>(ptr_))
65
66namespace QP {
67
68//============================================================================
84 std::uint_fast8_t const tickRate) noexcept
85 : QActive(Q_STATE_CAST(handler)),
86 m_timeEvt(this, static_cast<enum_t>(QXK_DELAY_SIG),
87 static_cast<std::uint_fast8_t>(tickRate))
88{
89 m_state.act = nullptr; // mark as extended thread
90}
91
92//============================================================================
93// QXThread virtual function implementations...
94void QXThread::init(void const * const e,
95 std::uint_fast8_t const qs_id) noexcept
96{
97 static_cast<void>(e); // unused parameter
98 static_cast<void>(qs_id); // unused parameter
99 Q_ERROR_ID(110);
100}
101
102//============================================================================
103void QXThread::dispatch(QEvt const * const e,
104 std::uint_fast8_t const qs_id) noexcept
105{
106 static_cast<void>(e); // unused parameter
107 static_cast<void>(qs_id); // unused parameter
108 Q_ERROR_ID(120);
109}
110
111//============================================================================
132void QXThread::start(std::uint_fast8_t const prio,
133 QEvt const * * const qSto, std::uint_fast16_t const qLen,
134 void * const stkSto, std::uint_fast16_t const stkSize,
135 void const * const par)
136{
137 static_cast<void>(par); // unused parameter
138
145 && (prio <= QF_MAX_ACTIVE)
146 && (stkSto != nullptr)
147 && (stkSize != 0U)
148 && (m_state.act == nullptr));
149
150 // is storage for the queue buffer provided?
151 if (qSto != nullptr) {
152 m_eQueue.init(qSto, qLen);
153 }
154
155 // extended threads provide their thread function in place of
156 // the top-most initial transition 'm_temp.act'
157 QXK_stackInit_(this, m_temp.thr, stkSto, stkSize);
158
159 m_prio = static_cast<std::uint8_t>(prio);
160 m_dynPrio = static_cast<std::uint8_t>(prio);
161
162 // the new thread is not blocked on any object
163 m_temp.obj = nullptr;
164
165 QF::add_(this); // make QF aware of this extended thread
166
168 QF_CRIT_E_();
169 // extended-thread becomes ready immediately
170 QXK_attr_.readySet.insert(static_cast<std::uint_fast8_t>(m_dynPrio));
171
172 // see if this thread needs to be scheduled in case QXK is running
173 static_cast<void>(QXK_sched_());
174 QF_CRIT_X_();
175}
176
177#ifdef Q_SPY
178//============================================================================
210bool QXThread::post_(QEvt const * const e,
211 std::uint_fast16_t const margin,
212 void const * const sender) noexcept
213#else
214bool QXThread::post_(QEvt const * const e,
215 std::uint_fast16_t const margin) noexcept
216#endif
217{
220
221 // is it the private time event?
222 bool status;
223 if (e == &m_timeEvt) {
224 QF_CRIT_E_();
225 // the private time event is disarmed and not in any queue,
226 // so it is safe to change its signal. The signal of 0 means
227 // that the time event has expired.
228 m_timeEvt.sig = 0U;
229
230 unblock_();
231 QF_CRIT_X_();
232
233 status = true;
234 }
235 // is the event queue provided?
236 else if (m_eQueue.m_end != 0U) {
237
239 Q_REQUIRE_ID(300, e != nullptr);
240
241 QF_CRIT_E_();
242 QEQueueCtr nFree = m_eQueue.m_nFree; // get volatile into temporary
243
244 // test-probe#1 for faking queue overflow
246 nFree = 0U;
247 )
248
249 if (margin == QF_NO_MARGIN) {
250 if (nFree > 0U) {
251 status = true; // can post
252 }
253 else {
254 status = false; // cannot post
255 Q_ERROR_CRIT_(310); // must be able to post the event
256 }
257 }
258 else if (nFree > static_cast<QEQueueCtr>(margin)) {
259 status = true; // can post
260 }
261 else {
262 status = false; // cannot post, but don't assert
263 }
264
265 // is it a dynamic event?
266 if (e->poolId_ != 0U) {
267 QF_EVT_REF_CTR_INC_(e); // increment the reference counter
268 }
269
270 if (status) { // can post the event?
271
272 --nFree; // one free entry just used up
273 m_eQueue.m_nFree = nFree; // update the volatile
274 if (m_eQueue.m_nMin > nFree) {
275 m_eQueue.m_nMin = nFree; // update minimum so far
276 }
277
279 QS_TIME_PRE_(); // timestamp
280 QS_OBJ_PRE_(sender); // the sender object
281 QS_SIG_PRE_(e->sig); // the signal of the event
282 QS_OBJ_PRE_(this); // this active object
283 QS_2U8_PRE_(e->poolId_, e->refCtr_); // poolID & refCtr
284 QS_EQC_PRE_(nFree); // number of free entries
285 QS_EQC_PRE_(m_eQueue.m_nMin); // min number of free entries
287
288 // queue empty?
289 if (m_eQueue.m_frontEvt == nullptr) {
290 m_eQueue.m_frontEvt = e; // deliver event directly
291
292 // is this thread blocked on the queue?
293 if (m_temp.obj == QXK_PTR_CAST_(QMState*, &m_eQueue)) {
294 static_cast<void>(teDisarm_());
296 static_cast<std::uint_fast8_t>(m_dynPrio));
297 if (!QXK_ISR_CONTEXT_()) {
298 static_cast<void>(QXK_sched_());
299 }
300 }
301 }
302 // queue is not empty, insert event into the ring-buffer
303 else {
304 // insert event into the ring buffer (FIFO)
305 m_eQueue.m_ring[m_eQueue.m_head] = e;
306
307 // need to wrap the head couner?
308 if (m_eQueue.m_head == 0U) {
309 m_eQueue.m_head = m_eQueue.m_end; // wrap around
310 }
311 // advance the head (counter clockwise)
312 m_eQueue.m_head = (m_eQueue.m_head - 1U);
313 }
314
315 QF_CRIT_X_();
316 }
317 else { // cannot post the event
318
320 QS_TIME_PRE_(); // timestamp
321 QS_OBJ_PRE_(sender); // the sender object
322 QS_SIG_PRE_(e->sig); // the signal of the event
323 QS_OBJ_PRE_(this); // this active object (recipient)
324 QS_2U8_PRE_(e->poolId_, e->refCtr_); // poolID & ref Count
325 QS_EQC_PRE_(nFree); // number of free entries
326 QS_EQC_PRE_(margin); // margin
328
329 QF_CRIT_X_();
330
331 QF::gc(e); // recycle the event to avoid a leak
332 }
333 }
334 else { // the queue is not available
335 QF::gc(e); // make sure the event is not leaked
336 status = false;
337 Q_ERROR_ID(320); // this extended thread cannot accept events
338 }
339
340 return status;
341}
342
343//============================================================================
352void QXThread::postLIFO(QEvt const * const e) noexcept {
353 static_cast<void>(e); // unused parameter
354 Q_ERROR_ID(410);
355}
356
357//============================================================================
377QEvt const *QXThread::queueGet(std::uint_fast16_t const nTicks) noexcept {
379 QF_CRIT_E_();
380
381 QXThread * const thr = QXTHREAD_CAST_(QXK_attr_.curr);
382
388 && (thr != nullptr)
389 && (thr->m_temp.obj == nullptr));
392
393 // is the queue empty? -- block and wait for event(s)
394 if (thr->m_eQueue.m_frontEvt == nullptr) {
395
396 // remember the blocking object (the thread's queue)
397 thr->m_temp.obj = QXK_PTR_CAST_(QMState*, &thr->m_eQueue);
398
399 thr->teArm_(static_cast<enum_t>(QXK_QUEUE_SIG), nTicks);
401 static_cast<std::uint_fast8_t>(thr->m_dynPrio));
402 static_cast<void>(QXK_sched_());
403 QF_CRIT_X_();
404 QF_CRIT_EXIT_NOP(); // BLOCK here
405
406 QF_CRIT_E_();
407 // the blocking object must be this queue
408 Q_ASSERT_ID(510, thr->m_temp.obj ==
409 QXK_PTR_CAST_(QMState *, &thr->m_eQueue));
410 thr->m_temp.obj = nullptr; // clear
411 }
412
413 // is the queue not empty?
414 QEvt const *e;
415 if (thr->m_eQueue.m_frontEvt != nullptr) {
416 e = thr->m_eQueue.m_frontEvt; // remove from the front
417 // volatile into tmp
418 QEQueueCtr const nFree = thr->m_eQueue.m_nFree + 1U;
419 thr->m_eQueue.m_nFree = nFree; // update the number of free
420
421 // any events in the ring buffer?
422 if (nFree <= thr->m_eQueue.m_end) {
423
424 // remove event from the tail
425 thr->m_eQueue.m_frontEvt =
426 thr->m_eQueue.m_ring[thr->m_eQueue.m_tail];
427 if (thr->m_eQueue.m_tail == 0U) {
428 thr->m_eQueue.m_tail = thr->m_eQueue.m_end; // wrap
429 }
430 // advance the tail (counter clockwise)
431 thr->m_eQueue.m_tail = (thr->m_eQueue.m_tail - 1U);
432
434 QS_TIME_PRE_(); // timestamp
435 QS_SIG_PRE_(e->sig); // the signal of this event
436 QS_OBJ_PRE_(&thr); // this active object
437 QS_2U8_PRE_(e->poolId_, e->refCtr_); // poolID & ref Count
438 QS_EQC_PRE_(nFree); // number of free entries
440 }
441 else {
442 thr->m_eQueue.m_frontEvt = nullptr; // the queue becomes empty
443
444 // all entries in the queue must be free (+1 for fronEvt)
445 Q_ASSERT_ID(520, nFree == (thr->m_eQueue.m_end + 1U));
446
448 QS_TIME_PRE_(); // timestamp
449 QS_SIG_PRE_(e->sig); // the signal of this event
450 QS_OBJ_PRE_(&thr); // this active object
451 QS_2U8_PRE_(e->poolId_, e->refCtr_); // poolID & ref Count
453 }
454 }
455 else { // the queue is still empty -- the timeout must have fired
456 e = nullptr;
457 }
458 QF_CRIT_X_();
459
460 return e;
461}
462
463//============================================================================
470void QXThread::block_(void) const noexcept {
472 Q_REQUIRE_ID(600, (QXK_attr_.lockHolder != m_prio));
473 QXK_attr_.readySet.rmove(static_cast<std::uint_fast8_t>(m_dynPrio));
474 static_cast<void>(QXK_sched_());
475}
476
477//============================================================================
484void QXThread::unblock_(void) const noexcept {
485 QXK_attr_.readySet.insert(static_cast<std::uint_fast8_t>(m_dynPrio));
486
487 if ((!QXK_ISR_CONTEXT_()) // not inside ISR?
488 && (QF::active_[0] != nullptr)) // kernel started?
489 {
490 static_cast<void>(QXK_sched_());
491 }
492}
493
494//============================================================================
503 std::uint_fast16_t const nTicks) noexcept
504{
506 Q_REQUIRE_ID(700, m_timeEvt.m_ctr == 0U);
507
508 m_timeEvt.sig = static_cast<QSignal>(sig);
509
510 if (nTicks != QXTHREAD_NO_TIMEOUT) {
511 m_timeEvt.m_ctr = static_cast<QTimeEvtCtr>(nTicks);
512 m_timeEvt.m_interval = 0U;
513
514 // is the time event unlinked?
515 // NOTE: For the duration of a single clock tick of the specified tick
516 // rate a time event can be disarmed and yet still linked in the list,
517 // because un-linking is performed exclusively in QF::tickX().
518 if (static_cast<std::uint8_t>(m_timeEvt.refCtr_ & TE_IS_LINKED) == 0U)
519 {
520 std::uint_fast8_t const tickRate =
521 static_cast<std::uint_fast8_t>(m_timeEvt.refCtr_);
522
523 // mark as linked
524 m_timeEvt.refCtr_ = static_cast<std::uint8_t>(
525 m_timeEvt.refCtr_ | TE_IS_LINKED);
526
527 // The time event is initially inserted into the separate
528 // "freshly armed" list based on QF::timeEvtHead_[tickRate].act.
529 // Only later, inside QF::tickX() function, the "freshly armed"
530 // list is appended to the main list of armed time events based on
531 // QF_timeEvtHead_[tickRate].next. Again, this is to keep any
532 // changes to the main list exclusively inside QF::tickX().
533 m_timeEvt.m_next
534 = QXK_PTR_CAST_(QTimeEvt*, QF::timeEvtHead_[tickRate].m_act);
535 QF::timeEvtHead_[tickRate].m_act = &m_timeEvt;
536 }
537 }
538}
539
540//============================================================================
547bool QXThread::teDisarm_(void) noexcept {
548 bool wasArmed;
549 // is the time evt running?
550 if (m_timeEvt.m_ctr != 0U) {
551 wasArmed = true;
552 // schedule removal from list
553 m_timeEvt.m_ctr = 0U;
554 }
555 // the time event was already automatically disarmed
556 else {
557 wasArmed = false;
558 }
559 return wasArmed;
560}
561
562//============================================================================
576bool QXThread::delay(std::uint_fast16_t const nTicks) noexcept {
578 QF_CRIT_E_();
579
581
588 && (nTicks != 0U)
589 && (thr != nullptr)
590 && (thr->m_temp.obj == nullptr));
593
594 // remember the blocking object
595 thr->m_temp.obj = QXK_PTR_CAST_(QMState*, &thr->m_timeEvt);
596 thr->teArm_(static_cast<enum_t>(QXK_DELAY_SIG), nTicks);
597 thr->block_();
598 QF_CRIT_X_();
599 QF_CRIT_EXIT_NOP(); // BLOCK here
600
601 QF_CRIT_E_();
602 // the blocking object must be the time event
603 Q_ENSURE_ID(890, thr->m_temp.obj
604 == QXK_PTR_CAST_(QMState*, &thr->m_timeEvt));
605 thr->m_temp.obj = nullptr; // clear
606 QF_CRIT_X_();
607
608 // signal of zero means that the time event was posted without
609 // being canceled.
610 return (thr->m_timeEvt.sig == 0U);
611}
612
613//============================================================================
623bool QXThread::delayCancel(void) noexcept {
625 QF_CRIT_E_();
626
627 bool wasArmed;
628 if (m_temp.obj == QXK_PTR_CAST_(QMState*, &m_timeEvt)) {
629 wasArmed = teDisarm_();
630 unblock_();
631 }
632 else {
633 wasArmed = false;
634 }
635 QF_CRIT_X_();
636
637 return wasArmed;
638}
639
640} // namespace QP
641
642
643//============================================================================
644extern "C" {
645
655void QXK_threadRet_(void) noexcept {
657 QF_CRIT_E_();
658
659 QP::QXThread const * const thr = QXTHREAD_CAST_(QXK_attr_.curr);
660
665 && (thr != nullptr));
668
669 std::uint_fast8_t const p =
670 static_cast<std::uint_fast8_t>(thr->m_prio);
671
672 // remove this thread from the QF
673 QP::QF::active_[p] = nullptr;
675 static_cast<void>(QXK_sched_());
676 QF_CRIT_X_();
677}
678
679} // extern "C"
QActive active object (based on QP::QHsm implementation)
Definition: qf.hpp:136
std::uint8_t m_prio
QF priority (1..QF_MAX_ACTIVE) of this active object.
Definition: qf.hpp:177
static QTimeEvt timeEvtHead_[QF_MAX_TICK_RATE]
heads of linked lists of time events, one for every clock tick rate
Definition: qf.hpp:606
static void gc(QEvt const *const e) noexcept
Recycle a dynamic event.
Definition: qf_dyn.cpp:212
static void add_(QActive *const a) noexcept
Register an active object to be managed by the framework.
Definition: qf_act.cpp:68
static QActive * active_[QF_MAX_ACTIVE+1U]
array of registered active objects
Definition: qf.hpp:571
QHsmAttr m_state
current active state (state-variable)
Definition: qep.hpp:250
QHsmAttr m_temp
temporary: transition chain, target state, etc.
Definition: qep.hpp:251
friend class QXThread
Definition: qep.hpp:455
Time Event class.
Definition: qf.hpp:395
void *volatile m_act
the active object that receives the time events
Definition: qf.hpp:405
Extended (blocking) thread of the QXK preemptive kernel.
Definition: qxthread.hpp:58
void start(std::uint_fast8_t const prio, QEvt const **const qSto, std::uint_fast16_t const qLen, void *const stkSto, std::uint_fast16_t const stkSize, void const *const par) override
Starts execution of an extended thread and registers the thread with the framework.
Definition: qxk_xthr.cpp:132
void block_(void) const noexcept
Definition: qxk_xthr.cpp:470
void init(void const *const e, std::uint_fast8_t const qs_id) noexcept override
Executes the top-most initial transition in HSM.
Definition: qxk_xthr.cpp:94
void postLIFO(QEvt const *const e) noexcept override
Posts an event directly to the event queue of the active object using the Last-In-First-Out (LIFO) po...
Definition: qxk_xthr.cpp:352
static bool delay(std::uint_fast16_t const nTicks) noexcept
delay (block) the current extended thread for a specified # ticks
Definition: qxk_xthr.cpp:576
bool delayCancel(void) noexcept
cancel the delay
Definition: qxk_xthr.cpp:623
bool post_(QEvt const *const e, std::uint_fast16_t const margin, void const *const sender) noexcept override
Definition: qxk_xthr.cpp:210
void dispatch(QEvt const *const e, std::uint_fast8_t const qs_id) noexcept override
Dispatches an event to HSM.
Definition: qxk_xthr.cpp:103
QTimeEvt m_timeEvt
time event to handle blocking timeouts
Definition: qxthread.hpp:123
void unblock_(void) const noexcept
Definition: qxk_xthr.cpp:484
static QEvt const * queueGet(std::uint_fast16_t const nTicks=QXTHREAD_NO_TIMEOUT) noexcept
obtain a message from the private message queue (block if no messages)
Definition: qxk_xthr.cpp:377
void teArm_(enum_t const sig, std::uint_fast16_t const nTicks) noexcept
Definition: qxk_xthr.cpp:502
bool teDisarm_(void) noexcept
Definition: qxk_xthr.cpp:547
namespace associated with the QP/C++ framework
Definition: exa_native.dox:1
std::uint8_t QEQueueCtr
The data type to store the ring-buffer counters based on the macro #QF_EQUEUE_CTR_SIZE.
Definition: qequeue.hpp:63
std::uint_fast16_t const QF_NO_MARGIN
special value of margin that causes asserting failure in case event allocation or event posting fails
Definition: qf.hpp:618
@ QS_QF_ACTIVE_GET
AO got an event and its queue is not empty.
Definition: qs.hpp:76
@ QS_QF_ACTIVE_POST_ATTEMPT
attempt to post an evt to AO failed
Definition: qs.hpp:119
@ QS_QF_ACTIVE_POST
an event was posted (FIFO) directly to AO
Definition: qs.hpp:74
@ QS_QF_ACTIVE_GET_LAST
AO got an event and its queue is empty.
Definition: qs.hpp:77
void(*)(QXThread *const me) QXThreadHandler
Pointer to a thread-handler function.
Definition: qep.hpp:214
QMState const * obj
pointer to QMState object
Definition: qep.hpp:224
static constexpr std::uint_fast16_t QXTHREAD_NO_TIMEOUT
no-timeout sepcification when blocking on queues or semaphores
Definition: qxthread.hpp:37
@ QXK_QUEUE_SIG
Definition: qxk_pkg.hpp:46
@ QXK_DELAY_SIG
Definition: qxk_pkg.hpp:45
constexpr std::uint8_t TE_IS_LINKED
Definition: qf_pkg.hpp:124
std::uint8_t QTimeEvtCtr
Definition: qf.hpp:91
QXThreadHandler thr
pointer to an thread-handler function
Definition: qep.hpp:223
std::uint16_t QSignal
QSignal represents the signal of an event.
Definition: qep.hpp:129
void QF_EVT_REF_CTR_INC_(QEvt const *const e) noexcept
increment the refCtr_ of an event e
Definition: qf_pkg.hpp:142
QActionHandler act
pointer to an action-handler function
Definition: qep.hpp:222
State object for the QP::QMsm class (QM State Machine).
Definition: qep.hpp:565
Customizable and memory-efficient assertions for embedded systems.
#define Q_DEFINE_THIS_MODULE(name_)
Definition: qassert.h:102
#define Q_ASSERT_ID(id_, test_)
Definition: qassert.h:135
#define Q_ENSURE_ID(id_, test_)
Definition: qassert.h:271
#define Q_REQUIRE_ID(id_, test_)
Definition: qassert.h:252
#define Q_ERROR_ID(id_)
Definition: qassert.h:187
int enum_t
alias for enumerations used for event signals
Definition: qep.hpp:66
#define Q_STATE_CAST(handler_)
Macro to perform casting to QStateHandler.
Definition: qep.hpp:622
#define QF_CRIT_EXIT_NOP()
No-operation for exiting a critical section.
Definition: qf.hpp:667
#define QF_CRIT_STAT_
This is an internal macro for defining the critical section status type.
Definition: qf_pkg.hpp:48
#define QF_CRIT_X_()
This is an internal macro for exiting a critical section.
Definition: qf_pkg.hpp:69
#define QF_CRIT_E_()
This is an internal macro for entering a critical section.
Definition: qf_pkg.hpp:58
#define Q_ERROR_CRIT_(id_)
Definition: qf_pkg.hpp:95
#define QS_TIME_PRE_()
Definition: qs.hpp:225
#define QS_TEST_PROBE_DEF(fun_)
QS macro to define the Test-Probe for a given fun_.
Definition: qs.hpp:1043
#define QS_TEST_PROBE_ID(id_, code_)
QS macro to apply a Test-Probe.
Definition: qs.hpp:1052
Internal (package scope) QS/C++ interface.
#define QS_BEGIN_NOCRIT_PRE_(rec_, qs_id_)
Internal QS macro to begin a predefined QS record without critical section.
Definition: qs_pkg.hpp:130
#define QS_OBJ_PRE_(obj_)
Internal QS macro to output object pointer data element.
Definition: qs_pkg.hpp:178
#define QS_END_NOCRIT_PRE_()
Internal QS macro to end a predefiend QS record without critical section.
Definition: qs_pkg.hpp:138
#define QS_2U8_PRE_(data1_, data2_)
Internal QS macro to output 2 unformatted uint8_t data elements.
Definition: qs_pkg.hpp:161
#define QS_EQC_PRE_(ctr_)
Internal QS macro to output an unformatted event queue counter data element.
Definition: qs_pkg.hpp:208
#define QF_MAX_ACTIVE
std::uint8_t volatile lockHolder
prio of the lock holder
Definition: qxk.hpp:71
#define QXK_ISR_CONTEXT_()
Internal port-specific macro that reports the execution context.
Definition: qxk.hpp:170
std::uint_fast8_t QXK_sched_(void) noexcept
QXK scheduler finds the highest-priority thread ready to run.
Definition: qxk.cpp:340
QP::QPSet readySet
ready-set of all threads
Definition: qxk.hpp:74
QP::QActive *volatile curr
currently executing thread
Definition: qxk.hpp:67
QXK_Attr QXK_attr_
global attributes of the QXK kernel
Definition: qxk.cpp:54
Internal (package scope) QXK/C++ interface.
void QXK_stackInit_(void *thr, QP::QXThreadHandler const handler, void *const stkSto, std::uint_fast16_t const stkSize) noexcept
initialize the private stack of a given AO
Definition: qxk_port.cpp:122
#define QXK_PTR_CAST_(type_, ptr_)
intertnal macro to encapsulate casting of pointers for MISRA deviations
Definition: qxk_pkg.hpp:75
void QXK_threadRet_(void) noexcept
called when a thread function returns
Definition: qxk_xthr.cpp:655
#define QXTHREAD_CAST_(ptr_)
intertnal macro to encapsulate casting of pointers for MISRA deviations *‍/
Definition: qxk_xthr.cpp:64
QEvt base class.
Definition: qep.hpp:191
QSignal sig
signal of the event instance
Definition: qep.hpp:192
std::uint8_t volatile refCtr_
reference counter
Definition: qep.hpp:194
std::uint8_t poolId_
pool ID (0 for static event)
Definition: qep.hpp:193
void insert(std::uint_fast8_t const n) noexcept
insert element n into the set, n = 1..QF_MAX_ACTIVE
Definition: qpset.hpp:93
void rmove(std::uint_fast8_t const n) noexcept
remove element n from the set, n = 1..QF_MAX_ACTIVE
Definition: qpset.hpp:101