Browse Source

rework

master
narnaud 3 years ago
parent
commit
08f5d8dab9
  1. 8
      philo/Makefile
  2. 58
      philo/philo_init.c
  3. 123
      philo/philo_launcher.c
  4. 132
      philo/philo_threads.c
  5. 90
      philo/philo_utils.c
  6. 38
      philo/philosophers.h

8
philo/Makefile

@ -1,10 +1,10 @@
NAME = philosophers
SRCS = philo_threads.c philo_launcher.c philo_utils.c philo_init.c
SRCS = philo_threads.c philo_launcher.c
OBJS = ${SRCS:.c=.o}
CC = gcc
CFLAGS = -Werror -Wextra -Wall -g -fsanitize=thread -D_REENTRANT
CC = clang
CFLAGS = -Werror -Wextra -Wall -g -D_REENTRANT
RM = rm -rf
.c.o:
@ -13,7 +13,7 @@ RM = rm -rf
all: $(NAME)
$(NAME): $(OBJS)
${CC} ${CFLAGS} -lpthread ${OBJS} -o ${NAME}
${CC} ${CFLAGS} -g -fsanitize=thread -lpthread ${OBJS} -o ${NAME}
clean:
${RM} ${OBJS}

58
philo/philo_init.c

@ -1,58 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* philo_init.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/04/11 10:33:01 by narnaud #+# #+# */
/* Updated: 2022/05/16 18:07:56 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;
static int i = 0;
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->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 = gettime();
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);
}

123
philo/philo_launcher.c

@ -6,13 +6,16 @@
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/24 15:44:04 by narnaud #+# #+# */
/* Updated: 2022/05/16 18:04:42 by narnaud ### ########.fr */
/* Updated: 2022/05/16 22:42:20 by narnaud ### ########.fr */
/* */
/* ************************************************************************** */
#include "philosophers.h"
int waiter(t_room *room);
void init_param(t_room *room, char **argv);
static t_room *init_room(char **argv);
static int clean_memory(t_room *room);
static int mini_atoi(char *str);
int main(int argc, char **argv)
{
@ -23,52 +26,108 @@ int main(int argc, char **argv)
room = init_room(argv + 1);
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);
usleep(50);
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->safe);
pthread_mutex_unlock(room->lock);
}
while (!waiter(room))
while (waiter(room))
usleep(CLOCK_TWO);
pthread_mutex_lock(room->lock);
room->running = 0;
return (clean_memory(room));
}
int waiter(t_room *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)
{
t_param *param;
int i;
int starvest;
int *param;
static int i = 0;
pthread_mutex_lock(room->safe);
i = 0;
param = room->param;
starvest = param->eat_amount;
while (i < param->philo_amount)
sleep(1);
while (i < param[PHILO_AMOUNT])
{
pthread_mutex_lock(room->philos[i]->safe);
if (room->philos[i]->eat_time + param->die_time < gettime())
{
safe_print("%ld %d died\n", room, i);
room->running = 0;
return (1);
}
if (room->philos[i]->eat_amount < starvest)
starvest = room->philos[i]->eat_amount;
pthread_mutex_unlock(room->philos[i]->safe);
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++;
}
if (starvest == param->eat_amount)
room->running = 0;
pthread_mutex_unlock(room->safe);
return (!room->running);
pthread_mutex_unlock(room->lock);
pthread_mutex_destroy(room->lock);
free(room->lock);
free(room->philos);
free(room);
return (0);
}
int mini_atoi(char *nbr)
{
int ret;
ret = 0;
while (*nbr >= '0' && *nbr <= '9')
{
ret = (*nbr - '0') + (10 * ret);
nbr++;
}
return (ret);
}

132
philo/philo_threads.c

