/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/22 11:19:48 by ljiriste #+# #+# */
-/* Updated: 2024/05/09 12:31:31 by ljiriste ### ########.fr */
+/* Updated: 2024/05/10 11:03:38 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
int main(int argc, char **argv)
{
- t_diner diner;
- pthread_t *threads;
- enum e_end res;
+ t_settings settings;
+ pid_t *philo_pids;
+ sem_t *semaphores[SEM_NUM];
- if (parse_input(&diner.setting, argc, argv))
+ if (parse_input(&settings, argc, argv))
{
return (1);
}
- if (init(&diner, &threads))
+ if (init(settings.philo_count, &philo_pids, semaphores))
{
- cleanup(&diner, threads);
+ cleanup(philo_pids, semaphores);
return (2);
}
- if (seat_philosophers(&diner, threads))
+ if (seat_philosophers(settings, philo_pids))
{
- cleanup(&diner, threads);
+ cleanup(philo_pids, semaphores);
return (3);
}
- res = watch_philosophers(&diner);
- cleanup(&diner, threads);
- if (res == well_fed)
- printf("All philosophers are well fed.\n");
+ handle_philosophers(semaphores);
+ cleanup(philo_pids, semaphores);
return (0);
}
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/28 09:39:55 by ljiriste #+# #+# */
-/* Updated: 2024/05/09 12:41:33 by ljiriste ### ########.fr */
+/* Updated: 2024/05/10 10:59:28 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
#include "philo.h"
-#include <pthread.h>
#include <stddef.h>
#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <semaphore.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)
+static int open_semaphores(sem_t *semaphores[sem_num])
{
- const size_t count = diner->setting.philo_count;
- size_t i;
+ size_t i;
- init_mutex(&diner->setting.terminal_lock, NULL);
- init_mutex(&diner->setting.end_lock, NULL);
- 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)
+ semaphores[forks] = sem_open(FORKS_SEM, O_CREAT | O_EXCL,
+ S_IRUSR | S_IWUSR, setings->philo_count);
+ semaphores[fed] = sem_open(WELL_FED_SEM, O_CREAT | O_EXCL,
+ S_IRUSR | S_IWUSR, setings->philo_count);
+ semaphores[death] = sem_open(DEATH_SEM, O_CREAT | O_EXCL,
+ S_IRUSR | S_IWUSR, setings->philo_count);
+ semaphores[term] = sem_open(TERM_SEM, O_CREAT | O_EXCL,
+ S_IRUSR | S_IWUSR, 1);
+ i = 0;
+ while (i < SEM_NUM)
+ if (semaphores[i++] == SEM_FAILED)
+ return (1);
+ return (0);
+}
+
+int init(unsigned int count, pid_t **philo_pids, sem_t *semaphores[sem_num])
+{
+ *philo_pids = malloc(count * sizeof(**philo_pids));
+ if (!*philo_pids)
+ return (1);
+ if (open_semaphores(semaphores))
return (1);
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;
- diner->philos[i].last_eaten = 0;
- diner->philos[i].id = i + 1;
- diner->philos[i].num_eaten = 0;
+ sem_wait(semaphores[death]);
+ sem_wait(semaphores[fed]);
++i;
}
- return (!all_mutexes_initialized(diner));
+ return (0);
}
-void cleanup(t_diner *diner, pthread_t *threads)
+void cleanup(pid_t *philo_pids, sem_t *semaphores[sem_num])
{
- const size_t count = diner->setting.philo_count;
- size_t i;
+ size_t i;
i = 0;
- if (diner->philos)
+ while (i < SEM_NUM)
{
- while (i < count)
- {
- pthread_join(threads[i], NULL);
- destroy_mutex(&diner->philos[i++].philo_lock);
- }
+ if (semaphores[i] != SEM_FAILED)
+ sem_close(semaphores[i]);
+ ++i;
}
- i = 0;
- if (diner->forks)
- while (i < count)
- destroy_mutex(diner->forks + (i++));
- destroy_mutex(&diner->setting.terminal_lock);
- destroy_mutex(&diner->setting.end_lock);
- free(diner->philos);
- free(diner->forks);
- free(threads);
+ free(philo_pids);
return ;
}
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/28 11:29:47 by ljiriste #+# #+# */
-/* Updated: 2024/05/09 10:38:14 by ljiriste ### ########.fr */
+/* Updated: 2024/05/10 11:01:04 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
return (0);
}
-#if SIZE_MAX > UINT_MAX
-
-int parse_arg_size(size_t *res, const char *arg)
-{
- t_big_uint tmp;
-
- if (inner_parse_arg(&tmp, arg))
- return (1);
- if (tmp > (size_t)-1)
- return (1);
- *res = (size_t)tmp;
- return (0);
-}
-
-#else
-
-int parse_arg_size(size_t *res, const char *arg)
-{
- t_big_uint tmp;
-
- if (inner_parse_arg(&tmp, arg))
- return (1);
- *res = (size_t)tmp;
- return (0);
-}
-
-#endif //SIZE_MAX > UINT_MAX
-
#if UINT_MAX > SIZE_MAX
int parse_arg_uint(unsigned int *res, const char *arg)
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/26 09:31:35 by ljiriste #+# #+# */
-/* Updated: 2024/05/09 12:35:58 by ljiriste ### ########.fr */
+/* Updated: 2024/05/10 11:00:20 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
{
if (argc != 5 && argc != 6)
return (1);
- settings->end = 0;
settings->should_check_hunger = 0;
- if (parse_arg_size(&settings->philo_count, argv[1])
+ if (parse_arg_uint(&settings->philo_count, argv[1])
|| parse_arg_usec(&settings->time_to_die, argv[2])
|| parse_arg_usec(&settings->time_to_eat, argv[3])
|| parse_arg_usec(&settings->time_to_sleep, argv[4]))
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/22 11:10:17 by ljiriste #+# #+# */
-/* Updated: 2024/05/10 09:34:17 by ljiriste ### ########.fr */
+/* Updated: 2024/05/10 10:59:31 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
# include <sys/time.h>
# include <unistd.h>
+# define FORKS_SEM "philosophers_forks"
+# define WELL_FED_SEM "philosophers_fed"
+# define DEATH_SEM "philosophers_death"
+# define TERM_SEM "philosophers_terminal"
+
+typedef enum e_semaphores
+{
+ forks,
+ fed,
+ death,
+ term,
+ sem_num,
+} t_my_sems
+
// The .start member holds the result of gettimeofday
// Every other member that holds time info counts
// microseconds from that point (in other structures also)
typedef struct s_settings
{
+ unsigned int philo_count;
int should_check_hunger;
unsigned int min_eat_num;
useconds_t time_to_die;
typedef struct s_philosopher
{
unsigned int num_eaten;
- size_t id;
+ unsigned int id;
useconds_t last_eaten;
sem_t *forks;
sem_t *well_fed_sem;
int parse_input(t_settings *settings, int argc, char **argv);
-int init(t_diner *diner, pthread_t **threads);
-void cleanup(t_diner *diner, pthread_t *threads);
+int init(unsigned int count, pid_t **philo_pids,
+ sem_t *semaphores[sem_num]);
+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);