├── philo ├── .philo.h.swp ├── Makefile ├── philo.h ├── philo_routines.c ├── philo_utils.c └── philo.c ├── IMG_8550-930x620.jpg ├── philo_bonus ├── Makefile ├── philo_bonus.h ├── philo_bonus_tools.c ├── philo_bonus_routines.c ├── philo_bonus_utils.c └── philo_bonus.c └── README.md /philo/.philo.h.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f0rkr/philosophers/HEAD/philo/.philo.h.swp -------------------------------------------------------------------------------- /IMG_8550-930x620.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f0rkr/philosophers/HEAD/IMG_8550-930x620.jpg -------------------------------------------------------------------------------- /philo/Makefile: -------------------------------------------------------------------------------- 1 | # **************************************************************************** # 2 | # # 3 | # ::: :::::::: # 4 | # Makefile :+: :+: :+: # 5 | # +:+ +:+ +:+ # 6 | # By: mashad +#+ +:+ +#+ # 7 | # +#+#+#+#+#+ +#+ # 8 | # Created: 2021/08/22 11:06:15 by mashad #+# #+# # 9 | # Updated: 2021/08/27 20:35:15 by mashad ### ########.fr # 10 | # # 11 | # **************************************************************************** # 12 | 13 | NAME=philo 14 | CC=gcc 15 | FLAGS=-Wall -Werror -Wextra -pthread 16 | SRCS=philo.c philo_utils.c philo_routines.c 17 | 18 | all: $(NAME) 19 | 20 | $(NAME) : $(SRCS) 21 | $(CC) $(FLAGS) $(SRCS) -o $(NAME) 22 | 23 | clean: 24 | rm -rf $(NAME) 25 | 26 | fclean: clean 27 | 28 | re: fclean all 29 | -------------------------------------------------------------------------------- /philo_bonus/Makefile: -------------------------------------------------------------------------------- 1 | # **************************************************************************** # 2 | # # 3 | # ::: :::::::: # 4 | # Makefile :+: :+: :+: # 5 | # +:+ +:+ +:+ # 6 | # By: mashad +#+ +:+ +#+ # 7 | # +#+#+#+#+#+ +#+ # 8 | # Created: 2021/08/22 11:06:15 by mashad #+# #+# # 9 | # Updated: 2021/08/25 08:46:16 by mashad ### ########.fr # 10 | # # 11 | # **************************************************************************** # 12 | 13 | NAME=philo_bonus 14 | CC=gcc 15 | FLAGS=-Wall -Werror -Wextra -pthread 16 | SRCS=philo_bonus.c philo_bonus_utils.c philo_bonus_routines.c philo_bonus_tools.c 17 | 18 | 19 | all: $(NAME) 20 | 21 | $(NAME) : $(SRCS) 22 | $(CC) $(FLAGS) $(SRCS) -o $(NAME) 23 | 24 | clean: 25 | rm -rf $(NAME) 26 | 27 | fclean: clean 28 | 29 | re: fclean all 30 | -------------------------------------------------------------------------------- /philo/philo.h: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* philo.h :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: mashad +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/08/18 16:39:08 by mashad #+# #+# */ 9 | /* Updated: 2021/08/27 17:51:05 by mashad ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #ifndef PHILO_H 14 | # define PHILO_H 15 | 16 | # include 17 | # include 18 | # include 19 | # include 20 | # include 21 | # include 22 | 23 | # define ERROR -1 24 | # define OFLOW -2 25 | # define STDIN 0 26 | # define STDOUT 1 27 | # define STDERR 2 28 | # define GOOD 3 29 | # define ARGVALUE 4 30 | # define EOL '\0' 31 | 32 | /* 33 | ** Philosopher struct 34 | ** Each philospher shoud have the same options: id[pid] number_of_ate[nta] 35 | ** last_time_ate[lta] 36 | */ 37 | 38 | typedef struct s_philo 39 | { 40 | pthread_mutex_t eating; 41 | pthread_t thd_philo; 42 | pthread_t myhem; 43 | int pid; 44 | int nta; 45 | int lf; 46 | int rf; 47 | int is_eating; 48 | long long lta; 49 | struct s_din *din_table; 50 | } t_philo; 51 | 52 | /* 53 | ** Each program should have the same options: number_of_philosophers[nop] 54 | ** time_to_die[ttd] time_to_eat[tte] 55 | ** time_to_sleep[tts] [number_of_times_each_philosopher_must_eat[ntpme]] 56 | ** starting_time[st] 57 | */ 58 | 59 | typedef struct s_din 60 | { 61 | pthread_mutex_t *forks; 62 | pthread_mutex_t write; 63 | t_philo **philos; 64 | long long st; 65 | int death; 66 | int nop; 67 | int ttd; 68 | int tte; 69 | int tts; 70 | int ntpme; 71 | } t_din; 72 | 73 | t_philo **initialize_philosphers(t_din *din_table); 74 | pthread_mutex_t *initialize_forks(t_din *din_table); 75 | int ft_is_number(char *string); 76 | long long ft_time_in_ms(void); 77 | int ft_atoi(const char *str); 78 | void *start_routine(void *data); 79 | void print_status(t_din *din_table, int pid, char *string); 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /philo_bonus/philo_bonus.h: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* philo_bonus.h :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: mashad +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/08/18 16:39:08 by mashad #+# #+# */ 9 | /* Updated: 2021/08/28 09:06:50 by mashad ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #ifndef PHILO_BONUS_H 14 | # define PHILO_BONUS_H 15 | 16 | # include 17 | # include 18 | # include 19 | # include 20 | # include 21 | # include 22 | # include 23 | # include 24 | # include 25 | # include 26 | # include 27 | # include 28 | 29 | # define ERROR -1 30 | # define OFLOW -2 31 | # define STDIN 0 32 | # define STDOUT 1 33 | # define STDERR 2 34 | # define GOOD 3 35 | # define ARGVALUE 4 36 | # define EOL '\0' 37 | 38 | /* 39 | ** Philosopher struct 40 | ** Each philospher shoud have the same options: id[pid] number_of_ate[nta] 41 | ** last_time_ate[lta] 42 | */ 43 | 44 | typedef struct s_philo 45 | { 46 | pthread_t myhem; 47 | sem_t *eating; 48 | int pid; 49 | int fpid; 50 | int nta; 51 | long long lta; 52 | struct s_din *din_table; 53 | } t_philo; 54 | 55 | /* 56 | ** Each program should have the same options: number_of_philosophers[nop] 57 | ** time_to_die[ttd] time_to_eat[tte] 58 | ** time_to_sleep [number_of_times_each_philosopher_must_eat[ntpme]] 59 | ** starting_time[st] 60 | */ 61 | 62 | typedef struct s_din 63 | { 64 | t_philo **philos; 65 | pthread_t eatcounter; 66 | sem_t *forks; 67 | sem_t *write; 68 | sem_t *death; 69 | sem_t *eat; 70 | int nop; 71 | int ttd; 72 | int tte; 73 | int tts; 74 | int ntpme; 75 | long long st; 76 | 77 | } t_din; 78 | 79 | t_philo **initialize_philosphers(t_din *din_table); 80 | int initialize_sems(t_din *din_table); 81 | int ft_is_number(char *string); 82 | long long ft_time_in_ms(void); 83 | int ft_atoi(const char *str); 84 | void *start_routine(t_philo *philo); 85 | void print_status(t_din *din_table, int pid, char *string); 86 | void ft_putnbr_fd(int n, int fd); 87 | void *mr_mayhem(void *data); 88 | void *eat_reaper(void *data); 89 | #endif 90 | -------------------------------------------------------------------------------- /philo_bonus/philo_bonus_tools.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* philo_bonus_tools.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: mashad +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/08/25 08:43:02 by mashad #+# #+# */ 9 | /* Updated: 2021/08/28 10:26:22 by mashad ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "philo_bonus.h" 14 | 15 | /* 16 | ** Putchar function 17 | */ 18 | void ft_putchar_fd(char c, int fd) 19 | { 20 | write(fd, &c, 1); 21 | return ; 22 | } 23 | 24 | /* 25 | ** put number function 26 | ** uses write 27 | */ 28 | void ft_putnbr_fd(int n, int fd) 29 | { 30 | if (n >= 0 && n < 10) 31 | ft_putchar_fd(n + '0', fd); 32 | else 33 | { 34 | ft_putnbr_fd(n / 10, fd); 35 | ft_putnbr_fd(n % 10, fd); 36 | } 37 | return ; 38 | } 39 | 40 | /* Mainly check if the in string 41 | ** doesn't contain any ascii than numbers 42 | */ 43 | int ft_is_number(char *string) 44 | { 45 | int i; 46 | 47 | i = 0; 48 | while (string[i] != EOL) 49 | { 50 | if (string[i] <= '0' || string[i] >= '9') 51 | return (ERROR); 52 | i++; 53 | } 54 | return (GOOD); 55 | } 56 | 57 | /* 58 | ** Mr mayhem check for a reason to kill 59 | ** one of the philospher either their 60 | ** time to die or number_of_times_each_philosopher_must_eat 61 | */ 62 | void *mr_mayhem(void *data) 63 | { 64 | t_philo *philo; 65 | 66 | philo = (t_philo *)data; 67 | while (1) 68 | { 69 | sem_wait(philo->eating); 70 | if (ft_time_in_ms() - philo->lta >= philo->din_table->ttd) 71 | { 72 | print_status(philo->din_table, philo->pid, "died\n"); 73 | exit(1); 74 | } 75 | sem_post(philo->eating); 76 | usleep(100); 77 | } 78 | return (NULL); 79 | } 80 | 81 | /* 82 | ** Await for philosohper their number_of_times_each_philosopher_must_eat[ntpme] 83 | ** then kill all childs 84 | */ 85 | void *eat_reaper(void *data) 86 | { 87 | t_din *din_table; 88 | int eat_counter; 89 | int i; 90 | 91 | din_table = (t_din *)data; 92 | eat_counter = 0; 93 | while (eat_counter < din_table->ntpme) 94 | { 95 | i = 0; 96 | while (i < din_table->nop) 97 | { 98 | sem_wait(din_table->eat); 99 | i++; 100 | } 101 | eat_counter++; 102 | } 103 | sem_wait(din_table->write); 104 | i = 0; 105 | while (i < din_table->nop) 106 | kill(din_table->philos[i++]->fpid, SIGKILL); 107 | return (NULL); 108 | } 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Philosophers dining problem 2 | 3 | 4 | 5 | The dining philosophers problem is an example problem often used in concurrent algorithm design to illustrate synchronization issues and techniques for resolving them. 6 | 7 | # Problem introduction: 8 | 9 | The Dining Philosopher Problem states that N philosophers seated around a circular table with a large bowl of spaghetti and one fork between each pair of philosopher. Each philosopher is doing one of the three things: eating, sleeping, thinking. While eating, they are not thinking or sleeping, while sleeping, they are not eating or thinking and of course, while thinking, they are not eating or sleeping. I should state that philosophers aren’t aware of other philosophers status. 10 | 11 | 12 | 13 | The goal here is to create a program that simulate the 3 states of philosophers and log print any change of status as follow: 14 | 15 | - **timestamp_in_ms** X has taken a fork 16 | - **timestamp_in_ms** X is eating 17 | - **timestamp_in_ms** X is sleeping 18 | - **timestamp_in_ms** X is thinking 19 | - **timestamp_in_ms** X died 20 | 21 | The program need 5 arguments which are: 22 | 23 | - **number_of_philosophers[nop]**: is the number of philosophers and also the number of forks. 24 | - **time_to_die[ttd]**: is in milliseconds, if a philosopher doesn’t start eating ’time_to_die’ milliseconds after starting his last meal or the beginning of the simulation, it dies. 25 | - **time_to_eat[tte]**: is in milliseconds and is the time it takes for a philosopher to eat. During that time he will need to keep the two forks. 26 | - **time_to_sleep[tts]**: is in milliseconds and is the time the philosopher will spend sleeping. 27 | - **number_of_times_each_philosopher_must_eat**: argument is optional, if all philosophers eat at least ’number_of_times_each_philosopher_must_eat’ the simulation will stop. If not specified, the simulation will stop only at the death of a philosopher. 28 | A philosopher may eat if he can pick up the two forks adjacent to him. One fork may be picked up by any one of its adjacent followers but not both as it would result in a problem that we will discuss forthcoming. 29 | 30 | Visit my blog to read more. 31 | 32 | # Resources I used: 33 | * [Parallel computing tutorial](https://hpc.llnl.gov/training/tutorials/introduction-parallel-computing-tutorial) 34 | * [POSIX threads programming](https://hpc-tutorials.llnl.gov/posix/) 35 | * [Thread and C](https://franckh.developpez.com/tutoriels/posix/pthreads/) 36 | * [Condition variables](https://greenteapress.com/thinkos/html/thinkos012.html) 37 | * [Mltiple child process](https://stackoverflow.com/questions/876605/multiple-child-process) 38 | * [Semaphores](https://stackoverflow.com/questions/9537068/sem-close-vs-sem-unlink-when-process-terminates) 39 | -------------------------------------------------------------------------------- /philo_bonus/philo_bonus_routines.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* philo_bonus_routines.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: mashad +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/08/22 10:24:51 by mashad #+# #+# */ 9 | /* Updated: 2021/08/28 09:24:34 by mashad ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "philo_bonus.h" 14 | 15 | /* 16 | ** Print status using a write mutex 17 | ** to avoid other philospher status be scrambled or intertwined 18 | ** with another philosopher’s status. 19 | */ 20 | void print_status(t_din *din_table, int pid, char *string) 21 | { 22 | sem_wait(din_table->write); 23 | ft_putnbr_fd(ft_time_in_ms() - din_table->st, 1); 24 | write(1, " ", 1); 25 | ft_putnbr_fd(pid + 1, 1); 26 | write(1, " ", 1); 27 | write(1, string, strlen(string)); 28 | if (string[0] != 'd') 29 | sem_post(din_table->write); 30 | } 31 | 32 | /* 33 | ** Philosopher get both forks then start eating 34 | ** for an amount of time ( tte ). 35 | */ 36 | void eat_routine(t_philo *philo) 37 | { 38 | sem_wait(philo->din_table->forks); 39 | print_status(philo->din_table, philo->pid, "taken left fork\n"); 40 | sem_wait(philo->din_table->forks); 41 | print_status(philo->din_table, philo->pid, "taken right fork\n"); 42 | print_status(philo->din_table, philo->pid, "is eating\n"); 43 | sem_wait(philo->eating); 44 | philo->lta = ft_time_in_ms(); 45 | usleep(philo->din_table->tte * 1000 - 15000); 46 | while (ft_time_in_ms() - philo->lta < philo->din_table->tte) 47 | continue ; 48 | sem_post(philo->din_table->eat); 49 | sem_post(philo->eating); 50 | sem_post(philo->din_table->forks); 51 | sem_post(philo->din_table->forks); 52 | return ; 53 | } 54 | 55 | /* 56 | ** Philospher time to sleep routine. 57 | */ 58 | void sleep_routine(t_philo *philo) 59 | { 60 | long long time; 61 | 62 | print_status(philo->din_table, philo->pid, "is sleeping\n"); 63 | time = ft_time_in_ms(); 64 | usleep(philo->din_table->tts * 1000 - 15000); 65 | while (ft_time_in_ms() - time < philo->din_table->tts) 66 | continue ; 67 | return ; 68 | } 69 | 70 | /* 71 | ** Philospher time to think routine 72 | */ 73 | void think_routine(t_philo *philo) 74 | { 75 | print_status(philo->din_table, philo->pid, "is thinking\n"); 76 | return ; 77 | } 78 | 79 | /* 80 | ** Routine start here with infinite loop 81 | ** that includes all routines that philospher must do 82 | ** which are eat - sleep - think. 83 | */ 84 | void *start_routine(t_philo *philo) 85 | { 86 | while (1) 87 | { 88 | eat_routine(philo); 89 | sleep_routine(philo); 90 | think_routine(philo); 91 | usleep(100); 92 | } 93 | return (NULL); 94 | } 95 | -------------------------------------------------------------------------------- /philo/philo_routines.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* philo_routines.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: mashad +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/08/22 10:24:51 by mashad #+# #+# */ 9 | /* Updated: 2021/08/27 20:27:04 by mashad ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "philo.h" 14 | 15 | /* 16 | ** Print status using a write mutex 17 | ** to avoid other philospher status be scrambled or intertwined 18 | ** with another philosopher’s status. 19 | */ 20 | void print_status(t_din *din_table, int pid, char *string) 21 | { 22 | pthread_mutex_lock(&din_table->write); 23 | printf("%lld %d %s", ft_time_in_ms() - din_table->st, pid + 1, string); 24 | if (string[0] != 'd') 25 | pthread_mutex_unlock(&din_table->write); 26 | } 27 | 28 | /* 29 | ** Philosopher get both forks then start eating 30 | ** for an amount of time ( tte ). 31 | */ 32 | void eat_routine(t_philo *philo) 33 | { 34 | pthread_mutex_lock(&philo->din_table->forks[philo->lf]); 35 | print_status(philo->din_table, philo->pid, "taken left fork\n"); 36 | pthread_mutex_lock(&philo->din_table->forks[philo->rf]); 37 | print_status(philo->din_table, philo->pid, "taken right fork\n"); 38 | pthread_mutex_lock(&philo->eating); 39 | print_status(philo->din_table, philo->pid, "is eating\n"); 40 | philo->lta = ft_time_in_ms(); 41 | philo->is_eating = 1; 42 | usleep(philo->din_table->tte * 1000 - 16000); 43 | while (ft_time_in_ms() - philo->lta < philo->din_table->tte) 44 | continue ; 45 | philo->nta++; 46 | philo->is_eating = 0; 47 | pthread_mutex_unlock(&philo->eating); 48 | pthread_mutex_unlock(&philo->din_table->forks[philo->lf]); 49 | pthread_mutex_unlock(&philo->din_table->forks[philo->rf]); 50 | return ; 51 | } 52 | 53 | /* 54 | ** Philospher time to sleep routine. 55 | */ 56 | void sleep_routine(t_philo *philo) 57 | { 58 | long long time; 59 | 60 | print_status(philo->din_table, philo->pid, "is sleeping\n"); 61 | time = ft_time_in_ms(); 62 | usleep(philo->din_table->tts * 1000 - 16000); 63 | while (ft_time_in_ms() - time < philo->din_table->tts) 64 | continue ; 65 | return ; 66 | } 67 | 68 | /* 69 | ** Philospher time to think routine 70 | */ 71 | void think_routine(t_philo *philo) 72 | { 73 | print_status(philo->din_table, philo->pid, "is thinking\n"); 74 | return ; 75 | } 76 | 77 | /* 78 | ** Routine start here with infinite loop 79 | ** that includes all routines that philospher must do 80 | ** which are eat - sleep - think. 81 | */ 82 | void *start_routine(void *data) 83 | { 84 | t_philo *philo; 85 | 86 | philo = (t_philo *)data; 87 | while (philo->din_table->death) 88 | { 89 | eat_routine(philo); 90 | sleep_routine(philo); 91 | think_routine(philo); 92 | usleep(100); 93 | } 94 | return (NULL); 95 | } 96 | -------------------------------------------------------------------------------- /philo/philo_utils.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* philo_utils.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: mashad +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/08/22 09:26:02 by mashad #+# #+# */ 9 | /* Updated: 2021/08/27 20:37:43 by mashad ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "philo.h" 14 | 15 | int ft_check(unsigned long pt, int s) 16 | { 17 | if (pt > 9223372036854775807 && s == -1) 18 | return (0); 19 | else if (pt > 2147483647) 20 | return (OFLOW); 21 | return (pt * s); 22 | } 23 | 24 | int ft_atoi(const char *str) 25 | { 26 | unsigned long long int j; 27 | unsigned long long int t_p; 28 | int tt; 29 | 30 | tt = 1; 31 | j = 0; 32 | t_p = 0; 33 | while (*str >= 8 && *str <= 32) 34 | { 35 | if (*str == 27) 36 | return (0); 37 | str++; 38 | } 39 | if (*str == '-') 40 | { 41 | tt = -1; 42 | str++; 43 | } 44 | else if (*str == '+') 45 | str++; 46 | while (*(str + j) >= 48 && *(str + j) <= 57) 47 | t_p = t_p * 10 + (unsigned long long int)(*(str + j++) - '0'); 48 | return (ft_check(t_p, tt)); 49 | } 50 | 51 | /* Mainly check if the in string 52 | ** doesn't contain any ascii than numbers 53 | */ 54 | int ft_is_number(char *string) 55 | { 56 | int i; 57 | 58 | i = 0; 59 | while (string[i] != EOL) 60 | { 61 | if (string[i] <= '0' || string[i] >= '9') 62 | return (ERROR); 63 | i++; 64 | } 65 | return (GOOD); 66 | } 67 | 68 | /* 69 | ** Get the current time in ms 70 | */ 71 | long long ft_time_in_ms(void) 72 | { 73 | struct timeval te; 74 | long long milliseconds; 75 | 76 | gettimeofday(&te, NULL); 77 | milliseconds = te.tv_sec * 1000LL + te.tv_usec / 1000; 78 | return (milliseconds); 79 | } 80 | 81 | /* 82 | ** Initialize philosophers struct 83 | */ 84 | t_philo **initialize_philosphers(t_din *din_table) 85 | { 86 | t_philo **philos; 87 | int i; 88 | 89 | i = 0; 90 | philos = (t_philo **)malloc(sizeof(t_philo *) * din_table->nop + 1); 91 | if (philos == NULL) 92 | return (NULL); 93 | while (i < din_table->nop) 94 | { 95 | philos[i] = (t_philo *)malloc(sizeof(t_philo) * 1); 96 | if (philos[i] == NULL) 97 | return (NULL); 98 | if (pthread_mutex_init(&philos[i]->eating, 0) != 0) 99 | return (NULL); 100 | philos[i]->din_table = din_table; 101 | philos[i]->pid = i; 102 | philos[i]->is_eating = 0; 103 | philos[i]->nta = 0; 104 | philos[i]->lf = i; 105 | philos[i]->rf = (i + 1) % philos[i]->din_table->nop; 106 | i++; 107 | } 108 | return (philos); 109 | } 110 | 111 | pthread_mutex_t *initialize_forks(t_din *din_table) 112 | { 113 | pthread_mutex_t *forks; 114 | int i; 115 | 116 | i = 0; 117 | if (din_table->nop == OFLOW || din_table->ttd == OFLOW 118 | || din_table->tte == OFLOW || din_table->tts == OFLOW 119 | || din_table->ntpme == OFLOW) 120 | { 121 | write(2, "Error: Invalid Argument\n", 23); 122 | return (NULL); 123 | } 124 | forks = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t) * din_table->nop); 125 | if (forks == NULL) 126 | return (NULL); 127 | while (i < din_table->nop) 128 | { 129 | if (pthread_mutex_init(&forks[i], 0) != 0) 130 | return (NULL); 131 | i++; 132 | } 133 | return (forks); 134 | } 135 | -------------------------------------------------------------------------------- /philo_bonus/philo_bonus_utils.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* philo_bonus_utils.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: mashad +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/08/22 09:26:02 by mashad #+# #+# */ 9 | /* Updated: 2021/08/28 10:20:38 by mashad ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "philo_bonus.h" 14 | 15 | int ft_check(unsigned long pt, int s) 16 | { 17 | if (pt > 9223372036854775807 && s == -1) 18 | return (0); 19 | else if (pt > 2147483647) 20 | return (OFLOW); 21 | return (pt * s); 22 | } 23 | 24 | int ft_atoi(const char *str) 25 | { 26 | unsigned long long int j; 27 | unsigned long long int t_p; 28 | int tt; 29 | 30 | tt = 1; 31 | j = 0; 32 | t_p = 0; 33 | while (*str >= 8 && *str <= 32) 34 | { 35 | if (*str == 27) 36 | return (0); 37 | str++; 38 | } 39 | if (*str == '-') 40 | { 41 | tt = -1; 42 | str++; 43 | } 44 | else if (*str == '+') 45 | str++; 46 | while (*(str + j) >= 48 && *(str + j) <= 57) 47 | t_p = t_p * 10 + (unsigned long long int)(*(str + j++) - '0'); 48 | return (ft_check(t_p, tt)); 49 | } 50 | 51 | /* 52 | ** Get the current time in ms 53 | */ 54 | long long ft_time_in_ms(void) 55 | { 56 | struct timeval te; 57 | long long milliseconds; 58 | 59 | gettimeofday(&te, NULL); 60 | milliseconds = te.tv_sec * 1000LL + te.tv_usec / 1000; 61 | return (milliseconds); 62 | } 63 | 64 | /* 65 | ** Initialize philosophers struct 66 | */ 67 | t_philo **initialize_philosphers(t_din *din_table) 68 | { 69 | t_philo **philos; 70 | int i; 71 | 72 | i = 0; 73 | philos = (t_philo **)malloc(sizeof(t_philo *) * din_table->nop + 1); 74 | if (philos == NULL) 75 | return (NULL); 76 | while (i < din_table->nop) 77 | { 78 | philos[i] = (t_philo *)malloc(sizeof(t_philo) * 1); 79 | if (philos[i] == NULL) 80 | return (NULL); 81 | sem_unlink("eating"); 82 | philos[i]->eating = sem_open("eating", O_CREAT, 0644, 1); 83 | if (din_table->write == SEM_FAILED) 84 | return (NULL); 85 | philos[i]->din_table = din_table; 86 | philos[i]->pid = i; 87 | philos[i]->nta = 0; 88 | i++; 89 | } 90 | return (philos); 91 | } 92 | 93 | /* 94 | ** Initialize forks semaphores 95 | */ 96 | int initialize_sems(t_din *din_table) 97 | { 98 | if (din_table->nop == OFLOW || din_table->ttd == OFLOW || din_table->tte 99 | == OFLOW || din_table->tts == OFLOW || din_table->ntpme == OFLOW) 100 | { 101 | write(2, "Error: Argument overflow\n", 23); 102 | return (ERROR); 103 | } 104 | sem_unlink("forking"); 105 | din_table->forks = sem_open("forking", O_CREAT, 0644, din_table->nop); 106 | if (din_table->forks == SEM_FAILED) 107 | return (ERROR); 108 | sem_unlink("death"); 109 | din_table->death = sem_open("death", O_CREAT, 0644, 1); 110 | if (din_table->death == SEM_FAILED) 111 | return (ERROR); 112 | sem_unlink("writing"); 113 | din_table->write = sem_open("writing", O_CREAT, 0644, 1); 114 | if (din_table->write == SEM_FAILED) 115 | return (ERROR); 116 | sem_unlink("eatcounter"); 117 | din_table->eat = sem_open("eatcounter", O_CREAT, 0644, 1); 118 | if (din_table->eat == SEM_FAILED) 119 | return (ERROR); 120 | return (GOOD); 121 | } 122 | -------------------------------------------------------------------------------- /philo_bonus/philo_bonus.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* philo_bonus.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: mashad +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/08/18 16:38:13 by mashad #+# #+# */ 9 | /* Updated: 2021/08/28 09:43:48 by mashad ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "philo_bonus.h" 14 | 15 | /* 16 | ** Mainly check arguments validity and return acceptance 17 | ** In case of an error a -1 is returned 18 | */ 19 | int check_arg_validity(int argSize, char **args) 20 | { 21 | int i; 22 | 23 | i = 1; 24 | if (argSize - 1 < ARGVALUE || argSize - 1 > 6) 25 | return (ERROR); 26 | while (i < argSize) 27 | { 28 | if (args[i][0] == '-' && ft_is_number(args[i]) != GOOD) 29 | return (ERROR); 30 | i++; 31 | } 32 | return (GOOD); 33 | } 34 | 35 | /* 36 | ** Parse arguments into a valid struct 37 | ** Which we will use later 38 | */ 39 | t_din *fill_table(int argSize, char **args) 40 | { 41 | t_din *din_table; 42 | int counter; 43 | 44 | counter = 1; 45 | din_table = (t_din *) malloc(sizeof(t_din) * 1); 46 | if (din_table == NULL) 47 | return (NULL); 48 | din_table->nop = ft_atoi(args[counter++]); 49 | din_table->ttd = ft_atoi(args[counter++]); 50 | din_table->tte = ft_atoi(args[counter++]); 51 | din_table->tts = ft_atoi(args[counter++]); 52 | din_table->ntpme = -1; 53 | if (argSize - 1 == 5) 54 | din_table->ntpme = ft_atoi(args[counter]); 55 | if (initialize_sems(din_table) != GOOD) 56 | return (NULL); 57 | din_table->philos = initialize_philosphers(din_table); 58 | if (din_table->philos == NULL || din_table->nop == 0) 59 | return (NULL); 60 | return (din_table); 61 | } 62 | 63 | /* 64 | ** Await for child to finish 65 | ** Then automatically kill them 66 | */ 67 | void childs_reaper(t_din *din_table) 68 | { 69 | int i; 70 | int j; 71 | int status; 72 | 73 | i = 0; 74 | while (i < din_table->nop) 75 | { 76 | j = 0; 77 | waitpid(-1, &status, 0); 78 | if (WIFEXITED(status) || WIFSIGNALED(status)) 79 | while (j < din_table->nop) 80 | kill(din_table->philos[j++]->fpid, SIGKILL); 81 | i++; 82 | } 83 | return ; 84 | } 85 | 86 | /* 87 | ** Initialize threads and start philospher 88 | */ 89 | int start_threads(t_din *din_table) 90 | { 91 | int i; 92 | 93 | i = 0; 94 | if (din_table->ntpme != ERROR && pthread_create(&din_table->eatcounter, 95 | NULL, &eat_reaper, (void *)din_table) != 0) 96 | return (ERROR); 97 | din_table->st = ft_time_in_ms(); 98 | while (i < din_table->nop) 99 | { 100 | din_table->philos[i]->fpid = fork(); 101 | din_table->philos[i]->lta = ft_time_in_ms(); 102 | if (din_table->philos[i]->fpid == 0) 103 | { 104 | if (pthread_create(&din_table->philos[i]->myhem, NULL, &mr_mayhem, 105 | (void *)din_table->philos[i]) != 0) 106 | return (ERROR); 107 | start_routine(din_table->philos[i]); 108 | exit(1); 109 | } 110 | usleep(100); 111 | i++; 112 | } 113 | childs_reaper(din_table); 114 | return (GOOD); 115 | } 116 | 117 | int main(int argc, char **argv) 118 | { 119 | t_din *din_table; 120 | int p_counter; 121 | 122 | p_counter = 0; 123 | din_table = NULL; 124 | if (check_arg_validity(argc, argv) != GOOD) 125 | { 126 | write(2, "Error: Invalid Argument\n", 23); 127 | return (ERROR); 128 | } 129 | din_table = fill_table(argc, argv); 130 | if (din_table == NULL) 131 | return (ERROR); 132 | if (start_threads(din_table) != GOOD) 133 | return (ERROR); 134 | return (GOOD); 135 | } 136 | -------------------------------------------------------------------------------- /philo/philo.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* philo.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: mashad +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/08/18 16:38:13 by mashad #+# #+# */ 9 | /* Updated: 2021/08/27 20:37:22 by mashad ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "philo.h" 14 | 15 | /* 16 | ** Mainly check arguments validity and return acceptance 17 | ** In case of an error a -1 is returned 18 | */ 19 | int check_arg_validity(int argSize, char **args) 20 | { 21 | int i; 22 | 23 | i = 1; 24 | if (argSize - 1 < ARGVALUE || argSize - 1 > 6) 25 | return (ERROR); 26 | while (i < argSize) 27 | { 28 | if (args[i][0] == '-' && ft_is_number(args[i]) != GOOD) 29 | return (ERROR); 30 | i++; 31 | } 32 | return (GOOD); 33 | } 34 | 35 | /* 36 | ** Parse arguments into a valid struct 37 | ** Which we will use later 38 | */ 39 | t_din *fill_table(int argSize, char **args) 40 | { 41 | t_din *din_table; 42 | int counter; 43 | 44 | counter = 1; 45 | din_table = (t_din *) malloc(sizeof(t_din) * 1); 46 | if (din_table == NULL) 47 | return (NULL); 48 | din_table->nop = ft_atoi(args[counter++]); 49 | din_table->ttd = ft_atoi(args[counter++]); 50 | din_table->tte = ft_atoi(args[counter++]); 51 | din_table->tts = ft_atoi(args[counter++]); 52 | din_table->ntpme = -1; 53 | din_table->death = 1; 54 | if (argSize - 1 == 5) 55 | din_table->ntpme = ft_atoi(args[counter]); 56 | din_table->forks = initialize_forks(din_table); 57 | if (din_table->forks == NULL) 58 | return (NULL); 59 | din_table->philos = initialize_philosphers(din_table); 60 | if (din_table->philos == NULL || din_table->nop == 0) 61 | return (NULL); 62 | if (pthread_mutex_init(&din_table->write, 0) != 0) 63 | return (NULL); 64 | return (din_table); 65 | } 66 | 67 | /* 68 | ** Mr mayhem check for a reason to kill 69 | ** one of the philospher either their 70 | ** time to die or number_of_times_each_philosopher_must_eat 71 | ** Each philosopher has it's own death master 72 | */ 73 | void *mr_mayhem(void *data) 74 | { 75 | t_philo *philo; 76 | 77 | philo = (t_philo *)data; 78 | while (philo->din_table->death) 79 | { 80 | if (!philo->is_eating 81 | && ft_time_in_ms() - philo->lta >= philo->din_table->ttd) 82 | { 83 | pthread_mutex_lock(&philo->eating); 84 | print_status(philo->din_table, philo->pid, "died\n"); 85 | philo->din_table->death = 0; 86 | pthread_mutex_unlock(&philo->eating); 87 | } 88 | if (philo->din_table->philos[philo->din_table->nop - 1]->nta 89 | == philo->din_table->ntpme) 90 | philo->din_table->death = 0; 91 | usleep(100); 92 | } 93 | return (NULL); 94 | } 95 | 96 | /* 97 | ** Initialize threads and start philospher 98 | */ 99 | int start_threads(t_din *din_table) 100 | { 101 | int i; 102 | 103 | i = 0; 104 | din_table->st = ft_time_in_ms(); 105 | while (i < din_table->nop) 106 | { 107 | din_table->philos[i]->lta = ft_time_in_ms(); 108 | if (pthread_create(&din_table->philos[i]->thd_philo, NULL, 109 | &start_routine, (void *)din_table->philos[i]) != 0) 110 | return (ERROR); 111 | i++; 112 | usleep(100); 113 | } 114 | i = 0; 115 | while (i < din_table->nop) 116 | { 117 | if (pthread_create(&din_table->philos[i]->myhem, NULL, &mr_mayhem, 118 | (void *)din_table->philos[i]) != 0) 119 | return (ERROR); 120 | usleep(100); 121 | i++; 122 | } 123 | while (din_table->death) 124 | continue ; 125 | return (GOOD); 126 | } 127 | 128 | int main(int argc, char **argv) 129 | { 130 | t_din *din_table; 131 | int p_counter; 132 | 133 | p_counter = 0; 134 | din_table = NULL; 135 | if (check_arg_validity(argc, argv) != GOOD) 136 | { 137 | write(2, "Error: Invalid Argument\n", 23); 138 | return (ERROR); 139 | } 140 | din_table = fill_table(argc, argv); 141 | if (din_table == NULL) 142 | return (ERROR); 143 | if (start_threads(din_table) != GOOD) 144 | return (ERROR); 145 | return (GOOD); 146 | } 147 | --------------------------------------------------------------------------------