diff --git a/philo/Makefile b/philo/Makefile index d9cd37c..d65e4a9 100644 --- a/philo/Makefile +++ b/philo/Makefile @@ -1,26 +1,26 @@ -NAME = philosophers +NAME = philo -SRCS = philo_threads.c philo_launcher.c philo_utils.c -OBJS = ${SRCS:.c=.o} +SRCS = philo.c philo_init.c philo_life.c philo_utils.c +OBJS = ${SRCS:.c=.o} -CC = clang -CFLAGS = -Werror -Wextra -Wall -g -D_REENTRANT -RM = rm -rf +CC = clang +CFLAGS = -Werror -Wextra -Wall -g -D_REENTRANT +RM = rm -rf -.c.o: - $(CC) $(CFLAGS) -c $< -o $(<:.c=.o) +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $(<:.c=.o) -all: $(NAME) +all : $(NAME) -$(NAME): $(OBJS) - ${CC} ${CFLAGS} -lpthread ${OBJS} -o ${NAME} +$(NAME) : $(OBJS) + $(CC) $(CFLAGS) -lpthread $(OBJS) -o $(NAME) -clean: - ${RM} ${OBJS} +clean : + $(RM) $(OBJS) -fclean: clean - ${RM} ${NAME} +fclean : clean + $(RM) $(NAME) -re: fclean all +re : fclean all -.PHONY: all clean fclean re +.PHONY : all clean fclean re diff --git a/philo/philo.c b/philo/philo.c new file mode 100644 index 0000000..7dafe04 --- /dev/null +++ b/philo/philo.c @@ -0,0 +1,88 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* philo.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: narnaud@student.42nice.fr +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2022/05/19 00:36:57 by narnaud@stude #+# #+# */ +/* Updated: 2022/05/19 00:47:15 by narnaud@stude ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "philo.h" + +static int waiter(t_room *room, t_philo *philo); +static int clean_memory(t_room *room, t_philo *philos); + +int main(int argc, char **argv) +{ + t_room *room; + t_philo *philos; + + if (argc < 5 || argc > 6) + return (EXIT_FAILURE); + room = create_room(argv + 1); + philos = create_philos(room); + invit_philos(philos); + while (waiter(room, philos)) + usleep(1000); + pthread_mutex_lock(room->lock); + room->running = 0; + pthread_mutex_unlock(room->lock); + sleep(2); + return (clean_memory(room, philos)); +} + +static int waiter(t_room *room, t_philo *philo) +{ + int starvest; + int ret; + + ret = 1; + pthread_mutex_lock(room->lock); + starvest = room->param[MEALS_AMOUNT]; + while (ret && philo->id >= 0) + { + pthread_mutex_lock(philo->lock); + if (philo->eat_time + room->param[DIE_TIME] < room_clock()) + { + safe_print(philo, "%d %d died\n"); + ret = 0; + } + if (philo->eat_amount < starvest) + starvest = philo->eat_amount; + pthread_mutex_unlock(philo->lock); + philo++; + } + pthread_mutex_unlock(room->lock); + if (starvest == room->param[MEALS_AMOUNT]) + ret = 0; + return (ret); +} + +static int clean_memory(t_room *room, t_philo *philos) +{ + static int i = 0; + + pthread_mutex_lock(room->lock); + while (i < room->param[PHILO_AMOUNT]) + { + pthread_mutex_lock(philos[i].lock); + pthread_mutex_unlock(philos[i].lock); + pthread_mutex_destroy(philos[i].lock); + pthread_mutex_lock(philos[i].fork); + pthread_mutex_unlock(philos[i].fork); + pthread_mutex_destroy(philos[i].fork); + free(philos[i].lock); + free(philos[i].thd); + i++; + } + pthread_mutex_unlock(room->lock); + pthread_mutex_destroy(room->lock); + free(room->lock); + free(room->forks); + free(philos); + free(room); + return (0); +} diff --git a/philo/philosophers.h b/philo/philo.h similarity index 61% rename from philo/philosophers.h rename to philo/philo.h index e98c901..9f8d9d2 100644 --- a/philo/philosophers.h +++ b/philo/philo.h @@ -1,19 +1,17 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* philosophers.h :+: :+: :+: */ +/* philo.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: narnaud +#+ +:+ +#+ */ +/* By: narnaud@student.42nice.fr +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2021/11/24 15:44:06 by narnaud #+# #+# */ -/* Updated: 2022/05/18 19:26:02 by narnaud@stude ### ########.fr */ +/* Created: 2022/05/18 22:23:52 by narnaud@stude #+# #+# */ +/* Updated: 2022/05/19 00:42:59 by narnaud@stude ### ########.fr */ /* */ /* ************************************************************************** */ -#ifndef PHILOSOPHERS_H -# define PHILOSOPHERS_H -# define CLOCK_ONE 500 -# define CLOCK_TWO 1000 +#ifndef PHILO_H +# define PHILO_H # include # include @@ -22,8 +20,8 @@ # include # include -enum e_params -{ +enum e_params +{ PHILO_AMOUNT, DIE_TIME, EAT_DURATION, @@ -31,30 +29,37 @@ enum e_params MEALS_AMOUNT, }; +typedef struct s_room +{ + int param[5]; + pthread_mutex_t *lock; + pthread_mutex_t *forks; + int running; +} t_room; + typedef struct s_philo { + t_room *room; pthread_mutex_t *fork; + pthread_mutex_t *fork_r; + pthread_mutex_t *next; pthread_mutex_t *lock; pthread_t *thd; int eat_time; int eat_amount; - int i; + int id; } t_philo; -typedef struct s_room -{ - int param[5]; - t_philo **philos; - pthread_mutex_t *lock; - int running; - int i; -} t_room; - -int waiter(t_room *room); +// ---------------------------------- philo_init +t_room *create_room(char **argv); +t_philo *create_philos(t_room *room); +void invit_philos(t_philo *philos); -void *philos_birth(void *r); +// ---------------------------------- philo_life +void *philos_life(void *r); -int safe_print(char *str, t_room *room, int id); +// ---------------------------------- philo_utils +int safe_print(t_philo *philo, char *str); int safe_wait(t_room *room, int start, int duration); int room_clock(); int mini_atoi(char *nbr); diff --git a/philo/philo_init.c b/philo/philo_init.c new file mode 100644 index 0000000..5272209 --- /dev/null +++ b/philo/philo_init.c @@ -0,0 +1,82 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* philo_init.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: narnaud +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2021/11/24 15:44:04 by narnaud #+# #+# */ +/* Updated: 2022/05/19 00:47:38 by narnaud@stude ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "philo.h" + +t_room *create_room(char **argv) +{ + t_room *room; + + room = malloc(sizeof(t_room)); + room->param[PHILO_AMOUNT] = mini_atoi(argv[0]); + room->param[DIE_TIME] = mini_atoi(argv[1]); + room->param[EAT_DURATION] = mini_atoi(argv[2]); + room->param[SLEEP_DURATION] = mini_atoi(argv[3]); + if (argv[4]) + room->param[MEALS_AMOUNT] = mini_atoi(argv[4]); + else + room->param[MEALS_AMOUNT] = 2147483647; + room->lock = malloc(sizeof(pthread_mutex_t)); + room->forks = (pthread_mutex_t *)malloc( + (room->param[PHILO_AMOUNT]) * sizeof(pthread_mutex_t)); + pthread_mutex_init(room->lock, NULL); + room->running = 1; + return (room); +} + +t_philo *create_philos(t_room *room) +{ + t_philo *ret; + static int i; + + ret = (t_philo *)malloc((room->param[PHILO_AMOUNT] + 1) * sizeof(t_philo)); + while (i < room->param[PHILO_AMOUNT]) + { + ret[i].fork = &room->forks[i]; + ret[i].fork_r = &room->forks[(i + 1) % room->param[PHILO_AMOUNT]]; + ret[i].lock = malloc(sizeof(pthread_mutex_t)); + ret[i].thd = malloc(sizeof(pthread_t)); + ret[i].room = room; + ret[i].eat_time = room_clock(); + ret[i].eat_amount = 0; + ret[i].id = i; + pthread_mutex_init(ret[i].fork, NULL); + pthread_mutex_init(ret[i++].lock, NULL); + } + ret[i].id = -1; + return (ret); +} + +void invit_philos(t_philo *philos) +{ + static int i; + t_room *room; + t_philo *philo; + + philo = philos; + room = philo->room; + while (i >= 0) + { + pthread_create(philo->thd, NULL, philos_life, (void *)philo); + pthread_detach(*philo->thd); + usleep(100); + if ((i % 2) == 0) + { + i += 2; + if (i >= room->param[PHILO_AMOUNT]) + i -= 1 + (room->param[PHILO_AMOUNT] % 2) * 2; + } + else if ((i % 2) == 1) + i -= 2; + philo = philos + i; + } +} diff --git a/philo/philo_launcher.c b/philo/philo_launcher.c deleted file mode 100644 index 7397eae..0000000 --- a/philo/philo_launcher.c +++ /dev/null @@ -1,120 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* philo_launcher.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: narnaud +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2021/11/24 15:44:04 by narnaud #+# #+# */ -/* Updated: 2022/05/18 19:27:01 by narnaud@stude ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "philosophers.h" - -void init_param(t_room *room, char **argv); -static t_room *init_room(char **argv); -static int clean_memory(t_room *room); - -int main(int argc, char **argv) -{ - t_room *room; - - if (argc < 5 || argc > 6) - return (1); - room = init_room(argv + 1); - while (room->i >= 0) - { - pthread_create(room->philos[room->i]->thd, NULL, \ - philos_birth, (void *)room); - pthread_detach(*room->philos[room->i]->thd); - usleep(100); - pthread_mutex_lock(room->lock); - if ((room->i % 2) == 0) - { - room->i += 2; - if (room->i >= room->param[PHILO_AMOUNT]) - room->i -= 1 + (room->param[PHILO_AMOUNT] % 2) * 2; - } - else if ((room->i % 2) == 1) - room->i -= 2; - pthread_mutex_unlock(room->lock); - } - while (waiter(room)) - usleep(CLOCK_TWO); - pthread_mutex_lock(room->lock); - room->running = 0; - pthread_mutex_unlock(room->lock); - sleep(2); - return (clean_memory(room)); -} - -void init_param(t_room *room, char **argv) -{ - room->param[PHILO_AMOUNT] = mini_atoi(argv[0]); - room->param[DIE_TIME] = mini_atoi(argv[1]); - room->param[EAT_DURATION] = mini_atoi(argv[2]); - room->param[SLEEP_DURATION] = mini_atoi(argv[3]); - if (argv[4]) - room->param[MEALS_AMOUNT] = mini_atoi(argv[4]); - else - room->param[MEALS_AMOUNT] = 2147483647; -} - -static t_room *init_room(char **argv) -{ - t_room *room; - static int i = 0; - - room = malloc(sizeof(t_room)); - init_param(room, argv); - room->lock = malloc(sizeof(pthread_mutex_t)); - pthread_mutex_init(room->lock, NULL); - room->philos = \ - (t_philo **)malloc(room->param[PHILO_AMOUNT] * sizeof(t_philo *)); - room->running = 1; - room->i = 0; - while (i < room->param[PHILO_AMOUNT]) - { - room->philos[i] = (t_philo *)malloc(sizeof(t_philo)); - room->philos[i]->fork = malloc(sizeof(pthread_mutex_t)); - room->philos[i]->lock = malloc(sizeof(pthread_mutex_t)); - room->philos[i]->thd = malloc(sizeof(pthread_t)); - room->philos[i]->eat_time = room_clock(); - room->philos[i]->eat_amount = 0; - room->philos[i]->i = i; - pthread_mutex_init(room->philos[i]->fork, NULL); - pthread_mutex_init(room->philos[i++]->lock, NULL); - } - return (room); -} - -static int clean_memory(t_room *room) -{ - int *param; - static int i = 0; - - pthread_mutex_lock(room->lock); - param = room->param; - while (i < param[PHILO_AMOUNT]) - { - - pthread_mutex_lock(room->philos[i]->lock); - pthread_mutex_unlock(room->philos[i]->lock); - pthread_mutex_destroy(room->philos[i]->lock); - pthread_mutex_lock(room->philos[i]->fork); - pthread_mutex_unlock(room->philos[i]->fork); - pthread_mutex_destroy(room->philos[i]->fork); - free(room->philos[i]->lock); - free(room->philos[i]->fork); - free(room->philos[i]->thd); - free(room->philos[i]); - i++; - } - pthread_mutex_unlock(room->lock); - pthread_mutex_destroy(room->lock); - free(room->lock); - free(room->philos); - free(room); - return (0); -} diff --git a/philo/philo_life.c b/philo/philo_life.c new file mode 100644 index 0000000..5abf433 --- /dev/null +++ b/philo/philo_life.c @@ -0,0 +1,60 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* philo_life.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: narnaud +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2021/11/26 07:43:48 by narnaud #+# #+# */ +/* Updated: 2022/05/19 00:48:41 by narnaud@stude ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "philo.h" + +static int eat(t_room *room, t_philo *philo) +{ + pthread_mutex_lock(philo->fork); + if (!safe_print(philo, "%d %d has taken a fork\n")) + return (1); + pthread_mutex_lock(philo->fork_r); + safe_print(philo, "%d %d has taken a fork\n"); + if (!safe_print(philo, "%d %d is eating\n")) + return (2); + pthread_mutex_lock(philo->lock); + philo->eat_time = room_clock(); + pthread_mutex_unlock(philo->lock); + if (!safe_wait(room, room_clock(), EAT_DURATION)) + return (2); + pthread_mutex_unlock(philo->fork); + pthread_mutex_unlock(philo->fork_r); + pthread_mutex_lock(philo->lock); + philo->eat_amount++; + pthread_mutex_unlock(philo->lock); + return (0); +} + +void *philos_life(void *ph) +{ + t_philo *philo; + int stop; + + philo = (t_philo *)ph; + while (1) + { + stop = eat(philo->room, philo); + if (stop) + break ; + if (!safe_print(philo, "%d %d is sleeping\n")) + break ; + if (!safe_wait(philo->room, room_clock(), SLEEP_DURATION)) + break ; + if (!safe_print(philo, "%d %d is thinking\n")) + break ; + } + if (stop--) + pthread_mutex_unlock(philo->fork); + if (stop--) + pthread_mutex_unlock(philo->fork_r); + return (NULL); +} diff --git a/philo/philo_threads.c b/philo/philo_threads.c deleted file mode 100644 index d2e05a8..0000000 --- a/philo/philo_threads.c +++ /dev/null @@ -1,101 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* philo_threads.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: narnaud +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2021/11/26 07:43:48 by narnaud #+# #+# */ -/* Updated: 2022/05/18 19:22:57 by narnaud@stude ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "philosophers.h" - -int waiter(t_room *room) -{ - int *param; - int i; - int starvest; - t_philo *philo; - int ret; - - ret = 1; - pthread_mutex_lock(room->lock); - i = 0; - param = room->param; - starvest = param[MEALS_AMOUNT]; - while (ret && i < param[PHILO_AMOUNT]) - { - philo = room->philos[i]; - pthread_mutex_lock(philo->lock); - if (philo->eat_time + param[DIE_TIME] < room_clock()) - { - printf("%d %d died\n", room_clock(), i); - ret = 0; - } - if (philo->eat_amount < starvest) - starvest = philo->eat_amount; - pthread_mutex_unlock(philo->lock); - i++; - } - pthread_mutex_unlock(room->lock); - if (starvest == param[MEALS_AMOUNT]) - ret = 0; - return (ret); -} - -static int philo_life(t_room *room, t_philo *philo, int id, int id_p, int *param) -{ - pthread_mutex_lock(philo->fork); - if (!safe_print("%d %d has taken a fork\n", room, id)) - return (1); - pthread_mutex_lock(room->philos[id_p]->fork); - safe_print("%d %d has taken a fork\n", room, id); - if(!safe_print("%d %d is eating\n", room, id)) - return (2); - pthread_mutex_lock(philo->lock); - philo->eat_time = room_clock(); - pthread_mutex_unlock(philo->lock); - if (!safe_wait(room, room_clock(), param[EAT_DURATION])) - return (2); - pthread_mutex_unlock(philo->fork); - pthread_mutex_unlock(room->philos[id_p]->fork); - if(!safe_print("%d %d is sleeping\n", room, id)) - return (-1); - pthread_mutex_lock(philo->lock); - philo->eat_amount++; - pthread_mutex_unlock(philo->lock); - if (!safe_wait(room, room_clock(), param[SLEEP_DURATION])) - return (-1); - if (!safe_print("%d %d is thinking\n", room, id)) - return (-1); - return (0); -} - -void *philos_birth(void *r) -{ - t_room *room; - int *param; - t_philo *philo; - int id; - int id_p; - int stop; - - stop = 0; - room = (t_room *)r; - param = room->param; - pthread_mutex_lock(room->lock); - id = room->i; - philo = room->philos[id]; - philo->eat_time = room_clock(); - id_p = (id + 1) % param[PHILO_AMOUNT]; - pthread_mutex_unlock(room->lock); - while (!stop) - stop = philo_life(room, philo, id, id_p, param); - if (stop-- > 0) - pthread_mutex_unlock(philo->fork); - if (stop-- > 0) - pthread_mutex_unlock(room->philos[id_p]->fork); - return (NULL); -} diff --git a/philo/philo_utils.c b/philo/philo_utils.c index 7c6adde..3017bbe 100644 --- a/philo/philo_utils.c +++ b/philo/philo_utils.c @@ -6,29 +6,32 @@ /* By: narnaud@student.42nice.fr +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/05/18 19:10:41 by narnaud@stude #+# #+# */ -/* Updated: 2022/05/18 19:27:30 by narnaud@stude ### ########.fr */ +/* Updated: 2022/05/19 00:50:56 by narnaud@stude ### ########.fr */ /* */ /* ************************************************************************** */ -#include "philosophers.h" +#include "philo.h" int is_running(t_room *room) { int ret; - + pthread_mutex_lock(room->lock); ret = room->running; pthread_mutex_unlock(room->lock); return (ret); } -int safe_print(char *str, t_room *room, int id) +int safe_print(t_philo *philo, char *str) { int ret; - ret = is_running(room); + + ret = is_running(philo->room); if (!ret) return (0); - printf(str, room_clock(), id); + pthread_mutex_lock(philo->room->lock); + printf(str, room_clock(), philo->id); + pthread_mutex_unlock(philo->room->lock); return (ret); } @@ -37,7 +40,8 @@ int safe_wait(t_room *room, int start, int duration) int ret; ret = is_running(room); - while (ret && (room_clock() < (start + duration))) + while (ret && (room_clock() + < (start + room->param[duration]))) { ret = is_running(room); usleep(50); @@ -45,15 +49,15 @@ int safe_wait(t_room *room, int start, int duration) return (ret); } -int room_clock() +int room_clock(void) { struct timeval time; - int ret; + int ret; static long int start_time = 0; gettimeofday(&time, NULL); if (!start_time) - start_time = time.tv_sec * 1000 + time.tv_usec / 1000; + start_time = time.tv_sec * 1000 + time.tv_usec / 1000; ret = (int)(time.tv_sec * 1000 + time.tv_usec / 1000 - start_time); return (ret); } @@ -68,5 +72,5 @@ int mini_atoi(char *nbr) ret = (*nbr - '0') + (10 * ret); nbr++; } -return (ret); + return (ret); }