dining-philosophers/DiningPhilosophers.c

214 lines
7.3 KiB
C
Raw Normal View History

2022-09-27 21:30:23 -05:00
#include <pthread.h>
#include <semaphore.h>
2022-09-27 22:58:47 -05:00
#include <stdbool.h>
2022-09-27 21:30:23 -05:00
#include <stdlib.h>
#include <stdio.h>
2022-09-27 22:58:47 -05:00
#include <unistd.h>
2022-09-27 21:30:23 -05:00
2022-09-27 22:58:47 -05:00
// #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*/
2022-09-27 21:30:23 -05:00
#define THINKING 0 /*philosopher is thinking*/
#define HUNGRY 1 /*philosopher is trying to get forks*/
#define EATING 2 /*philosopher is eating*/
2022-09-27 22:58:47 -05:00
pthread_mutex_t mutex; /*mutual exclusion for critical region*/
2022-09-27 21:30:23 -05:00
2022-09-27 22:58:47 -05:00
typedef struct PhilosopherData {
int eatingCount;
int position;
sem_t semaphore;
int state;
2022-09-30 01:04:23 -05:00
pthread_t thread;
2022-09-27 22:58:47 -05:00
} PhilosopherData;
bool AllPhilosophersFull(PhilosopherData PhilosopherList[], int numPhilosophers);
void Down();
2022-09-30 01:04:23 -05:00
void Eat(PhilosopherData* philosopherSelected);
int GetPhilosopherCount(char* argv);
2022-09-30 01:04:23 -05:00
void* Philosopher(void* philosopherPassed);
void PhilosopherInit(int philosopherTotal);
void PhilosopherListInit(PhilosopherData PhilosopherList[], int philosopherTotal);
2022-09-30 01:04:23 -05:00
void PutForks(PhilosopherData* philosopherSelected);
void TakeForks(PhilosopherData* philosopherSelected);
bool PhilosopherCanEat(PhilosopherData PhilosopherList[], int selectedPosition, int philosopherTotal);
2022-09-30 01:04:23 -05:00
void Think(PhilosopherData* philosopherSelected);
void Up();
2022-09-27 21:30:23 -05:00
/*
* Todo:
* Add prints to each state change
2022-09-28 15:18:52 -05:00
* Fix each function's requirements
2022-09-27 21:30:23 -05:00
* 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");
return 0;
}
if (argc > 2)
2022-09-27 21:30:23 -05:00
{
printf("Too many arguments, exiting...\n");
return 0;
2022-09-27 21:30:23 -05:00
}
int philosopherTotal;
philosopherTotal = GetPhilosopherCount(argv[1]);
PhilosopherInit(philosopherTotal);
2022-09-27 21:30:23 -05:00
return 0;
}
2022-09-27 22:58:47 -05:00
// 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++)
2022-09-29 22:06:05 -05:00
if (PhilosopherList[i].eatingCount < 2)
2022-09-27 22:58:47 -05:00
return false;
return true;
}
2022-09-27 21:30:23 -05:00
//
// TODO:
2022-09-28 15:18:52 -05:00
// Turn function into picking up forks (starting waits)
// (Right fork is owned by selectedPhilosopher number for consistency)
// Add sem_wait
void Down()
2022-09-27 21:30:23 -05:00
{
printf("Down() was called...\n");
2022-09-27 21:30:23 -05:00
}
//
// TODO:
// Add changing state to function
// Add increasing eating count functionality
//
2022-09-30 01:04:23 -05:00
void Eat(PhilosopherData* philosopherSelected)
2022-09-27 21:30:23 -05:00
{
printf("Eat() was called...\n");
2022-09-27 21:30:23 -05:00
}
// Takes in char* and converts into a number
// Returns a number
int GetPhilosopherCount(char* argv)
2022-09-27 21:30:23 -05:00
{
int philosopherTotal;
sscanf(argv, "%d", &philosopherTotal);
return philosopherTotal;
}
2022-09-27 21:30:23 -05:00
// Takes in the number of philosophers, from 0 to N-1
// Finishes when all philosophers have eaten twice
2022-09-28 15:18:52 -05:00
// TODO:
// Add splitting function into multiple pthreads
2022-09-30 01:04:23 -05:00
void* Philosopher(void* philosopherPassed)
2022-09-27 21:30:23 -05:00
{
2022-09-30 01:04:23 -05:00
PhilosopherData *philosopherSelected = (PhilosopherData*) philosopherPassed;
2022-09-27 22:58:47 -05:00
// 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];
2022-09-27 21:30:23 -05:00
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*/
2022-09-28 15:18:52 -05:00
break;
2022-09-27 21:30:23 -05:00
}
}
void PhilosopherInit(int philosopherTotal)
2022-09-27 21:30:23 -05:00
{
PhilosopherData PhilosopherList[philosopherTotal];
2022-09-30 01:04:23 -05:00
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);
}
}
2022-09-30 01:04:23 -05:00
break;
}
}
void PhilosopherListInit(PhilosopherData PhilosopherList[], int philosopherTotal)
{
for (int i = 0; i < philosopherTotal; i++)
{
PhilosopherList[i].position = i;
PhilosopherList[i].eatingCount = 0;
2022-09-30 01:04:23 -05:00
sem_init(&PhilosopherList[i].semaphore, 0, 1);
pthread_create(&PhilosopherList[i].thread, NULL, &Philosopher, &PhilosopherList[i]);
pthread_join(PhilosopherList[i].thread, NULL);
}
}
2022-09-30 01:04:23 -05:00
void PutForks(PhilosopherData* philosopherSelected)
{
printf("PutForks() was called...\n");
2022-09-27 22:58:47 -05:00
// 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*/
2022-09-27 21:30:23 -05:00
}
// Takes in a number for a selected philosopher, from 0 to N-1
2022-09-30 01:04:23 -05:00
void TakeForks(PhilosopherData* philosopherSelected)
2022-09-27 21:30:23 -05:00
{
printf("TakeForks() was called...\n");
2022-09-30 01:04:23 -05:00
sem_wait(&philosopherSelected->semaphore);
2022-09-27 22:58:47 -05:00
// Down(&mutex); /*enter critical region*/
// PhilosopherList.state = HUNGRY; /*philosopher has finished eating*/
2022-09-27 22:58:47 -05:00
// Test(selectedPhilosopher, ); /*see if left neighbor can now eat*/
// Up(&mutex); /*see if right neighbor can now eat*/
// Down(&philosopherSemaphore[selectedPhilosopher]); /*exit critical region*/
2022-09-27 21:30:23 -05:00
}
// 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)
2022-09-27 21:30:23 -05:00
{
if (PhilosopherList[selectedPosition].state != HUNGRY)
return false;
int leftPhilosopher = (selectedPosition + (philosopherTotal-1)) % philosopherTotal;
int rightPhilosopher = (selectedPosition + 1) % philosopherTotal;
2022-09-27 22:58:47 -05:00
if (PhilosopherList[leftPhilosopher].state == EATING)
return false;
2022-09-27 22:58:47 -05:00
if (PhilosopherList[rightPhilosopher].state == EATING)
return false;
return true;
2022-09-27 21:30:23 -05:00
}
2022-09-30 01:04:23 -05:00
void Think(PhilosopherData* philosopherSelected)
2022-09-27 21:30:23 -05:00
{
// printf("%d is now thinking.\n", PhilosopherList.position);
// PhilosopherList.state = THINKING; /*philosopher has finished eating*/
2022-09-30 01:04:23 -05:00
philosopherSelected->state = THINKING;
printf("Philosopher %d is thinking...\n", philosopherSelected->position);
2022-09-27 21:30:23 -05:00
}
2022-09-28 15:18:52 -05:00
// Todo:
// Make function release hold on semaphore
// Use 'sem_post'
void Up()
2022-09-27 21:30:23 -05:00
{
printf("Up() was called...\n");
2022-09-27 21:30:23 -05:00
}