From: Lukas Jiriste Date: Thu, 28 Mar 2024 09:55:38 +0000 (+0100) Subject: Implement initialization, cleanup and mutex struct X-Git-Url: https://git.ljiriste.work/?a=commitdiff_plain;h=29613319e593e2349c7de434ab87f2865f2fcbc2;p=42%2Fphilosophers.git Implement initialization, cleanup and mutex struct The mutex struct is implemented because pthread_mutex_destroy produces undefined behaviour when supplied with uninitialized mutex. The struct holds information whether the mutex has been initialized succesfully. The header file philo.h has also been filled with declarations of functions used in main so that Makefiles compiles every file to object. This is done for easier checking of compile errors. --- diff --git a/philo/Makefile b/philo/Makefile index dde328d..5d5094c 100644 --- a/philo/Makefile +++ b/philo/Makefile @@ -6,9 +6,11 @@ NAME := philo INCDIR := . SRCDIR := . -SRCS := main.c \ - parsing.c \ - parsing_misc.c \ +SRCS := main.c \ + parsing.c \ + parsing_misc.c \ + mem_management.c \ + mutex.c \ SRCS := $(addprefix $(SRCDIR)/, $(SRCS)) OBJS := $(SRCS:%.c=%.o) diff --git a/philo/main.c b/philo/main.c index 2e83049..c4a9e7c 100644 --- a/philo/main.c +++ b/philo/main.c @@ -6,7 +6,7 @@ /* By: ljiriste +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/03/22 11:19:48 by ljiriste #+# #+# */ -/* Updated: 2024/03/28 09:38:05 by ljiriste ### ########.fr */ +/* Updated: 2024/03/28 10:00:52 by ljiriste ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,7 +23,7 @@ int main(int argc, char **argv) { return (1); } - if (init(&diner, threads)) + if (init(&diner, &threads)) { cleanup(&diner, threads); return (2); diff --git a/philo/mem_management.c b/philo/mem_management.c new file mode 100644 index 0000000..6ac0713 --- /dev/null +++ b/philo/mem_management.c @@ -0,0 +1,65 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* mem_management.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ljiriste +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/03/28 09:39:55 by ljiriste #+# #+# */ +/* Updated: 2024/03/28 10:49:03 by ljiriste ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "philo.h" +#include +#include +#include + +// Shortcircuiting does no harm here as when any mutex_init fails +// the program will end anyway. +int init(t_diner *diner, pthread_t **threads) +{ + const size_t count = diner->setting.philo_count; + size_t i; + + diner->philos = malloc(sizeof(diner->philos) * count); + diner->forks = malloc(sizeof(diner->forks) * count); + *threads = malloc(sizeof(*threads) * count); + if (!diner->philos || !diner->forks || !*threads) + return (1); + init_mutex(&diner->setting.terminal_lock, NULL); + init_mutex(&diner->setting.end_lock, NULL); + i = 0; + while (i < count) + { + init_mutex(diner->forks + i, NULL); + init_mutex(&diner->philos[i].philo_lock, NULL); + diner->philos[i].forks[i % 2] = diner->forks + i; + diner->philos[i].forks[(i + 1) % 2] = diner->forks + + (i + 1) % count; + diner->philos[i].settings = &diner->setting; + ++i; + } + return (!all_mutexes_initialized(diner)); +} + +void cleanup(t_diner *diner, pthread_t *threads) +{ + const size_t count = diner->setting.philo_count; + size_t i; + + destroy_mutex(&diner->setting.terminal_lock); + destroy_mutex(&diner->setting.end_lock); + i = 0; + if (diner->forks) + while (i < count) + destroy_mutex(diner->forks + (i++)); + i = 0; + if (diner->philos) + while (i < count) + destroy_mutex(&diner->philos[i++].philo_lock); + free(diner->philos); + free(diner->forks); + free(threads); + return ; +} diff --git a/philo/mutex.c b/philo/mutex.c new file mode 100644 index 0000000..54ae20b --- /dev/null +++ b/philo/mutex.c @@ -0,0 +1,45 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* mutex.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ljiriste +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/03/28 10:35:16 by ljiriste #+# #+# */ +/* Updated: 2024/03/28 10:49:35 by ljiriste ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "philo.h" +#include + +int init_mutex(t_mutex *mutex, pthread_mutexattr_t *attr) +{ + mutex->is_init = !(pthread_mutex_init(&mutex->mutex, attr)); + return (mutex->is_init); +} + +void destroy_mutex(t_mutex *mutex) +{ + if (mutex->is_init) + pthread_mutex_destroy(&mutex->mutex); + mutex->is_init = 0; +} + +int all_mutexes_initialized(t_diner *diner) +{ + int res; + size_t i; + + res = 1; + res = res && diner->setting.terminal_lock.is_init; + res = res && diner->setting.end_lock.is_init; + i = 0; + while (i < diner->setting.philo_count) + { + res = res && diner->forks[i].is_init; + res = res && diner->philos[i].philo_lock.is_init; + ++i; + } + return (res); +} diff --git a/philo/philo.h b/philo/philo.h index 399fc0e..f9f47d4 100644 --- a/philo/philo.h +++ b/philo/philo.h @@ -6,7 +6,7 @@ /* By: ljiriste +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/03/22 11:10:17 by ljiriste #+# #+# */ -/* Updated: 2024/03/28 09:32:08 by ljiriste ### ########.fr */ +/* Updated: 2024/03/28 10:50:26 by ljiriste ### ########.fr */ /* */ /* ************************************************************************** */ @@ -33,6 +33,12 @@ typedef size_t t_big_uint; typedef unsigned int t_big_uint; # endif //SIZE_MAX > UINT_MAX +typedef struct s_mutex +{ + int is_init; + pthread_mutex_t mutex; +} t_mutex; + // The .start member holds the result of gettimeofday // Every other member that holds time info counts // microseconds from that point (in other structures also) @@ -46,30 +52,43 @@ typedef struct s_settings useconds_t time_to_sleep; size_t philo_count; struct timeval start; - pthread_mutex_t terminal_lock; - pthread_mutex_t end_lock; + t_mutex terminal_lock; + t_mutex end_lock; } t_settings; typedef struct s_philosopher { - int num_eaten; - size_t id; - useconds_t last_eaten; - t_settings *settings; - pthread_mutex_t *forks[2]; - pthread_mutex_t philo_lock; + int num_eaten; + size_t id; + useconds_t last_eaten; + t_settings *settings; + t_mutex *forks[2]; + t_mutex philo_lock; } t_philo; typedef struct s_diner { - t_settings setting; - t_philo *philos; - pthread_mutex_t *forks; -} t_diner; + t_settings setting; + t_philo *philos; + t_mutex *forks; +} t_diner; int parse_input(t_settings *settings, int argc, char **argv); t_big_uint ft_atobui(const char *str); char *ft_buitoa(t_big_uint num); int same_number(const char *num1, const char *num2); +int init(t_diner *diner, pthread_t **threads); +void cleanup(t_diner *diner, pthread_t *threads); + +int init_mutex(t_mutex *mutex, pthread_mutexattr_t *attr); +void destroy_mutex(t_mutex *mutex); +int all_mutexes_initialized(t_diner *diner); + +int seat_philosophers(t_diner *diner, pthread_t *threads); +void wait_till_death_possible(useconds_t time_to_die, + struct timeval start); +void report_end(int end); +int watch_philosophers(t_diner *diner); + #endif //PHILO_H