/* * CS560: Operating Systems * Jim Plank * dphil_7.c -- Making the central queue work better. * January, 2009 */ #include #include #include "cbthread.h" #include "dphil.h" #include "dllist.h" #define talloc(ty, sz) (ty *) malloc ((sz) * sizeof(ty)) #define BEGIN 0 #define GOT_STICK_1 1 #define GOT_STICK_2 2 #define GOT_SEM_1 3 #define GOT_SEM_2 4 #define BLOCKED 5 #define QUEUED 6 typedef struct { Dllist q; cbthread_gsem *sems; int *sticks_free; int *my_pstates; } MyPhil; int test_philosopher(int pid, MyPhil *m, Simulation *s) { return (m->my_pstates[pid] == QUEUED && m->q->flink->val.i == pid && m->sticks_free[pid] && m->sticks_free[(pid+1)%s->nphil]); } void i_am_hungry(Philosopher *p) { MyPhil *m; int s1, s2; m = (MyPhil *) p->s->v; s1 = p->id; s2 = (p->id + 1) % p->s->nphil; if (m->my_pstates[p->id] == BEGIN) { dll_append(m->q, new_jval_i(p->id)); m->my_pstates[p->id] = QUEUED; } if (test_philosopher(p->id, m, p->s)) { dll_delete_node(m->q->flink); m->sticks_free[s1] = 0; m->sticks_free[s2] = 0; m->my_pstates[p->id] = GOT_STICK_1; pick_up_stick(p, s1, i_am_hungry); } else if (m->my_pstates[p->id] == QUEUED) { cbthread_gsem_P(m->sems[p->id], i_am_hungry, p); } else if (m->my_pstates[p->id] == GOT_STICK_1) { m->my_pstates[p->id] = GOT_STICK_2; pick_up_stick(p, s2, i_am_hungry); } else { p->state = GOTSTICKS; philosopher(p); cbthread_exit(); } } void test_queue_front(MyPhil *m, Simulation *s) { if (dll_empty(m->q)) return; if (test_philosopher(m->q->flink->val.i, m, s)) cbthread_gsem_V(m->sems[m->q->flink->val.i]); } void i_am_sated(Philosopher *p) { MyPhil *m; int s1, s2; m = (MyPhil *) p->s->v; s1 = p->id; s2 = (p->id+1)%p->s->nphil; if (m->my_pstates[p->id] == GOT_STICK_2) { m->my_pstates[p->id] = GOT_STICK_1; put_down_stick(p, s1, i_am_sated); } else if (m->my_pstates[p->id] == GOT_STICK_1) { m->sticks_free[s1] = 1; test_queue_front(m, p->s); m->my_pstates[p->id] = BEGIN; put_down_stick(p, s2, i_am_sated); } else { m->sticks_free[s2] = 1; test_queue_front(m, p->s); p->state = STARTING; philosopher(p); cbthread_exit(); } } void initialize_simulation(Simulation *s) { MyPhil *m; int i; m = talloc(MyPhil, 1); m->my_pstates = talloc(int, s->nphil); m->sticks_free = talloc(int, s->nphil); m->sems = talloc(cbthread_gsem, s->nphil); m->q = new_dllist(); for (i = 0; i < s->nphil; i++) { m->sems[i] = cbthread_make_gsem(0); m->my_pstates[i] = BEGIN; m->sticks_free[i] = 1; } s->v = (void *) m; return; }