pars_arg.c \
inner_pars_arg.c \
mem_management.c \
+ hunger_watcher.c \
SRCS := $(addprefix $(SRCDIR)/, $(SRCS))
OBJS := $(SRCS:%.c=%.o)
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */
}
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 ;
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* hunger_watcher.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/05/24 08:49:46 by ljiriste #+# #+# */
+/* Updated: 2024/05/24 10:33:27 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "philo.h"
+#include <pthread.h>
+
+// 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 ;
+}
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */
#include <stdio.h>
#include <stdlib.h>
-static void open_semaphores(t_philo *philo)
+static int open_semaphores(t_philo *philo)
{
char *sem_name;
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]);
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);
}
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */
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