Implement initialization, cleanup and mutex struct
authorLukas Jiriste <ljiriste@student.42prague.com>
Thu, 28 Mar 2024 09:55:38 +0000 (10:55 +0100)
committerLukas Jiriste <ljiriste@student.42prague.com>
Thu, 28 Mar 2024 09:55:38 +0000 (10:55 +0100)
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.

philo/Makefile
philo/main.c
philo/mem_management.c [new file with mode: 0644]
philo/mutex.c [new file with mode: 0644]
philo/philo.h

index dde328dc7613ba719a8cd411916de9f6205f802c..5d5094c1a67366eb7e9292b7a4f07c5f5bca99bf 100644 (file)
@@ -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)
index 2e830492bd8bbfb93c0055933c6d10b2a87ac78e..c4a9e7ceea43b2912c01af5481200b8174498e27 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   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 (file)
index 0000000..6ac0713
--- /dev/null
@@ -0,0 +1,65 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   mem_management.c                                   :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/03/28 09:39:55 by ljiriste          #+#    #+#             */
+/*   Updated: 2024/03/28 10:49:03 by ljiriste         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "philo.h"
+#include <pthread.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+//     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 (file)
index 0000000..54ae20b
--- /dev/null
@@ -0,0 +1,45 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   mutex.c                                            :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/03/28 10:35:16 by ljiriste          #+#    #+#             */
+/*   Updated: 2024/03/28 10:49:35 by ljiriste         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "philo.h"
+#include <pthread.h>
+
+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);
+}
index 399fc0ed63d9feb8c5c51655a6e985e2eba5c905..f9f47d4ceaf0e13a9048198be83a6219d50a5572 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   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