Dining Philosopher Problem example NOTE: Requries QP5. static uint8_t registered = (uint8_t)0; /* starts off with 0, per C-standard */ (void)e; /* suppress the compiler warning about unused parameter */ if (registered == (uint8_t)0) { registered = (uint8_t)1; QS_OBJ_DICTIONARY(&l_philo[0]); QS_OBJ_DICTIONARY(&l_philo[0].timeEvt); QS_OBJ_DICTIONARY(&l_philo[1]); QS_OBJ_DICTIONARY(&l_philo[1].timeEvt); QS_OBJ_DICTIONARY(&l_philo[2]); QS_OBJ_DICTIONARY(&l_philo[2].timeEvt); QS_OBJ_DICTIONARY(&l_philo[3]); QS_OBJ_DICTIONARY(&l_philo[3].timeEvt); QS_OBJ_DICTIONARY(&l_philo[4]); QS_OBJ_DICTIONARY(&l_philo[4].timeEvt); QS_FUN_DICTIONARY(&Philo_initial); QS_FUN_DICTIONARY(&Philo_thinking); QS_FUN_DICTIONARY(&Philo_hungry); QS_FUN_DICTIONARY(&Philo_eating); } QS_SIG_DICTIONARY(HUNGRY_SIG, me); /* signal for each Philos */ QS_SIG_DICTIONARY(TIMEOUT_SIG, me); /* signal for each Philos */ QActive_subscribe(&me->super, EAT_SIG); QActive_subscribe(&me->super, TEST_SIG); QTimeEvt_armX(&me->timeEvt, THINK_TIME, 0U); QTimeEvt_disarm(&me->timeEvt); /* EAT or DONE must be for other Philos than this one */ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG); pe->philoNum = PHILO_ID(me); QACTIVE_POST(AO_Table, &pe->super, me); Q_EVT_CAST(TableEvt)->philoNum == PHILO_ID(me) /* DONE must be for other Philos than this one */ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); QF_PUBLISH(&pe->super, me); /* EAT or DONE must be for other Philos than this one */ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); uint8_t n; (void)e; /* suppress the compiler warning about unused parameter */ QS_OBJ_DICTIONARY(&l_table); QS_FUN_DICTIONARY(&QHsm_top); QS_FUN_DICTIONARY(&Table_initial); QS_FUN_DICTIONARY(&Table_active); QS_FUN_DICTIONARY(&Table_serving); QS_FUN_DICTIONARY(&Table_paused); QS_SIG_DICTIONARY(DONE_SIG, (void *)0); /* global signals */ QS_SIG_DICTIONARY(EAT_SIG, (void *)0); QS_SIG_DICTIONARY(PAUSE_SIG, (void *)0); QS_SIG_DICTIONARY(SERVE_SIG, (void *)0); QS_SIG_DICTIONARY(TEST_SIG, (void *)0); QS_SIG_DICTIONARY(HUNGRY_SIG, me); /* signal just for Table */ QActive_subscribe(&me->super, DONE_SIG); QActive_subscribe(&me->super, PAUSE_SIG); QActive_subscribe(&me->super, SERVE_SIG); QActive_subscribe(&me->super, TEST_SIG); for (n = 0U; n < N_PHILO; ++n) { me->fork[n] = FREE; me->isHungry[n] = 0U; BSP_displayPhilStat(n, "thinking"); } Q_ERROR(); uint8_t n; for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ if ((me->isHungry[n] != 0U) && (me->fork[LEFT(n)] == FREE) && (me->fork[n] == FREE)) { TableEvt *te; me->fork[LEFT(n)] = USED; me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; QF_PUBLISH(&te->super, me); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } } uint8_t n, m; n = Q_EVT_CAST(TableEvt)->philoNum; /* phil ID must be in range and he must be not hungry */ Q_ASSERT((n < N_PHILO) && (me->isHungry[n] == 0U)); BSP_displayPhilStat(n, "hungry "); m = LEFT(n); (me->fork[m] == FREE) && (me->fork[n] == FREE) TableEvt *pe; me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; QF_PUBLISH(&pe->super, me); BSP_displayPhilStat(n, "eating "); else me->isHungry[n] = 1U; uint8_t n, m; TableEvt *pe; n = Q_EVT_CAST(TableEvt)->philoNum; /* phil ID must be in range and he must be not hungry */ Q_ASSERT((n < N_PHILO) && (me->isHungry[n] == 0U)); BSP_displayPhilStat(n, "thinking"); m = LEFT(n); /* both forks of Phil[n] must be used */ Q_ASSERT((me->fork[n] == USED) && (me->fork[m] == USED)); me->fork[m] = FREE; me->fork[n] = FREE; m = RIGHT(n); /* check the right neighbor */ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->fork[n] = USED; me->fork[m] = USED; me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; QF_PUBLISH(&pe->super, me); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ n = LEFT(m); /* left fork of the left neighbor */ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->fork[m] = USED; me->fork[n] = USED; me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; QF_PUBLISH(&pe->super, me); BSP_displayPhilStat(m, "eating "); } Q_ERROR(); BSP_displayPaused(1U); BSP_displayPaused(0U); uint8_t n = Q_EVT_CAST(TableEvt)->philoNum; /* philo ID must be in range and he must be not hungry */ Q_ASSERT((n < N_PHILO) && (me->isHungry[n] == 0U)); me->isHungry[n] = 1U; BSP_displayPhilStat(n, "hungry "); uint8_t n, m; n = Q_EVT_CAST(TableEvt)->philoNum; /* phil ID must be in range and he must be not hungry */ Q_ASSERT((n < N_PHILO) && (me->isHungry[n] == 0U)); BSP_displayPhilStat(n, "thinking"); m = LEFT(n); /* both forks of Phil[n] must be used */ Q_ASSERT((me->fork[n] == USED) && (me->fork[m] == USED)); me->fork[m] = FREE; me->fork[n] = FREE; uint8_t n; Philo *me; for (n = 0U; n < N_PHILO; ++n) { me = &l_philo[n]; QActive_ctor(&me->super, Q_STATE_CAST(&Philo_initial)); QTimeEvt_ctorX(&me->timeEvt, &me->super, TIMEOUT_SIG, 0U); } uint8_t n; Table *me = &l_table; QActive_ctor(&me->super, Q_STATE_CAST(&Table_initial)); for (n = 0U; n < N_PHILO; ++n) { me->fork[n] = FREE; me->isHungry[n] = 0U; } #ifndef dpp_h #define dpp_h enum DPPSignals { EAT_SIG = Q_USER_SIG, /* published by Table to let a philosopher eat */ DONE_SIG, /* published by Philosopher when done eating */ PAUSE_SIG, /* published by BSP to pause serving forks */ SERVE_SIG, /* published by BSP to serve re-start serving forks */ TEST_SIG, /* published by BSP to test the application */ MAX_PUB_SIG, /* the last published signal */ HUNGRY_SIG, /* posted direclty to Table from hungry Philo */ TIMEOUT_SIG, /* used by Philosophers for time events */ MAX_SIG /* the last signal */ }; $declare(Events::TableEvt) /* number of philosophers */ #define N_PHILO ((uint8_t)5) $declare(AOs::Philo_ctor) $declare(AOs::AO_Philo[N_PHILO]) $declare(AOs::Table_ctor) $declare(AOs::AO_Table) #ifdef qxk_h void Test1_ctor(void); extern QXThread * const XT_Test1; void Test2_ctor(void); extern QXThread * const XT_Test2; #endif /* qxk_h */ #endif /* dpp_h */ #include "qpc.h" #include "dpp.h" #include "bsp.h" Q_DEFINE_THIS_FILE /* Active object class -----------------------------------------------------*/ $declare(AOs::Philo) /* Local objects -----------------------------------------------------------*/ static Philo l_philo[N_PHILO]; /* storage for all Philos */ #define THINK_TIME \ (QTimeEvtCtr)((BSP_random() % BSP_TICKS_PER_SEC) + (BSP_TICKS_PER_SEC/2U)) #define EAT_TIME \ (QTimeEvtCtr)((BSP_random() % BSP_TICKS_PER_SEC) + BSP_TICKS_PER_SEC) /* helper macro to provide the ID of Philo "me_" */ #define PHILO_ID(me_) ((uint8_t)((me_) - l_philo)) /* Global objects ----------------------------------------------------------*/ QMActive * const AO_Philo[N_PHILO] = { /* "opaque" pointers to Philo AO */ &l_philo[0].super, &l_philo[1].super, &l_philo[2].super, &l_philo[3].super, &l_philo[4].super }; /* Philo definition --------------------------------------------------------*/ $define(AOs::Philo_ctor) $define(AOs::Philo) #include "qpc.h" #include "dpp.h" #include "bsp.h" Q_DEFINE_THIS_FILE /* Active object class -----------------------------------------------------*/ $declare(AOs::Table) #define RIGHT(n_) ((uint8_t)(((n_) + (N_PHILO - 1U)) % N_PHILO)) #define LEFT(n_) ((uint8_t)(((n_) + 1U) % N_PHILO)) #define FREE ((uint8_t)0) #define USED ((uint8_t)1) /* Local objects -----------------------------------------------------------*/ static Table l_table; /* the single instance of the Table active object */ /* Global-scope objects ----------------------------------------------------*/ QMActive * const AO_Table = &l_table.super; /* "opaque" AO pointer */ /*..........................................................................*/ $define(AOs::Table_ctor) $define(AOs::Table)