philosophers_prep/rendu/state_monitor.c

180 lines
5.3 KiB
C

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* state_monitor.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: ruiferna <ruiferna@student.42porto.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/07 20:54:07 by ruiferna #+# #+# */
/* Updated: 2025/10/07 22:07:12 by ruiferna ### ########.fr */
/* */
/* ************************************************************************** */
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdbool.h> // Para usar bool, true, false
#define NUM_WORKERS 3
#define WORK_DURATION 2000
#define REST_DURATION 1000
#define THINK_DURATION 1500
#define STUCK_THRESHOLD 3000
bool g_simulation_running = true;
typedef enum e_state {
WORKING,
RESTING,
THINKING
} State;
const char* state_to_string(State state) {
switch (state) {
case WORKING: return "WORKING";
case RESTING: return "RESTING";
case THINKING: return "THINKING";
default: return "UNKNOWN";
}
}
typedef struct s_worker
{
int id;
long long init_time;
long long last_state_update;
State current_state;
pthread_mutex_t data_mutex;
} t_worker;
long long get_current_time()
{
struct timeval tv;
gettimeofday(&tv,NULL);
return ((tv.tv_sec * 1000LL) + (tv.tv_usec / 1000LL));
}
long long time_diff(long long start, long long end)
{
return (end - start);
}
void precise_sleep(int ms)
{
long long start_time = get_current_time();
while ((get_current_time() - start_time) < ms)
{
usleep(100);
}
}
// ROTINA DO MONITOR
void *monitor_routine(void *arg)
{
t_worker *workers = (t_worker *)arg;
while (g_simulation_running)
{
for (int i = 0; i < NUM_WORKERS; i++)
{
pthread_mutex_lock(&workers[i].data_mutex);
long long current_time = get_current_time();
long long time_since_update = current_time - workers[i].last_state_update;
// Only check for stuck workers if they have been running for at least 1 second
if (current_time - workers[i].init_time > 1000 && time_since_update > STUCK_THRESHOLD)
{
printf("[%lld] WARNING: Worker %d stuck in %s\n",
time_diff(workers[i].init_time, current_time),
workers[i].id,
state_to_string(workers[i].current_state));
}
pthread_mutex_unlock(&workers[i].data_mutex);
}
usleep(100 * 1000);
}
return (NULL);
}
void *worker_routine(void *arg)
{
t_worker *worker = (t_worker *)arg;
while (g_simulation_running)
{
// WORKING
pthread_mutex_lock(&worker->data_mutex);
worker->current_state = WORKING;
worker->last_state_update = get_current_time();
printf("[%lld] Worker %d is %s\n", time_diff(worker->init_time, worker->last_state_update), worker->id, state_to_string(worker->current_state));
pthread_mutex_unlock(&worker->data_mutex);
precise_sleep(WORK_DURATION);
// RESTING
pthread_mutex_lock(&worker->data_mutex);
worker->current_state = RESTING;
worker->last_state_update = get_current_time();
printf("[%lld] Worker %d is %s\n", time_diff(worker->init_time, worker->last_state_update), worker->id, state_to_string(worker->current_state));
pthread_mutex_unlock(&worker->data_mutex);
precise_sleep(REST_DURATION);
// THINKING
pthread_mutex_lock(&worker->data_mutex);
worker->current_state = THINKING;
worker->last_state_update = get_current_time();
printf("[%lld] Worker %d is %s\n", time_diff(worker->init_time, worker->last_state_update), worker->id, state_to_string(worker->current_state));
pthread_mutex_unlock(&worker->data_mutex);
precise_sleep(THINK_DURATION);
}
return (NULL);
}
int main()
{
pthread_t monitor;
pthread_t workers_threads[NUM_WORKERS];
t_worker workers[NUM_WORKERS];
long long start_time = get_current_time();
for (int i = 0; i < NUM_WORKERS; i++)
{
workers[i].id = i + 1;
workers[i].current_state = WORKING;
workers[i].init_time = start_time;
workers[i].last_state_update = start_time;
pthread_mutex_init(&workers[i].data_mutex, NULL); // Inicializar o mutex
}
pthread_create(&monitor, NULL, &monitor_routine, workers);
for (int i = 0; i < NUM_WORKERS; i++)
{
pthread_create(&workers_threads[i], NULL, &worker_routine, &workers[i]);
}
sleep(10);
g_simulation_running = false;
for (int i = 0; i < NUM_WORKERS; i++)
{
pthread_join(workers_threads[i], NULL);
}
pthread_join(monitor, NULL);
for (int i = 0; i < NUM_WORKERS; i++)
{
pthread_mutex_destroy(&workers[i].data_mutex);
}
return (0);
}