From 901f15dd562fdb160e4834fc6ee25f8b06f49940 Mon Sep 17 00:00:00 2001 From: Rui Ribeiro <42305006+ruiribeiro04@users.noreply.github.com> Date: Tue, 7 Oct 2025 22:08:15 +0100 Subject: [PATCH] Added subject resolutions for the first 4 exercices --- rendu/mutex_basics.c | 68 ++++++++++++++++ rendu/precise_timing.c | 52 ++++++++++++ rendu/state_monitor.c | 179 +++++++++++++++++++++++++++++++++++++++++ rendu/thread_basics.c | 73 +++++++++++++++++ 4 files changed, 372 insertions(+) create mode 100644 rendu/mutex_basics.c create mode 100644 rendu/precise_timing.c create mode 100644 rendu/state_monitor.c create mode 100644 rendu/thread_basics.c diff --git a/rendu/mutex_basics.c b/rendu/mutex_basics.c new file mode 100644 index 0000000..6df3cac --- /dev/null +++ b/rendu/mutex_basics.c @@ -0,0 +1,68 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* mutex_basics.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ruiferna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/10/07 16:09:59 by ruiferna #+# #+# */ +/* Updated: 2025/10/07 20:25:56 by ruiferna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include +#include +#include + +void *increase_amount(void *arg); + +pthread_mutex_t mutex; + +int main() +{ + pthread_t thread1; + pthread_t thread2; + pthread_t thread3; + pthread_t thread4; + + int value = 0; + struct timeval start, end; + long long elapsed_ms; + + pthread_mutex_init(&mutex, NULL); + + gettimeofday(&start, NULL); + + pthread_create(&thread1, NULL, increase_amount, &value); + pthread_create(&thread2, NULL, increase_amount, &value); + pthread_create(&thread3, NULL, increase_amount, &value); + pthread_create(&thread4, NULL, increase_amount, &value); + + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); + pthread_join(thread3, NULL); + pthread_join(thread4, NULL); + + gettimeofday(&end, NULL); + elapsed_ms = (long long)(end.tv_sec - start.tv_sec) * 1000LL + (end.tv_usec - start.tv_usec) / 1000LL; + + pthread_mutex_destroy(&mutex); + printf("counter: %d\n", value); + printf("time: %lld ms\n", elapsed_ms); + return (0); +} + +void *increase_amount(void *arg) +{ + pthread_mutex_lock(&mutex); + int *amount = (int *)arg; + int i = 0; + while (i < 1000) + { + *amount +=1; + i++; + } + pthread_mutex_unlock(&mutex); + return (NULL); +} \ No newline at end of file diff --git a/rendu/precise_timing.c b/rendu/precise_timing.c new file mode 100644 index 0000000..c1948e7 --- /dev/null +++ b/rendu/precise_timing.c @@ -0,0 +1,52 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* precise_timing.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ruiferna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/10/07 20:17:52 by ruiferna #+# #+# */ +/* Updated: 2025/10/07 20:49:11 by ruiferna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include +#include + +long long get_current_time() +{ + struct timeval tv; + gettimeofday(&tv,NULL); + /* + A stuct tv tem tv_sec que sao os segundos desde a epoch e temos a tv_usec + que retorna os microsegundos ate completar 1 segundo (um milhão de microssegundos = 1 segundo). + Por isso, para conseguirmos realmente medir os milisegundos precisamos de juntar os dois + */ + 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; + + start_time = get_current_time(); + while ((get_current_time() - start_time) < ms) + { + usleep(100); + } +} + +int main() +{ + long long start = get_current_time(); + precise_sleep(100); + long long end = get_current_time(); + printf("Time difference: %lld ms", time_diff(start, end)); + return (0); +} \ No newline at end of file diff --git a/rendu/state_monitor.c b/rendu/state_monitor.c new file mode 100644 index 0000000..6f400a9 --- /dev/null +++ b/rendu/state_monitor.c @@ -0,0 +1,179 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* 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); +} diff --git a/rendu/thread_basics.c b/rendu/thread_basics.c new file mode 100644 index 0000000..7330d77 --- /dev/null +++ b/rendu/thread_basics.c @@ -0,0 +1,73 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* thread_basics.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ruiferna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/10/07 15:05:44 by ruiferna #+# #+# */ +/* Updated: 2025/10/07 16:46:44 by ruiferna ### ########.fr */ +/* */ +/* ************************************************************************** */ + + +// https://www.youtube.com/watch?v=ldJ8WGZVXZk + +#include +#include +#include + +typedef struct s_thread_data +{ + int id; + int p_times; +} t_thread_data; + +void *print_hello(void *arg); + +int main(int ac, char **av) +{ + pthread_t thread1; + pthread_t thread2; + t_thread_data *data1; + t_thread_data *data2; + + if (ac != 2) + { + printf("Usage: %s \n", av[0]); + return (1); + } + + int p_times = atoi(av[1]); + + data1 = malloc(sizeof(t_thread_data)); + data1->id = 1; + data1->p_times = p_times; + + data2 = malloc(sizeof(t_thread_data)); + data2->id = 2; + data2->p_times = p_times; + + pthread_create(&thread1, NULL, print_hello, data1); + pthread_create(&thread2, NULL, print_hello, data2); + + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); + + free(data1); + free(data2); + + return (0); +} + +void *print_hello(void *arg) +{ + int i = 0; + t_thread_data *data = (t_thread_data *)arg; + while (i < data->p_times) + { + printf("Thread %i: Hello from thread %i\n", data->id, data->id); + i++; + } + return (NULL); +} \ No newline at end of file