/* dinning philosophers simulation: NOTE: this code was written during class. I'am assuming you took notes */ #include #include #include #include "utils.c" #define NUM 6 #define THINKING 0 #define EATING 1 #define HUNGRY 2 #define RANDRANGE 3 /* globals here are used for convenience */ int philosopher[NUM]; int chopstick[NUM]; pthread_mutex_t cmu[NUM]; pthread_mutex_t mu; // protects access to chopstick array[] pthread_cond_t cq; // hungry philsophers /* values of philosopher array: EATHING, THINKING, HUNGRY+n values chopstick array: -1 for free, 0...NUM-1 if held by a philosopher */ int lneighbor(int i) {return (i+1) % NUM;} // left philosopher int rneighbor(int i) {return (i+NUM-1)%NUM;} int lstick(int i) {return i;} // left chopstick int rstick(int i) {return (i+NUM-1)%NUM;} void think(int id) { philosopher[id] = THINKING; printf("Philosopher %d is now thinking\n",id); sleepwait(random()%RANDRANGE); } void eat(int id) { philosopher[id] = EATING; /* ???? */ printf("\aPhilosopher %d is now eating\n",id); sleepwait(random()%RANDRANGE); } /* getsticks0 and dropsticks0 uses the cmu array of mutexes - one mutex for each chopstick - to protect the chopsticks. It will create deadlock */ void getsticks0(int id) { philosopher[id] = HUNGRY; pthread_mutex_lock(&cmu[lstick(id)]); printf(" philosopher %d now has chopstick %d\n",id,lstick(id)); sleepwait(0.01); // simulated delay pthread_mutex_lock(&cmu[rstick(id)]); printf(" philosopher %d now has chopstick %d\n",id,rstick(id)); } void dropsticks0(int id) { pthread_mutex_unlock(&cmu[lstick(id)]); pthread_mutex_unlock(&cmu[rstick(id)]); } /* getsticks and dropsticks implements a "monitor" using a pthread_cond in conjuction with pthread_mutex. A philosopher will not pick up a chopstick unless both left and right sticks are available. One mutex (mu) is used by all philosophers to gain access to values of the chopstick array. */ void getsticks(int id) { philosopher[id] = HUNGRY; pthread_mutex_lock(&mu); while (!((chopstick[lstick(id)]==-1) && (chopstick[rstick(id)]==-1))) { philosopher[id] += 1; // get hungrier if (philosopher[id]>HUNGRY+10) { pthread_mutex_unlock(&mu); printf("philosopher %d has starved to death!\n",id); pthread_exit(NULL); } pthread_cond_wait(&cq,&mu); } // pick up sticks chopstick[lstick(id)] = id; chopstick[rstick(id)] = id; pthread_mutex_unlock(&mu); } void dropsticks(int id) { pthread_mutex_lock(&mu); chopstick[lstick(id)] = -1; chopstick[rstick(id)] = -1; pthread_cond_broadcast(&cq); // wakes up all threads pthread_mutex_unlock(&mu); } // thread function for philosopher void * philthread(void * info) { int id; id = (int) info; while (1<2) { think(id); getsticks(id); eat(id); dropsticks(id); } } // philthread int main() { int i; // counter pthread_t tid[NUM]; srandom(i); // resets random number generator for(i=0;i