Skip to content
Snippets Groups Projects
Commit 5060be8f authored by iliya's avatar iliya
Browse files

ex2 done, ex1 for later

parent b71d2051
No related branches found
No related tags found
No related merge requests found
# Exercice 1
Le coeur des 3 threads ci-dessous (appelés en boucle) peuvent avoir grand nombre d’occurrences
chacun. Les mutex sont déjà initialisés correctement. Les appels aux ressources X(), Y() et Z() ne
sont pas thread-safe.
## Coeur du thread A
```c
mutex_lock(&mutex_x);
use_X();
mutex_unlock(&mutex_x);
```
## Coeur du thread B
```c
mutex_lock(&mutex_y);
use_Y();
mutex_unlock(&mutex_y)
```
## Coeur du thread C
```c
mutex_lock(&mutex_z);
use_Z();
mutex_unlock(&mutex_z)
```
## Exécution
avec :
```c
use_X() {
X() ;
mutex_lock(&mutex_y);
Y();
mutex_unlock(&mutex_y);
}
use_Y() {
Y() ;
mutex_lock(&mutex_z);
Z();
mutex_unlock(&mutex_z);
}
use_Z() {
Z() ;
mutex_lock(&mutex_x);
X();
mutex_unlock(&mutex_x);
}
```
## Questions
1. Mais cette solution peut présenter un dead-lock . Démontrez-le de façon explicite.
2. Est-ce que la solution proposée ci-dessus fonctionnerait si seulement les version A et B des
threads étaient utilisés (à plusieurs exemplaires) ?
3. Corrigez la solution complète, **en conservant des sections critiques les plus courtes possibles.**
*.o
prog
CC := clang
CFLAGS := -g -pedantic -std=gnu11 -Wall -Wextra
LDFLAGS := -fsanitize=address,leak,undefined -lpthread
TARGET := prog
all: $(TARGET)
$(TARGET): prog.o
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -c $<
.PHONY: clean
clean:
rm -f *.o $(TARGET)
.PHONY: rebuild
rebuild: clean all
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int nb_threads;
pthread_mutex_t counter_lock;
int counter;
pthread_cond_t can_proceed;
} barrier_t;
barrier_t b;
void barrier_init(barrier_t *b, int count) {
if (count < 1) {
fprintf(stderr, "Cannot initialize a barrier for less than 1 thread\n");
return;
}
b->nb_threads = count;
b->counter = 0;
pthread_cond_init(&b->can_proceed, NULL);
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&b->counter_lock, &attr);
fprintf(stdout, "Barrier has been successfully initialized\n");
}
void barrier_wait(barrier_t *b) {
pthread_mutex_lock(&b->counter_lock);
b->counter++;
if (b->counter == b->nb_threads) {
b->counter = 0;
pthread_cond_broadcast(&b->can_proceed);
} else {
while (pthread_cond_wait(&b->can_proceed, &b->counter_lock) != 0) {
}
}
pthread_mutex_unlock(&b->counter_lock);
}
void barrier_destroy(barrier_t *b) {
pthread_cond_destroy(&b->can_proceed);
pthread_mutex_destroy(&b->counter_lock);
}
void *routine(void __attribute__((unused)) * arg) {
fprintf(stdout, "2nd thread BEFORE barrier\n");
barrier_wait(&b);
fprintf(stdout, "2nd thread AFTER barrier\n");
return NULL;
}
int main(void) {
fprintf(stdout, "main thread started\n");
barrier_init(&b, 2);
pthread_t thread;
if (pthread_create(&thread, NULL, routine, NULL) == -1) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
fprintf(stdout, "main thread BEFORE barrier\n");
barrier_wait(&b);
fprintf(stdout, "main thread AFTER barrier\n");
if (pthread_join(thread, NULL) == -1) {
perror("pthread_join");
exit(EXIT_FAILURE);
}
barrier_destroy(&b);
return EXIT_SUCCESS;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment