From 598e5a5851c2bce6f62ea9cb3dfab4b96af875ee Mon Sep 17 00:00:00 2001 From: Lukas Jiriste Date: Fri, 24 May 2024 10:13:27 +0200 Subject: [PATCH] Implement the hunger watcher, rename function The hunger watcher watches for starvation in calling philo making him die when he starves (is hungry for too long). The function print_timestamp is split to make it possible to ensure the "philo died" message is the last one. --- philo_bonus/Makefile | 1 + philo_bonus/helpers.c | 12 +++++-- philo_bonus/hunger_watcher.c | 61 ++++++++++++++++++++++++++++++++++++ philo_bonus/philo.c | 28 +++++++++-------- philo_bonus/philo.h | 7 +++-- 5 files changed, 91 insertions(+), 18 deletions(-) create mode 100644 philo_bonus/hunger_watcher.c diff --git a/philo_bonus/Makefile b/philo_bonus/Makefile index 0044792..67db9eb 100644 --- a/philo_bonus/Makefile +++ b/philo_bonus/Makefile @@ -14,6 +14,7 @@ SRCS := main.c \ pars_arg.c \ inner_pars_arg.c \ mem_management.c \ + hunger_watcher.c \ SRCS := $(addprefix $(SRCDIR)/, $(SRCS)) OBJS := $(SRCS:%.c=%.o) diff --git a/philo_bonus/helpers.c b/philo_bonus/helpers.c index 20dfa30..bfed896 100644 --- a/philo_bonus/helpers.c +++ b/philo_bonus/helpers.c @@ -6,7 +6,7 @@ /* By: ljiriste +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/09 09:13:40 by ljiriste #+# #+# */ -/* Updated: 2024/05/24 09:21:50 by ljiriste ### ########.fr */ +/* Updated: 2024/05/24 10:26:10 by ljiriste ### ########.fr */ /* */ /* ************************************************************************** */ @@ -34,12 +34,18 @@ int is_alive(t_philo *philo) } void print_timestamp(t_philo *philo, const char *str) +{ + printf("%u %u %s\n", usecs_since_start(philo->settings.start) + / 1000, philo->id, str); + return ; +} + +void report(t_philo *philo, const char *str) { if (is_alive(philo)) { sem_wait(philo->semaphores[term]); - printf("%u %u %s\n", usecs_since_start(philo->settings.start) - / 1000, philo->id, str); + print_timestamp(philo, str); sem_post(philo->semaphores[term]); } return ; diff --git a/philo_bonus/hunger_watcher.c b/philo_bonus/hunger_watcher.c new file mode 100644 index 0000000..b22b59b --- /dev/null +++ b/philo_bonus/hunger_watcher.c @@ -0,0 +1,61 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* hunger_watcher.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ljiriste +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/24 08:49:46 by ljiriste #+# #+# */ +/* Updated: 2024/05/24 10:33:27 by ljiriste ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "philo.h" +#include + +// This function should only be called when the philo_sem is locked +// by this thread. +static useconds_t time_till_death(t_philo *philo) +{ + const useconds_t cur_time = usecs_since_start(philo->settings.start); + + if (cur_time >= philo->last_eaten + philo->settings.time_to_die) + return (0); + return (philo->last_eaten + philo->settings.time_to_die - cur_time); +} + +// The lock of philo_sem is done this way because philo has to be lock +// between the time calculation and setting him as not alive. +// Else the philo could eat in between the watcher deciding to kill him +// and executing it. +static void *watch_for_starvation(void *philo_void) +{ + t_philo *philo; + useconds_t time; + + philo = philo_void; + sem_wait(philo->philo_sem); + time = time_till_death(philo); + while (time == 0) + { + sem_post(philo->philo_sem); + usleep(time / 2); + sem_wait(philo->philo_sem); + time = time_till_death(philo); + } + philo->alive = 0; + sem_post(philo->semaphores[death]); + sem_post(philo->philo_sem); + return (NULL); +} + +int create_hunger_watcher(t_philo *philo, pthread_t *hunger_watcher) +{ + return (pthread_create(hunger_watcher, NULL, watch_for_starvation, philo)); +} + +void destroy_hunger_watcher(pthread_t hunger_watcher) +{ + pthread_join(hunger_watcher, NULL); + return ; +} diff --git a/philo_bonus/philo.c b/philo_bonus/philo.c index 6c49920..b9ce802 100644 --- a/philo_bonus/philo.c +++ b/philo_bonus/philo.c @@ -6,7 +6,7 @@ /* By: ljiriste +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/09 08:45:21 by ljiriste #+# #+# */ -/* Updated: 2024/05/24 08:44:24 by ljiriste ### ########.fr */ +/* Updated: 2024/05/24 10:32:38 by ljiriste ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,7 +16,7 @@ #include #include -static void open_semaphores(t_philo *philo) +static int open_semaphores(t_philo *philo) { char *sem_name; @@ -32,28 +32,28 @@ static void open_semaphores(t_philo *philo) sem_wait(philo->semaphores[term]); printf("An error has occured.\n"); sem_wait(philo->semaphores[death]); - exit(2); + return (1); } - return ; + return (0); } static void philo_think(t_philo *philo) { - print_timestamp(philo, "is thinking"); + report(philo, "is thinking"); return ; } static void philo_eat(t_philo *philo) { sem_wait(philo->semaphores[forks]); - print_timestamp(philo, "has taken a fork"); + report(philo, "has taken a fork"); sem_wait(philo->semaphores[forks]); - print_timestamp(philo, "has taken a fork"); + report(philo, "has taken a fork"); sem_wait(philo->philo_sem); philo->last_eaten = usecs_since_start(philo->settings.start); ++philo->num_eaten; sem_post(philo->philo_sem); - print_timestamp(philo, "is eating"); + report(philo, "is eating"); if (philo->settings.should_check_hunger && philo->num_eaten == philo->settings.min_eat_num) sem_post(philo->semaphores[fed]); @@ -65,23 +65,25 @@ static void philo_eat(t_philo *philo) static void philo_sleep(t_philo *philo) { - print_timestamp(philo, "is sleeping"); + report(philo, "is sleeping"); usleep(philo->settings.time_to_sleep); return ; } void be_a_philosopher(t_philo *philo) { - pid_t hunger_watcher_pid; + pthread_t hunger_watcher; - open_semaphores(philo); - hunger_watcher_pid = create_hunger_watcher(philo); + if (open_semaphores(philo)) + exit(2); + if (create_hunger_watcher(philo, &hunger_watcher)) + exit(3); while (is_alive(philo)) { philo_think(philo); philo_eat(philo); philo_sleep(philo); } - destroy_hunger_watcher(hunger_watcher_pid); + destroy_hunger_watcher(hunger_watcher); exit(0); } diff --git a/philo_bonus/philo.h b/philo_bonus/philo.h index 625c60f..65af18e 100644 --- a/philo_bonus/philo.h +++ b/philo_bonus/philo.h @@ -6,7 +6,7 @@ /* By: ljiriste +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/03/22 11:10:17 by ljiriste #+# #+# */ -/* Updated: 2024/05/24 09:21:24 by ljiriste ### ########.fr */ +/* Updated: 2024/05/24 10:32:59 by ljiriste ### ########.fr */ /* */ /* ************************************************************************** */ @@ -72,10 +72,13 @@ int init(unsigned int count, pid_t **philo_pids, void cleanup(pid_t *philo_pids, sem_t *semaphores[sem_num]); useconds_t usecs_since_start(struct timeval start); -int report(t_philo *philo, const char *str); int is_alive(t_philo *philo); +void report(t_philo *philo, const char *str); void print_timestamp(t_philo *philo, const char *str); +int create_hunger_watcher(t_philo *philo, pthread_t *hunger_watcher); +void destroy_hunger_watcher(pthread_t hunger_watcher); + void be_a_philosopher(t_philo *philo); #endif //PHILO_H -- 2.30.2