diff --git a/Makefile b/Makefile index c5a4a67..cc57f9f 100644 --- a/Makefile +++ b/Makefile @@ -1,21 +1,21 @@ -SRCS = philo/main.c philo/parsing.c philo/philo.c philo/threads.c +SRCS = mandatory/main.c mandatory/parsing.c mandatory/philo.c mandatory/threads.c SRCS_BONUS = OBJS = ${SRCS:.c=.o} OBJS_BONUS = ${SRCS_BONUS:.c=.o} UTILS = utils/utils.a CC = clang CFLAGS = -g -Wall -Wextra -Werror -pthread -NAME = philosopher +NAME = philo all: ${NAME} ${NAME}: ${OBJS} make -C utils - ${CC} ${CFLAGS} -o ${NAME} ${OBJS} ${UTILS} + ${CC} ${CFLAGS} -o ${NAME} ${OBJS} ${UTILS} bonus: ${OBJS_BONUS} make -C utils - ${CC} ${CFLAGS} -o ${NAME} ${OBJS_BONUS} ${UTILS} + ${CC} ${CFLAGS} -o ${NAME} ${OBJS_BONUS} ${UTILS} clean: rm -f ${OBJS} diff --git a/philo/.philo.c.swp b/mandatory/.philo.c.swp similarity index 100% rename from philo/.philo.c.swp rename to mandatory/.philo.c.swp diff --git a/philo/main.c b/mandatory/main.c similarity index 100% rename from philo/main.c rename to mandatory/main.c diff --git a/mandatory/main.o b/mandatory/main.o new file mode 100644 index 0000000..3331701 Binary files /dev/null and b/mandatory/main.o differ diff --git a/philo/parsing.c b/mandatory/parsing.c similarity index 100% rename from philo/parsing.c rename to mandatory/parsing.c diff --git a/mandatory/parsing.o b/mandatory/parsing.o new file mode 100644 index 0000000..1da745b Binary files /dev/null and b/mandatory/parsing.o differ diff --git a/philo/philo.c b/mandatory/philo.c similarity index 100% rename from philo/philo.c rename to mandatory/philo.c diff --git a/philo/philo.h b/mandatory/philo.h similarity index 83% rename from philo/philo.h rename to mandatory/philo.h index 99815f2..8e2f3ee 100644 --- a/philo/philo.h +++ b/mandatory/philo.h @@ -18,6 +18,9 @@ # include # include # include +# include +# include +# include typedef struct s_config { @@ -28,11 +31,24 @@ typedef struct s_config int must_eat; } t_config; +typedef struct s_same +{ + t_config *config; + pthread_mutex_t *mutex; + long long *time; + int *death; + +} t_same; + +typedef struct s_only +{ + int *id; +} t_only; + typedef struct s_philo { - t_config conf; - pthread_mutex_t mutex; - int *id; + t_same *same; + t_only *only; } t_philo; int parsing(char *argv[], t_config *conf); diff --git a/mandatory/philo.o b/mandatory/philo.o new file mode 100644 index 0000000..2602361 Binary files /dev/null and b/mandatory/philo.o differ diff --git a/mandatory/threads.c b/mandatory/threads.c new file mode 100644 index 0000000..7b0f7e8 --- /dev/null +++ b/mandatory/threads.c @@ -0,0 +1,194 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* threads.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: erey-bet +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/03/08 20:08:33 by erey-bet #+# #+# */ +/* Updated: 2023/03/13 18:33:50 by erey-bet ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "philo.h" + +long get_usec(long long time) +{ + return (time % 1000000); +} + + +void *philosopher(t_philo *philo) +{ + long long *time; + long long last_eat_time; + int id; + int next_id; + + time = philo->same->time; + id = *philo->only->id; + next_id = (*philo->only->id + 1) % philo->same->config->nbr_philo; + while (*time <= 0) + ; + usleep((*philo->only->id % 2)); + last_eat_time = *time; + while (1) + { + printf("%ld %d is thinking\n" , get_usec(*time), id); + if (!*philo->same->death && !pthread_mutex_lock(&philo->same->mutex[id])) + { + // printf("%ld %d is taking %d fork\n" , get_usec(*time), id, id); + if (!*philo->same->death && !pthread_mutex_lock(&philo->same->mutex[next_id])) + { + //printf("%ld %d is taking %d fork\n" , get_usec(*time), id, next_id); + printf("%ld %d is eating\n" , get_usec(*time), id); + last_eat_time = *time; + if (*time - last_eat_time + philo->same->config->time_eat >= philo->same->config->time_die || *philo->same->death) + { + printf("%lld | %d dieing 1\n",*time - last_eat_time, id); + break; + } + else + usleep(philo->same->config->time_eat); + printf("after eat last_eat_time: %lld\n" , *time - last_eat_time); + pthread_mutex_unlock(&philo->same->mutex[next_id]); + pthread_mutex_unlock(&philo->same->mutex[id]); + printf("%ld %d is sleeping\n" , get_usec(*time), id); + if (*time - last_eat_time + philo->same->config->time_sleep >= philo->same->config->time_die || *philo->same->death) + { + printf("%lld | %d dieing 2\n",*time - last_eat_time, id); + break; + } + else + usleep(philo->same->config->time_sleep); + printf("after sleep last_eat_time: %lld\n" , *time - last_eat_time); + } + else + pthread_mutex_unlock(&philo->same->mutex[id]); + } + if (*time - last_eat_time >= philo->same->config->time_die || *philo->same->death) + { + printf("%lld | %d dieing 3\n",*time - last_eat_time, id); + break; + } + } + if (!*philo->same->death) + { + *philo->same->death = 1; + printf("%ld %d died\n" , get_usec(*time), id); + } + //else + //printf("%ld %d stop\n" , get_usec(*time), id); + return (NULL); +} + +void init_mutex(pthread_mutex_t *mutex, int nbr) +{ + int i; + + i = -1; + while (++i < nbr) + pthread_mutex_init(&mutex[i], NULL); +} + +void destroy_mutex(pthread_mutex_t *mutex, int nbr) +{ + int i; + + i = -1; + while (++i < nbr) + pthread_mutex_destroy(&mutex[i]); +} + +long long get_time() +{ + struct timeval time; + long long new_time; + + gettimeofday(&time, NULL); + new_time = time.tv_sec * 1000000; + new_time += time.tv_usec; + return (new_time); +} + +void *timer(t_philo *timer) +{ + *timer->same->time = get_time(); + while (!*timer->same->death) + *timer->same->time = get_time(); + return (NULL); +} + +t_same *create_struct_same(t_config *config) +{ + t_same *same; + pthread_mutex_t *mutex; + long long *time; + int *death; + + same = ft_calloc(sizeof(t_same), 1); + time = ft_calloc(sizeof(long long), 1); + mutex = ft_calloc(sizeof(pthread_mutex_t), config->nbr_philo + 1); + init_mutex(mutex, config->nbr_philo + 1); + same->config = config; + same->mutex = mutex; + same->time = time; + death = ft_calloc(sizeof(int), 1); + *death = 0; + same->death = death; + return (same); +} + +t_only *create_struct_only(int id) +{ + t_only *only; + int *id_alloc; + + only = ft_calloc(sizeof(t_only), 1); + id_alloc = ft_calloc(sizeof(int), 1); + *id_alloc = id; + only->id = id_alloc; + return (only); +} + +t_philo *init_philo(t_same *same, t_only *only) +{ + t_philo *philo; + + philo = ft_calloc(sizeof(t_philo), 1); + philo->same = same; + philo->only = only; + return (philo); +} + +int manage_threads(t_config *config) +{ + pthread_t *threads; + t_same *same; + int i; + + threads = ft_calloc(config->nbr_philo + 1, sizeof(pthread_t)); + if (threads == NULL) + return (1); + same = create_struct_same(config); + pthread_create(&threads[0], NULL, (void *)&timer, init_philo(same, create_struct_only(-1))); + i = -1; + while (++i < config->nbr_philo) + { + if (pthread_create(&threads[i + 1], NULL, (void *)&philosopher, init_philo(same, create_struct_only(i))) != 0) + { + write(2, "Error thread creation\n", 21); + return (1); + } + } + while (--i > -1) + { + if (pthread_join(threads[i], NULL) != 0) + { + write(2, "Error thread finish\n", 20); + return (1); + } + } + destroy_mutex(same->mutex, 3); + return (0); +} diff --git a/mandatory/threads.o b/mandatory/threads.o new file mode 100644 index 0000000..dc84aee Binary files /dev/null and b/mandatory/threads.o differ diff --git a/philo b/philo new file mode 100755 index 0000000..c944b3f Binary files /dev/null and b/philo differ diff --git a/philo/threads.c b/philo/threads.c deleted file mode 100644 index 44573e9..0000000 --- a/philo/threads.c +++ /dev/null @@ -1,64 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* threads.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: erey-bet +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2023/03/08 20:08:33 by erey-bet #+# #+# */ -/* Updated: 2023/03/13 18:33:50 by erey-bet ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "philo.h" -#include - -void *philosopher(t_philo *philo) -{ - pthread_mutex_lock(&philo->mutex); - write(1, "Hey i'm ", 8); - ft_putnbr_fd(*philo->id, 1); - write(1, "\n", 1); - pthread_mutex_unlock(&philo->mutex); - return (NULL); -} - -int manage_threads(t_config *config) -{ - pthread_t *threads; - pthread_mutex_t mutex_first_fork; - pthread_mutex_t mutex_second_fork; - pthread_mutex_t mutex_dead; - t_philo *philo; - int i; - - threads = malloc(config->nbr_philo * sizeof(pthread_t)); - if (threads == NULL) - return (1); - pthread_mutex_init(&mutex, NULL); - philo = ft_calloc(sizeof(t_philo), 1); - if (!philo) - return (1); - philo->conf = *config; - philo->mutex = mutex; - i = -1; - while (++i < config->nbr_philo) - { - philo->id = &i; - if (pthread_create(&threads[i], NULL, (void *)&philosopher, philo) != 0) - { - write(2, "Error thread creation\n", 21); - return (1); - } - } - while (--i > -1) - { - if (pthread_join(threads[i], NULL) != 0) - { - write(2, "Error thread finish\n", 20); - return (1); - } - } - pthread_mutex_destroy(&mutex); - return (0); -} diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..48ffe08 --- /dev/null +++ b/start.sh @@ -0,0 +1,227 @@ +#!/bin/zsh + +echo ' _____ _ _ _ _ _____ _ +| _ | |_|_| |___ ___ ___ ___| |_ ___ ___ ___ |_ _|__ ___| |_ ___ ___ +| __| | | | . |_ -| . | . | | -_| _|_ -| | || -_|_ -| _| -_| _| +|__| |_|_|_|_|___|___|___| _|_|_|___|_| |___| |_||___|___|_| |___|_| + |_| ' + +if [ "$#" -ne 2 ]; then + echo "Usage: start.sh " + echo "\tType 0: test philo, and philo_bonus" + echo "\tType 1: test philo only" + echo "\tType 2: test philo_bonus only" + + exit +fi + +if [ "$2" -gt 2 -o "$2" -lt 0 ]; then + echo "[Error]: Wrong Arguments" + exit +fi + +echo "\e[92m[+] Given Folder: $1" +echo "[+] Test Type: $2\e[0m\n" +echo "\e[94m[+] In Case of a failed test, please check ./errors_log file for more information\e[0m\n" + +error_log () +{ + echo "[$1-$2]: $3" >> ./errors_log +} + +test_one () +{ + ("$2/$1" 4 310 200 100 > "./log_$1")& + sleep 5 + pkill $1 + output=$(grep died -m 1 "./log_$1" | awk '{print $NF}') + if [ "$output" = "died" ];then + echo "\e[92m[+] Test #1 Succeeded !\e[0m" + else + echo "\e[91m[+] Test #1 Failed !\e[0m" + error_log $1 "Test #1" "Given 4 310 200 100 arguments to $1, a philosopher should die !" + fi + rm -rf "./log_$1" +} + +test_two () +{ + echo "\e[94m[+] Test #2: Executing your program for 180 second, please wait...\e[0m" + ("$2/$1" 4 410 200 200 > /dev/null)& + i=1 + error=0 + while [ $i -lt 180 ];do + printf "\r[%d...]" $i + pgrep $1 > /dev/null + if [ "$?" -ne 0 ];then + echo "\r\e[91m[+] Test #2 Failed\e[0m" + error_log $1 "Test #2" "Given 4 410 200 200 arguments to $1, no philosopher should die !" + error=1 + break + fi + sleep 1 + i=$(( $i + 1 )) + done + sleep 1 + if [ $error -eq 0 ];then + pkill $1 + echo "\r\e[92m[+] Test #2 Succeeded\e[0m" + fi +} + +test_three () +{ + echo "\e[94m[+] Test #3: Executing your program for 180 second, please wait...\e[0m" + ("$2/$1" 5 800 200 200 > /dev/null)& + i=1 + error=0 + while [ $i -lt 180 ];do + printf "\r[%d...]" $i + pgrep $1 > /dev/null + if [ "$?" -ne 0 ];then + echo "\r\e[91m[+] Test #3 Failed\e[0m" + error_log $1 "Test #3" "Given 4 800 200 200 arguments to $1, no philosopher should die !" + error=1 + break + fi + sleep 1 + i=$(( $i + 1 )) + done + sleep 1 + if [ $error -eq 0 ];then + pkill $1 + echo "\r\e[92m[+] Test #3 Succeeded\e[0m" + fi +} + +test_four () +{ + ("$2/$1" 4 410 200 200 $3 > "./log_$1")& + sleep 10 + pgrep $1 > /dev/null + if [ "$?" -eq 1 ];then + lines=$(grep eating "./log_$1" | wc -l) + if [ $lines -ge $4 ];then + echo "\t\e[92m[+] Test #4-$5 Succeeded\e[0m" + else + echo "\t\e[91m[+] Test #4-$5 Failed\e[0m" + error_log $1 "Test #4" "Given 4 410 200 200 $3 arguments to $1, $1 should only be stopped if each philosopher ate at least $3 times !" + fi + else + echo "\t\e[91m[+] Test #4-$5 Failed\e[0m" + error_log $1 "Test #4" "Given 4 410 200 200 $3 arguments to $1, $1 should stop !" + pkill $1 + fi + rm -rf "./log_$1" +} + +test_five () +{ + echo "\e[94m[+] Test #5 on progress, please wait...\e[0m" + i=1 + t=0 + error=0 + while [ $i -le 10 ];do + ("$2/$1" 2 60 60 60 > "./log_$1")& + sleep 2 + pgrep $1 > /dev/null + if [ "$?" -eq 1 ];then + printf "\r[%d/10]" $i + tmp=$(grep died -m 1 "./log_$1" | awk '{print $1}' | sed 's/[^0-9]*//g') + if [ $i -gt 1 ];then + x=$(expr $tmp - $t) + x=${x#-} + if [ $x -gt 10 ];then + printf "\r\e[91m[+] Test #5 Failed\e[0m\n" + error_log $1 "Test #5" "Given 2 60 60 60 arguments to $1, the time difference of each death shouldn't be bigger than 10ms !" + error=1 + break + fi + else + t=$tmp + fi + else + printf "\r\e[91m[+] Test #5 Failed\e[0m\n" + error_log $1 "Test #5" "Given 2 60 60 60 arguments to $1, a philosopher should die !" + pkill $1 + break + fi + i=$(( $i + 1 )) + done + + if [ $error -eq 0 ];then + echo "\r\e[92m[+] Test #5 Succeeded\e[0m" + fi +} + +test_six () +{ + ("$2/$1" 10 410 200 200 > /dev/null)& + sleep 2 + forks=$(pgrep $1 | wc -l) + if [ "$forks" -eq 11 ];then + printf "\r\e[92m[+] Test #6 Succeeded\e[0m\n" + else + printf "\r\e[91m[+] Test #6 Failed\e[0m\n" + error_log $1 "Test #6" "Given 10 410 200 200 arguments to $1, 10 processes should be forked, each process for a philosopher !" + fi + pkill $1 +} + +if [ "$2" -eq 1 -o "$2" -eq 0 ];then + + echo "[============[Testing philo]==============]\n" + + target="philo" + make -C $1 > /dev/null + + if [ "$?" -ne 0 ];then + echo "\n[+] There's a problem while compiling $target, please recheck your inputs" + exit + fi + + test_one $target $1 + + test_two $target $1 + + test_three $target $1 + + echo "\e[94m[+] Test #4 on progress, please wait...\e[0m" + test_four $target $1 7 28 1 + test_four $target $1 10 40 2 + test_four $target $1 12 48 3 + test_four $target $1 15 60 4 + + test_five $target $1 + rm -rf "./log_$target" +fi + +if [ "$2" -eq 2 -o "$2" -eq 0 ];then + + echo "\n[============[Testing philo_bonus]==============]\n" + + target="philo_bonus" + make -C "$1/$target" > /dev/null + + if [ "$?" -ne 0 ];then + echo "\n[+] There's a problem while compiling $target, please recheck your inputs" + exit + fi + + test_one $target $1 + + test_two $target $1 + + test_three $target $1 + + echo "\e[94m[+] Test #4 on progress, please wait...\e[0m" + test_four $target $1 7 28 1 + test_four $target $1 10 40 2 + test_four $target $1 12 48 3 + test_four $target $1 15 60 4 + + test_five $target $1 + + test_six $target $1 + rm -rf "./log_$target" +fi diff --git a/utils/ft_atoi.o b/utils/ft_atoi.o new file mode 100644 index 0000000..0184cb4 Binary files /dev/null and b/utils/ft_atoi.o differ diff --git a/utils/ft_atoi_check.o b/utils/ft_atoi_check.o new file mode 100644 index 0000000..26fd49a Binary files /dev/null and b/utils/ft_atoi_check.o differ diff --git a/utils/ft_bzero.o b/utils/ft_bzero.o new file mode 100644 index 0000000..5973250 Binary files /dev/null and b/utils/ft_bzero.o differ diff --git a/utils/ft_calloc.o b/utils/ft_calloc.o new file mode 100644 index 0000000..e8d963b Binary files /dev/null and b/utils/ft_calloc.o differ diff --git a/utils/ft_memset.o b/utils/ft_memset.o new file mode 100644 index 0000000..94728ca Binary files /dev/null and b/utils/ft_memset.o differ diff --git a/utils/ft_putchar_fd.o b/utils/ft_putchar_fd.o new file mode 100644 index 0000000..5921886 Binary files /dev/null and b/utils/ft_putchar_fd.o differ diff --git a/utils/ft_putnbr_fd.o b/utils/ft_putnbr_fd.o new file mode 100644 index 0000000..61f45d2 Binary files /dev/null and b/utils/ft_putnbr_fd.o differ diff --git a/utils/ft_putstr_fd.o b/utils/ft_putstr_fd.o new file mode 100644 index 0000000..6dffd1a Binary files /dev/null and b/utils/ft_putstr_fd.o differ diff --git a/utils/ft_strlen.o b/utils/ft_strlen.o new file mode 100644 index 0000000..cc75435 Binary files /dev/null and b/utils/ft_strlen.o differ diff --git a/utils/utils.a b/utils/utils.a new file mode 100644 index 0000000..0ed46fb Binary files /dev/null and b/utils/utils.a differ