Skip to content

Instantly share code, notes, and snippets.

@suhassumukh
Created November 13, 2016 12:22
Show Gist options
  • Save suhassumukh/cd40a9a72c50511e5aacd54ce9790f90 to your computer and use it in GitHub Desktop.
Save suhassumukh/cd40a9a72c50511e5aacd54ce9790f90 to your computer and use it in GitHub Desktop.
Dining philosopher with mutex locks
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#define NPHIL 5
#define MAXFOOD 50
#define MAXTHINK 5
#define SPAGHETTI_SPEED_SERVE 5000 // in microseconds
#define SPAGHETTI_SPEED_EAT 10000 // in microseconds
#define MAX_SPAGHETTI_PER_SERVE 10
typedef enum fork_status
{
FREE = 0,
ACQUIRED = 1
} FORK_STATUS;
// shared memory
int spaghetti_left = MAXFOOD;
FORK_STATUS forks[NPHIL];
pthread_mutex_t mutex_forks[NPHIL];
pthread_mutex_t mutex_bowl;
pthread_cond_t two_spoons[NPHIL];
int phil_stomach[NPHIL];
void acquire_forks(int f)
{
pthread_mutex_lock(&mutex_forks[f]);
}
void relinquish_forks(int f)
{
pthread_mutex_unlock(&mutex_forks[f]);
}
void* philosopher(void* arg)
{
int id = (int) arg;
// initialize philosopher
int plate = 0;
int thinking_time = 0;
while(spaghetti_left > 0)
{
printf("philosopher %d thinking...\n", id);
thinking_time = rand() % MAXTHINK;
usleep(thinking_time);
printf("philosopher %d ready to eat...\n", id);
// get left forks
acquire_forks(id);
// register forks state as acquired
forks[id] = ACQUIRED;
// if right forks is occupied, no point of having left forks
while(forks[(id + 1) % NPHIL] == ACQUIRED)
{
forks[id] = FREE;
pthread_cond_wait(&two_spoons[(id + 1) % NPHIL], &mutex_forks[id]);
}
forks[id] = ACQUIRED;
acquire_forks((id + 1) % NPHIL);
forks[(id + 1) % NPHIL] = ACQUIRED;
// critical section
printf("philosopher %d acquires left-right forkss...\n", id);
plate = 0;
pthread_mutex_lock(&mutex_bowl);
if(spaghetti_left > 0)
{
plate = rand() % (MAX_SPAGHETTI_PER_SERVE+1);
plate = (spaghetti_left >= plate) ? plate : spaghetti_left;
spaghetti_left = spaghetti_left - plate;
usleep(plate * SPAGHETTI_SPEED_SERVE);
#ifdef DEBUG
printf("plate: %d, left: %d\n", plate, spaghetti_left);
#endif
}
pthread_mutex_unlock(&mutex_bowl);
if(plate > 0)
{
printf("philosopher %d started eating...\n", id);
usleep(plate * SPAGHETTI_SPEED_EAT);
phil_stomach[id] += plate;
printf("philosopher %d done eating...\n", id);
}
forks[(id + 1) % NPHIL] = FREE;
relinquish_forks((id + 1) % NPHIL);
forks[id] = FREE;
pthread_cond_signal(&two_spoons[id]);
relinquish_forks(id % NPHIL);
}
return NULL;
}
int main(int argc, char const *argv[])
{
srand(time(NULL));
// creating threads
pthread_t phil[NPHIL];
pthread_attr_t attr;
// starting threads
pthread_attr_init(&attr);
// starting all philosophers
printf("Dinner starts\n");
int i;
for (i = 0; i < NPHIL; ++i)
{
pthread_create(&phil[i], &attr, philosopher, (void*) i);
}
// threads must report hence wait for them
for (i = 0; i < NPHIL; ++i)
{
pthread_join(phil[i], NULL);
}
printf("Dinner ends\n");
// generating report
printf("\n");
for (i = 0; i < NPHIL; ++i)
{
printf("philosopher %d ate %d noodle strands\n", i, phil_stomach[i]);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment