From 47beba686ff9d2aab63738fba7176a5235703d05 Mon Sep 17 00:00:00 2001 From: yctct Date: Sun, 13 Sep 2026 18:58:14 +0200 Subject: Add all files, first commit --- src/destroy.c | 66 +++++++++++++++++++++++++++++++++ src/forks.c | 75 ++++++++++++++++++++++++++++++++++++++ src/free_memory.c | 38 +++++++++++++++++++ src/init.c | 66 +++++++++++++++++++++++++++++++++ src/main.c | 39 ++++++++++++++++++++ src/monitoring.c | 44 ++++++++++++++++++++++ src/philos.c | 83 ++++++++++++++++++++++++++++++++++++++++++ src/print.c | 45 +++++++++++++++++++++++ src/queue.c | 55 ++++++++++++++++++++++++++++ src/routine.c | 57 +++++++++++++++++++++++++++++ src/scheduler.c | 86 +++++++++++++++++++++++++++++++++++++++++++ src/sim.c | 23 ++++++++++++ src/starve.c | 84 ++++++++++++++++++++++++++++++++++++++++++ src/threads.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++ src/time.c | 29 +++++++++++++++ src/utils.c | 20 ++++++++++ src/utils_routine.c | 81 +++++++++++++++++++++++++++++++++++++++++ src/validate_parameters.c | 30 +++++++++++++++ 18 files changed, 1014 insertions(+) create mode 100644 src/destroy.c create mode 100644 src/forks.c create mode 100644 src/free_memory.c create mode 100644 src/init.c create mode 100644 src/main.c create mode 100644 src/monitoring.c create mode 100644 src/philos.c create mode 100644 src/print.c create mode 100644 src/queue.c create mode 100644 src/routine.c create mode 100644 src/scheduler.c create mode 100644 src/sim.c create mode 100644 src/starve.c create mode 100644 src/threads.c create mode 100644 src/time.c create mode 100644 src/utils.c create mode 100644 src/utils_routine.c create mode 100644 src/validate_parameters.c (limited to 'src') diff --git a/src/destroy.c b/src/destroy.c new file mode 100644 index 0000000..6a274ad --- /dev/null +++ b/src/destroy.c @@ -0,0 +1,66 @@ +#include "codexion.h" + +static void destroy_mutex_philos(t_sim *sim) +{ + t_philo **philos; + t_philo *philo; + int number_of_philos; + + number_of_philos = sim->number_of_philos; + philos = sim->philos; + while (number_of_philos-- > 0) + { + philo = *philos++; + (void)pthread_mutex_destroy(&philo->mutex_number_of_eats_done); + (void)pthread_mutex_destroy(&philo->mutex_beginning_last_eat_time); + (void)pthread_mutex_destroy(&philo->mutex_id); + (void)pthread_mutex_destroy(&philo->mutex_sim); + } +} + +static void destroy_mutex_forks(t_sim *sim) +{ + t_fork **forks; + t_fork *fork; + int number_of_philos; + + number_of_philos = sim->number_of_philos; + forks = sim->forks; + while (number_of_philos-- > 0) + { + fork = *forks++; + (void)pthread_mutex_destroy(&fork->mutex); + (void)pthread_mutex_destroy(&fork->mutex_last_released); + (void)pthread_mutex_destroy(&fork->mutex_right_philo); + (void)pthread_mutex_destroy(&fork->mutex_left_philo); + (void)pthread_mutex_destroy(&fork->mutex_ticket_next); + (void)pthread_mutex_destroy(&fork->mutex_cond); + (void)pthread_mutex_destroy(&fork->mutex_sim); + (void)pthread_cond_destroy(&fork->cond_signal); + (void)pthread_mutex_destroy(&fork->mutex_pq); + } +} + +static void destroy_mutex_sim(t_sim *sim) +{ + (void)pthread_mutex_destroy(&sim->mutex_philo_starved); + (void)pthread_mutex_destroy(&sim->mutex_print_log); + (void)pthread_mutex_destroy(&sim->mutex_cooldown); + (void)pthread_mutex_destroy(&sim->mutex_start_time); + (void)pthread_mutex_destroy(&sim->mutex_number_of_eat_required); + (void)pthread_mutex_destroy(&sim->mutex_philos); + (void)pthread_mutex_destroy(&sim->mutex_number_of_philos); + (void)pthread_mutex_destroy(&sim->mutex_time_to_starve); + (void)pthread_mutex_destroy(&sim->mutex_time_to_think); + (void)pthread_mutex_destroy(&sim->mutex_time_to_reflect); + (void)pthread_mutex_destroy(&sim->mutex_time_to_eat); + (void)pthread_mutex_destroy(&sim->mutex_scheduler); + (void)pthread_mutex_destroy(&sim->mutex_forks); +} + +void destroy_mutex(t_sim *sim) +{ + destroy_mutex_philos(sim); + destroy_mutex_forks(sim); + destroy_mutex_sim(sim); +} diff --git a/src/forks.c b/src/forks.c new file mode 100644 index 0000000..534ccc4 --- /dev/null +++ b/src/forks.c @@ -0,0 +1,75 @@ +#include "codexion.h" +# include // for atoi(), malloc() + +/* +fork's last used is a negative value of waiting time so first philos can +start compiling at the start of the simulation +*/ + +t_fork *create_fork(t_sim *sim) +{ + t_fork *fork; + t_queue pq; + + fork = (t_fork *)malloc(sizeof(t_fork)); + if (!fork) + { + free_forks(sim); + free(sim); + return (NULL); + } + fork->last_released = -1 * sim->fork_cooldown; + fork->ticket_next = 1; + fork->sim = sim; + pq.size = 0; + fork->pq = pq; + return (fork); +} + +t_fork **create_arr_forks(t_sim *sim) +{ + t_fork **forks; + t_fork *fork; + int i; + int number_of_philos; + + i = 0; + number_of_philos = sim->number_of_philos; + forks = (t_fork **)malloc((sizeof(t_fork *) * (number_of_philos + + 1))); + if (!forks) + { + free(sim); + return (NULL); + } + while (number_of_philos-- > 0) + { + fork = create_fork(sim); + fork->id = i + 1; + forks[i++] = fork; + } + forks[i] = NULL; + sim->number_of_forks_actual = i; + sim->forks = forks; + return (forks); +} + +t_philo **assign_forks(t_sim *sim) +{ + t_philo **philos; + t_fork **forks; + int number_of_philos; + int i; + + philos = sim->philos; + forks = sim->forks; + number_of_philos = sim->number_of_philos; + i = 0; + while (philos[i]) + { + philos[i]->left_fork = forks[i]; + philos[i]->right_fork = forks[(i + 1) % number_of_philos]; + i++; + } + return (philos); +} diff --git a/src/free_memory.c b/src/free_memory.c new file mode 100644 index 0000000..3853e33 --- /dev/null +++ b/src/free_memory.c @@ -0,0 +1,38 @@ +#include "codexion.h" +# include // for atoi(), malloc() + +void free_philos(t_sim *sim) +{ + t_philo **philos; + t_philo *philo; + int number_of_philos; + + philos = sim->philos; + number_of_philos = sim->number_of_philos_actual; + while (number_of_philos-- > 0) + { + philo = *philos++; + free(philo); + } + philos = sim->philos; + free(philos); + sim->philos = NULL; +} + +void free_forks(t_sim *sim) +{ + t_fork **forks; + t_fork *fork; + int number_of_forks; + + forks = sim->forks; + number_of_forks = sim->number_of_forks_actual; + while (number_of_forks-- > 0) + { + fork = *forks++; + free(fork); + } + forks = sim->forks; + free(forks); + sim->forks = NULL; +} diff --git a/src/init.c b/src/init.c new file mode 100644 index 0000000..623a7bb --- /dev/null +++ b/src/init.c @@ -0,0 +1,66 @@ +#include "codexion.h" + +static void init_mutex_philos(t_sim *sim) +{ + t_philo **philos; + t_philo *philo; + int number_of_philos; + + number_of_philos = sim->number_of_philos; + philos = sim->philos; + while (number_of_philos-- > 0) + { + philo = *philos++; + (void)pthread_mutex_init(&philo->mutex_number_of_eats_done, NULL); + (void)pthread_mutex_init(&philo->mutex_beginning_last_eat_time, NULL); + (void)pthread_mutex_init(&philo->mutex_id, NULL); + (void)pthread_mutex_init(&philo->mutex_sim, NULL); + } +} + +static void init_mutex_forks(t_sim *sim) +{ + t_fork **forks; + t_fork *fork; + int number_of_philos; + + number_of_philos = sim->number_of_philos; + forks = sim->forks; + while (number_of_philos-- > 0) + { + fork = *forks++; + (void)pthread_mutex_init(&fork->mutex, NULL); + (void)pthread_mutex_init(&fork->mutex_last_released, NULL); + (void)pthread_mutex_init(&fork->mutex_left_philo, NULL); + (void)pthread_mutex_init(&fork->mutex_right_philo, NULL); + (void)pthread_mutex_init(&fork->mutex_ticket_next, NULL); + (void)pthread_mutex_init(&fork->mutex_cond, NULL); + (void)pthread_mutex_init(&fork->mutex_sim, NULL); + (void)pthread_cond_init(&fork->cond_signal, NULL); + (void)pthread_mutex_init(&fork->mutex_pq, NULL); + } +} + +static void init_mutex_sim(t_sim *sim) +{ + (void)pthread_mutex_init(&sim->mutex_philo_starved, NULL); + (void)pthread_mutex_init(&sim->mutex_print_log, NULL); + (void)pthread_mutex_init(&sim->mutex_cooldown, NULL); + (void)pthread_mutex_init(&sim->mutex_start_time, NULL); + (void)pthread_mutex_init(&sim->mutex_number_of_eat_required, NULL); + (void)pthread_mutex_init(&sim->mutex_philos, NULL); + (void)pthread_mutex_init(&sim->mutex_number_of_philos, NULL); + (void)pthread_mutex_init(&sim->mutex_time_to_starve, NULL); + (void)pthread_mutex_init(&sim->mutex_time_to_think, NULL); + (void)pthread_mutex_init(&sim->mutex_time_to_reflect, NULL); + (void)pthread_mutex_init(&sim->mutex_time_to_eat, NULL); + (void)pthread_mutex_init(&sim->mutex_scheduler, NULL); + (void)pthread_mutex_init(&sim->mutex_forks, NULL); +} + +void init_mutex(t_sim *sim) +{ + init_mutex_philos(sim); + init_mutex_forks(sim); + init_mutex_sim(sim); +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..216e903 --- /dev/null +++ b/src/main.c @@ -0,0 +1,39 @@ +#include "codexion.h" +# include // or atoi(), malloc() + +int main(int argc, char **argv) +{ + t_sim *sim; + t_philo **philos; + t_fork **forks; + int ret; + + if (argc != 9) + { + print_usage(); + return (0); + } + if (!valid_params(argv)) + return (0); + sim = create_sim(argv); + if (sim == NULL) + return (1); + start_timer(sim); + philos = create_arr_philos(sim); + if (philos == NULL) + return (1); + forks = create_arr_forks(sim); + if (forks == NULL) + return (1); + init_mutex(sim); + assign_forks(sim); + assign_philos(sim); + ret = run_threads(sim); + if (ret != 0) + return (1); + destroy_mutex(sim); + free_forks(sim); + free_philos(sim); + free(sim); + return (0); +} diff --git a/src/monitoring.c b/src/monitoring.c new file mode 100644 index 0000000..7c74b4d --- /dev/null +++ b/src/monitoring.c @@ -0,0 +1,44 @@ +#include "codexion.h" +# include // for usleep() + +static int check_if_philos_done(t_sim *sim) +{ + t_philo **philos; + t_philo *philo; + int number_of_philos; + int diff; + + (void)pthread_mutex_lock(&sim->mutex_philos); + philos = sim->philos; + (void)pthread_mutex_unlock(&sim->mutex_philos); + (void)pthread_mutex_lock(&sim->mutex_number_of_philos); + number_of_philos = sim->number_of_philos; + (void)pthread_mutex_unlock(&sim->mutex_number_of_philos); + while (number_of_philos-- > 0) + { + philo = *philos++; + (void)pthread_mutex_lock(&sim->mutex_number_of_eat_required); + (void)pthread_mutex_lock(&philo->mutex_number_of_eats_done); + diff = philo->number_of_eats_done + != sim->number_of_eat_required; + (void)pthread_mutex_unlock(&philo->mutex_number_of_eats_done); + (void)pthread_mutex_unlock(&sim->mutex_number_of_eat_required); + if (diff != 0) + return (0); + } + return (1); +} + +void *monitoring_routine(void *arg) +{ + t_sim *sim; + + sim = (t_sim *)arg; + while (check_if_philos_done(sim) == 0) + { + if (check_for_starves(sim) == 1) + return (NULL); + usleep(100); + } + return (NULL); +} diff --git a/src/philos.c b/src/philos.c new file mode 100644 index 0000000..17cb34d --- /dev/null +++ b/src/philos.c @@ -0,0 +1,83 @@ +#include "codexion.h" +# include // for atoi(), malloc() + +t_philo *create_philo(t_sim *sim) +{ + t_philo *philo; + + philo = NULL; + philo = (t_philo *)malloc(sizeof(t_philo)); + if (!philo) + { + free_philos(sim); + free(sim); + return (NULL); + } + philo->beginning_last_eat_time = 0; + philo->number_of_eats_done = 0; + philo->ticket = 0; + philo->sim = sim; + return (philo); +} + +t_philo **create_arr_philos(t_sim *sim) +{ + t_philo **philos; + t_philo *philo; + int i; + int number_of_philos; + + number_of_philos = sim->number_of_philos; + philos = (t_philo **)malloc(sizeof(t_philo *) * (number_of_philos + 1)); + if (!philos) + { + free(sim); + return (NULL); + } + i = 0; + while (i < number_of_philos) + { + philo = create_philo(sim); + if (!philo) + return (NULL); + philo->id = i + 1; + philos[i++] = philo; + } + sim->number_of_philos_actual = i; + philos[i] = NULL; + sim->philos = philos; + return (philos); +} + +/* this function assigns 2 philos to each forks */ +/* the 'if' is used to assign the last philo to the */ +/* first fork. Then, in the 'else', the i is offset */ +/* by minus 1 to assign the first philo to the second */ +/* fork */ +t_fork **assign_philos(t_sim *sim) +{ + t_fork **forks; + t_philo **philos; + int number_of_philos; + int i; + + forks = sim->forks; + philos = sim->philos; + number_of_philos = sim->number_of_philos; + i = 0; + while (forks[i]) + { + if (i == 0) + { + forks[i]->left_philo = philos[number_of_philos - 1]; + forks[i]->right_philo = philos[i]; + } + else + { + forks[i]->left_philo = philos[i - 1]; + forks[i]->right_philo = philos[(i) % number_of_philos]; + } + i++; + } + return (forks); +} diff --git a/src/print.c b/src/print.c new file mode 100644 index 0000000..db8cf69 --- /dev/null +++ b/src/print.c @@ -0,0 +1,45 @@ +#include "codexion.h" +# include // for printf() + +/* +This functions deal with all log printing activities. Logs are serialized by +usage of mutex_print_log. There are 2 scenarios for printing. The first one +scenarios applies if no philo has starved, the second one only prints if a +philo has starved; that is when flag = 1. +*/ +void print_log(t_philo *philo, char *msg, int flag) +{ + int id; + long start; + t_sim *sim; + + (void)pthread_mutex_lock(&philo->mutex_sim); + sim = philo->sim; + (void)pthread_mutex_unlock(&philo->mutex_sim); + (void)pthread_mutex_lock(&philo->mutex_id); + id = philo->id; + (void)pthread_mutex_unlock(&philo->mutex_id); + (void)pthread_mutex_lock(&philo->sim->mutex_start_time); + start = philo->sim->start_time; + (void)pthread_mutex_unlock(&philo->sim->mutex_start_time); + (void)pthread_mutex_lock(&philo->sim->mutex_print_log); + if (!check_if_philo_starved(sim) && flag == 0) + printf("%d %i %s\n", get_rel_time(sim), id, msg); + else if (flag == 1) + printf("%lu %d %d %s\n", time_ms() - start, get_rel_time(sim), id, msg); + (void)pthread_mutex_unlock(&philo->sim->mutex_print_log); +} + +/* +This function prints usage when the program is ran without parameters +*/ +void print_usage(void) +{ + printf("Usage: $ ./codexion number_of_philos " + "time_to_starve " + "time_to_eat " + "time_to_reflect " + "time_to_think " + "number_of_eats_required " + "fork_cooldown scheduler"); +} diff --git a/src/queue.c b/src/queue.c new file mode 100644 index 0000000..76907d9 --- /dev/null +++ b/src/queue.c @@ -0,0 +1,55 @@ +#include "codexion.h" +# include // for atoi(), malloc() +# include // for printf() + +void heapify(t_fork *fork) +{ + t_ticket t1; + t_ticket t2; + + (void)pthread_mutex_lock(&fork->mutex_pq); + if (fork->pq.size < 2) + { + (void)pthread_mutex_unlock(&fork->mutex_pq); + return ; + } + (void)pthread_mutex_unlock(&fork->mutex_pq); + t1 = fork->pq.items[0]; + t2 = fork->pq.items[1]; + if (t1.num > t2.num) + swap(t1, t2); +} + +void enqueue(t_fork *fork, t_ticket ticket) +{ + int queue_size; + + (void)pthread_mutex_lock(&fork->mutex_pq); + queue_size = fork->pq.size; + (void)pthread_mutex_unlock(&fork->mutex_pq); + if (queue_size == MAX) + { + printf("Priority queue is full\n"); + return ; + } + (void)pthread_mutex_lock(&fork->mutex_pq); + fork->pq.items[fork->pq.size++] = ticket; + (void)pthread_mutex_unlock(&fork->mutex_pq); +} + +void dequeue(t_fork *fork) +{ + int queue_size; + + (void)pthread_mutex_lock(&fork->mutex_pq); + queue_size = fork->pq.size; + (void)pthread_mutex_unlock(&fork->mutex_pq); + if (!queue_size) + { + printf("Priority queue is empty\n"); + return ; + } + (void)pthread_mutex_lock(&fork->mutex_pq); + fork->pq.items[0] = fork->pq.items[--fork->pq.size]; + (void)pthread_mutex_unlock(&fork->mutex_pq); +} diff --git a/src/routine.c b/src/routine.c new file mode 100644 index 0000000..6d867cf --- /dev/null +++ b/src/routine.c @@ -0,0 +1,57 @@ +#include "codexion.h" +# include // for usleep() +# include // for printf() + +static void send_signal(t_fork *fork) +{ + (void)pthread_mutex_lock(&fork->mutex_cond); + pthread_cond_signal(&fork->cond_signal); + (void)pthread_mutex_unlock(&fork->mutex_cond); +} + +static void lock_forks(t_philo *philo, t_fork *f1, + t_fork *f2) +{ + if (get_id(philo) % 2 == 0) + { + (void)pthread_mutex_lock(&f1->mutex); + (void)pthread_mutex_lock(&f2->mutex); + } + else + { + if (philo->number_of_eats_done < 1) + usleep(50); + (void)pthread_mutex_lock(&f2->mutex); + (void)pthread_mutex_lock(&f1->mutex); + } + wait_for_longest_cooldown(philo, f1, f2); +} + +int philo_routine(t_philo *philo, t_fork *f1, + t_fork *f2) +{ + t_sim *sim; + + (void)pthread_mutex_lock(&philo->mutex_sim); + sim = philo->sim; + (void)pthread_mutex_unlock(&philo->mutex_sim); + if (check_if_philo_starved(sim)) + return (1); + if (queue_routine(philo, f1, f2) == 1) + return (1); + if (check_if_philo_starved(sim)) + return (1); + lock_forks(philo, f1, f2); + print_log(philo, "has taken a fork", 0); + print_log(philo, "has taken a fork", 0); + update_last_released(sim, f1, f2); + eat(philo); + (void)pthread_mutex_unlock(&f2->mutex); + dequeue(f2); + send_signal(f2); + (void)pthread_mutex_unlock(&f1->mutex); + dequeue(f1); + send_signal(f1); + reflect_and_think(philo); + return (0); +} diff --git a/src/scheduler.c b/src/scheduler.c new file mode 100644 index 0000000..76c2f8d --- /dev/null +++ b/src/scheduler.c @@ -0,0 +1,86 @@ +#include "codexion.h" +# include // for usleep() +# include // for strcmp() + +static t_ticket take_ticket(t_philo *philo, t_fork *fork) +{ + t_ticket my_ticket; + char *scheduler; + t_sim *sim; + + (void)pthread_mutex_lock(&philo->sim->mutex_scheduler); + scheduler = philo->sim->scheduler; + (void)pthread_mutex_unlock(&philo->sim->mutex_scheduler); + if (strcmp(scheduler, "fifo") == 0) + { + (void)pthread_mutex_lock(&fork->mutex_ticket_next); + my_ticket.num = fork->ticket_next++; + (void)pthread_mutex_unlock(&fork->mutex_ticket_next); + } + if (strcmp(scheduler, "edf") == 0) + { + (void)pthread_mutex_lock(&philo->mutex_sim); + sim = philo->sim; + (void)pthread_mutex_unlock(&philo->mutex_sim); + my_ticket.num = get_rel_time(sim) + sim->time_to_starve; + } + enqueue(fork, my_ticket); + heapify(fork); + return (my_ticket); +} + +int get_first_item_queue(t_fork *fork) +{ + int first_item; + + (void)pthread_mutex_lock(&fork->mutex_pq); + first_item = fork->pq.items[0].num; + (void)pthread_mutex_unlock(&fork->mutex_pq); + return (first_item); +} + +static int is_ticket_first(t_philo *philo, t_fork *f1, + t_fork *f2, t_ticket ticket) +{ + t_sim *sim; + + (void)pthread_mutex_lock(&philo->mutex_sim); + sim = philo->sim; + (void)pthread_mutex_unlock(&philo->mutex_sim); + wait_for_longest_cooldown(philo, f1, f2); + (void)pthread_mutex_lock(&f1->mutex_cond); + while (ticket.num != get_first_item_queue(f1)) + { + if (check_if_philo_starved(sim)) + { + (void)pthread_mutex_unlock(&f1->mutex_cond); + return (1); + } + pthread_cond_wait(&f1->cond_signal, &f1->mutex_cond); + wait_for_longest_cooldown(philo, f1, f2); + } + (void)pthread_mutex_unlock(&f1->mutex_cond); + return (0); +} + +int queue_routine(t_philo *philo, t_fork *f1, t_fork *f2) +{ + t_ticket t1; + t_ticket t2; + //t_sim *sim; + + //(void)pthread_mutex_lock(&philo->mutex_sim); + //sim = philo->sim; + //(void)pthread_mutex_unlock(&philo->mutex_sim); + if (get_id(philo) % 2 != 0 && philo->number_of_eats_done < 1) + { + usleep(100); + } + t1 = take_ticket(philo, f1); + t2 = take_ticket(philo, f2); + if (is_ticket_first(philo, f1, f2, t1) == 1) + return (1); + if (is_ticket_first(philo, f2, f1, t2) == 1) + return (1); + return (0); +} diff --git a/src/sim.c b/src/sim.c new file mode 100644 index 0000000..5b84be9 --- /dev/null +++ b/src/sim.c @@ -0,0 +1,23 @@ +#include "codexion.h" +# include // for atoi(), malloc() + +t_sim *create_sim(char **argv) +{ + t_sim *sim; + + sim = NULL; + sim = (t_sim *)malloc(sizeof(t_sim)); + if (!sim) + return (NULL); + sim->number_of_philos = atoi(argv[1]); + sim->time_to_starve = atoi(argv[2]); + sim->time_to_eat = atoi(argv[3]); + sim->time_to_reflect = atoi(argv[4]); + sim->time_to_think = atoi(argv[5]); + sim->number_of_eat_required = atoi(argv[6]); + sim->philo_starved = 0; + sim->fork_cooldown = atoi(argv[7]); + sim->scheduler = argv[8]; + sim->start_time = 0; + return (sim); +} diff --git a/src/starve.c b/src/starve.c new file mode 100644 index 0000000..3dba831 --- /dev/null +++ b/src/starve.c @@ -0,0 +1,84 @@ +#include "codexion.h" +# include // for printf() + +static void broadcast_signals(t_sim *sim) +{ + t_fork **forks; + t_fork *fork; + int number_of_philos; + + (void)pthread_mutex_lock(&sim->mutex_forks); + forks = sim->forks; + (void)pthread_mutex_unlock(&sim->mutex_forks); + (void)pthread_mutex_lock(&sim->mutex_number_of_philos); + number_of_philos = sim->number_of_philos; + (void)pthread_mutex_unlock(&sim->mutex_number_of_philos); + while (number_of_philos-- > 0) + { + fork = *forks++; + (void)pthread_mutex_lock(&fork->mutex_cond); + pthread_cond_broadcast(&fork->cond_signal); + (void)pthread_mutex_unlock(&fork->mutex_cond); + } +} + +/* Computes a philo's time until he/she burns out */ +int time_until_starve(t_philo *philo) +{ + int time_until_starve; + int time_to_starve; + int beginning_last_eat_time; + t_sim *sim; + + (void)pthread_mutex_lock(&philo->mutex_sim); + sim = philo->sim; + (void)pthread_mutex_unlock(&philo->mutex_sim); + (void)pthread_mutex_lock(&sim->mutex_time_to_starve); + time_to_starve = sim->time_to_starve; + (void)pthread_mutex_unlock(&sim->mutex_time_to_starve); + (void)pthread_mutex_lock(&philo->mutex_beginning_last_eat_time); + beginning_last_eat_time = philo->beginning_last_eat_time; + (void)pthread_mutex_unlock(&philo->mutex_beginning_last_eat_time); + time_until_starve = time_to_starve - (get_rel_time(sim) + - beginning_last_eat_time); + return (time_until_starve); +} + +int check_if_philo_starved(t_sim *sim) +{ + int starved_status; + + (void)pthread_mutex_lock(&sim->mutex_philo_starved); + starved_status = sim->philo_starved; + (void)pthread_mutex_unlock(&sim->mutex_philo_starved); + return (starved_status); +} + +int check_for_starves(t_sim *sim) +{ + t_philo **philos; + t_philo *philo; + int number_of_philos; + + (void)pthread_mutex_lock(&sim->mutex_philos); + philos = sim->philos; + (void)pthread_mutex_unlock(&sim->mutex_philos); + philo = *philos; + (void)pthread_mutex_lock(&sim->mutex_number_of_philos); + number_of_philos = sim->number_of_philos; + (void)pthread_mutex_unlock(&sim->mutex_number_of_philos); + while (number_of_philos-- > 0) + { + philo = *philos++; + if (time_until_starve(philo) == 0) + { + (void)pthread_mutex_lock(&sim->mutex_philo_starved); + sim->philo_starved = 1; + (void)pthread_mutex_unlock(&sim->mutex_philo_starved); + print_log(philo, "starved", 1); + broadcast_signals(sim); + return (1); + } + } + return (0); +} diff --git a/src/threads.c b/src/threads.c new file mode 100644 index 0000000..4d8776d --- /dev/null +++ b/src/threads.c @@ -0,0 +1,93 @@ +#include "codexion.h" +# include // for atoi(), malloc() + +void *routine(void *arg) +{ + t_philo *philo; + int number_of_eat_required; + + philo = (t_philo *)arg; + if (philo->sim->number_of_philos == 1) + { + print_log(philo, "has taken a fork", 0); + return (0); + } + (void)pthread_mutex_lock(&philo->sim->mutex_number_of_eat_required); + number_of_eat_required = philo->sim->number_of_eat_required; + (void)pthread_mutex_unlock(&philo->sim->mutex_number_of_eat_required); + while (philo->number_of_eats_done != number_of_eat_required) + { + (void)pthread_mutex_lock(&philo->sim->mutex_number_of_eat_required); + number_of_eat_required = philo->sim->number_of_eat_required; + (void)pthread_mutex_unlock(&philo->sim->mutex_number_of_eat_required); + if (philo_routine(philo, philo->right_fork, philo->left_fork) != 0) + return (NULL); + } + return (0); +} + +int create_threads(t_sim *sim) +{ + t_philo **philos; + int number_of_philos; + t_philo *philo; + + philos = sim->philos; + number_of_philos = sim->number_of_philos; + if (pthread_create(&sim->monitor_thread, NULL, monitoring_routine, + sim) != 0) + { + free_philos(sim); + free(sim); + return (1); + } + while (number_of_philos-- > 0) + { + philo = *philos++; + if (pthread_create(&philo->thread_id, NULL, routine, philo) != 0) + { + free_philos(sim); + free(sim); + return (1); + } + } + return (0); +} + +int join_threads(t_sim *sim) +{ + t_philo **philos; + t_philo *philo; + int threads; + + philos = sim->philos; + threads = sim->number_of_philos; + while (threads-- > 0) + { + philo = *philos++; + if (pthread_join(philo->thread_id, NULL) != 0) + { + free_philos(sim); + free_forks(sim); + free(sim); + return (1); + } + } + if (pthread_join(sim->monitor_thread, NULL) != 0) + { + free_philos(sim); + free_forks(sim); + free(sim); + return (1); + } + return (0); +} + +int run_threads(t_sim *sim) +{ + if (create_threads(sim) != 0) + return (1); + if (join_threads(sim) != 0) + return (1); + return (0); +} diff --git a/src/time.c b/src/time.c new file mode 100644 index 0000000..76f3528 --- /dev/null +++ b/src/time.c @@ -0,0 +1,29 @@ +#include "codexion.h" +# include // for getimeofday() + +long time_ms(void) +{ + long current_time_ms; + struct timeval current_t; + + gettimeofday(¤t_t, NULL); + current_time_ms = current_t.tv_sec * 1000L + current_t.tv_usec / 1000L; + return (current_time_ms); +} + +void start_timer(t_sim *sim) +{ + sim->start_time = time_ms(); +} + +int get_rel_time(t_sim *sim) +{ + int current_rel_time; + long start_time; + + (void)pthread_mutex_lock(&sim->mutex_start_time); + start_time = sim->start_time; + (void)pthread_mutex_unlock(&sim->mutex_start_time); + current_rel_time = time_ms() - start_time; + return (current_rel_time); +} diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..e409f7d --- /dev/null +++ b/src/utils.c @@ -0,0 +1,20 @@ +#include "codexion.h" + +void swap(t_ticket a, t_ticket b) +{ + t_ticket temp; + + temp = a; + a = b; + b = temp; +} + +int get_id(t_philo *philo) +{ + int id; + + (void)pthread_mutex_lock(&philo->mutex_id); + id = philo->id; + (void)pthread_mutex_unlock(&philo->mutex_id); + return (id); +} diff --git a/src/utils_routine.c b/src/utils_routine.c new file mode 100644 index 0000000..37e3f3d --- /dev/null +++ b/src/utils_routine.c @@ -0,0 +1,81 @@ +#include "codexion.h" +# include // for printf() +# include // for usleep() + +void eat(t_philo *philo) +{ + t_sim *sim; + + (void)pthread_mutex_lock(&philo->mutex_sim); + sim = philo->sim; + (void)pthread_mutex_unlock(&philo->mutex_sim); + (void)pthread_mutex_lock(&philo->mutex_beginning_last_eat_time); + philo->beginning_last_eat_time = get_rel_time(sim); + (void)pthread_mutex_unlock(&philo->mutex_beginning_last_eat_time); + print_log(philo, "is eating", 0); + usleep(philo->sim->time_to_eat * 1000); + (void)pthread_mutex_lock(&philo->mutex_number_of_eats_done); + philo->number_of_eats_done++; + (void)pthread_mutex_unlock(&philo->mutex_number_of_eats_done); +} + +void reflect_and_think(t_philo *philo) +{ + print_log(philo, "is reflecting", 0); + usleep(philo->sim->time_to_reflect * 1000); + print_log(philo, "is thinking", 0); + usleep(philo->sim->time_to_think * 1000); +} + +int wait_for_fork(t_philo *philo, t_fork *fork) +{ + int cooldown; + int wait; + int last_released; + t_sim *sim; + + (void)pthread_mutex_lock(&philo->mutex_sim); + sim = philo->sim; + (void)pthread_mutex_unlock(&philo->mutex_sim); + (void)pthread_mutex_lock(&philo->sim->mutex_cooldown); + cooldown = philo->sim->fork_cooldown; + (void)pthread_mutex_unlock(&philo->sim->mutex_cooldown); + (void)pthread_mutex_lock(&fork->mutex_last_released); + last_released = fork->last_released; + (void)pthread_mutex_unlock(&fork->mutex_last_released); + wait = cooldown - (get_rel_time(sim) - last_released); + return (wait); +} + +void wait_for_longest_cooldown(t_philo *philo, t_fork *f1, t_fork *f2) +{ + int w1; + int w2; + int wait; + + wait = 0; + if (get_id(philo) % 2 != 0 && philo->number_of_eats_done < 1) + usleep(50); + w1 = wait_for_fork(philo, f1); + w2 = wait_for_fork(philo, f2); + if (w1 >= w2 && w1 > 0) + wait = w1; + else if (w2 >= w1 && w2 > 0) + wait = w2; + usleep(wait * 1000); +} + +void update_last_released(t_sim *sim, t_fork *f1, t_fork *f2) +{ + int time_to_eat; + + (void)pthread_mutex_lock(&sim->mutex_time_to_eat); + time_to_eat = sim->time_to_eat; + (void)pthread_mutex_unlock(&sim->mutex_time_to_eat); + (void)pthread_mutex_lock(&f1->mutex_last_released); + f1->last_released = get_rel_time(sim) + time_to_eat; + (void)pthread_mutex_unlock(&f1->mutex_last_released); + (void)pthread_mutex_lock(&f2->mutex_last_released); + f2->last_released = get_rel_time(sim) + time_to_eat; + (void)pthread_mutex_unlock(&f2->mutex_last_released); +} diff --git a/src/validate_parameters.c b/src/validate_parameters.c new file mode 100644 index 0000000..9f09250 --- /dev/null +++ b/src/validate_parameters.c @@ -0,0 +1,30 @@ +#include "codexion.h" +# include // for atoi(), malloc() +# include // for strlen() +# include // for printf() + +int valid_params(char **argv) +{ + int i; + + if (atoi(argv[1]) < 1) + { + printf("Not enough philos\n"); + return (0); + } + i = 2; + while (i <= 7) + { + if (atoi(argv[i++]) < 0) + { + printf("Input cannot be negative\n"); + return (0); + } + } + if (strcmp(argv[8], "fifo") != 0 && strcmp(argv[8], "edf") != 0) + { + printf("Scheduler must be either 'fifo' or 'edf'\n"); + return (0); + } + return (1); +} -- cgit v1.2.3