Skip to content

Commit

Permalink
make error printing thread-safe, test all error case (no thread issue…
Browse files Browse the repository at this point in the history
…s, no memory issues etc.), add script for testing usleep() performance
  • Loading branch information
Alexander Schenk committed Oct 12, 2024
1 parent 3f64304 commit ab36924
Show file tree
Hide file tree
Showing 16 changed files with 172 additions and 107 deletions.
24 changes: 15 additions & 9 deletions philo/include/philo.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* By: aschenk <aschenk@student.42berlin.de> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/08/14 19:21:56 by aschenk #+# #+# */
/* Updated: 2024/10/11 22:11:17 by aschenk ### ########.fr */
/* Updated: 2024/10/12 14:39:21 by aschenk ### ########.fr */
/* */
/* ************************************************************************** */

Expand Down Expand Up @@ -81,7 +81,6 @@ the risk of starvation among others while still prioritizing their own needs.
// 1_check_args.c

int check_args(int argc, char **argv);
int simulate_single_philo(t_sim *sim);

// 2_init_philos.c

Expand All @@ -97,15 +96,22 @@ int pick_forks_and_log(t_philo *philo);
int eat_and_log(t_philo *philo, int t_eat);
int is_philo_full(t_philo *philo, int max_meals);

// 3_run_sim.c
// 3_eat_sleep_think.c

int run_sim(t_sim *sim);
void *eat_sleep_think(void *arg);

// X_dining.c
// 4_monitor.c

void *eat_sleep_think(void *arg);
void *monitor(void *arg);

// 5_run_sim_utils.c

int simulate_single_philo(t_sim *sim);

// 5_run_sim.c

int run_sim(t_sim *sim);

// utils/0_libft.c

int ft_atoi(const char *str);
Expand All @@ -119,12 +125,12 @@ int print_action(t_ull timestamp, t_philo *philo, t_action action,

// utils/1_print_error.c

void print_err_msg(char *msg);
void print_err_msg(char *msg, t_sim *sim);
void print_usage(void);

// utils/2_mutex.c

int mtx_action(t_mtx *mutex, t_mtx_action action);
int mtx_action(t_mtx *mutex, t_mtx_action action, t_sim *sim);

// utils/3_time.c

Expand All @@ -133,7 +139,7 @@ int set_start_time(t_sim *sim);
int record_time_of_death(t_philo *philo);
int precise_wait(int duration_to_wait);

// utils/X_free.c
// utils/4_free.c

void cleanup_sim(t_sim **sim_ptr);

Expand Down
33 changes: 32 additions & 1 deletion philo/include/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* By: aschenk <aschenk@student.42berlin.de> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/09/19 17:19:12 by aschenk #+# #+# */
/* Updated: 2024/10/11 23:38:34 by aschenk ### ########.fr */
/* Updated: 2024/10/12 14:21:55 by aschenk ### ########.fr */
/* */
/* ************************************************************************** */

Expand All @@ -21,6 +21,37 @@ This header file defines custom types and data structures.

typedef pthread_mutex_t t_mtx; // Abbreviation for 'pthread_mutex_t'
typedef unsigned long long t_ull; // Abbreviation for 'unsigned long long'

/**
Structure representing the overall simulation state:
- nr_philo: Total number of philosophers participating in the simulation.
- t_die: Time in milliseconds after which a philosopher dies if they
haven't start eating.
- t_eat: Time in milliseconds a philosopher takes to eat.
- t_sleep: Time in milliseconds a philosopher sleeps after eating.
- t_think: Philosophers are altruistic in this simulation, meaning they
delay taking forks and eating for as long as possible without
starving. This behavior helps keep every philosopher alive as
long as possible, especially when there's an odd number of
philosophers: t_think = t_die - t_eat - t_sleep.
- max_meals: Max. number of meals a philosopher can eat before they stop
dining; `-1` means unlimited meals.
- full_philos: The number of philosophers who have eaten their maximum number
of meals (if specified) and have stopped eating.
- stop_sim: Flag indicating if to stop the simulation.
- t_start_sim: Timestamp in milliseconds for when the simulation started.
- forks: Array of forks available for the philosophers.
- philos: Array of philosophers participating in the simulation.
- monitor: Thread handle for the monitoring thread that observes the
state of the simulation.
- mtx_print: Mutex for synchronizing output to the console (printing).
- mtx_print_init: Flag checking if 'print' mutex has been initialized.
- mtx_full_philos: Mutex for checking / increasing 'full_philos'.
- mtx_full_philos_init: Flag checking if 'full_philos' mutex has been
initialized.
- mtx_stop_sim: Mutex for synchronizing access to the `stop_sim` flag.
- mtx_stop_sim_init: Flag checking if 'stop_sim' mutex has been initialized.
*/
typedef struct s_sim t_sim;

/**
Expand Down
7 changes: 3 additions & 4 deletions philo/src/1_check_args.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* By: aschenk <aschenk@student.42berlin.de> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/09/10 16:27:51 by aschenk #+# #+# */
/* Updated: 2024/10/11 22:07:13 by aschenk ### ########.fr */
/* Updated: 2024/10/12 15:24:43 by aschenk ### ########.fr */
/* */
/* ************************************************************************** */

Expand All @@ -22,7 +22,6 @@ and usage instructions.
// IN FILE:

int check_args(int argc, char **argv);
int simulate_lonely_philo(t_sim *sim);

/**
Converts a string to an integer and validates the input.
Expand Down Expand Up @@ -54,7 +53,7 @@ static int check_arg_count(int argc)
{
if (argc < 5 || argc > 6)
{
print_err_msg(ERR_ARGS_NR);
print_err_msg(ERR_ARGS_NR, NULL);
print_usage();
return (1);
}
Expand All @@ -76,7 +75,7 @@ static int check_phil_nr(char *arg)
return (2);
if (ft_atoi(arg) < 1)
{
print_err_msg(ERR_ARGS_MIN_P);
print_err_msg(ERR_ARGS_MIN_P, NULL);
print_usage();
return (1);
}
Expand Down
8 changes: 4 additions & 4 deletions philo/src/2_init_philos.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* By: aschenk <aschenk@student.42berlin.de> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/11 17:43:15 by aschenk #+# #+# */
/* Updated: 2024/10/11 18:20:11 by aschenk ### ########.fr */
/* Updated: 2024/10/12 15:35:58 by aschenk ### ########.fr */
/* */
/* ************************************************************************** */

Expand Down Expand Up @@ -40,7 +40,7 @@ static int initialize_philosopher(t_philo *philo, t_sim *sim, int index,
philo->right_fork = &sim->forks[(index + 1) % nr_philo];
philo->odd = (philo->id % 2 == 1);
philo->mtx_last_meal_init = 0;
if (mtx_action(&philo->mtx_last_meal, INIT))
if (mtx_action(&philo->mtx_last_meal, INIT, sim))
return (1);
philo->mtx_last_meal_init = 1;
return (0);
Expand All @@ -65,7 +65,7 @@ int init_philos(t_sim *sim)
sim->philos = malloc(sizeof(t_philo) * nr_philo);
if (!sim->philos)
{
print_err_msg(ERR_MALLOC);
print_err_msg(ERR_MALLOC, sim);
return (1);
}
i = 0;
Expand All @@ -74,7 +74,7 @@ int init_philos(t_sim *sim)
if (initialize_philosopher(&sim->philos[i], sim, i, nr_philo))
{
while (i > 0)
mtx_action(&sim->philos[--i].mtx_last_meal, DESTROY);
(void)mtx_action(&sim->philos[--i].mtx_last_meal, DESTROY, sim);
free(sim->philos);
sim->philos = NULL;
return (1);
Expand Down
19 changes: 10 additions & 9 deletions philo/src/2_init_sim.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* By: aschenk <aschenk@student.42berlin.de> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/09/05 13:53:20 by aschenk #+# #+# */
/* Updated: 2024/10/11 23:39:03 by aschenk ### ########.fr */
/* Updated: 2024/10/12 15:42:41 by aschenk ### ########.fr */
/* */
/* ************************************************************************** */

Expand Down Expand Up @@ -63,17 +63,18 @@ static int init_sim_state(t_sim *sim, int argc, char **argv)
sim->forks = NULL;
sim->philos = NULL;
sim->mtx_print_init = 0;
sim->mtx_full_philos_init = 0;
sim->mtx_stop_sim_init = 0;
if (init_args(sim, argc, argv))
return (1);
sim->t_think = sim->t_die - sim->t_eat - sim->t_sleep;
if (mtx_action(&sim->mtx_print, INIT))
if (mtx_action(&sim->mtx_print, INIT, NULL))
return (1);
if (mtx_action(&sim->mtx_full_philos, INIT))
sim->mtx_print_init = 1;
if (mtx_action(&sim->mtx_full_philos, INIT, sim))
return (1);
sim->mtx_full_philos_init = 1;
sim->mtx_print_init = 1;
if (mtx_action(&sim->mtx_stop_sim, INIT))
if (mtx_action(&sim->mtx_stop_sim, INIT, sim))
return (1);
sim->mtx_stop_sim_init = 1;
return (0);
Expand All @@ -97,16 +98,16 @@ static int init_forks(t_sim *sim)
sim->forks = malloc(sizeof(t_fork) * nr_philo);
if (!sim->forks)
{
print_err_msg(ERR_MALLOC);
print_err_msg(ERR_MALLOC, sim);
return (1);
}
i = 0;
while (i < nr_philo)
{
if (mtx_action(&sim->forks[i].fork, INIT))
if (mtx_action(&sim->forks[i].fork, INIT, sim))
{
while (i > 0)
mtx_action(&sim->forks[--i].fork, DESTROY);
(void)mtx_action(&sim->forks[--i].fork, DESTROY, sim);
free(sim->forks);
sim->forks = NULL;
return (1);
Expand All @@ -133,7 +134,7 @@ int init_sim(t_sim **sim, int argc, char **argv)
*sim = malloc(sizeof(t_sim));
if (!(*sim))
{
print_err_msg(ERR_MALLOC);
print_err_msg(ERR_MALLOC, *sim);
return (1);
}
if (init_sim_state(*sim, argc, argv))
Expand Down
28 changes: 14 additions & 14 deletions philo/src/3_eat.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* By: aschenk <aschenk@student.42berlin.de> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/11 16:23:15 by aschenk #+# #+# */
/* Updated: 2024/10/11 23:30:19 by aschenk ### ########.fr */
/* Updated: 2024/10/12 15:45:19 by aschenk ### ########.fr */
/* */
/* ************************************************************************** */

Expand Down Expand Up @@ -43,22 +43,22 @@ static int pick_forks(t_philo *philo)
{
if (philo->odd)
{
if (mtx_action(&philo->left_fork->fork, LOCK))
if (mtx_action(&philo->left_fork->fork, LOCK, philo->sim))
return (1);
if (print_action(0, philo, FORK_L, 1))
return (1);
if (mtx_action(&philo->right_fork->fork, LOCK))
if (mtx_action(&philo->right_fork->fork, LOCK, philo->sim))
return (1);
if (print_action(0, philo, FORK_R, 1))
return (1);
}
else
{
if (mtx_action(&philo->right_fork->fork, LOCK))
if (mtx_action(&philo->right_fork->fork, LOCK, philo->sim))
return (1);
if (print_action(0, philo, FORK_R, 1))
return (1);
if (mtx_action(&philo->left_fork->fork, LOCK))
if (mtx_action(&philo->left_fork->fork, LOCK, philo->sim))
return (1);
if (print_action(0, philo, FORK_L, 1))
return (1);
Expand Down Expand Up @@ -106,16 +106,16 @@ static int drop_forks(t_philo *philo)
{
if (philo->odd)
{
if (mtx_action(&philo->right_fork->fork, UNLOCK))
if (mtx_action(&philo->right_fork->fork, UNLOCK, philo->sim))
return (1);
if (mtx_action(&philo->left_fork->fork, UNLOCK))
if (mtx_action(&philo->left_fork->fork, UNLOCK, philo->sim))
return (1);
}
else
{
if (mtx_action(&philo->left_fork->fork, UNLOCK))
if (mtx_action(&philo->left_fork->fork, UNLOCK, philo->sim))
return (1);
if (mtx_action(&philo->right_fork->fork, UNLOCK))
if (mtx_action(&philo->right_fork->fork, UNLOCK, philo->sim))
return (1);
}
return (0);
Expand All @@ -140,19 +140,19 @@ ensuring that resources are properly released.
int eat_and_log(t_philo *philo, int t_eat)
{
philo->meals_eaten++;
if (mtx_action(&philo->mtx_last_meal, LOCK))
if (mtx_action(&philo->mtx_last_meal, LOCK, philo->sim))
{
drop_forks(philo);
return (1);
}
philo->t_last_meal = get_time();
if (philo->t_last_meal == 0)
{
mtx_action(&philo->mtx_last_meal, UNLOCK);
(void)mtx_action(&philo->mtx_last_meal, UNLOCK, philo->sim);
drop_forks(philo);
return (1);
}
if (mtx_action(&philo->mtx_last_meal, UNLOCK)
if (mtx_action(&philo->mtx_last_meal, UNLOCK, philo->sim)
|| print_action(0, philo, EAT, 1) || precise_wait(t_eat))
{
drop_forks(philo);
Expand Down Expand Up @@ -180,10 +180,10 @@ int is_philo_full(t_philo *philo, int max_meals)
{
if (philo->meals_eaten != max_meals)
return (0);
if (mtx_action(&philo->sim->mtx_full_philos, LOCK))
if (mtx_action(&philo->sim->mtx_full_philos, LOCK, philo->sim))
return (2);
philo->sim->full_philos++;
if (mtx_action(&philo->sim->mtx_full_philos, UNLOCK))
if (mtx_action(&philo->sim->mtx_full_philos, UNLOCK, philo->sim))
return (2);
if (FANCY && print_action(0, philo, STUFFED, 1))
return (2);
Expand Down
13 changes: 7 additions & 6 deletions philo/src/3_eat_sleep_think.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
/* By: aschenk <aschenk@student.42berlin.de> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/05 18:47:34 by aschenk #+# #+# */
/* Updated: 2024/10/11 23:41:10 by aschenk ### ########.fr */
/* Updated: 2024/10/12 14:46:18 by aschenk ### ########.fr */
/* */
/* ************************************************************************** */

/**
Defines the core functions involved in a philosopher's life cycle during the
dining simulation. It includes routines for eating, sleeping, and thinking,
as well as checks for stopping the simulation when a philosopher dies or
as well as checks for stopping the simulation when a philosopher dies or
reaches the maximum number of meals.
*/

Expand All @@ -37,10 +37,10 @@ static int stop_sim(t_philo *philo)
{
int dead;

if (mtx_action(&philo->sim->mtx_stop_sim, LOCK))
if (mtx_action(&philo->sim->mtx_stop_sim, LOCK, philo->sim))
return (2);
dead = philo->sim->stop_sim;
if (mtx_action(&philo->sim->mtx_stop_sim, UNLOCK))
if (mtx_action(&philo->sim->mtx_stop_sim, UNLOCK, philo->sim))
return (2);
return (dead);
}
Expand Down Expand Up @@ -118,8 +118,9 @@ The function first checks if the philosopher has zero meals to eat.
If not, the philosopher repeatedly attempts to eat, sleep, and think until the
simulation detects a death or the philosopher is full.
Error handling is not checked intentionally, as this falls outside the
project's scope and can be somewhat tedious when dealing with thread routines.
Error handling is intentionally omitted, as it falls outside the project's
scope and would be cumbersome due to the project's limitations (cannot use
`pthread_exit()`).
@param arg A void pointer cast to the `t_philo` struct representing
the philosopher.
Expand Down
Loading

0 comments on commit ab36924

Please sign in to comment.