#include #include #include #include #include #include // #define N 5 /*number of philosophers*/ // #define LEFT (i+N-1)%N /*number of i's left neighbor*/ // #define RIGHT (i+1)%N /*number of i's right neighbor*/ #define THINKING 0 /*philosopher is thinking*/ #define HUNGRY 1 /*philosopher is trying to get forks*/ #define EATING 2 /*philosopher is eating*/ // pthread_mutex_t mutex; /*mutual exclusion for critical region*/ typedef struct PhilosopherData { int eatingCount; int position; sem_t semaphore; int state; pthread_t thread; } PhilosopherData; bool AllPhilosophersFull(PhilosopherData PhilosopherList[], int numPhilosophers); void Down(); 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(); /* * Todo: * Add prints to each state change * Fix each function's requirements * Theories: * Threads should be put to sleep if can't eat * Sleep has to be awoken by something else, process can't wake own thread * Place semaphores so states can be checked by all * Total fork count = N / 2 * */ 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; } // // TODO: // Turn function into picking up forks (starting waits) // (Right fork is owned by selectedPhilosopher number for consistency) // Add sem_wait void Down() { printf("Down() was called...\n"); } // // TODO: // Add changing state to function // Add increasing eating count functionality // void Eat(PhilosopherData* philosopherSelected) { printf("Philosopher %d is eating...\n", philosopherSelected->position); philosopherSelected->state = EATING; ++philosopherSelected->eatingCount; } // Takes in char* and converts into a number // Returns a number int GetPhilosopherCount(char* argv) { int philosopherTotal; sscanf(argv, "%d", &philosopherTotal); return philosopherTotal; } // Takes in the number of philosophers, from 0 to N-1 // Finishes when all philosophers have eaten twice // TODO: // Add splitting function into multiple pthreads void* Philosopher(void* philosopherPassed) { PhilosopherData *philosopherSelected = (PhilosopherData*) philosopherPassed; // Below replaced by PhilosopherData // int philosopherEatingCount[numPhilosophers]; // sem_t philosopherSemaphore[numPhilosophers]; /*one semaphore per philospher*/ // // array to keep track of everyone's state // int philosopherState[numPhilosophers]; 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*/ break; } } 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)) { Down(PhilosopherList[i-1].semaphore); Down(PhilosopherList[i].semaphore); } } break; } } 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); } } void PutForks(PhilosopherData* philosopherSelected) { printf("Philosopher %d is putting forks down...\n", philosopherSelected->position); // Down(&mutex); /*enter critical region*/ // philosopherState[selectedPhilosopher] = THINKING; /*record fact that philosopher i is hungry*/ // Test(selectedPhilosopher, numPhilosophers); // Test(LEFT); /*try to acquire 2 forks*/ // Test(RIGHT); /*exit critical region*/ // Up(&mutex); /*block if forks were not acquired*/ } // Takes in a number for a selected philosopher, from 0 to N-1 void TakeForks(PhilosopherData* philosopherSelected) { printf("Philosopher %d is taking forks...\n", philosopherSelected->position); sem_wait(&philosopherSelected->semaphore); // Down(&mutex); /*enter critical region*/ // PhilosopherList.state = HUNGRY; /*philosopher has finished eating*/ // Test(selectedPhilosopher, ); /*see if left neighbor can now eat*/ // Up(&mutex); /*see if right neighbor can now eat*/ // Down(&philosopherSemaphore[selectedPhilosopher]); /*exit critical region*/ } // Takes in the number of philosophers, from 0 to N-1 // Checks if left and right philosopher is not eating, // and philosopher is hungry, then philosopher will eat 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; } void Think(PhilosopherData* philosopherSelected) { // printf("%d is now thinking.\n", PhilosopherList.position); // PhilosopherList.state = THINKING; /*philosopher has finished eating*/ philosopherSelected->state = THINKING; printf("Philosopher %d is thinking...\n", philosopherSelected->position); } // Todo: // Make function release hold on semaphore // Use 'sem_post' void Up() { printf("Up() was called...\n"); }