//**************************************************************************** //! obtain a message from the private message queue (block if no messages) void const *QXThread::queueGet(uint_fast16_t const nTicks, uint_fast8_t const tickRate) { QEQueueCtr nFree; QEvt const *e; QF_CRIT_STAT_ QF_CRIT_ENTRY_(); QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr); Q_REQUIRE_ID(900, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */ /* this must be a "naked" thread (no state) */ && (thr->m_state.act == (QActionHandler)0)); // is the queue empty? -- block and wait for event(s) if (thr->m_eQueue.m_frontEvt == static_cast<QEvt *>(0)) { thr->m_temp.obj = reinterpret_cast<QMState const *>(&thr->m_eQueue); thr->teArm_(static_cast<enum_t>(QXK_QUEUE_SIG), nTicks, tickRate); QXK_attr_.readySet.remove(thr->m_prio); QXK_sched_(); QF_CRIT_EXIT_(); QF_CRIT_EXIT_NOP(); QF_CRIT_ENTRY_(); } // is the queue not empty? if (thr->m_eQueue.m_frontEvt != static_cast<QEvt *>(0)) { e = thr->m_eQueue.m_frontEvt; // always remove from the front // volatile into tmp nFree= thr->m_eQueue.m_nFree + static_cast<QEQueueCtr>(1); thr->m_eQueue.m_nFree = nFree; // update the number of free // any events in the ring buffer? if (nFree <= thr->m_eQueue.m_end) { // remove event from the tail thr->m_eQueue.m_frontEvt = QF_PTR_AT_(thr->m_eQueue.m_ring, thr->m_eQueue.m_tail); if (thr->m_eQueue.m_tail == static_cast<QEQueueCtr>(0)) { thr->m_eQueue.m_tail = thr->m_eQueue.m_end; // wrap } --thr->m_eQueue.m_tail; QS_BEGIN_NOCRIT_(QP::QS_QF_ACTIVE_GET, QP::QS::priv_.aoObjFilter, thr) QS_TIME_(); // timestamp QS_SIG_(e->sig); // the signal of this event QS_OBJ_(&thr); // this active object QS_2U8_(e->poolId_, e->refCtr_); // pool Id & ref Count QS_EQC_(nFree); // number of free entries QS_END_NOCRIT_() }
void QF_tickX_(uint_fast8_t const tickRate, void const * const sender) #endif { QTimeEvt *prev = &QF_timeEvtHead_[tickRate]; QF_CRIT_STAT_ QF_CRIT_ENTRY_(); QS_BEGIN_NOCRIT_(QS_QF_TICK, (void *)0, (void *)0) QS_TEC_((QTimeEvtCtr)(++prev->ctr)); /* tick ctr */ QS_U8_((uint8_t)tickRate); /* tick rate */ QS_END_NOCRIT_() /* scan the linked-list of time events at this rate... */ for (;;) { QTimeEvt *t = prev->next; /* advance down the time evt. list */ /* end of the list? */ if (t == (QTimeEvt *)0) { /* any new time events armed since the last run of QF_tickX_()? */ if (QF_timeEvtHead_[tickRate].act != (void *)0) { /* sanity check */ Q_ASSERT_ID(110, prev != (QTimeEvt *)0); prev->next = (QTimeEvt *)QF_timeEvtHead_[tickRate].act; QF_timeEvtHead_[tickRate].act = (void *)0; t = prev->next; /* switch to the new list */ } else { break; /* all currently armed time evts. processed */ } } /* time event scheduled for removal? */ if (t->ctr == (QTimeEvtCtr)0) { prev->next = t->next; t->super.refCtr_ &= (uint8_t)0x7F; /* mark as unlinked */ /* do NOT advance the prev pointer */ QF_CRIT_EXIT_(); /* exit crit. section to reduce latency */ /* prevent merging critical sections, see NOTE1 below */ QF_CRIT_EXIT_NOP(); } else { --t->ctr; /* is time event about to expire? */ if (t->ctr == (QTimeEvtCtr)0) { QMActive *act = (QMActive *)t->act; /* temp. for volatile */ /* periodic time evt? */ if (t->interval != (QTimeEvtCtr)0) { t->ctr = t->interval; /* rearm the time event */ prev = t; /* advance to this time event */ } /* one-shot time event: automatically disarm */ else { prev->next = t->next; t->super.refCtr_ &= (uint8_t)0x7F; /* mark as unlinked */ /* do NOT advance the prev pointer */ QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_AUTO_DISARM, QS_priv_.teObjFilter, t) QS_OBJ_(t); /* this time event object */ QS_OBJ_(act); /* the target AO */ QS_U8_((uint8_t)tickRate); /* tick rate */ QS_END_NOCRIT_() } QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_POST, QS_priv_.teObjFilter, t) QS_TIME_(); /* timestamp */ QS_OBJ_(t); /* the time event object */ QS_SIG_(t->super.sig); /* signal of this time event */ QS_OBJ_(act); /* the target AO */ QS_U8_((uint8_t)tickRate); /* tick rate */ QS_END_NOCRIT_() QF_CRIT_EXIT_(); /* exit critical section before posting */ /* QACTIVE_POST() asserts internally if the queue overflows */ QACTIVE_POST(act, &t->super, sender); } else { prev = t; /* advance to this time event */ QF_CRIT_EXIT_(); /* exit crit. section to reduce latency */ /* prevent merging critical sections, see NOTE1 below */ QF_CRIT_EXIT_NOP(); } }