/*..........................................................................*/ void QF_poolInit(void *poolSto, uint32_t poolSize, QEventSize evtSize) { /* cannot exceed the number of available memory pools */ /* ------------------------------------------------------------------------- This precondition (see Chapter 6, “Customized Assertions in C/C++”) asserts that the application does not attempt to initialize more than the supported number of event pools (currently three). -------------------------------------------------------------------------*/ Q_REQUIRE(QF_maxPool_ < (uint8_t)Q_DIM(QF_pool_)); /* please initialize event pools in ascending order of evtSize: */ /* ------------------------------------------------------------------------- For possibly quick event allocation, the event pool array QF_pool_[] must be sorted in ascending order of block sizes. This precondition asserts that the application initializes event pools in the increasing order of the event sizes. This assertion significantly simplifies the QF_poolInit() function without causing any true inconvenience for the application implementer. -------------------------------------------------------------------------*/ Q_REQUIRE((QF_maxPool_ == (uint8_t)0) || (QF_EPOOL_EVENT_SIZE_(QF_pool_[QF_maxPool_ - 1]) < evtSize)); /* perfom the platform-dependent initialization of the pool */ QF_EPOOL_INIT_(QF_pool_[QF_maxPool_], poolSto, poolSize, evtSize); ++QF_maxPool_; /* one more pool */ }
/*..........................................................................*/ void QF_poolInit(void *poolSto, uint32_t poolSize, QEventSize evtSize) { /* cannot exceed the number of available memory pools */ Q_REQUIRE(QF_maxPool_ < (uint8_t)Q_DIM(QF_pool_)); /* please initialize event pools in ascending order of evtSize: */ Q_REQUIRE((QF_maxPool_ == (uint8_t)0) || (QF_EPOOL_EVENT_SIZE_(QF_pool_[QF_maxPool_ - (uint8_t)1]) < evtSize)); /* perfom the platform-dependent initialization of the pool */ QF_EPOOL_INIT_(QF_pool_[QF_maxPool_], poolSto, poolSize, evtSize); ++QF_maxPool_; /* one more pool */ }
/*..........................................................................*/ void QFsm_init_(QFsm * const me, QEvt const * const e) { QS_CRIT_STAT_ Q_REQUIRE((me->vptr != (QMsmVtbl const *)0) /* ctor must be executed */ && (me->temp.fun != Q_STATE_CAST(0)) /* ctor must be executed */ && (me->state.fun == Q_STATE_CAST(0)));/*init tran. NOT taken */ QS_BEGIN_(QS_QEP_STATE_INIT, QS_priv_.smObjFilter, me) QS_OBJ_(me); /* this state machine object */ QS_FUN_(Q_STATE_CAST(0)); /* source state (not defined for a FSM) */ QS_FUN_(me->temp.fun); /* the target of the transition */ QS_END_() /* execute the top-most initial transition */ Q_ALLEGE((*me->temp.fun)(me, e) == (QState)Q_RET_TRAN);/* must be taken */ (void)QEP_TRIG_(me->temp.fun, Q_ENTRY_SIG); /* enter the target */ me->state.fun = me->temp.fun; /* record the new active state */ QS_BEGIN_(QS_QEP_INIT_TRAN, QS_priv_.smObjFilter, me) QS_TIME_(); /* time stamp */ QS_OBJ_(me); /* this state machine object */ QS_FUN_(me->state.fun); /* the new active state */ QS_END_() }
//............................................................................ static void dispatch(QSignal sig) { QEvt e; Q_REQUIRE((A_SIG <= sig) && (sig <= I_SIG)); e.sig = sig; fprintf(l_outFile, "\n%c:", 'A' + sig - A_SIG); the_hsm->dispatch(&e); // dispatch the event }
/*..........................................................................*/ uint8_t QTimeEvt_rearm(QTimeEvt * const me, QTimeEvtCtr const nTicks) { uint8_t isArmed; QF_CRIT_STAT_ Q_REQUIRE((nTicks != (QTimeEvtCtr)0) /* cannot arm a timer with 0 ticks */ && (me->act != (QActive *)0) /* active object must be valid */ && (me->super.sig >= (QSignal)Q_USER_SIG)); /* valid signal */ QF_CRIT_ENTRY_(); if (me->ctr == (QTimeEvtCtr)0) { /* is the time evt disarmed? */ isArmed = (uint8_t)0; if (QF_EVT_REF_CTR_(&me->super) == (uint8_t)0) { /* not linked? */ me->next = QF_timeEvtListHead_; QF_timeEvtListHead_ = me; QF_EVT_REF_CTR_INC_(&me->super); /* mark as linked */ } } else { /* the time event is armed */ isArmed = (uint8_t)1; } me->ctr = nTicks; /* re-load the tick counter (shift the phasing) */ QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_REARM, QS_teObj_, me) QS_TIME_(); /* timestamp */ QS_OBJ_(me); /* this time event object */ QS_OBJ_(me->act); /* the active object */ QS_TEC_(me->ctr); /* the number of ticks */ QS_TEC_(me->interval); /* the interval */ QS_U8_(isArmed); /* was the timer armed? */ QS_END_NOCRIT_() QF_CRIT_EXIT_(); return isArmed; }
/*..........................................................................*/ void QTimeEvt_arm_(QTimeEvt *me, QActive *act, QTimeEvtCtr nTicks) { QF_CRIT_STAT_ Q_REQUIRE((nTicks > (QTimeEvtCtr)0) /* cannot arm a timer with 0 ticks */ && (me->super.sig >= (QSignal)Q_USER_SIG) /* valid signal */ && (me->prev == (QTimeEvt *)0) /* time evt must NOT be used */ && (act != (QActive *)0)); /* active object must be provided */ me->ctr = nTicks; me->prev = me; /* mark the timer in use */ me->act = act; QF_CRIT_ENTRY_(); QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_ARM, QS_teObj_, me) QS_TIME_(); /* timestamp */ QS_OBJ_(me); /* this time event object */ QS_OBJ_(act); /* the active object */ QS_TEC_(nTicks); /* the number of ticks */ QS_TEC_(me->interval); /* the interval */ QS_END_NOCRIT_() me->next = QF_timeEvtListHead_; if (QF_timeEvtListHead_ != (QTimeEvt *)0) { QF_timeEvtListHead_->prev = me; } QF_timeEvtListHead_ = me; QF_CRIT_EXIT_(); }
//............................................................................ void QMsm::dispatch(QEvt const * const e) { QMState const *s = m_state.obj; // store the current state QMState const *t; QState r = Q_RET_HANDLED; QS_CRIT_STAT_ Q_REQUIRE(s != (QMState const *)0); // must be initialized QS_BEGIN_(QS_QEP_DISPATCH, QS::priv_.smObjFilter, this) QS_TIME_(); // time stamp QS_SIG_(e->sig); // the signal of the event QS_OBJ_(this); // this state machine object QS_FUN_(s->stateHandler); // the current state handler QS_END_() for (t = s; t != static_cast<QMState const *>(0); t = t->parent) { r = (*t->stateHandler)(this, e); if (r != Q_RET_SUPER) { if (r == Q_RET_UNHANDLED) { // unhandled due to a guard? QS_BEGIN_(QS_QEP_UNHANDLED, QS::priv_.smObjFilter, this) QS_SIG_(e->sig); // the signal of the event QS_OBJ_(this); // this state machine object QS_FUN_(t->stateHandler); // the current state QS_END_() } else { break; // event handled--break out of the loop } }
//............................................................................ void BSP_displayPhilStat(uint8_t n, char_t const *stat) { static QLabel * const philoLabel[] = { Gui::instance()->m_philoLabel_0, Gui::instance()->m_philoLabel_1, Gui::instance()->m_philoLabel_2, Gui::instance()->m_philoLabel_3, Gui::instance()->m_philoLabel_4 }; static QPixmap thinking(":/res/thinking.png"); static QPixmap hungry (":/res/hungry.png"); static QPixmap eating (":/res/eating.png"); Q_REQUIRE(n < Q_DIM(philoLabel)); switch (stat[0]) { case 't': philoLabel[n]->setPixmap(thinking); break; case 'h': philoLabel[n]->setPixmap(hungry); break; case 'e': philoLabel[n]->setPixmap(eating); break; } qDebug("philo[%d] is %s", n, stat); }
//............................................................................ static void simHardKey(int keyIndex, int keyState) { static const QEvent keyEvt[] = { { KEY_UP_REL_SIG, 0 }, // hardkey UP released { KEY_UP_PRESS_SIG, 0 }, // hardkey UP pressed { KEY_RIGHT_REL_SIG, 0 }, // hardkey RIGHT released { KEY_RIGHT_PRESS_SIG, 0 }, // hardkey RIGHT pressed { KEY_CENTER_REL_SIG, 0 }, // hardkey CENTER released { KEY_CENTER_PRESS_SIG, 0 }, // hardkey CENTER pressed { KEY_LEFT_REL_SIG, 0 }, // hardkey LEFT released { KEY_LEFT_PRESS_SIG, 0 }, // hardkey LEFT pressed { KEY_DOWN_REL_SIG, 0 }, // hardkey DOWN released { KEY_DOWN_PRESS_SIG, 0 }, // hardkey DOWN pressed { KEY_POWER_REL_SIG, 0 }, // hardkey POWER released { KEY_POWER_PRESS_SIG, 0 } // hardkey POWER pressed }; // do not overrun the array Q_REQUIRE((keyIndex * 2) + keyState < Q_DIM(keyEvt)); // post the hardkey event to the Table active object (GUI manager) AO_Table->POST(&keyEvt[(keyIndex * 2) + keyState], &l_simHardKey); if ((keyIndex == 5) && (keyState == 0)) { // hardkey POWER released? QF::stop(); // terminate the simulation } }
/*..........................................................................*/ void QActive_unsubscribeAll(QActive const *me) { uint8_t p = me->prio; uint8_t i; QSignal sig; Q_REQUIRE(((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE) && (QF_active_[p] == me)); i = QF_div8Lkup[p]; for (sig = (QSignal)Q_USER_SIG; sig < QF_maxSignal_; ++sig) { QF_CRIT_STAT_ QF_CRIT_ENTRY_(); if ((QF_PTR_AT_(QF_subscrList_, sig).bits[i] & Q_ROM_BYTE(QF_pwr2Lkup[p])) != (uint8_t)0) { QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_UNSUBSCRIBE, QS_aoObj_, me) QS_TIME_(); /* timestamp */ QS_SIG_(sig); /* the signal of this event */ QS_OBJ_(me); /* this active object */ QS_END_NOCRIT_() /* clear the priority bit */ QF_PTR_AT_(QF_subscrList_, sig).bits[i] &= Q_ROM_BYTE(QF_invPwr2Lkup[p]); } QF_CRIT_EXIT_(); } }
/* initial pseudostate of the QBomb FSM ....................................*/ QState QBomb_initial(QBomb *me, QEvent const *e) { Q_REQUIRE(e != (QEvent *)0); /* initialization event expected */ QBomb_updateState(me, "top-INIT"); me->timeout = INIT_TIMEOUT; me->defuse = ((QBombInitEvt const *)e)->defuse; return Q_TRAN(&QBomb_setting); /* initial transition */ }
/*..........................................................................*/ QHsm *Mine2_ctor(uint8_t id) { Mine2 *me; Q_REQUIRE(id < GAME_MINES_MAX); me = &l_mine2[id]; QHsm_ctor(&me->super, (QStateHandler)&Mine2_initial);/*superclass' ctor */ return (QHsm *)me; }
/* @(/2/12) ................................................................*/ QMsm * Mine2_ctor(uint8_t id) { Mine2 *me; Q_REQUIRE(id < GAME_MINES_MAX); me = &l_mine2[id]; /* superclass' ctor */ QMsm_ctor(&me->super, Q_STATE_CAST(&Mine2_initial)); return (QMsm *)me; }
void QF_publish_(QEvt const * const e, void const * const sender) #endif { QF_CRIT_STAT_ /* make sure that the published signal is within the configured range */ Q_REQUIRE(e->sig < (QSignal)QF_maxSignal_); QF_CRIT_ENTRY_(); QS_BEGIN_NOCRIT_(QS_QF_PUBLISH, (void *)0, (void *)0) QS_TIME_(); /* the timestamp */ QS_OBJ_(sender); /* the sender object */ QS_SIG_(e->sig); /* the signal of the event */ QS_2U8_(e->poolId_, e->refCtr_);/* pool Id & ref Count of the event */ QS_END_NOCRIT_() if (e->poolId_ != (uint8_t)0) { /* is it a dynamic event? */ QF_EVT_REF_CTR_INC_(e); /* increment reference counter, NOTE01 */ } QF_CRIT_EXIT_(); #if (QF_MAX_ACTIVE <= 8) { uint8_t tmp = QF_subscrList_[e->sig].bits[0]; while (tmp != (uint8_t)0) { uint8_t p = QF_LOG2(tmp); tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]); /* clear subscriber bit */ Q_ASSERT(QF_active_[p] != (QActive *)0); /* must be registered */ /* QACTIVE_POST() asserts internally if the queue overflows */ QACTIVE_POST(QF_active_[p], e, sender); } } #else { uint_t i = (uint_t)Q_DIM(QF_subscrList_[0].bits); do { /* go through all bytes in the subscription list */ uint8_t tmp; --i; tmp = QF_PTR_AT_(QF_subscrList_, e->sig).bits[i]; while (tmp != (uint8_t)0) { uint8_t p = QF_LOG2(tmp); tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);/*clear subscriber bit */ p = (uint8_t)(p + (uint8_t)(i << 3));/* adjust the priority */ Q_ASSERT(QF_active_[p] != (QActive *)0);/*must be registered*/ /* QACTIVE_POST() asserts internally if the queue overflows */ QACTIVE_POST(QF_active_[p], e, sender); } } while (i != (uint_t)0); } #endif QF_gc(e); /* run the garbage collector, see NOTE01 */ }
/*..........................................................................*/ void QMPool_put(QMPool *me, void *b) { QF_CRIT_STAT_ Q_REQUIRE(me->nFree <= me->nTot); /* # free blocks must be < total */ Q_REQUIRE(QF_PTR_RANGE_(b, me->start, me->end)); /* b must be in range */ QF_CRIT_ENTRY_(); ((QFreeBlock *)b)->next = (QFreeBlock *)me->free_head;/* link into list */ me->free_head = b; /* set as new head of the free list */ ++me->nFree; /* one more free block in this pool */ QS_BEGIN_NOCRIT_(QS_QF_MPOOL_PUT, QS_mpObj_, me->start) QS_TIME_(); /* timestamp */ QS_OBJ_(me->start); /* the memory managed by this pool */ QS_MPC_(me->nFree); /* the number of free blocks in the pool */ QS_END_NOCRIT_() QF_CRIT_EXIT_(); }
/*..........................................................................*/ void QTimeEvt_ctor(QTimeEvt *me, QSignal sig) { Q_REQUIRE(sig >= (QSignal)Q_USER_SIG); /* valid signal */ me->prev = (QTimeEvt *)0; me->next = (QTimeEvt *)0; me->act = (QActive *)0; me->ctr = (QTimeEvtCtr)0; me->interval = (QTimeEvtCtr)0; me->super.sig = sig; me->super.dynamic_ = (uint8_t)0; /* time event must be static, NOTE01 */ }
/*..........................................................................*/ uint32_t QF_getPoolMargin(uint8_t poolId) { uint32_t margin; QF_INT_LOCK_KEY_ Q_REQUIRE(((uint8_t)1 <= poolId) && (poolId <= QF_maxPool_)); QF_INT_LOCK_(); margin = (uint32_t)QF_pool_[poolId - (uint8_t)1].nMin; QF_INT_UNLOCK_(); return margin; }
/*..........................................................................*/ void QTimeEvt_ctor(QTimeEvt *me, QSignal sig) { Q_REQUIRE(sig >= (QSignal)Q_USER_SIG); /* valid signal */ me->prev = (QTimeEvt *)0; me->next = (QTimeEvt *)0; me->act = (QActive *)0; me->ctr = (QTimeEvtCtr)0; me->interval = (QTimeEvtCtr)0; me->super.sig = sig; /* time event must be static, see NOTE01 */ QF_EVT_POOL_ID_(&me->super) = (uint8_t)0; }
QP::QState Txr::freeRun(Txr * const me, QP::QEvt const * const e) { QP::QState status_; switch (e->sig) { case Q_ENTRY_SIG: { ENC_RED_LED_OFF(); analogWrite(ENC_GREEN_LED, 15); me->mPacket.mode = FREE_MODE; status_ = Q_HANDLED(); break; } case Q_EXIT_SIG: { status_ = Q_HANDLED(); break; } case SEND_TIMEOUT_SIG: { me->UpdatePosition(me); status_ = Q_HANDLED(); break; } case POSITION_BUTTON_SIG: { // only save position if finished flashing from previous save if (me->mFlashTimeout.ctr() == 0) { me->mPrevPositionButtonPressed = ((PositionButtonEvt*)e)->ButtonNum; Q_REQUIRE(me->mPrevPositionButtonPressed < NUM_POSITION_BUTTONS); me->mSavedPositions[me->mPrevPositionButtonPressed] = me->mCurPos; settings.SetSavedPos((int)me->mCurPos,me->mPrevPositionButtonPressed); BSP_TurnOnSpeedLED(me->mPrevPositionButtonPressed); me->mFlashTimeout.postIn(me, FLASH_RATE_TOUT); } status_ = Q_HANDLED(); break; } case FLASH_RATE_SIG: { // turn off flashed LED BSP_TurnOffSpeedLED(me->mPrevPositionButtonPressed); status_ = Q_HANDLED(); break; } default: { status_ = Q_SUPER(&calibrated); break; } } return status_; }
/*..........................................................................*/ void QActive_start_(QActive * const me, uint_fast8_t prio, QEvt const *qSto[], uint_fast16_t qLen, void *stkSto, uint_fast16_t stkSize, QEvt const *ie, const char* taskName) { pthread_t thread; pthread_attr_t attr; struct sched_param param; Q_REQUIRE(stkSto == (void *)0); /* p-threads allocate stack internally */ QEQueue_init(&me->eQueue, qSto, qLen); pthread_cond_init(&me->osObject, 0); me->prio = (uint8_t)prio; QF_add_(me); /* make QF aware of this active object */ QMSM_INIT(&me->super, ie); /* execute the initial transition */ pthread_attr_init(&attr); /* SCHED_FIFO corresponds to real-time preemptive priority-based scheduler * NOTE: This scheduling policy requires the superuser privileges */ pthread_attr_setschedpolicy(&attr, SCHED_FIFO); /* see NOTE04 */ param.sched_priority = prio + (sched_get_priority_max(SCHED_FIFO) - QF_MAX_ACTIVE - 3); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (stkSize == 0U) { /* set the allowed minimum */ stkSize = (uint_fast16_t)PTHREAD_STACK_MIN; } pthread_attr_setstacksize(&attr, (size_t)stkSize); if (pthread_create(&thread, &attr, &thread_routine, me) != 0) { /* Creating the p-thread with the SCHED_FIFO policy failed. Most * probably this application has no superuser privileges, so we just * fall back to the default SCHED_OTHER policy and priority 0. */ pthread_attr_setschedpolicy(&attr, SCHED_OTHER); param.sched_priority = 0; pthread_attr_setschedparam(&attr, ¶m); Q_ALLEGE(pthread_create(&thread, &attr, &thread_routine, me)== 0); } pthread_attr_destroy(&attr); me->thread = (uint8_t)1; }
/*..........................................................................*/ void QMPool_init(QMPool * const me, void * const poolSto, uint32_t poolSize, QMPoolSize blockSize) { QFreeBlock *fb; uint32_t nblocks; QS_CRIT_STAT_ /* The memory block must be valid * and the poolSize must fit at least one free block * and the blockSize must not be too close to the top of the dynamic range */ Q_REQUIRE((poolSto != (void *)0) && (poolSize >= (uint32_t)sizeof(QFreeBlock)) && ((QMPoolSize)(blockSize + (QMPoolSize)sizeof(QFreeBlock)) > blockSize)); me->free_head = poolSto; /* round up the blockSize to fit an integer # free blocks, no division */ me->blockSize = (QMPoolSize)sizeof(QFreeBlock); /* start with just one */ nblocks = (uint32_t)1; /* # free blocks that fit in one memory block */ while (me->blockSize < blockSize) { me->blockSize += (QMPoolSize)sizeof(QFreeBlock); ++nblocks; } blockSize = me->blockSize; /* use the rounded-up value from now on */ /* the pool buffer must fit at least one rounded-up block */ Q_ASSERT(poolSize >= (uint32_t)blockSize); /* chain all blocks together in a free-list... */ poolSize -= (uint32_t)blockSize; /* don't count the last block */ me->nTot = (QMPoolCtr)1; /* the last block already in the pool */ fb = (QFreeBlock *)me->free_head; /* start at the head of the free list */ while (poolSize >= (uint32_t)blockSize) { fb->next = &QF_PTR_AT_(fb, nblocks);/*point next link to next block */ fb = fb->next; /* advance to the next block */ poolSize -= (uint32_t)blockSize; /* reduce the available pool size */ ++me->nTot; /* increment the number of blocks so far */ } fb->next = (QFreeBlock *)0; /* the last link points to NULL */ me->nFree = me->nTot; /* all blocks are free */ me->nMin = me->nTot; /* the minimum number of free blocks */ me->start = poolSto; /* the original start this pool buffer */ me->end = fb; /* the last block in this pool */ QS_BEGIN_(QS_QF_MPOOL_INIT, QS_priv_.mpObjFilter, me->start) QS_OBJ_(me->start); /* the memory managed by this pool */ QS_MPC_(me->nTot); /* the total number of blocks */ QS_END_() }
/*..........................................................................*/ void QF_run(void) { uint8_t p; QActive *a; QEvent const *e; QF_INT_LOCK_KEY_ QF_onStartup(); /* startup callback */ for (;;) { /* the background loop */ QF_INT_LOCK_(); #if (QF_MAX_ACTIVE <= 8) if (QPSet8_notEmpty(&QF_readySet_)) { QPSet8_findMax(&QF_readySet_, p); #else if (QPSet64_notEmpty(&QF_readySet_)) { QPSet64_findMax(&QF_readySet_, p); #endif a = QF_active_[p]; QF_INT_UNLOCK_(); e = QActive_get_(a); /* get the next event for this AO */ QF_ACTIVE_DISPATCH_(&a->super, e); /* dispatch to the AO */ QF_gc(e); /* determine if event is garbage and collect it if so */ } else { #ifndef QF_INT_KEY_TYPE QF_onIdle(); /* see NOTE01 */ #else QF_onIdle(intLockKey_); /* see NOTE01 */ #endif /* QF_INT_KEY_TYPE */ } } } /*..........................................................................*/ void QActive_start(QActive *me, uint8_t prio, QEvent const *qSto[], uint32_t qLen, void *stkSto, uint32_t stkSize, QEvent const *ie) { Q_REQUIRE(((uint8_t)0 < prio) && (prio <= (uint8_t)QF_MAX_ACTIVE) && (stkSto == (void *)0)); /* does not need per-actor stack */ (void)stkSize; /* avoid the "unused parameter" compiler warning */ QEQueue_init(&me->eQueue, qSto, (QEQueueCtr)qLen);/* initialize QEQueue */ me->prio = prio; /* set the QF priority of this active object */ QF_add_(me); /* make QF aware of this active object */ QF_ACTIVE_INIT_(&me->super, ie); /* execute initial transition */ QS_FLUSH(); /* flush the trace buffer to the host */ }
/*..........................................................................*/ uint32_t QF_getQueueMargin(uint8_t prio) { uint32_t margin; QF_INT_LOCK_KEY_ Q_REQUIRE((prio <= (uint8_t)QF_MAX_ACTIVE) && (QF_active_[prio] != (QActive *)0)); QF_INT_LOCK_(); margin = (uint32_t)(QF_active_[prio]->eQueue__.nTot__ - QF_active_[prio]->eQueue__.nMax__); QF_INT_UNLOCK_(); return margin; }
/*..........................................................................*/ void QHsm_init(QHsm * const me, QEvt const * const e) { QStateHandler t = me->state.fun; QS_CRIT_STAT_ Q_REQUIRE((me->vptr != (QMsmVtbl const *)0) /* ctor must be executed */ && (me->temp.fun != Q_STATE_CAST(0)) /* ctor must be executed */ && (t == Q_STATE_CAST(&QHsm_top))); /*initial tran. NOT taken */ /* the top-most initial transition must be taken */ Q_ALLEGE((*me->temp.fun)(me, e) == (QState)Q_RET_TRAN); do { /* drill into the target... */ QStateHandler path[QEP_MAX_NEST_DEPTH_]; int_t ip = (int_t)0; /* transition entry path index */ QS_BEGIN_(QS_QEP_STATE_INIT, QS_priv_.smObjFilter, me) QS_OBJ_(me); /* this state machine object */ QS_FUN_(t); /* the source state */ QS_FUN_(me->temp.fun); /* the target of the initial transition */ QS_END_() path[0] = me->temp.fun; (void)QEP_TRIG_(me->temp.fun, QEP_EMPTY_SIG_); while (me->temp.fun != t) { ++ip; path[ip] = me->temp.fun; (void)QEP_TRIG_(me->temp.fun, QEP_EMPTY_SIG_); } me->temp.fun = path[0]; /* entry path must not overflow */ Q_ASSERT(ip < (int_t)QEP_MAX_NEST_DEPTH_); do { /* retrace the entry path in reverse (desired) order... */ QEP_ENTER_(path[ip]); /* enter path[ip] */ --ip; } while (ip >= (int_t)0); t = path[0]; /* current state becomes the new source */ } while (QEP_TRIG_(t, Q_INIT_SIG) == (QState)Q_RET_TRAN); QS_BEGIN_(QS_QEP_INIT_TRAN, QS_priv_.smObjFilter, me) QS_TIME_(); /* time stamp */ QS_OBJ_(me); /* this state machine object */ QS_FUN_(t); /* the new active state */ QS_END_() me->state.fun = t; /* change the current active state */ me->temp.fun = t; /* mark the configuration as stable */ }
/*..........................................................................*/ void QHsm_init(QHsm *me, QEvent const *e) { QHsmState s; /* this state machine must be initialized with QHsm_ctor_() */ Q_REQUIRE(((QFsm *)me)->state__.fsm != (QState)0); s = &QHsm_top; /* an HSM starts in the top state */ /* trigger the initial transition */ (*((QFsm *)me)->state__.fsm)((QFsm *)me, e); do { /* drill into the target... */ QHsmState path[QEP_MAX_NEST_DEPTH_]; int8_t ip = (int8_t)0; /* transition entry path index */ QHsmState t = ((QFsm *)me)->state__.hsm; QS_BEGIN_(QS_QEP_STATE_INIT, QS_smObj_, me); QS_OBJ_(me); /* this state machine object */ QS_FUN_(s); /* the source state */ QS_FUN_(((QFsm *)me)->state__.hsm); /* the target */ QS_END_(); path[0] = t; for (t = QEP_TRIG_(t, QEP_EMPTY_SIG_); t != s; t = QEP_TRIG_(t, QEP_EMPTY_SIG_)) { path[++ip] = t; } /* entry path must not overflow */ Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); do { /* retrace the entry path in reverse (desired) order... */ /* enter path[ip] */ if (QEP_TRIG_(path[ip], Q_ENTRY_SIG) == (QHsmState)0) { QS_BEGIN_(QS_QEP_STATE_ENTRY, QS_smObj_, me); QS_OBJ_(me); /* this state machine object */ QS_FUN_(path[ip]); /* the entered state */ QS_END_(); } } while (--ip >= (int8_t)0); s = ((QFsm *)me)->state__.hsm; } while (QEP_TRIG_(s, Q_INIT_SIG) == (QHsmState)0); QS_BEGIN_(QS_QEP_INIT_TRAN, QS_smObj_, me); QS_TIME_(); /* time stamp */ QS_OBJ_(me); /* this state machine object */ QS_FUN_(((QFsm *)me)->state__.hsm); /* the new active state */ QS_END_(); }
//............................................................................ void QActive::start(uint8_t prio, QEvent const *qSto[], uint32_t qLen, void *stkSto, uint32_t /*lint -e1904 stkSize */, QEvent const *ie) { Q_REQUIRE(((uint8_t)0 < prio) && (prio <= (uint8_t)QF_MAX_ACTIVE) && (stkSto == (void *)0)); // does not need per-actor stack m_eQueue.init(qSto, (QEQueueCtr)qLen); // initialize QEQueue m_prio = prio; // set the QF priority of this active object QF::add_(this); // make QF aware of this active object init(ie); // execute initial transition QS_FLUSH(); // flush the trace buffer to the host }
/*..........................................................................*/ void QActive_start_(QActive * const me, uint_t prio, QEvt const *qSto[], uint_t qLen, void *stkSto, uint_t stkSize, QEvt const *ie) { DWORD threadId; int p; Q_REQUIRE((qSto != (QEvt const **)0) /* queue storage must be provided */ && (stkSto == (void *)0)); /* Windows allocates stack internally */ me->prio = (uint8_t)prio; QF_add_(me); /* make QF aware of this active object */ QEQueue_init(&me->eQueue, qSto, qLen); me->osObject = CreateEvent(NULL, FALSE, FALSE, NULL); QMSM_INIT(&me->super, ie); /* execute initial transition */ if (stkSize == 0U) { /* stack size not provided? */ stkSize = 1024U; /* NOTE: will be rounded up to the nearest page */ } me->thread = CreateThread(NULL, stkSize, &thread_function, me, 0, &threadId); Q_ASSERT(me->thread != (HANDLE)0); /* thread must be created */ switch (me->prio) { /* remap QF priority to Win32 priority */ case 1: p = THREAD_PRIORITY_IDLE; break; case 2: p = THREAD_PRIORITY_LOWEST; break; case 3: p = THREAD_PRIORITY_BELOW_NORMAL; break; case (QF_MAX_ACTIVE - 1): p = THREAD_PRIORITY_ABOVE_NORMAL; break; case QF_MAX_ACTIVE: p = THREAD_PRIORITY_HIGHEST; break; default: p = THREAD_PRIORITY_NORMAL; break; } SetThreadPriority(me->thread, p); }
/*..........................................................................*/ uint8_t QEQueue_post(QEQueue * const me, QEvt const * const e, uint16_t const margin) { QEQueueCtr nFree; /* temporary to avoid UB for volatile access */ uint8_t status; QF_CRIT_STAT_ Q_REQUIRE(e != (QEvt const *)0); /* event must be valid */ QF_CRIT_ENTRY_(); nFree = me->nFree; /* get volatile into the temporary */ if (nFree > (QEQueueCtr)margin) { /* required margin available? */ QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_POST_FIFO, QS_priv_.eqObjFilter, me) QS_TIME_(); /* timestamp */ QS_SIG_(e->sig); /* the signal of this event */ QS_OBJ_(me); /* this queue object */ QS_2U8_(e->poolId_, e->refCtr_); /* pool Id & ref Count */ QS_EQC_(nFree); /* number of free entries */ QS_EQC_(me->nMin); /* min number of free entries */ QS_END_NOCRIT_() if (e->poolId_ != (uint8_t)0) { /* is it a pool event? */ QF_EVT_REF_CTR_INC_(e); /* increment the reference counter */ } --nFree; /* one free entry just used up */ me->nFree = nFree; /* update the volatile */ if (me->nMin > nFree) { me->nMin = nFree; /* update minimum so far */ } if (me->frontEvt == (QEvt const *)0) { /* was the queue empty? */ me->frontEvt = e; /* deliver event directly */ } else { /* queue was not empty, insert event into the ring-buffer */ /* insert event into the ring buffer (FIFO) */ QF_PTR_AT_(me->ring, me->head) = e; /* insert e into buffer */ if (me->head == (QEQueueCtr)0) { /* need to wrap the head? */ me->head = me->end; /* wrap around */ } --me->head; } status = (uint8_t)1; /* event posted successfully */ }
/*..........................................................................*/ void QActive_start(QActive *me, uint8_t prio, QEvent const *qSto[], uint32_t qLen, void *stkSto, uint32_t stkSize, QEvent const *ie) { pthread_attr_t attr; struct sched_param param; Q_REQUIRE(stkSto == (void *)0); /* p-threads allocate stack internally */ QEQueue_init(&me->eQueue, qSto, (QEQueueCtr)qLen); pthread_cond_init(&me->osObject, 0); me->prio = prio; QF_add_(me); /* make QF aware of this active object */ QF_ACTIVE_INIT_(&me->super, ie); /* execute the initial transition */ QS_FLUSH(); /* flush the trace buffer to the host */ pthread_attr_init(&attr); /* SCHED_FIFO corresponds to real-time preemptive priority-based scheduler * NOTE: This scheduling policy requires the superuser privileges */ pthread_attr_setschedpolicy(&attr, SCHED_FIFO); /* see NOTE04 */ param.sched_priority = prio + (sched_get_priority_max(SCHED_FIFO) - QF_MAX_ACTIVE - 3); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (pthread_create(&me->thread, &attr, &thread_routine, me) != 0) { /* Creating the p-thread with the SCHED_FIFO policy failed. * Most probably this application has no superuser privileges, * so we just fall back to the default SCHED_OTHER policy * and priority 0. */ pthread_attr_setschedpolicy(&attr, SCHED_OTHER); param.sched_priority = 0; pthread_attr_setschedparam(&attr, ¶m); Q_ALLEGE(pthread_create(&me->thread, &attr, &thread_routine, me)== 0); } pthread_attr_destroy(&attr); }
//............................................................................ void GuiQActive::start(uint_fast8_t const prio, QEvt const *qSto[], uint_fast16_t const /*qLen*/, void * const stkSto, uint_fast16_t const /*stkSize*/, QEvt const * const ie) { Q_REQUIRE((static_cast<uint_fast8_t>(0) < prio) && (prio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE)) && (qSto == (QEvt const **)0)/* does not need per-actor queue */ && (stkSto == static_cast<void *>(0))); // AOs don't need stack setPrio(prio); // set the QF priority of this AO QF::add_(this); // make QF aware of this AO static_cast<GuiApp *>(QApplication::instance())->registerAct(this); this->init(ie); // execute initial transition (virtual call) QS_FLUSH(); // flush the trace buffer to the host }