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
|
|
|
|
|
|
|
#define THINKING 0 /*philosopher is thinking*/
|
|
|
|
#define HUNGRY 1 /*philosopher is trying to get forks*/
|
|
|
|
#define EATING 2 /*philosopher is eating*/
|
2022-09-30 01:14:57 -05:00
|
|
|
// pthread_mutex_t mutex; /*mutual exclusion for critical region*/
|
2022-09-27 21:30:23 -05:00
|
|
|
|
2022-09-30 00:03:37 -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);
|
2022-09-30 15:39:21 -05:00
|
|
|
void Down(sem_t* semaphore);
|
2022-09-30 01:04:23 -05:00
|
|
|
void Eat(PhilosopherData* philosopherSelected);
|
2022-09-30 00:03:37 -05:00
|
|
|
int GetPhilosopherCount(char* argv);
|
2022-09-30 01:04:23 -05:00
|
|
|
void* Philosopher(void* philosopherPassed);
|
2022-09-30 00:03:37 -05:00
|
|
|
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);
|
2022-09-30 00:03:37 -05:00
|
|
|
bool PhilosopherCanEat(PhilosopherData PhilosopherList[], int selectedPosition, int philosopherTotal);
|
2022-09-30 01:04:23 -05:00
|
|
|
void Think(PhilosopherData* philosopherSelected);
|
2022-09-30 15:39:21 -05:00
|
|
|
void Up(sem_t* semaphore);
|
2022-09-27 21:30:23 -05:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Todo:
|
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[])
|
|
|
|
{
|
2022-09-30 00:03:37 -05:00
|
|
|
if (argc < 2)
|
|
|
|
printf("Too few arguments, exiting...\n");
|
|
|
|
if (argc > 2)
|
|
|
|
printf("Too many arguments, exiting...\n");
|
2022-09-30 01:14:57 -05:00
|
|
|
if (argc == 2)
|
|
|
|
{
|
|
|
|
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-30 15:39:21 -05:00
|
|
|
// Takes a pointer to a philosopher and puts semaphore into waiting state.
|
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
|
2022-09-30 15:39:21 -05:00
|
|
|
void Down(sem_t* semaphore)
|
2022-09-27 21:30:23 -05:00
|
|
|
{
|
2022-09-30 15:39:21 -05:00
|
|
|
sem_wait(semaphore);
|
|
|
|
printf("A semaphore was put into waiting...\n");
|
2022-09-27 21:30:23 -05:00
|
|
|
}
|
|
|
|
|
2022-09-30 15:39:21 -05:00
|
|
|
// Sets philosopher to eating state and increments eating count.
|
2022-09-30 01:04:23 -05:00
|
|
|
void Eat(PhilosopherData* philosopherSelected)
|
2022-09-27 21:30:23 -05:00
|
|
|
{
|
2022-09-30 01:20:28 -05:00
|
|
|
printf("Philosopher %d is eating...\n", philosopherSelected->position);
|
|
|
|
philosopherSelected->state = EATING;
|
|
|
|
++philosopherSelected->eatingCount;
|
2022-09-27 21:30:23 -05:00
|
|
|
}
|
|
|
|
|
2022-09-30 15:39:21 -05:00
|
|
|
// Converts char* to number.
|
2022-09-30 00:03:37 -05:00
|
|
|
int GetPhilosopherCount(char* argv)
|
2022-09-27 21:30:23 -05:00
|
|
|
{
|
2022-09-30 00:03:37 -05:00
|
|
|
int philosopherTotal;
|
|
|
|
sscanf(argv, "%d", &philosopherTotal);
|
|
|
|
return philosopherTotal;
|
|
|
|
}
|
|
|
|
|
2022-09-30 15:39:21 -05:00
|
|
|
// Main function that each thread runs.
|
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 21:30:23 -05:00
|
|
|
while (true)
|
|
|
|
{
|
2022-09-30 00:03:37 -05:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-30 15:39:21 -05:00
|
|
|
// Handles all philosopher threads, finishes when all philosophers are full.
|
2022-09-30 00:03:37 -05:00
|
|
|
void PhilosopherInit(int philosopherTotal)
|
2022-09-27 21:30:23 -05:00
|
|
|
{
|
2022-09-30 00:03:37 -05:00
|
|
|
PhilosopherData PhilosopherList[philosopherTotal];
|
2022-09-30 01:04:23 -05:00
|
|
|
PhilosopherListInit(PhilosopherList, philosopherTotal);
|
2022-09-30 00:03:37 -05:00
|
|
|
while (!AllPhilosophersFull(PhilosopherList, philosopherTotal))
|
|
|
|
{
|
|
|
|
for (int i = 0; i < philosopherTotal; i++)
|
|
|
|
{
|
|
|
|
if (PhilosopherCanEat(PhilosopherList, i, philosopherTotal))
|
|
|
|
{
|
2022-09-30 15:39:21 -05:00
|
|
|
Up(&(PhilosopherList[i-1].semaphore));
|
|
|
|
Up(&(PhilosopherList[i].semaphore));
|
2022-09-30 00:03:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 00:03:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-30 01:04:23 -05:00
|
|
|
void PutForks(PhilosopherData* philosopherSelected)
|
2022-09-30 00:03:37 -05:00
|
|
|
{
|
2022-09-30 01:20:28 -05:00
|
|
|
printf("Philosopher %d is putting forks down...\n", philosopherSelected->position);
|
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
|
|
|
}
|
|
|
|
|
2022-09-30 15:39:21 -05:00
|
|
|
// Philosopher takes the forks on the left and right.
|
2022-09-30 01:04:23 -05:00
|
|
|
void TakeForks(PhilosopherData* philosopherSelected)
|
2022-09-27 21:30:23 -05:00
|
|
|
{
|
2022-09-30 01:20:28 -05:00
|
|
|
printf("Philosopher %d is taking forks...\n", philosopherSelected->position);
|
2022-09-30 15:39:21 -05:00
|
|
|
Down(&philosopherSelected->semaphore);
|
2022-09-27 22:58:47 -05:00
|
|
|
// Down(&mutex); /*enter critical region*/
|
2022-09-30 00:03:37 -05:00
|
|
|
// 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
|
|
|
}
|
|
|
|
|
2022-09-30 15:39:21 -05:00
|
|
|
// 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
|
2022-09-30 00:03:37 -05:00
|
|
|
bool PhilosopherCanEat(PhilosopherData PhilosopherList[], int selectedPosition, int philosopherTotal)
|
2022-09-27 21:30:23 -05:00
|
|
|
{
|
2022-09-30 00:03:37 -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)
|
2022-09-30 00:03:37 -05:00
|
|
|
return false;
|
2022-09-27 22:58:47 -05:00
|
|
|
if (PhilosopherList[rightPhilosopher].state == EATING)
|
2022-09-30 00:03:37 -05:00
|
|
|
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
|
|
|
{
|
2022-09-30 00:03:37 -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'
|
2022-09-30 15:39:21 -05:00
|
|
|
void Up(sem_t* semaphore)
|
2022-09-27 21:30:23 -05:00
|
|
|
{
|
2022-09-30 15:39:21 -05:00
|
|
|
sem_post(semaphore);
|
|
|
|
printf("A semaphore was released...\n");
|
2022-09-27 21:30:23 -05:00
|
|
|
}
|