diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..e10d105 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,33 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug philo", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/philo/philo", + "args": [ + "5", "800", "200", "200", "7" + ], + "stopAtEntry": false, + "cwd": "${workspaceFolder}/philo", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "build philo", + "miDebuggerPath": "/usr/bin/gdb", + "logging": { + "moduleLoad": false, + "trace": false + }, + "internalConsoleOptions": "openOnSessionStart" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index e69de29..58a7db6 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -0,0 +1,20 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build philo", + "type": "shell", + "command": "make", + "args": [ + "-C", + "philo" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": ["$gcc"], + "detail": "Build the philo project using the Makefile" + } + ] +} \ No newline at end of file diff --git a/philo/Makefile b/philo/Makefile index e772ede..a2a4c72 100644 --- a/philo/Makefile +++ b/philo/Makefile @@ -14,12 +14,10 @@ NAME = philo SRC_PATH = src INC_PATH = inc - OBJ_PATH = obj VPATH = src:src/utils SOURCES = $(shell basename -a $(shell find $(SRC_PATH) -type f -name "*.c")) - OBJECTS = $(addprefix $(OBJ_PATH)/, $(SOURCES:.c=.o)) DEPENDS = ${OBJECTS:.o=.d} @@ -27,7 +25,7 @@ CC = cc RM = rm -rf INCLUDES = -I./$(INC_PATH) -CFLAGS = -Wall -Wextra -Werror -MMD +CFLAGS = -Wall -Wextra -Werror -MMD -g UNAME_S := $(shell uname -s) ifeq ($(UNAME_S),Linux) diff --git a/philo/inc/philo.h b/philo/inc/philo.h index e58f18e..949fe08 100644 --- a/philo/inc/philo.h +++ b/philo/inc/philo.h @@ -12,6 +12,8 @@ # define SUCCESS 1 # define FAILURE 0 +# define START_DELAY 500 + # define ERROR_USAGE "Usage: ./philo number_of_philosophers time_to_die " \ "time_to_eat time_to_sleep [number_of_times_each_philosopher_must_eat]\n" # define ERROR_MUTEX "Can not create mutex" @@ -25,10 +27,10 @@ typedef struct s_rules int time_to_eat; int time_to_sleep; int n_must_eat; - int death; + int finished; int start_time; pthread_mutex_t *print_lock; - pthread_mutex_t *death_lock; + pthread_mutex_t *finished_lock; pthread_mutex_t *forks; struct s_philo *philos; @@ -64,10 +66,9 @@ void print_status(t_philo *philo, char *status); void *philo_routine(void *philo); int join_threads(t_rules *rules); void print_rules(t_rules *rules); -int check_alive(t_philo *philo); - - - - +int check_death(t_philo *philo); +void philo_die(t_philo *philo); +int philo_died_while_sleeping(t_philo *philo, int time); +int philo_eat(t_philo *philo); #endif \ No newline at end of file diff --git a/philo/philo b/philo/philo index 2de1e7f..8ce4455 100755 Binary files a/philo/philo and b/philo/philo differ diff --git a/philo/src/check_alive.c b/philo/src/check_alive.c index 96555c6..d6d29f7 100644 --- a/philo/src/check_alive.c +++ b/philo/src/check_alive.c @@ -1,17 +1,7 @@ #include "philo.h" -int check_alive(t_philo *philo) +int check_death(t_philo *philo) { - if (get_time() - philo->last_meal > philo->rules->time_to_die) - { - print_status(philo, "died"); - philo->death = 1; - pthread_mutex_lock(philo->rules->death_lock); - philo->rules->death = 1; - pthread_mutex_unlock(philo->rules->death_lock); - pthread_mutex_unlock(philo->l_fork); - pthread_mutex_unlock(philo->r_fork); - return (FAILURE); - } - return (SUCCESS); -} \ No newline at end of file + return (get_time() - philo->last_meal >= philo->rules->time_to_die); +} + diff --git a/philo/src/create_mutexes.c b/philo/src/create_mutexes.c index edf94af..699e9ba 100644 --- a/philo/src/create_mutexes.c +++ b/philo/src/create_mutexes.c @@ -6,7 +6,7 @@ int create_mutexes(t_rules *rules) i = 0; printf("creating mutexes\n"); - if (pthread_mutex_init(rules->death_lock, NULL)) + if (pthread_mutex_init(rules->finished_lock, NULL)) return(printf("death mutex created"), FAILURE); if (pthread_mutex_init(rules->print_lock, NULL)) return(printf("print mutex created"), FAILURE); diff --git a/philo/src/create_philos.c b/philo/src/create_philos.c index c0cf919..08a8a76 100644 --- a/philo/src/create_philos.c +++ b/philo/src/create_philos.c @@ -18,7 +18,7 @@ int create_philos(t_rules *rules) philo->death = 0; philo->pid = 0; philo->rules = rules; - philo->last_meal = get_time(); + philo->last_meal = get_time() + START_DELAY; i++; } return (SUCCESS); diff --git a/philo/src/destroy_mutexes.c b/philo/src/destroy_mutexes.c index 89a7a89..e446f94 100644 --- a/philo/src/destroy_mutexes.c +++ b/philo/src/destroy_mutexes.c @@ -5,7 +5,7 @@ int destroy_mutexes(t_rules *rules) int i; i = 0; - if (pthread_mutex_destroy(rules->death_lock)) + if (pthread_mutex_destroy(rules->finished_lock)) return(FAILURE); if (pthread_mutex_destroy(rules->print_lock)) return(FAILURE); diff --git a/philo/src/free_philos.c b/philo/src/free_philos.c index 1950c1d..cc493fb 100644 --- a/philo/src/free_philos.c +++ b/philo/src/free_philos.c @@ -5,5 +5,5 @@ void free_philos(t_rules *rules) free(rules->philos); free(rules->forks); free(rules->print_lock); - free(rules->death_lock); + free(rules->finished_lock); } \ No newline at end of file diff --git a/philo/src/main.c b/philo/src/main.c index 7aba7cc..20da70c 100644 --- a/philo/src/main.c +++ b/philo/src/main.c @@ -13,13 +13,13 @@ int main(int argc, char *argv[]) if (FAILURE == create_mutexes(&rules)) return (printf(ERROR_MUTEX), EXIT_FAILURE); printf("mutexes created\n"); - rules.start_time = get_time(); + rules.start_time = get_time() + START_DELAY; if (FAILURE == create_threads(&rules)) return (printf(ERROR_THREADS), EXIT_FAILURE); printf("threads created\n"); if (FAILURE == join_threads(&rules)) return (printf(ERROR_THREADS), EXIT_FAILURE); - + printf("threads joined\n"); if (FAILURE == destroy_mutexes(&rules)) return (printf(ERROR_MUTEX), EXIT_FAILURE); printf("mutexes destroyed\n"); diff --git a/philo/src/monitor_death.c b/philo/src/monitor_death.c deleted file mode 100644 index 9835129..0000000 --- a/philo/src/monitor_death.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "philo.h" - -void *monitor_death(void *arg) -{ - int i; - t_rules *rules; - - rules = (t_rules *) i = 0; - while (i < rules->n_philos) - if (rules->philos[i].last_meal - get_time() < rules->time_to_die) - -} \ No newline at end of file diff --git a/philo/src/parse_arguments.c b/philo/src/parse_arguments.c index 19131d7..4dae160 100644 --- a/philo/src/parse_arguments.c +++ b/philo/src/parse_arguments.c @@ -17,8 +17,8 @@ int parse_arguments(int argc,char *argv[], t_rules *rules) if (argc == 6 && !ph_atoi(argv[5], &rules->n_must_eat)) return (FAILURE); rules->print_lock = malloc(sizeof(pthread_mutex_t)); - rules->death_lock = malloc(sizeof(pthread_mutex_t)); - if (!rules->print_lock || !rules->death_lock) + rules->finished_lock = malloc(sizeof(pthread_mutex_t)); + if (!rules->print_lock || !rules->finished_lock) return (FAILURE); rules->forks = malloc(rules->n_philos * sizeof(pthread_mutex_t)); if (!rules->forks) diff --git a/philo/src/philo_routine.c b/philo/src/philo_routine.c index 79daba7..f2807e1 100644 --- a/philo/src/philo_routine.c +++ b/philo/src/philo_routine.c @@ -1,36 +1,86 @@ #include "philo.h" +void set_finished(t_rules *rules) +{ + pthread_mutex_lock(rules->finished_lock); + rules->finished = 1; + pthread_mutex_unlock(rules->finished_lock); +} + +int get_finished(t_rules *rules) +{ + int finished; + + pthread_mutex_lock(rules->finished_lock); + finished = rules->finished; + pthread_mutex_unlock(rules->finished_lock); + return (finished); +} +void philo_die(t_philo *philo) +{ + print_status(philo, "died 💀"); + philo->death = 1; + set_finished(philo->rules); + pthread_mutex_unlock(philo->l_fork); + pthread_mutex_unlock(philo->r_fork); +} + +int philo_died_while_sleeping(t_philo *philo, int time) +{ + const int start = get_time(); + while(get_time() - start < time) + { + if (philo->last_meal - get_time() >= philo->rules->time_to_die) + return (SUCCESS); + usleep(500); + } + return (FAILURE); +} +int philo_eat(t_philo *philo) +{ + if (philo->id % 2 == 1) + { + pthread_mutex_lock(philo->r_fork); + print_status(philo, "has taken a fork 🍴"); + } + pthread_mutex_lock(philo->l_fork); + print_status(philo, "has taken a fork 🍴"); + if (philo->id % 2 == 0) + { + pthread_mutex_lock(philo->r_fork); + print_status(philo, "has taken a fork 🍴"); + } + if (check_death(philo)) + return (philo_die(philo), FAILURE); + print_status(philo, "is eating 🍝"); + philo->last_meal = get_time(); + philo->n_eat++; + return (SUCCESS); +} void *philo_routine(void *arg) { t_philo *philo; philo = (t_philo *)arg; - while (!philo->death && !philo->rules->death + + while (get_time() < philo->rules->start_time) + usleep(50); + while (!philo->death && !philo->rules->finished && (philo->n_eat < philo->rules->n_must_eat || philo->rules->n_must_eat == -1)) { - if (philo->id % 2 == 1) - { - pthread_mutex_lock(philo->r_fork); - print_status(philo, "has taken a fork"); - } - pthread_mutex_lock(philo->l_fork); - print_status(philo, "has taken a fork"); - if (philo->id % 2 == 0) - { - pthread_mutex_lock(philo->r_fork); - print_status(philo, "has taken a fork"); - } - if (!check_alive(philo)) - break ; - print_status(philo, "is eating"); - philo->last_meal = get_time(); - philo->n_eat++; - usleep(philo->rules->time_to_eat * 1000); + + if (check_death(philo)) + return (philo_die(philo), NULL); + if (!philo_eat(philo)) + return (NULL); + if (philo_died_while_sleeping(philo, philo->rules->time_to_eat)) + return (philo_die(philo), NULL); pthread_mutex_unlock(philo->l_fork); pthread_mutex_unlock(philo->r_fork); - print_status(philo, "is sleeping"); - usleep(philo->rules->time_to_sleep * 1000); - print_status(philo, "is thinking"); + print_status(philo, "is sleeping 💤"); + if (philo_died_while_sleeping(philo, philo->rules->time_to_sleep)) + return (philo_die(philo), NULL); + print_status(philo, "is thinking 💭"); } return (NULL); } \ No newline at end of file diff --git a/philo/src/get_time.c b/philo/src/utils/get_time.c similarity index 100% rename from philo/src/get_time.c rename to philo/src/utils/get_time.c diff --git a/philo/src/print_rules.c b/philo/src/utils/print_rules.c similarity index 100% rename from philo/src/print_rules.c rename to philo/src/utils/print_rules.c diff --git a/philo/src/print_status.c b/philo/src/utils/print_status.c similarity index 100% rename from philo/src/print_status.c rename to philo/src/utils/print_status.c