diff --git a/serie4/ex1/ex1.md b/serie4/ex1/ex1.md new file mode 100644 index 0000000000000000000000000000000000000000..e072aea6ff6efe342fbd0c1475af08dc7f947293 --- /dev/null +++ b/serie4/ex1/ex1.md @@ -0,0 +1,34 @@ +# Exercice 1 + +## Question + +Est-ce que l'algorithme ci-dessous garanti l'exclusion mutuelle sur un monoprocesseur (exclusion +mutuelle, progression, attente bornée) entre les threads T0 et T1 ? Si ce n’est pas la cas, justifiez +votre réponse en décrivant une séquence possible d’opérations qui prouve le contraire. + +```c +bool inside[2] = {false, false}; + +// id is the thread number (0 or 1) +void prelude(int id) { + while (inside[1 - id]) {} + inside[id] = true; +} + +void postlude(int id) { + inside[id] = false; +} +``` + +## Réponse + +Vu que nous sommes sur une architecture monoprocesseur, cela signifie que le +code ne pourra pas s'exécuter de manière parallèle, il n'y aura que des +changements de contexte. + +Si l'on part du principe que T0 rentre dans la fonction `prelude`, exécute la +ligne correspondante à la boucle `while (false)` qu'à la suite de cela, il y'a +un changement de contexte dans lequel T1 exécute les deux lignes de la fonction +`prelude` et que finalement T0 reprend l'exécution, à la fin on aboutira avec +les deux variables du tableau `inside` à `true` ce qui implique le fait que cet +algorithme ne garanti pas l'exclusion mutuelle car les deux variables sont à `true`. diff --git a/serie4/ex2/.gitignore b/serie4/ex2/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b6de771d2fff3a218dbc1b3de5b6b6cc1dc54e08 --- /dev/null +++ b/serie4/ex2/.gitignore @@ -0,0 +1,2 @@ +*.o +prog diff --git a/serie4/ex2/Makefile b/serie4/ex2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f702d8a6c8186500ac1ba446cff2df5a7e11690f --- /dev/null +++ b/serie4/ex2/Makefile @@ -0,0 +1,26 @@ +CC := clang +CFLAGS := -g -pedantic -Wall -Wextra -std=c11 +LDFLAGS := -fsanitize=address -fsanitize=leak -fsanitize=undefined -lm -lpthread +TARGET := prog + +all: $(TARGET) + +$(TARGET): prog.o + @printf "=================== Building executable ===================\n" + $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) + @printf "\n" + +%.o: %.c + @printf "================== Building object files ==================\n" + $(CC) $(CFLAGS) -c $< + @printf "\n" + + +.PHONY: clean + +clean: + rm -f *.o $(TARGET) + +.PHONY: rebuild + +rebuild: clean all diff --git a/serie4/ex2/prog.c b/serie4/ex2/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..0571354d24c52ef6a7113b8ffbd4ee58db3bc849 --- /dev/null +++ b/serie4/ex2/prog.c @@ -0,0 +1,53 @@ +#include <pthread.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +#define NB_THREADS 2 +#define MAX_INCREMENT 10000 + +int lock; +int counter; + +void init_lock(int *lock_ptr) { __sync_val_compare_and_swap(lock_ptr, 0, 0); } + +void acquire_lock(int *lock_ptr) { + __sync_val_compare_and_swap(lock_ptr, *lock_ptr, 1); +} + +void release_lock(int *lock_ptr) { + __sync_val_compare_and_swap(lock_ptr, *lock_ptr, 0); +} + +void *routine(void *arg) { + int *counter = (int *)arg; + acquire_lock(&lock); + for (int i = 0; i < MAX_INCREMENT; i++) { + (*counter)++; + } + release_lock(&lock); + + return NULL; +} + +int main(void) { + pthread_t threads[NB_THREADS]; + + init_lock(&lock); + + for (int i = 0; i < NB_THREADS; i++) { + if (pthread_create(&threads[i], NULL, routine, &counter) == -1) { + perror("pthread_create"); + } + } + + for (int i = 0; i < NB_THREADS; i++) { + if (pthread_join(threads[i], NULL)) { + perror("pthread_join"); + } + } + + fprintf(stdout, "Value of counter = %d\n", counter); + + return EXIT_SUCCESS; +}