summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoryctct <yctct@yctct.com>2026-09-13 18:58:14 +0200
committeryctct <yctct@yctct.com>2026-09-13 18:58:14 +0200
commit47beba686ff9d2aab63738fba7176a5235703d05 (patch)
treef839ed36a9e9d4476fcdc59379b17903abfa35c8 /src
Add all files, first commit
Diffstat (limited to 'src')
-rw-r--r--src/destroy.c66
-rw-r--r--src/forks.c75
-rw-r--r--src/free_memory.c38
-rw-r--r--src/init.c66
-rw-r--r--src/main.c39
-rw-r--r--src/monitoring.c44
-rw-r--r--src/philos.c83
-rw-r--r--src/print.c45
-rw-r--r--src/queue.c55
-rw-r--r--src/routine.c57
-rw-r--r--src/scheduler.c86
-rw-r--r--src/sim.c23
-rw-r--r--src/starve.c84
-rw-r--r--src/threads.c93
-rw-r--r--src/time.c29
-rw-r--r--src/utils.c20
-rw-r--r--src/utils_routine.c81
-rw-r--r--src/validate_parameters.c30
18 files changed, 1014 insertions, 0 deletions
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 <stdlib.h> // 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 <stdlib.h> // 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 <stdlib.h> // 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 <unistd.h> // 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 <stdlib.h> // 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 <stdio.h> // 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 <stdlib.h> // for atoi(), malloc()
+# include <stdio.h> // 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 <unistd.h> // for usleep()
+# include <stdio.h> // 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 <unistd.h> // for usleep()
+# include <string.h> // 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 <stdlib.h> // 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 <stdio.h> // 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 <stdlib.h> // 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 <sys/time.h> // for getimeofday()
+
+long time_ms(void)
+{
+ long current_time_ms;
+ struct timeval current_t;
+
+ gettimeofday(&current_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 <stdio.h> // for printf()
+# include <unistd.h> // 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 <stdlib.h> // for atoi(), malloc()
+# include <string.h> // for strlen()
+# include <stdio.h> // 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);
+}