/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* state_monitor.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: ruiferna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/07 20:54:07 by ruiferna #+# #+# */ /* Updated: 2025/10/07 22:07:12 by ruiferna ### ########.fr */ /* */ /* ************************************************************************** */ #include #include #include #include #include #include // 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); }