Added subject resolutions for the first 4 exercices
This commit is contained in:
parent
8779aa24a6
commit
901f15dd56
68
rendu/mutex_basics.c
Normal file
68
rendu/mutex_basics.c
Normal 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
52
rendu/precise_timing.c
Normal 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
179
rendu/state_monitor.c
Normal 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
73
rendu/thread_basics.c
Normal 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);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user