Added subject resolutions for the first 4 exercices

This commit is contained in:
Rui Ribeiro 2025-10-07 22:08:15 +01:00
parent 8779aa24a6
commit 901f15dd56
4 changed files with 372 additions and 0 deletions

68
rendu/mutex_basics.c Normal file
View File

@ -0,0 +1,68 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* mutex_basics.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: ruiferna <ruiferna@student.42porto.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/07 16:09:59 by ruiferna #+# #+# */
/* Updated: 2025/10/07 20:25:56 by ruiferna ### ########.fr */
/* */
/* ************************************************************************** */
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/time.h>
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);
}

52
rendu/precise_timing.c Normal file
View File

@ -0,0 +1,52 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* precise_timing.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: ruiferna <ruiferna@student.42porto.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/07 20:17:52 by ruiferna #+# #+# */
/* Updated: 2025/10/07 20:49:11 by ruiferna ### ########.fr */
/* */
/* ************************************************************************** */
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
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);
}

179
rendu/state_monitor.c Normal file
View File

@ -0,0 +1,179 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

73
rendu/thread_basics.c Normal file
View File

@ -0,0 +1,73 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* thread_basics.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: ruiferna <ruiferna@student.42porto.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <stdio.h>
#include <pthread.h>
#include <stdlib.h>
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 <number_of_times>\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);
}