@ -6,49 +6,139 @@
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/26 07:43:48 by narnaud #+# #+# */
/* Updated: 2022/05/16 17:51:21 by narnaud ### ########.fr */
/* Updated: 2022/05/16 22:28:37 by narnaud ### ########.fr */
/* */
/* ************************************************************************** */
#include "philosophers.h"
static int safe_print(char *str, t_room *room, int id)
{
int ret;
if (!room->running)
return (0);
pthread_mutex_lock(room->lock);
printf(str, room_clock(), id);
ret = room->running;
pthread_mutex_unlock(room->lock);
return (ret);
}
int safe_wait(t_room *room, int start, int duration)
{
int ret;
ret = room->running;
while (ret && (room_clock() < (start + duration)))
{
pthread_mutex_lock(room->lock);
ret = room->running;
pthread_mutex_unlock(room->lock);
usleep(50);
}
return (ret);
}
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);
}
void *philos_life(void *r)
{
t_room *room;
t_param *param;
int *param;
t_philo *philo;
int id;
int id_p;
room = (t_room *)r;
param = room->param;
pthread_mutex_lock(room->safe);
pthread_mutex_lock(room->lock);
id = room->i;
printf("Philo %d: \n", id);
philo = room->philos[id];
philo->eat_time = gettime();
id_p = (id + 1) % param->philo_amount;
while (room->running)
philo->eat_time = room_clock();
id_p = (id + 1) % param[PHILO_AMOUNT];
pthread_mutex_unlock(room->lock);
while (1)
{
pthread_mutex_unlock(room->safe);
pthread_mutex_lock(philo->fork);
safe_print("%ld %d has taken a fork\n", room, id);
if (!safe_print("%d %d has taken a fork\n", room, id))
{
pthread_mutex_unlock(philo->fork);
break ;
}
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);
if (!safe_wait(room, gettime(), param->eat_duration * 1000))
return (NULL);
safe_print("%d %d has taken a fork\n", room, id);
if(!safe_print("%d %d is eating\n", room, id))
{
pthread_mutex_unlock(philo->fork);
pthread_mutex_unlock(room->philos[id_p]->fork);
break;
}
pthread_mutex_lock(philo->lock);
philo->eat_time = room_clock();
pthread_mutex_unlock(philo->lock);
if (!safe_wait(room, room_clock(), param[EAT_DURATION]))
{
pthread_mutex_unlock(philo->fork);
pthread_mutex_unlock(room->philos[id_p]->fork);
pthread_mutex_lock(philo->safe);
philo->eat_time = gettime();
break;
}
pthread_mutex_unlock(philo->fork);
pthread_mutex_unlock(room->philos[id_p]->fork);
if(!safe_print("%d %d is sleeping\n", room, id))
break ;
pthread_mutex_lock(philo->lock);
philo->eat_amount++;
pthread_mutex_unlock(philo->safe);
safe_print("%ld %d is sleeping\n", room, id);
if (!safe_wait(room, gettime(), param->sleep_duration * 1000))
return (NULL);
safe_print("%ld %d is thinking\n", room, id);
pthread_mutex_lock(room->safe);
pthread_mutex_unlock(philo->lock);
if (!safe_wait(room, room_clock(), param[SLEEP_DURATION]))
break ;
if (!safe_print("%d %d is thinking\n", room, id))
break ;
}
pthread_mutex_unlock(room->safe);
return (NULL);
}
int room_clock()
{
struct timeval time;
int ret;
static long int start_time = 0;
gettimeofday(&time, NULL);
if (!start_time)
start_time = time.tv_sec * 1000 + time.tv_usec / 1000;
ret = (int)(time.tv_sec * 1000 + time.tv_usec / 1000 - start_time);
return (ret);
}

90
philo/philo_utils.c

@ -1,90 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* philo_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/04/11 10:29:50 by narnaud #+# #+# */
/* Updated: 2022/05/16 18:03:12 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);
}
size_t gettime(void)
{
static struct timeval start = {0,0};
struct timeval actualtime;
size_t ret;
if(start.tv_sec == 0 && start.tv_usec == 0)
gettimeofday(&start, NULL);
gettimeofday(&actualtime, NULL);
ret = (size_t)((actualtime.tv_sec * 1000 + actualtime.tv_usec / 1000)\
- (start.tv_sec * 1000 + start.tv_usec / 1000));
return (ret);
}
void safe_print(char *str, t_room *room, int id)
{
pthread_mutex_lock(room->safe);
printf(str, gettime(), id);
pthread_mutex_unlock(room->safe);
}
int safe_wait(t_room *room, size_t start, size_t duration)
{
int ret;
ret = 1;
while (ret && (gettime() < start + duration))
{
pthread_mutex_lock(room->safe);
if (!room->running)
ret = 0;
pthread_mutex_unlock(room->safe);
usleep(5000);
}
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);
}

38
philo/philosophers.h

@ -6,7 +6,7 @@
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/24 15:44:06 by narnaud #+# #+# */
/* Updated: 2022/05/16 18:06:07 by narnaud ### ########.fr */
/* Updated: 2022/03/31 12:37:23 by narnaud ### ########.fr */
/* */
/* ************************************************************************** */
@ -22,46 +22,36 @@
# include <pthread.h>
# include <sys/time.h>
typedef struct s_param
enum e_params
{
int philo_amount;
int die_time;
int eat_duration;
int sleep_duration;
int eat_amount;
} t_param;
PHILO_AMOUNT,
DIE_TIME,
EAT_DURATION,
SLEEP_DURATION,
MEALS_AMOUNT,
};
typedef struct s_philo
{
pthread_mutex_t *fork;
pthread_mutex_t *safe;
pthread_mutex_t *lock;
pthread_t *thd;
size_t eat_time;
int eat_time;
int eat_amount;
int i;
} t_philo;
typedef struct s_room
{
t_param *param;
int param[5];
t_philo **philos;
pthread_mutex_t *safe;
pthread_mutex_t *lock;
int running;
int i;
} t_room;
//philo_threads.c
int waiter(t_room *room);
void *philos_life(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 safe_wait(t_room *room, size_t start, size_t duration);
size_t gettime(void);
int room_clock();
#endif

Loading…
Cancel
Save