simple dining philosophers code (Linux only)
This commit is contained in:
9
threads-sema/Makefile
Normal file
9
threads-sema/Makefile
Normal file
@@ -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
|
||||||
|
|
||||||
12
threads-sema/README.md
Normal file
12
threads-sema/README.md
Normal file
@@ -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`.
|
||||||
|
|
||||||
78
threads-sema/dining_philosophers_deadlock.c
Normal file
78
threads-sema/dining_philosophers_deadlock.c
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#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 <num_loops>\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;
|
||||||
|
}
|
||||||
98
threads-sema/dining_philosophers_deadlock_print.c
Normal file
98
threads-sema/dining_philosophers_deadlock_print.c
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#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 <num_loops>\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;
|
||||||
|
}
|
||||||
83
threads-sema/dining_philosophers_no_deadlock.c
Normal file
83
threads-sema/dining_philosophers_no_deadlock.c
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#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 <num_loops>\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;
|
||||||
|
}
|
||||||
105
threads-sema/dining_philosophers_no_deadlock_print.c
Normal file
105
threads-sema/dining_philosophers_no_deadlock_print.c
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#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 <num_loops>\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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user