Created
November 13, 2016 12:22
-
-
Save suhassumukh/cd40a9a72c50511e5aacd54ce9790f90 to your computer and use it in GitHub Desktop.
Dining philosopher with mutex locks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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