#include #include #include #include #include #include #define THINKING 0 /*philosopher is thinking*/ #define HUNGRY 1 /*philosopher is trying to get forks*/ #define EATING 2 /*philosopher is eating*/ typedef struct PhilosopherData { int eatingCount; int position; sem_t semaphore; int state; pthread_t thread; } PhilosopherData; bool AllPhilosophersFull(PhilosopherData PhilosopherList[], int numPhilosophers); void Down(sem_t* semaphore); void Eat(PhilosopherData* philosopherSelected); int GetPhilosopherCount(char* argv); void* Philosopher(void* philosopherPassed); void PhilosopherInit(int philosopherTotal); void PhilosopherListInit(PhilosopherData PhilosopherList[], int philosopherTotal); void PutForks(PhilosopherData* philosopherSelected); void TakeForks(PhilosopherData* philosopherSelected); bool PhilosopherCanEat(PhilosopherData PhilosopherList[], int selectedPosition, int philosopherTotal); void Think(PhilosopherData* philosopherSelected); void Up(sem_t* semaphore); int main(int argc, char* argv[]) { if (argc < 2) printf("Too few arguments, exiting...\n"); if (argc > 2) printf("Too many arguments, exiting...\n"); if (argc == 2) { int philosopherTotal; philosopherTotal = GetPhilosopherCount(argv[1]); PhilosopherInit(philosopherTotal); } return 0; } // Takes in array of times each philosopher has eaten // If all philosophers have ate twice, then returns true // Otherwise, if a philosopher has not eaten twice, returns false bool AllPhilosophersFull(PhilosopherData PhilosopherList[], int numPhilosophers) { for (int i = 0; i < numPhilosophers; i++) if (PhilosopherList[i].eatingCount < 2) return false; return true; } // Philosopher enters critical section. void Down(sem_t* semaphore) { sem_wait(semaphore); printf("A semaphore was put into waiting...\n"); } // Sets philosopher to eating state and increments eating count. void Eat(PhilosopherData* philosopherSelected) { printf("Philosopher %d is eating...\n", philosopherSelected->position); philosopherSelected->state = EATING; ++philosopherSelected->eatingCount; } // Converts char* to number. int GetPhilosopherCount(char* argv) { int philosopherTotal; sscanf(argv, "%d", &philosopherTotal); return philosopherTotal; } // Main function that each thread runs. void* Philosopher(void* philosopherPassed) { PhilosopherData *philosopherSelected = (PhilosopherData*) philosopherPassed; while (true) { Think(philosopherSelected); /*philosopher is thinking*/ TakeForks(philosopherSelected); /*acquire two forks or block*/ Eat(philosopherSelected); /*yum-yum, spaghetti*/ PutForks(philosopherSelected); /*put both forks back on table*/ } } // Handles all philosopher threads, finishes when all philosophers are full. void PhilosopherInit(int philosopherTotal) { PhilosopherData PhilosopherList[philosopherTotal]; PhilosopherListInit(PhilosopherList, philosopherTotal); while (!AllPhilosophersFull(PhilosopherList, philosopherTotal)) { for (int i = 0; i < philosopherTotal; i++) { if (PhilosopherCanEat(PhilosopherList, i, philosopherTotal)) { Up(&(PhilosopherList[i].semaphore)); } } } } // Initializes full list of philosophers. void PhilosopherListInit(PhilosopherData PhilosopherList[], int philosopherTotal) { for (int i = 0; i < philosopherTotal; i++) { PhilosopherList[i].position = i; PhilosopherList[i].eatingCount = 0; sem_init(&PhilosopherList[i].semaphore, 0, 1); pthread_create(&PhilosopherList[i].thread, NULL, &Philosopher, &PhilosopherList[i]); pthread_join(PhilosopherList[i].thread, NULL); } } // Philosopher puts forks down. void PutForks(PhilosopherData* philosopherSelected) { printf("Philosopher %d is putting forks down...\n", philosopherSelected->position); } // Philosopher takes the forks on the left and right. void TakeForks(PhilosopherData* philosopherSelected) { printf("Philosopher %d is taking forks...\n", philosopherSelected->position); Down(&philosopherSelected->semaphore); } // If philosopher is hungry and forks are free, then returns true. // Else, philosopher returns false. // Left philosopher math: (i+N-1)%N Right philosopher math: (i+1)%N bool PhilosopherCanEat(PhilosopherData PhilosopherList[], int selectedPosition, int philosopherTotal) { if (PhilosopherList[selectedPosition].state != HUNGRY) return false; int leftPhilosopher = (selectedPosition + (philosopherTotal-1)) % philosopherTotal; int rightPhilosopher = (selectedPosition + 1) % philosopherTotal; if (PhilosopherList[leftPhilosopher].state == EATING) return false; if (PhilosopherList[rightPhilosopher].state == EATING) return false; return true; } // Philosopher begins thinking void Think(PhilosopherData* philosopherSelected) { philosopherSelected->state = THINKING; printf("Philosopher %d is thinking...\n", philosopherSelected->position); } // Philosopher exits critical section void Up(sem_t* semaphore) { sem_post(semaphore); printf("A semaphore was released...\n"); }