/* * CS560: * dphil_skeleton.c -- Dining philosophers driver program. * James S. Plank * January, 2009 */ #define talloc(ty, sz) (ty *) malloc ((sz) * sizeof(ty)) #include #include #include #include "cbthread.h" #include "dphil.h" void update_times(Philosopher *p) { double last_event_time; last_event_time = p->last_event_time; p->last_event_time = cbthread_get_fake_time(); switch (p->state) { case STARTING: p->blocked_time += (p->last_event_time - last_event_time); break; case THINKING: p->thinktime += (p->last_event_time - last_event_time); break; case HUNGRY: p->blocked_time += (p->last_event_time - last_event_time); break; case GOTSTICKS: p->blocked_time += (p->last_event_time - last_event_time); break; case EATING: p->eattime += (p->last_event_time - last_event_time); break; case SATED: p->blocked_time += (p->last_event_time - last_event_time); break; default: fprintf(stderr, "update_times -- shouldn't get here\n"); exit(1); } } void pick_up_stick(Philosopher *p, int stick, void (*func)()) { if (p->s->verbose) { printf("%10.3lf: %03d Picking up stick %03d\n", cbthread_get_fake_time(), p->id, stick); fflush(stdout); } if (p->s->chopsticks_in_use[stick]) { printf("Error: pick_up_stick(%d) called on a stick in use.\n", stick); exit(1); } p->s->chopsticks_in_use[stick] = 1; cbthread_fake_sleep(p->s->sticktime, func, p); } void put_down_stick(Philosopher *p, int stick, void (*func)()) { if (p->s->verbose) { printf("%10.3lf: %03d Putting down stick %03d\n", cbthread_get_fake_time(), p->id, stick); fflush(stdout); } if (!p->s->chopsticks_in_use[stick]) { printf("Error: put_down_stick(%d) called on a stick not in use.\n", stick); exit(1); } p->s->chopsticks_in_use[stick] = 0; cbthread_fake_sleep(p->s->sticktime, func, p); } void philosopher(Philosopher *p) { Simulation *s; double thinktime, eattime; s = p->s; update_times(p); if (p->state == STARTING) { thinktime = drand48()*s->thinkavg*2.0; if (s->verbose) { printf("%10.3lf: %03d Thinking for %10.3lf.\n", cbthread_get_fake_time(), p->id, thinktime); fflush(stdout); } p->state = THINKING; cbthread_fake_sleep(thinktime, philosopher, p); } else if (p->state == THINKING) { if (s->verbose) { printf("%10.3lf: %03d Hungry.\n", cbthread_get_fake_time(), p->id); fflush(stdout); } p->state = HUNGRY; i_am_hungry(p); fprintf(stderr, "Error: i_am_hungry(%d) returned\n", p->id); exit(1); } else if (p->state == GOTSTICKS) { eattime = (drand48()*s->eatavg*2.0); if (s->verbose) { printf("%10.3lf: %03d Eating for %10.3lf.\n", cbthread_get_fake_time(), p->id, eattime); fflush(stdout); } p->state = EATING; cbthread_fake_sleep(eattime, philosopher, p); } else if (p->state == EATING) { if (s->verbose) { printf("%10.3lf: %03d Sated.\n", cbthread_get_fake_time(), p->id); fflush(stdout); } p->state = SATED; i_am_sated(p); fprintf(stderr, "Error: i_am_sated(%d) returned\n", p->id); exit(1); } printf("%10.3lf: At the end of philosopher(%d). Shouldn't get here.\n", cbthread_get_fake_time(), p->id); exit(1); } void usage(char *s) { fprintf(stderr, "usage: dphil nphilosophers thinkavg eatavg sticktime interval duration seed verbose\n"); if (s != NULL) fprintf(stderr, "%s\n", s); exit(1); } void timer(Simulation *s) { double t; double tthink; double teat; double tblock; double total; double dn; int i; tthink = 0; teat = 0; tblock = 0; total = 0; dn = s->nphil; t = cbthread_get_fake_time(); if (t != 0) { for (i = 0; i < s->nphil; i++) { update_times(s->p[i]); tthink += s->p[i]->thinktime; teat += s->p[i]->eattime; tblock += s->p[i]->blocked_time; total += t; } printf("%10.3lf: Thinktime: %10.3lf Eattime: %10.3lf Blocked_time: %10.3lf\n", t, tthink/dn, teat/dn, tblock/dn); } if (t >= s->duration) { for (i = 0; i < s->nphil; i++) { printf("Philosopher %03d: Think: %10.3lf Eat: %10.3lf Blocked: %10.3lf\n", i, s->p[i]->thinktime, s->p[i]->eattime, s->p[i]->blocked_time); } exit(0); } if (t + s->interval <= s->duration) { cbthread_fake_sleep(s->interval, timer, s); } else { cbthread_fake_sleep(s->duration-t, timer, s); } } main(int argc, char **argv) { Simulation *s; Philosopher *p; long seed; int i; if (argc != 9) usage(NULL); s = talloc(Simulation, 1); if (sscanf(argv[1], "%d", &s->nphil) == 0 || s->nphil <= 0) usage("Bad nphil"); if (sscanf(argv[2], "%lf", &s->thinkavg) == 0 || s->thinkavg < 0) usage("Bad thinkavg"); if (sscanf(argv[3], "%lf", &s->eatavg) == 0 || s->eatavg < 0) usage("Bad eatavg"); if (sscanf(argv[4], "%lf", &s->sticktime) == 0 || s->sticktime < 0) usage("Bad sticktime"); if (sscanf(argv[5], "%lf", &s->interval) == 0 || s->interval <= 0) usage("Bad interval"); if (sscanf(argv[6], "%lf", &s->duration) == 0 || s->duration <= 0) usage("Bad duration"); if (sscanf(argv[7], "%ld", &seed) == 0) usage("Bad seed"); s->verbose = (argv[8][0] == 'y' || argv[8][0] == 'Y'); s->p = talloc(Philosopher *, s->nphil); s->chopsticks_in_use = talloc(int, s->nphil); for (i = 0; i < s->nphil; i++) s->chopsticks_in_use[i] = 0; srand48(seed); initialize_simulation(s); for (i = 0; i < s->nphil; i++) { p = talloc(Philosopher, 1); s->p[i] = p; p->id = i; p->state = STARTING; p->s = s; p->thinktime = 0; p->eattime = 0; p->blocked_time = 0; p->last_event_time = 0; cbthread_fork(philosopher, p); } cbthread_fork(timer, s); cbthread_exit(); }