#include #include #include #include #include // Include for semaphore functions #define NUMP 5 pthread_mutex_t fork_mutex[NUMP]; sem_t space_avail; // Semaphore to manage eating slots void *diner(int *i); int main() { int i; pthread_t diner_thread[NUMP]; int dn[NUMP]; // Initialize semaphores and mutexes sem_init(&space_avail, 0, NUMP - 1); // Allows up to NUMP-1 diners to eat for (i = 0; i < NUMP; i++) pthread_mutex_init(&fork_mutex[i], NULL); // Create diner threads for (i = 0; i < NUMP; i++) { dn[i] = i; pthread_create(&diner_thread[i], NULL, (void *)diner, &dn[i]); } // Wait for diner threads to complete for (i = 0; i < NUMP; i++) pthread_join(diner_thread[i], NULL); // Clean up sem_destroy(&space_avail); for (i = 0; i < NUMP; i++) pthread_mutex_destroy(&fork_mutex[i]); return 0; } void *diner(int *i) { int v = *i; int eating = 0; printf("I'm diner %d\n", v); while (eating < 25) { printf("%d is thinking\n", v); sleep(v / 2); printf("%d is hungry\n", v); // Wait for available eating slot sem_wait(&space_avail); // Pick up forks pthread_mutex_lock(&fork_mutex[v]); pthread_mutex_lock(&fork_mutex[(v + 1) % NUMP]); printf("%d is eating\n", v); eating++; sleep(1); // Put down forks printf("%d is done eating\n", v); pthread_mutex_unlock(&fork_mutex[v]); pthread_mutex_unlock(&fork_mutex[(v + 1) % NUMP]); // Signal an available eating slot sem_post(&space_avail); } pthread_exit(NULL); }