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].timeEvt); QS_OBJ_DICTIONARY(&l_philo[1].timeEvt); QS_OBJ_DICTIONARY(&l_philo[2].timeEvt); QS_OBJ_DICTIONARY(&l_philo[3].timeEvt); 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_ID(10, 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_ID(20, 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); QTimeEvt_disarm(&me->timeEvt); /* EAT or DONE must be for other Philos than this one */ Q_ASSERT_ID(30, Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); uint8_t n; (void)e; /* suppress the compiler warning about unused parameter */ 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_ID(60); 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_ID(40, (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_ID(50, (n < N_PHILO) && (me->isHungry[n] == 0U)); BSP_displayPhilStat(n, "thinking"); m = LEFT(n); /* both forks of Phil[n] must be used */ Q_ASSERT_ID(51, (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 "); } 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_ID(60, (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_ID(70, (n < N_PHILO) && (me->isHungry[n] == 0U)); BSP_displayPhilStat(n, "thinking"); m = LEFT(n); /* both forks of Phil[n] must be used */ Q_ASSERT_ID(71, (me->fork[n] == USED) && (me->fork[m] == USED)); me->fork[m] = FREE; me->fork[n] = FREE; /* opaque pointers to the Philo AOs */ = { &l_philo[0].super, &l_philo[1].super, &l_philo[2].super, &l_philo[3].super, &l_philo[4].super }; /* opaque pointer to the Table AO */ = &l_table.super; 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_MODULE("philo") /* 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 ----------------------------------------------------------*/ $define${AOs::AO_Philo[N_PHILO]} /* Philo definition --------------------------------------------------------*/ $define${AOs::Philo_ctor} $define${AOs::Philo} #include "qpc.h" #include "dpp.h" #include "bsp.h" Q_DEFINE_THIS_MODULE("table") /* 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 ----------------------------------------------------*/ $define${AOs::AO_Table} /*..........................................................................*/ $define${AOs::Table_ctor} $define${AOs::Table}