Browse Source

first

master
narnaud 3 years ago
parent
commit
23b74464dd
  1. 27
      README.md
  2. 26
      philo/Makefile
  3. 62
      philo/philo_init.c
  4. 77
      philo/philo_launcher.c
  5. 84
      philo/philo_threads.c
  6. 71
      philo/philo_utils.c
  7. 70
      philo/philosophers.h
  8. 102
      philo_bonus/philo.c
  9. 60
      philo_bonus/philo_utils.c
  10. 71
      philo_bonus/philosophers.h

27
README.md

@ -1,3 +1,30 @@
# Philosophers
42 school project
PHILOSOPHERS BONUS
===
## Subject :
<https://cdn.intra.42.fr/pdf/pdf/48443/fr.subject.pdf>
## Docs :
[Semaphores](https://sites.uclouvain.be/SyllabusC/notes/Theorie/Threads/coordination.html)
## Structure :
Main :
- parsing() ->
- create table and *philos
- setup parameters
- create sticks semaphore
- init_philos() ->
- create array of childs pids
- for each philo, create a fork() :
- philo_life() ->
-
- loop

26
philo/Makefile

@ -0,0 +1,26 @@
NAME = philosophers
SRCS = philo_threads.c philo_launcher.c philo_utils.c philo_init.c
OBJS = ${SRCS:.c=.o}
CC = gcc
CFLAGS = -Werror -Wextra -Wall -g -fsanitize=thread -D_REENTRANT
RM = rm -rf
.c.o:
$(CC) $(CFLAGS) -c $< -o $(<:.c=.o)
all: $(NAME)
$(NAME): $(OBJS)
${CC} ${CFLAGS} -lpthread ${OBJS} -o ${NAME}
clean:
${RM} ${OBJS}
fclean: clean
${RM} ${NAME}
re: fclean all
.PHONY: all clean fclean re

62
philo/philo_init.c

@ -0,0 +1,62 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* philo_init.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/04/11 10:33:01 by narnaud #+# #+# */
/* Updated: 2022/04/11 10:35:12 by narnaud ### ########.fr */
/* */
/* ************************************************************************** */
#include "philosophers.h"
t_param *init_param(char **argv)
{
t_param *ret;
ret = malloc(sizeof(t_param));
ret->philo_amount = mini_atoi(argv[0]);
ret->die_time = mini_atoi(argv[1]);
ret->eat_duration = mini_atoi(argv[2]);
ret->sleep_duration = mini_atoi(argv[3]);
if (argv[4])
ret->eat_amount = mini_atoi(argv[4]);
else
ret->eat_amount = 2147483647;
return (ret);
}
t_room *init_room(char **argv)
{
t_room *room;
struct timeval time;
static int i = 0;
gettimeofday(&time, NULL);
room = malloc(sizeof(t_room));
room->param = init_param(argv);
room->safe = malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(room->safe, NULL);
room->philos = \
(t_philo **)malloc(room->param->philo_amount * sizeof(t_philo *));
room->running = 1;
room->start_time = time.tv_sec * 1000 + time.tv_usec / 1000;
room->time = 0;
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]->safe = malloc(sizeof(pthread_mutex_t));
room->philos[i]->thd = malloc(sizeof(pthread_t));
room->philos[i]->eat_time = room->time;
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++]->safe, NULL);
}
return (room);
}

77
philo/philo_launcher.c

