From 2621d03f99e8a9d248e590d8913f4812b49c1816 Mon Sep 17 00:00:00 2001 From: "Remzi H. Arpaci-Dusseau" Date: Tue, 16 Apr 2019 16:17:36 -0500 Subject: [PATCH] simple dining philosophers code (Linux only) --- threads-sema/Makefile | 9 ++ threads-sema/README.md | 12 ++ threads-sema/dining_philosophers_deadlock.c | 78 +++++++++++++ .../dining_philosophers_deadlock_print.c | 98 ++++++++++++++++ .../dining_philosophers_no_deadlock.c | 83 ++++++++++++++ .../dining_philosophers_no_deadlock_print.c | 105 ++++++++++++++++++ 6 files changed, 385 insertions(+) create mode 100644 threads-sema/Makefile create mode 100644 threads-sema/README.md create mode 100644 threads-sema/dining_philosophers_deadlock.c create mode 100644 threads-sema/dining_philosophers_deadlock_print.c create mode 100644 threads-sema/dining_philosophers_no_deadlock.c create mode 100644 threads-sema/dining_philosophers_no_deadlock_print.c diff --git a/threads-sema/Makefile b/threads-sema/Makefile new file mode 100644 index 0000000..4619c72 --- /dev/null +++ b/threads-sema/Makefile @@ -0,0 +1,9 @@ + +FLAGS = -Wall -pthread -I../include + +all: + gcc $(FLAGS) -o dining_philosophers_deadlock dining_philosophers_deadlock.c + gcc $(FLAGS) -o dining_philosophers_deadlock_print dining_philosophers_deadlock_print.c + gcc $(FLAGS) -o dining_philosophers_no_deadlock dining_philosophers_no_deadlock.c + gcc $(FLAGS) -o dining_philosophers_no_deadlock_print dining_philosophers_no_deadlock_print.c + diff --git a/threads-sema/README.md b/threads-sema/README.md new file mode 100644 index 0000000..a6804c4 --- /dev/null +++ b/threads-sema/README.md @@ -0,0 +1,12 @@ + +# Dining Philosophers + +The dining philosophers example from the text is found herein, in a few +different forms: +- `dining_philosophers.c`: code with deadlock +- `dining_philosophers_print.c`: code with deadlock, and some useful printing +- `dining_philosophers_no_deadlock.c`: code without deadlock +- `dining_philosophers_no_deadlock_print.c`: code without deadlock, and some useful printing + +Run `make` to build all of them with the highly primitive `Makefile`. + diff --git a/threads-sema/dining_philosophers_deadlock.c b/threads-sema/dining_philosophers_deadlock.c new file mode 100644 index 0000000..28c3170 --- /dev/null +++ b/threads-sema/dining_philosophers_deadlock.c @@ -0,0 +1,78 @@ +#include +#include +#include + +#include "common.h" +#include "common_threads.h" + +typedef struct { + int num_loops; + int thread_id; +} arg_t; + +sem_t forks[5]; + +int left(int p) { + return p; +} + +int right(int p) { + return (p + 1) % 5; +} + +void get_forks(int p) { + Sem_wait(&forks[left(p)]); + Sem_wait(&forks[right(p)]); +} + +void put_forks(int p) { + Sem_post(&forks[left(p)]); + Sem_post(&forks[right(p)]); +} + +void think() { + return; +} + +void eat() { + return; +} + +void *philosopher(void *arg) { + arg_t *args = (arg_t *) arg; + + int i; + for (i = 0; i < args->num_loops; i++) { + think(); + get_forks(args->thread_id); + eat(); + put_forks(args->thread_id); + } + return NULL; +} + +int main(int argc, char *argv[]) { + if (argc != 2) { + fprintf(stderr, "usage: dining_philosophers_deadlock \n"); + exit(1); + } + printf("dining: started\n"); + + int i; + for (i = 0; i < 5; i++) + Sem_init(&forks[i], 1); + + pthread_t p[5]; + arg_t a[5]; + for (i = 0; i < 5; i++) { + a[i].num_loops = atoi(argv[1]); + a[i].thread_id = i; + Pthread_create(&p[i], NULL, philosopher, &a[i]); + } + + for (i = 0; i < 5; i++) + Pthread_join(p[i], NULL); + + printf("dining: finished\n"); + return 0; +} diff --git a/threads-sema/dining_philosophers_deadlock_print.c b/threads-sema/dining_philosophers_deadlock_print.c new file mode 100644 index 0000000..4951dd6 --- /dev/null +++ b/threads-sema/dining_philosophers_deadlock_print.c @@ -0,0 +1,98 @@ +#include +#include +#include + +#include "common.h" +#include "common_threads.h" + +typedef struct { + int num_loops; + int thread_id; +} arg_t; + +sem_t forks[5]; +sem_t print_lock; + +void space(int s) { + Sem_wait(&print_lock); + int i; + for (i = 0; i < s * 10; i++) + printf(" "); +} + +void space_end() { + Sem_post(&print_lock); +} + +int left(int p) { + return p; +} + +int right(int p) { + return (p + 1) % 5; +} + +void get_forks(int p) { + space(p); printf("%d: try %d\n", p, left(p)); space_end(); + Sem_wait(&forks[left(p)]); + space(p); printf("%d: try %d\n", p, right(p)); space_end(); + Sem_wait(&forks[right(p)]); +} + +void put_forks(int p) { + Sem_post(&forks[left(p)]); + Sem_post(&forks[right(p)]); +} + +void think() { + return; +} + +void eat() { + return; +} + +void *philosopher(void *arg) { + arg_t *args = (arg_t *) arg; + + space(args->thread_id); printf("%d: start\n", args->thread_id); space_end(); + + int i; + for (i = 0; i < args->num_loops; i++) { + space(args->thread_id); printf("%d: think\n", args->thread_id); space_end(); + think(); + get_forks(args->thread_id); + space(args->thread_id); printf("%d: eat\n", args->thread_id); space_end(); + eat(); + put_forks(args->thread_id); + space(args->thread_id); printf("%d: done\n", args->thread_id); space_end(); + } + return NULL; +} + +int main(int argc, char *argv[]) { + if (argc != 2) { + fprintf(stderr, "usage: dining_philosophers \n"); + exit(1); + } + printf("dining: started\n"); + + int i; + for (i = 0; i < 5; i++) + Sem_init(&forks[i], 1); + Sem_init(&print_lock, 1); + + pthread_t p[5]; + arg_t a[5]; + for (i = 0; i < 5; i++) { + a[i].num_loops = atoi(argv[1]); + a[i].thread_id = i; + Pthread_create(&p[i], NULL, philosopher, &a[i]); + } + + for (i = 0; i < 5; i++) + Pthread_join(p[i], NULL); + + printf("dining: finished\n"); + return 0; +} diff --git a/threads-sema/dining_philosophers_no_deadlock.c b/threads-sema/dining_philosophers_no_deadlock.c new file mode 100644 index 0000000..c9d409f --- /dev/null +++ b/threads-sema/dining_philosophers_no_deadlock.c @@ -0,0 +1,83 @@ +#include +#include +#include + +#include "common.h" +#include "common_threads.h" + +typedef struct { + int num_loops; + int thread_id; +} arg_t; + +sem_t forks[5]; + +int left(int p) { + return p; +} + +int right(int p) { + return (p + 1) % 5; +} + +void get_forks(int p) { + if (p == 4) { + Sem_wait(&forks[right(p)]); + Sem_wait(&forks[left(p)]); + } else { + Sem_wait(&forks[left(p)]); + Sem_wait(&forks[right(p)]); + } +} + +void put_forks(int p) { + Sem_post(&forks[left(p)]); + Sem_post(&forks[right(p)]); +} + +void think() { + return; +} + +void eat() { + return; +} + +void *philosopher(void *arg) { + arg_t *args = (arg_t *) arg; + + int i; + for (i = 0; i < args->num_loops; i++) { + think(); + get_forks(args->thread_id); + eat(); + put_forks(args->thread_id); + } + return NULL; +} + +int main(int argc, char *argv[]) { + if (argc != 2) { + fprintf(stderr, "usage: dining_philosophers \n"); + exit(1); + } + printf("dining: started\n"); + + int i; + for (i = 0; i < 5; i++) + Sem_init(&forks[i], 1); + + pthread_t p[5]; + arg_t a[5]; + for (i = 0; i < 5; i++) { + a[i].num_loops = atoi(argv[1]); + a[i].thread_id = i; + Pthread_create(&p[i], NULL, philosopher, &a[i]); + } + + for (i = 0; i < 5; i++) + Pthread_join(p[i], NULL); + + printf("dining: finished\n"); + return 0; +} diff --git a/threads-sema/dining_philosophers_no_deadlock_print.c b/threads-sema/dining_philosophers_no_deadlock_print.c new file mode 100644 index 0000000..84afce8 --- /dev/null +++ b/threads-sema/dining_philosophers_no_deadlock_print.c @@ -0,0 +1,105 @@ +#include +#include +#include + +#include "common.h" +#include "common_threads.h" + +typedef struct { + int num_loops; + int thread_id; +} arg_t; + +sem_t forks[5]; +sem_t print_lock; + +void space(int s) { + Sem_wait(&print_lock); + int i; + for (i = 0; i < s * 10; i++) + printf(" "); +} + +void space_end() { + Sem_post(&print_lock); +} + +int left(int p) { + return p; +} + +int right(int p) { + return (p + 1) % 5; +} + +void get_forks(int p) { + if (p == 4) { + space(p); printf("4 try %d\n", right(p)); space_end(); + Sem_wait(&forks[right(p)]); + space(p); printf("4 try %d\n", left(p)); space_end(); + Sem_wait(&forks[left(p)]); + } else { + space(p); printf("try %d\n", left(p)); space_end(); + Sem_wait(&forks[left(p)]); + space(p); printf("try %d\n", right(p)); space_end(); + Sem_wait(&forks[right(p)]); + } +} + +void put_forks(int p) { + Sem_post(&forks[left(p)]); + Sem_post(&forks[right(p)]); +} + +void think() { + return; +} + +void eat() { + return; +} + +void *philosopher(void *arg) { + arg_t *args = (arg_t *) arg; + + space(args->thread_id); printf("%d: start\n", args->thread_id); space_end(); + + int i; + for (i = 0; i < args->num_loops; i++) { + space(args->thread_id); printf("%d: think\n", args->thread_id); space_end(); + think(); + get_forks(args->thread_id); + space(args->thread_id); printf("%d: eat\n", args->thread_id); space_end(); + eat(); + put_forks(args->thread_id); + space(args->thread_id); printf("%d: done\n", args->thread_id); space_end(); + } + return NULL; +} + +int main(int argc, char *argv[]) { + if (argc != 2) { + fprintf(stderr, "usage: dining_philosophers \n"); + exit(1); + } + printf("dining: started\n"); + + int i; + for (i = 0; i < 5; i++) + Sem_init(&forks[i], 1); + Sem_init(&print_lock, 1); + + pthread_t p[5]; + arg_t a[5]; + for (i = 0; i < 5; i++) { + a[i].num_loops = atoi(argv[1]); + a[i].thread_id = i; + Pthread_create(&p[i], NULL, philosopher, &a[i]); + } + + for (i = 0; i < 5; i++) + Pthread_join(p[i], NULL); + + printf("dining: finished\n"); + return 0; +}