philosophers_prep/rendu/death_monitor.c

139 lines
3.4 KiB
C

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* death_monitor.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: ruiferna <ruiferna@student.42porto.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/09 20:16:37 by ruiferna #+# #+# */
/* Updated: 2025/10/10 20:51:41 by ruiferna ### ########.fr */
/* */
/* ************************************************************************** */
#include "simple_philosophers.h"
#define WORKERS 900
static pthread_mutex_t random_mutex = PTHREAD_MUTEX_INITIALIZER;
int get_random_sleep_duration() {
unsigned int seed;
pthread_mutex_lock(&random_mutex);
seed = time(NULL) ^ pthread_self();
/* produce a duration between 1000 and 4000 ms (1-4 seconds) */
int duration = 1000 + rand_r(&seed) % 6001;
pthread_mutex_unlock(&random_mutex);
return duration;
}
typedef struct
{
pthread_mutex_t mutex;
struct timeval last_activity_time;
int alive; // 1 if alive, 0 if dead
} WorkerState;
typedef struct s_shared
{
int id;
int is_dead;
pthread_t workers[WORKERS];
long long last_updated[WORKERS];
pthread_mutex_t workers_mutexes[WORKERS];
pthread_mutex_t mutex_id;
} t_shared;
void *worker_routine(void *arg)
{
t_shared *shared;
int worker_id;
int sleep_time;
shared = (t_shared *) arg;
/* assign a unique id in range [0, WORKERS-1] */
pthread_mutex_lock(&shared->mutex_id);
shared->id += 1;
worker_id = shared->id;
pthread_mutex_unlock(&shared->mutex_id);
while (1)
{
pthread_mutex_lock(&shared->workers_mutexes[worker_id]);
shared->last_updated[worker_id] = get_current_time();
pthread_mutex_unlock(&shared->workers_mutexes[worker_id]);
sleep_time = get_random_sleep_duration();
printf("Worker %i will stop for %i seconds.\n", worker_id, (int)(sleep_time / 1000));
precise_sleep(sleep_time);
}
return (NULL);
}
void *monitor_routine(void *arg)
{
t_shared *shared;
long long time_diff;
int i;
shared = (t_shared *) arg;
while (1)
{
i = 0;
while (i < WORKERS)
{
pthread_mutex_lock(&shared->workers_mutexes[i]);
time_diff = get_current_time() - shared->last_updated[i];
pthread_mutex_unlock(&shared->workers_mutexes[i]);
if (time_diff > 3000)
{
printf("Worker %i died.\n", i);
return (NULL);
}
i++;
}
/* sleep once per full scan to keep checks frequent and non-blocking */
precise_sleep(50);
}
return (NULL);
}
int main()
{
t_shared shared;
pthread_t monitor;
int i;
i = 0;
shared.id = 0;
while (i < WORKERS)
{
pthread_mutex_init(&shared.workers_mutexes[i], NULL);
i++;
}
pthread_mutex_init(&shared.mutex_id, NULL);
i = 0;
while (i < WORKERS)
{
if (pthread_create(&shared.workers[i], NULL, worker_routine, &shared) != 0)
{
perror("pthread_create");
exit(EXIT_FAILURE);
}
i++;
}
pthread_create(&monitor, NULL, monitor_routine, &shared);
pthread_join(monitor, NULL);
// i = 0;
// while (i < WORKERS)
// {
// pthread_join(shared.workers[i], NULL);
// i++;
// }
return (0);
}