@ -0,0 +1,77 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* philo_launcher.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/24 15:44:04 by narnaud #+# #+# */
/* Updated: 2022/04/11 14:55:43 by narnaud ### ########.fr */
/* */
/* ************************************************************************** */
#include "philosophers.h"
int waiter(t_room *room);
int main(int argc, char **argv)
{
t_room *room;
if (argc < 5 || argc > 6)
return (1);
room = init_room(argv + 1);
pthread_create(&room->clock_thd, NULL, room_clock, (void *)room);
while (room->i >= 0)
{
pthread_mutex_lock(room->safe);
if (room->i >= room->param->philo_amount)
room->i -= 1 + (room->param->philo_amount % 2) * 2;
pthread_create(room->philos[room->i]->thd, NULL, \
philos_life, (void *)room);
pthread_detach(*room->philos[room->i]->thd);
pthread_mutex_unlock(room->safe);
usleep(CLOCK_ONE);
pthread_mutex_lock(room->safe);
if ((room->i % 2) == 0)
room->i += 2;
else if ((room->i % 2) == 1)
room->i -= 2;
pthread_mutex_unlock(room->safe);
}
while (!waiter(room))
usleep(CLOCK_TWO);
return (clean_memory(room));
}
int waiter(t_room *room)
{
t_param *param;
int i;
int starvest;
pthread_mutex_lock(room->safe);
i = 0;
param = room->param;
starvest = param->eat_amount;
while (i < param->philo_amount)
{
pthread_mutex_lock(room->philos[i]->safe);
if (room->philos[i]->eat_time + param->die_time < room->time)
{
safe_print("%ld %d died\n", room, i);
room->running = 0;
pthread_mutex_unlock(room->philos[i]->safe);
pthread_mutex_unlock(room->safe);
return (1);
}
if (room->philos[i]->eat_amount < starvest)
starvest = room->philos[i]->eat_amount;
pthread_mutex_unlock(room->philos[i]->safe);
i++;
}
if (starvest == param->eat_amount)
room->running = 0;
pthread_mutex_unlock(room->safe);
return (!room->running);
}

84
philo/philo_threads.c

@ -0,0 +1,84 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* philo_threads.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/26 07:43:48 by narnaud #+# #+# */
/* Updated: 2022/04/11 14:52:22 by narnaud ### ########.fr */
/* */
/* ************************************************************************** */
#include "philosophers.h"
void *philos_life(void *r)
{
t_room *room;
t_param *param;
t_philo *philo;
int id;
int id_p;
room = (t_room *)r;
param = room->param;
pthread_mutex_lock(room->safe);
id = room->i;
philo = room->philos[id];
philo->eat_time = room->time;
id_p = (id + 1) % param->philo_amount;
pthread_mutex_unlock(room->safe);
while (room->running)
{
pthread_mutex_lock(philo->fork);
safe_print("%ld %d has taken a fork\n", room, id);
pthread_mutex_lock(room->philos[id_p]->fork);
safe_print("%ld %d has taken a fork\n", room, id);
safe_print("%ld %d is eating\n", room, id);
pthread_mutex_lock(philo->safe);
philo->eat_time = room->time;
pthread_mutex_unlock(philo->safe);
if (check_end(room))
{
pthread_mutex_unlock(philo->fork);
pthread_mutex_unlock(room->philos[id_p]->fork);
return (NULL);
}
usleep(param->eat_duration * 1000);
pthread_mutex_unlock(philo->fork);
pthread_mutex_unlock(room->philos[id_p]->fork);
if (check_end(room))
return (NULL);
safe_print("%ld %d is sleeping\n", room, id);
pthread_mutex_lock(philo->safe);
philo->eat_amount++;
pthread_mutex_unlock(philo->safe);
usleep(param->sleep_duration * 1000);
if (check_end(room))
return (NULL);
safe_print("%ld %d is thinking\n", room, id);
}
return (NULL);
}
void *room_clock(void *r)
{
t_room *room;
struct timeval time;
room = (t_room *)r;
while (1)
{
gettimeofday(&time, NULL);
pthread_mutex_lock(room->safe);
room->time = time.tv_sec * 1000 + time.tv_usec / 1000 - room->start_time;
if (!room->running)
{
pthread_mutex_unlock(room->safe);
return(NULL);
}
pthread_mutex_unlock(room->safe);
usleep(CLOCK_TWO);
}
return (NULL);
}

71
philo/philo_utils.c

