Advertisement
okpalan

philosophers.c

Nov 4th, 2023
760
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.50 KB | Source Code | 0 0
  1. /**
  2.  * Problem statement
  3. Five philosophers dine together at the same table. Each philosopher has his own
  4. plate at the table. There is a fork between each plate. The dish served is a kind
  5.  of spaghetti which has to be eaten with two forks. Each philosopher can only
  6.  alternately think and eat. Moreover, a philosopher can only eat his spaghetti
  7.   when he has both a left and right fork. Thus two forks will only be available
  8.   when his two nearest neighbors are thinking, not eating. After an individual philosopher
  9.    finishes eating, he will put down both forks.
  10.  The problem is how to design a regimen (a concurrent algorithm) such that no philosopher will
  11.  starve; i.e., each can forever continue to alternate between eating and thinking,
  12.   assuming that no philosopher can know when others may want to eat or think
  13.   (an issue of incomplete information).
  14. */
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <time.h>
  18. #include <unistd.h>
  19. #include <pthread.h>
  20. #include <semaphore.h>
  21.  
  22. #define N 5
  23.  
  24. typedef enum {
  25.     THINKING = 0,
  26.     HUNGRY = 1,
  27.     EATING = 2
  28. } State;
  29.  
  30. size_t left(size_t i) {
  31.     return (i - 1 + N) % N;
  32. }
  33.  
  34. size_t right(size_t i) {
  35.     return (i + 1) % N;
  36. }
  37.  
  38. State state[N];
  39. pthread_mutex_t critical_region_mtx;
  40. pthread_mutex_t output_mtx;
  41.  
  42. sem_t both_forks_available[N];
  43.  
  44. size_t my_rand(size_t min, size_t max) {
  45.     static int initialized = 0;
  46.     if (!initialized) {
  47.         srand(time(NULL));
  48.         initialized = 1;
  49.     }
  50.     return rand() % (max - min + 1) + min;
  51. }
  52.  
  53. void test(size_t i) {
  54.     if (state[i] == HUNGRY &&
  55.         state[left(i)] != EATING &&
  56.         state[right(i)] != EATING) {
  57.         state[i] = EATING;
  58.         sem_post(&both_forks_available[i]);
  59.     }
  60. }
  61.  
  62. void think(size_t i) {
  63.     size_t duration = my_rand(400, 800);
  64.     pthread_mutex_lock(&output_mtx);
  65.     printf("%zu is thinking %zums\n", i, duration);
  66.     pthread_mutex_unlock(&output_mtx);
  67.     usleep(duration * 1000);
  68. }
  69.  
  70. void take_forks(size_t i) {
  71.     pthread_mutex_lock(&critical_region_mtx);
  72.     state[i] = HUNGRY;
  73.     pthread_mutex_lock(&output_mtx);
  74.     printf("\t\t%zu is HUNGRY\n", i);
  75.     pthread_mutex_unlock(&output_mtx);
  76.     test(i);
  77.     pthread_mutex_unlock(&critical_region_mtx);
  78.     sem_wait(&both_forks_available[i]);
  79. }
  80.  
  81. void eat(size_t i) {
  82.     size_t duration = my_rand(400, 800);
  83.     pthread_mutex_lock(&output_mtx);
  84.     printf("\t\t\t\t%zu is eating %zums\n", i, duration);
  85.     pthread_mutex_unlock(&output_mtx);
  86.     usleep(duration * 1000);
  87. }
  88.  
  89. void put_forks(size_t i) {
  90.     pthread_mutex_lock(&critical_region_mtx);
  91.     state[i] = THINKING;
  92.     test(left(i));
  93.     test(right(i));
  94.     pthread_mutex_unlock(&critical_region_mtx);
  95. }
  96.  
  97. void* philosopher(void* arg) {
  98.     size_t i = *(size_t*)arg;
  99.     while (1) {
  100.         think(i);
  101.         take_forks(i);
  102.         eat(i);
  103.         put_forks(i);
  104.     }
  105.     return NULL;
  106. }
  107.  
  108. int main() {
  109.     printf("dp_14\n");
  110.     pthread_t t[N];
  111.     pthread_mutex_init(&critical_region_mtx, NULL);
  112.     pthread_mutex_init(&output_mtx, NULL);
  113.     for (size_t i = 0; i < N; i++) {
  114.         sem_init(&both_forks_available[i], 0, 0);
  115.     }
  116.     for (size_t i = 0; i < N; i++) {
  117.         pthread_create(&t[i], NULL, philosopher, &i);
  118.     }
  119.     for (size_t i = 0; i < N; i++) {
  120.         pthread_join(t[i], NULL);
  121.     }
  122.     pthread_mutex_destroy(&critical_region_mtx);
  123.     pthread_mutex_destroy(&output_mtx);
  124.     for (size_t i = 0; i < N; i++) {
  125.         sem_destroy(&both_forks_available[i]);
  126.     }
  127.     return 0;
  128. }
  129.  
  130.  
  131.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement