Skip to content

Commit

Permalink
Dining savages
Browse files Browse the repository at this point in the history
  • Loading branch information
xxyzz committed Nov 2, 2021
1 parent 4349d72 commit 113a87f
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 33 deletions.
3 changes: 2 additions & 1 deletion 31/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
CFLAGS := -Wall -pthread

all: fork-join.out rendezvous.out barrier.out reader-writer.out \
reader-writer-nostarve.out mutex-nostarve.out cigarette_smokers.out
reader-writer-nostarve.out mutex-nostarve.out cigarette_smokers.out \
dining_savages.out

%.out: %.c common_threads.h
$(CC) -o $@ $< $(CFLAGS)
Expand Down
85 changes: 58 additions & 27 deletions 31/cigarette_smokers.c
Original file line number Diff line number Diff line change
@@ -1,67 +1,98 @@
#include "common_threads.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h> // free, malloc

// Little Book of Semaphores: chapter 4.5

sem_t tobacco_sem, paper_sem, match_sem, agent_sem, lock;
sem_t *tobacco_sem, *paper_sem, *match_sem, *agent_sem, *lock;
bool has_tobacco = false;
bool has_paper = false;
bool has_match = false;

void init_sem() {
Sem_init(&tobacco_sem, 0, 0);
Sem_init(&paper_sem, 0, 0);
Sem_init(&match_sem, 0, 0);
Sem_init(&agent_sem, 0, 1);
Sem_init(&lock, 0, 1);
#ifdef __APPLE__
tobacco_sem = Sem_open("/tobacco_sem", 0);
paper_sem = Sem_open("/paper_sem", 0);
match_sem = Sem_open("/match_sem", 0);
agent_sem = Sem_open("/agent_sem", 1);
lock = Sem_open("/lock", 1);
#else
tobacco_sem = malloc(sizeof(sem_t));
Sem_init(tobacco_sem, 0, 0);
paper_sem = malloc(sizeof(sem_t));
Sem_init(paper_sem, 0, 0);
match_sem = malloc(sizeof(sem_t));
Sem_init(match_sem, 0, 0);
agent_sem = malloc(sizeof(sem_t));
Sem_init(agent_sem, 0, 1);
lock = malloc(sizeof(sem_t));
Sem_init(lock, 0, 1);
#endif
}

void destroy_sem() {
Sem_destroy(&tobacco_sem);
Sem_destroy(&paper_sem);
Sem_destroy(&match_sem);
Sem_destroy(&agent_sem);
Sem_destroy(&lock);
#ifdef __APPLE__
Sem_close(tobacco_sem);
Sem_unlink("/tobacco_sem");
Sem_close(paper_sem);
Sem_unlink("/paper_sem");
Sem_close(match_sem);
Sem_unlink("/match_sem");
Sem_close(agent_sem);
Sem_unlink("/agent_sem");
Sem_close(lock);
Sem_unlink("/lock");
#else
Sem_destroy(tobacco_sem);
free(tobacco_sem);
Sem_destroy(paper_sem);
free(paper_sem);
Sem_destroy(match_sem);
free(match_sem);
Sem_destroy(agent_sem);
free(agent_sem);
Sem_destroy(lock);
free(lock);
#endif
}

void tobacco_pusher() {
if (has_paper) {
has_paper = false;
Sem_post(&match_sem);
Sem_post(match_sem);
} else if (has_match) {
has_match = false;
Sem_post(&paper_sem);
Sem_post(paper_sem);
} else
has_tobacco = true;
}

void paper_pusher() {
if (has_match) {
has_match = false;
Sem_post(&tobacco_sem);
Sem_post(tobacco_sem);
} else if (has_tobacco) {
has_tobacco = false;
Sem_post(&match_sem);
Sem_post(match_sem);
} else
has_paper = true;
}

void match_pusher() {
if (has_paper) {
has_paper = false;
Sem_post(&tobacco_sem);
Sem_post(tobacco_sem);
} else if (has_tobacco) {
has_tobacco = false;
Sem_post(&paper_sem);
Sem_post(paper_sem);
} else
has_match = true;
}

void *agent(void *arg) {
int type = *(int *)arg;
Sem_wait(&agent_sem);
Sem_wait(&lock);
Sem_wait(agent_sem);
Sem_wait(lock);
switch (type) {
case 0:
tobacco_pusher();
Expand All @@ -75,27 +106,27 @@ void *agent(void *arg) {
tobacco_pusher();
match_pusher();
}
Sem_post(&lock);
Sem_post(lock);
return NULL;
}

void *smoker(void *arg) {
int type = *(int *)arg;
switch (type) {
case 0:
Sem_wait(&tobacco_sem);
Sem_wait(tobacco_sem);
printf("Smoker with tobacco is getting a little bit of cancer.\n");
Sem_post(&agent_sem);
Sem_post(agent_sem);
break;
case 1:
Sem_wait(&paper_sem);
Sem_wait(paper_sem);
printf("Smoker with paper is getting a little bit of cancer.\n");
Sem_post(&agent_sem);
Sem_post(agent_sem);
break;
case 2:
Sem_wait(&match_sem);
Sem_wait(match_sem);
printf("Smoker with match is getting a little bit of cancer.\n");
Sem_post(&agent_sem);
Sem_post(agent_sem);
}
return NULL;
}
Expand Down
10 changes: 5 additions & 5 deletions 31/common_threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@
#define Sem_close(sem) assert(sem_close(sem) == 0)
#define Sem_unlink(sem) assert(sem_unlink(sem) == 0)

sem_t *Sem_open(char *sem, int value) {
sem_t *newSem;
newSem = sem_open(sem, O_CREAT, S_IRWXU, value);
assert(newSem != SEM_FAILED);
return newSem;
sem_t *Sem_open(char *name, int value) {
sem_t *sem;
sem = sem_open(name, O_CREAT, S_IRWXU, value);
assert(sem != SEM_FAILED);
return sem;
}

#endif // __common_threads_h__
111 changes: 111 additions & 0 deletions 31/dining_savages.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#include "common_threads.h"
#include <stdio.h>
#include <stdlib.h> // exit, free, malloc
#include <unistd.h> // getopt

sem_t *empty_pot, *full_pot, *mutex;
int stewed_missionaries = 0, pot_size = 2;

void init_sem() {
#ifdef __APPLE__
empty_pot = Sem_open("/empty_pot", 0);
full_pot = Sem_open("/full_pot", 0);
mutex = Sem_open("/mutex", 1);
#else
empty_pot = malloc(sizeof(sem_t));
Sem_init(empty_pot, 0, 0);
full_pot = malloc(sizeof(sem_t));
Sem_init(full_pot, 0, 0);
mutex = malloc(sizeof(sem_t));
Sem_init(mutex, 0, 1);
#endif
}

void destroy_sem() {
#ifdef __APPLE__
Sem_close(empty_pot);
Sem_unlink("/empty_pot");
Sem_close(full_pot);
Sem_unlink("/full_pot");
Sem_close(mutex);
Sem_unlink("/mutex");
#else
Sem_destroy(empty_pot);
free(empty_pot);
Sem_destroy(full_pot);
free(full_pot);
Sem_destroy(mutex);
free(mutex);
#endif
}

void *cook(void *arg) {
int savages_num = *(int *)arg;
int loop = 0;
if (savages_num % pot_size == 0)
loop = savages_num / pot_size;
else
loop = savages_num / pot_size + 1;
for (int i = 0; i < loop; i++) {
Sem_wait(empty_pot);
printf("Cook fills the pot with %d stewed missionaries\n", pot_size);
Sem_post(full_pot);
}
return NULL;
}

void *savage(void *arg) {
int index = *(int *)arg;
Sem_wait(mutex);
if (stewed_missionaries == 0) {
Sem_post(empty_pot);
Sem_wait(full_pot);
stewed_missionaries = pot_size;
}
stewed_missionaries--;
printf("Savage %d feats on a missionary\n", index);
Sem_post(mutex);
return NULL;
}

int main(int argc, char *argv[]) {
int opt, savages_num = 3;
while ((opt = getopt(argc, argv, "p:s:")) != -1) {
switch (opt) {
case 'p':
pot_size = atoi(optarg);
if (pot_size <= 0) {
fprintf(stderr, "A missionary walks into a pot...\n");
exit(EXIT_FAILURE);
}
break;
case 's':
savages_num = atoi(optarg);
if (savages_num <= 0) {
fprintf(stderr, "A savage walks into a bar...\n");
exit(EXIT_FAILURE);
}
break;
default:
fprintf(stderr, "Usage: %s [-p pot_size] [-s savages_number]\n", argv[0]);
exit(EXIT_FAILURE);
}
}

pthread_t cook_thread;
pthread_t savages_threads[savages_num];
int stupid_arr[savages_num];
init_sem();

Pthread_create(&cook_thread, NULL, cook, &savages_num);
for (int i = 0; i < savages_num; i++) {
stupid_arr[i] = i;
Pthread_create(&savages_threads[i], NULL, savage, &stupid_arr[i]);
}

Pthread_join(cook_thread, NULL);
for (int i = 0; i < savages_num; i++)
Pthread_join(savages_threads[i], NULL);
destroy_sem();
return 0;
}

0 comments on commit 113a87f

Please sign in to comment.