@ -0,0 +1,71 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* philo_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/04/11 10:29:50 by narnaud #+# #+# */
/* Updated: 2022/04/11 14:50:59 by narnaud ### ########.fr */
/* */
/* ************************************************************************** */
#include "philosophers.h"
int mini_atoi(char *nbr)
{
int ret;
ret = 0;
while (*nbr >= '0' && *nbr <= '9')
{
ret = (*nbr - '0') + (10 * ret);
nbr++;
}
return (ret);
}
void safe_print(char *str, t_room *room, int id)
{
pthread_mutex_lock(room->safe);
printf(str, room->time, id);
pthread_mutex_unlock(room->safe);
}
int check_end(t_room *room)
{
int ret;
ret = 0;
pthread_mutex_lock(room->safe);
if (!room->running)
ret = 1;
pthread_mutex_unlock(room->safe);
return (ret);
}
int clean_memory(t_room *room)
{
t_param *param;
int i;
i = 0;
param = room->param;
while (i < param->philo_amount)
{
pthread_mutex_destroy(room->philos[i]->safe);
pthread_mutex_destroy(room->philos[i]->fork);
free(room->philos[i]->safe);
free(room->philos[i]->fork);
free(room->philos[i]->thd);
free(room->philos[i]);
i++;
}
pthread_mutex_destroy(room->safe);
free(room->safe);
free(room->philos);
free(room->param);
free(room);
return (0);
}

70
philo/philosophers.h

@ -0,0 +1,70 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* philosophers.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/24 15:44:06 by narnaud #+# #+# */
/* Updated: 2022/05/16 14:09:56 by narnaud ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef PHILOSOPHERS_H
# define PHILOSOPHERS_H
# define CLOCK_ONE 500
# define CLOCK_TWO 1000
# include <unistd.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <pthread.h>
# include <sys/time.h>
typedef struct s_param
{
int philo_amount;
int die_time;
int eat_duration;
int sleep_duration;
int eat_amount;
} t_param;
typedef struct s_philo
{
pthread_mutex_t *fork;
pthread_mutex_t *safe;
pthread_t *thd;
unsigned long eat_time;
int eat_amount;
int i;
} t_philo;
typedef struct s_room
{
t_param *param;
t_philo **philos;
pthread_mutex_t *safe;
pthread_t clock_thd;
int running;
unsigned long start_time;
unsigned long time;
int i;
} t_room;
//philo_threads.c
void *philos_life(void *r);
void *room_clock(void *r);
//philo_init.c
t_param *init_param(char **argv);
t_room *init_room(char **argv);
//philo_utils.c
int mini_atoi(char *nbr);
void safe_print(char *str, t_room *room, int id);
int clean_memory(t_room *room);
int check_end(t_room *room);
#endif

102
philo_bonus/philo.c

@ -0,0 +1,102 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* philo.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/05/16 14:03:42 by narnaud #+# #+# */
/* Updated: 2022/05/16 14:03:47 by narnaud ### ########.fr */
/* */
/* ************************************************************************** */
#include "philosophers.h"
void *check_halt(void * p)
{
size_t time;
t_philo *philo;
philo = p;
while (1)
{
usleep(1000);
time = gettime();
philo->table->time = time;
if (time - philo->last_meal_time > philo->table->time_to_die)
{
printf("%lu %d died\n", time, philo->id);
exit(EXIT_SUCCESS);
}
}
}
void philo_life(t_philo *philo)
{
t_table *table;
table = philo->table;
while (1)
{
sem_wait(table->sptr);
printf("%lu %d has taken a fork\n", table->time, philo->id);
sem_wait(table->sptr);
printf("%lu %d has taken a fork\n", table->time, philo->id);
philo->last_meal_time = table->time;
printf("%lu %d is eating\n", table->time, philo->id);
usleep(table->eating_time * 1000);
sem_post(table->sptr);
sem_post(table->sptr);
printf("%lu %d is sleeping\n", table->time, philo->id);
usleep(table->sleeping_time * 1000);
printf("%lu %d is thinking\n", table->time, philo->id);
}
}
void init_philos(t_table *table)
{
size_t i;
pthread_t checks;
table->pid = malloc(sizeof(pid_t) * table->nb_of_philos);
memset(table->pid, 0, sizeof(pid_t) * table->nb_of_philos);
i = 0;
while (i < table->nb_of_philos)
{
table->pid[i] = fork();
table->philos[i].table = table;
table->philos[i].id = i;
if (!table->pid[i])
{
pthread_create(&checks, NULL, check_halt, table->philos + i);
philo_life(table->philos + i);
}
usleep(500);
i++;
}
}
int main(int argc, char **argv)
{
static t_table *table;
static size_t i = 0;
int status;
sem_unlink("/chopsticks");
sem_unlink("/death");
if (argc < 5 || argc > 6)
return (1);
table = parsing(argv + 1);
table->sptr = sem_open("/chopsticks", O_CREAT, 0664, table->nb_of_philos);
table->death = sem_open("/death", O_CREAT, 0664, 1);
init_philos(table);
waitpid(-1, &status, 0);
while (i < table->nb_of_philos)
{
kill(table->pid[i], SIGINT);
i++;
}
sem_unlink("/chopsticks");
sem_unlink("/deaths");
return(0);
}

