/* philosophers.c */ #define _XOPEN_SOURCE 500 #include #include #include #include #include #include #include #include #include #include #include #include "chopsticks.h" int nsteps, maxsteps = 0; /* number of steps to run this test */ int eat_count; /* number of times each thread ate */ /* The subprogram trace is for testing and debugging. It allows us to see what is happening, and to shut down the philosophers when the program has run long enough for us to see that it seems to be working. The output from this subprogram will be interleaved, because we have provided no mechanism for mutual exclusion on the standard output file. */ void trace(int i, char *s) /* print out message, for use in execution tracing i = philospher ID s = message */ { if (strcmp (s, "eating") == 0) eat_count++; /* fprintf(stdout,"%d: %s\n",i,s); */ if (nsteps++ > maxsteps) { /* don't exit while we are holding any chopsticks */ if (strcmp(s,"thinking") == 0) { fprintf (stderr, "thread %d ate %d times\n", i, eat_count); exit (0); } } } void * philosopher_body (void *arg) { int self = (int) arg; for (;;) { trace (self,"thinking"); sched_yield(); chopsticks_take (self); trace (self,"eating"); sched_yield(); chopsticks_put (self); } } void alarm_handler (int sig) { fprintf (stderr, "main program timed out\n"); chopsticks_emergency_stop(); } int main() { int i; pid_t child; int status; struct sigaction act; pid_t pid[NTHREADS]; /* install handler for alarm signal */ sigaction (SIGALRM, NULL, &act); act.sa_handler = alarm_handler; sigaction (SIGALRM, &act, NULL); /* initialize the package "chopsticks" */ chopsticks_init(); fprintf(stdout, "enter number of steps to run: "); fflush(stdout); fscanf(stdin,"%d", &maxsteps); /* start up the philosopher processes */ for (i = 1; i < NTHREADS; i++) { child = fork (); if (child) /* we are the parent */ pid[i] = child; else { /* we are the child */ eat_count = 0; (void) philosopher_body ((void *) i); fprintf (stderr, "should never get here\n"); exit (0); } } fprintf (stdout, "main waiting 30 seconds\n"); alarm (30); for (i = 1; i < NTHREADS; i++) waitpid (child, &status, 0); chopsticks_finalize(); return 0; }