60
philo_bonus/philo_utils.c

@ -0,0 +1,60 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* philo_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/05/16 14:04:06 by narnaud #+# #+# */
/* Updated: 2022/05/16 14:04:11 by narnaud ### ########.fr */
/* */
/* ************************************************************************** */
#include "philosophers.h"
static int mini_atoi(char *nbr)
{
int ret;
ret = 0;
while (*nbr >= '0' && *nbr <= '9')
{
ret = (*nbr - '0') + (10 * ret);
nbr++;
}
return (ret);
}
t_table *parsing(char **argv)
{
t_table *table;
table = malloc(sizeof(t_table));
memset(table, 0, sizeof(t_table));
table->nb_of_philos = mini_atoi(argv[0]);
table->philos = malloc(sizeof(t_philo) * table->nb_of_philos);
memset(table->philos, 0, sizeof(t_philo) * table->nb_of_philos);
table->time_to_die = mini_atoi(argv[1]);
table->eating_time = mini_atoi(argv[2]);
table->sleeping_time = mini_atoi(argv[3]);
table->time = gettime();
if (argv[4])
table->nb_of_meal = mini_atoi(argv[4]);
else
table->nb_of_meal = 2147483647;
return (table);
}
size_t gettime(void)
{
static struct timeval time = {0,0};
struct timeval actualtime;
size_t ret;
if(time.tv_sec == 0 && time.tv_usec == 0)
gettimeofday(&time, NULL);
gettimeofday(&actualtime, NULL);
ret = (size_t)((actualtime.tv_sec * 1000 + actualtime.tv_usec / 1000)\
- (time.tv_sec * 1000 + time.tv_usec / 1000));
return (ret);
}

71
philo_bonus/philosophers.h

@ -0,0 +1,71 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* philosophers.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/05/16 14:03:01 by narnaud #+# #+# */
/* Updated: 2022/05/16 14:03:20 by narnaud ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef PHILOSOPHERS_H
# define PHILOSOPHERS_H
/*
Chaque philosophe doit être représenté par un thread.
Toutes les fourchettes sont au centre de la table.
Elles nont pas détat spécifique en mémoire, mais le nombre de fourchettes
disponibles est représenté par un sémaphore. Chaque philosophe est représenté
par un processus différent. Cependant, le processus principal ne doit pas être
un philosophe.
*/
# include <unistd.h>
# include <stdio.h>
# include <stdlib.h>
# include <pthread.h>
# include <string.h>
# include <errno.h>
# include <fcntl.h>
# include <signal.h>
# include <sys/wait.h>
# include <sys/time.h>
# include <sys/stat.h>
# include <semaphore.h>
typedef struct s_table t_table;
typedef struct s_philo
{
int id;
size_t meals_done;
size_t last_meal_time;
t_table *table;
} t_philo;
typedef struct s_table
{
size_t nb_of_philos;
size_t time_to_die;
size_t eating_time;
size_t sleeping_time;
size_t nb_of_meal;
int i;
sem_t *sptr;
sem_t *death;
t_philo *philos;
size_t time;
size_t start_time;
int *pid;
} t_table;
/***************************/
t_table *parsing(char **argv);
size_t gettime(void);
#endif
Loading…
Cancel
Save