Add TD 8 & 9
This commit is contained in:
parent
7665dec314
commit
973b6eacd6
84
TD/TD8/exercise1a.c
Normal file
84
TD/TD8/exercise1a.c
Normal file
@ -0,0 +1,84 @@
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define N 20
|
||||
#define PROD 5
|
||||
#define CONS 5
|
||||
#define PROD_MAX 500
|
||||
|
||||
int shared_buffer[N];
|
||||
|
||||
void* producteur(void* args) {
|
||||
int j, product = 0;
|
||||
int count = 0;
|
||||
while (1) {
|
||||
int i = -1;
|
||||
while (++i < N) {
|
||||
if (shared_buffer[i] == -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= N) {
|
||||
sleep(0.05);
|
||||
continue;
|
||||
}
|
||||
product = (rand()%500+product)%20000;
|
||||
j = (i+j)%20000;
|
||||
shared_buffer[i] = product;
|
||||
count++;
|
||||
if (!(count % 5000))
|
||||
printf("produit: %d %d\n", j, product);
|
||||
sleep(0.05);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* consommateur(void* args) {
|
||||
int j, product = 0;
|
||||
int count = 0;
|
||||
while (1) {
|
||||
int i = -1;
|
||||
while (++i < N) {
|
||||
if (shared_buffer[i] != -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= N) {
|
||||
sleep(0.05);
|
||||
continue;
|
||||
}
|
||||
product = (shared_buffer[i]+product)%20000;
|
||||
j = (i+j)%20000;
|
||||
shared_buffer[i] = -1;
|
||||
count++;
|
||||
if (!(count %5000))
|
||||
printf("résultat: %d %d %d\n", j, product);
|
||||
sleep(0.05);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main() {
|
||||
for (int i=0; i < N; i++) {
|
||||
shared_buffer[i] = -1;
|
||||
}
|
||||
|
||||
pthread_t tid[PROD+CONS];
|
||||
for (int i=0; i < PROD; i++) {
|
||||
pthread_create(&(tid[i]), NULL, &producteur, NULL);
|
||||
}
|
||||
|
||||
for (int i=0; i < CONS; i++) {
|
||||
pthread_create(&(tid[i+PROD]), NULL, &consommateur, NULL);
|
||||
}
|
||||
|
||||
for (int i=0; i < PROD+CONS; i++) {
|
||||
pthread_join(tid[i], NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
120
TD/TD8/exercise1b.c
Normal file
120
TD/TD8/exercise1b.c
Normal file
@ -0,0 +1,120 @@
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#define N 10
|
||||
#define PROD 5
|
||||
#define CONS 3
|
||||
#define PROD_MAX 500
|
||||
#define DELAY 1
|
||||
|
||||
#define RED "\033[31m"
|
||||
#define RESET "\033[0m"
|
||||
|
||||
|
||||
sem_t sem_prod;
|
||||
sem_t sem_cons;
|
||||
sem_t sem_renderer;
|
||||
|
||||
int shared_buffer[N];
|
||||
pthread_mutex_t lock;
|
||||
|
||||
void* producteur(void* args) {
|
||||
while (1) {
|
||||
sem_wait(&sem_prod);
|
||||
pthread_mutex_lock(&lock);
|
||||
int i = -1;
|
||||
while (++i < N) {
|
||||
if (shared_buffer[i] == -1) {
|
||||
shared_buffer[i] = rand()%PROD_MAX;
|
||||
sem_post(&sem_cons);
|
||||
sem_post(&sem_renderer);
|
||||
//printf("placed@%d !\n", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= N) {
|
||||
fprintf(stderr, "Can't place my product !\n");
|
||||
exit(1);
|
||||
}
|
||||
pthread_mutex_unlock(&lock);
|
||||
sleep(DELAY);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* consommateur(void* args) {
|
||||
while (1) {
|
||||
sem_wait(&sem_cons);
|
||||
pthread_mutex_lock(&lock);
|
||||
int i = -1;
|
||||
while (++i < N) {
|
||||
if (shared_buffer[i] != -1) {
|
||||
shared_buffer[i] = -1;
|
||||
//printf("got@%d !\n", i);
|
||||
sem_post(&sem_prod);
|
||||
sem_post(&sem_renderer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= N) {
|
||||
fprintf(stderr, "Can't get a product !\n");
|
||||
exit(1);
|
||||
}
|
||||
pthread_mutex_unlock(&lock);
|
||||
sleep(DELAY);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* renderer(void* args) {
|
||||
while (1) {
|
||||
sem_wait(&sem_renderer);
|
||||
pthread_mutex_lock(&lock);
|
||||
printf("\r");
|
||||
for (int i=0; i < N; i++) {
|
||||
if (shared_buffer[i] == -1) {
|
||||
printf(RED "%3d " RESET, shared_buffer[i]);
|
||||
} else {
|
||||
printf("%3d ", shared_buffer[i]);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main() {
|
||||
for (int i=0; i < N; i++) {
|
||||
shared_buffer[i] = -1;
|
||||
}
|
||||
|
||||
pthread_mutex_init(&lock, NULL);
|
||||
|
||||
pthread_t tid[PROD+CONS+1];
|
||||
sem_init(&sem_prod, 0, N);
|
||||
sem_init(&sem_cons, 0, 0);
|
||||
sem_init(&sem_renderer, 0, 1);
|
||||
for (int i=0; i < PROD; i++) {
|
||||
pthread_create(&(tid[i]), NULL, &producteur, NULL);
|
||||
}
|
||||
|
||||
for (int i=0; i < CONS; i++) {
|
||||
pthread_create(&(tid[i+PROD]), NULL, &consommateur, NULL);
|
||||
}
|
||||
|
||||
// Additional renderer thread to display the state of the market
|
||||
pthread_create(&(tid[CONS+PROD]), NULL, &renderer, NULL);
|
||||
|
||||
|
||||
for (int i=0; i < PROD+CONS+1; i++) {
|
||||
pthread_join(tid[i], NULL);
|
||||
}
|
||||
sem_destroy(&sem_cons);
|
||||
sem_destroy(&sem_prod);
|
||||
|
||||
return 0;
|
||||
}
|
146
TD/TD8/exercise2.c
Normal file
146
TD/TD8/exercise2.c
Normal file
@ -0,0 +1,146 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
Ordre des pipes:
|
||||
AB 0
|
||||
AC 1
|
||||
AD 2
|
||||
BI 3
|
||||
CE 4
|
||||
CF 5
|
||||
DH 6
|
||||
EG 7
|
||||
FG 8
|
||||
GI 9
|
||||
HI 10
|
||||
IA 11
|
||||
*/
|
||||
|
||||
int main() {
|
||||
int* fds[12];
|
||||
|
||||
for (int i=0; i < 12; i++) {
|
||||
fds[i] = malloc(sizeof(int)*2);
|
||||
pipe(fds[i]);
|
||||
}
|
||||
|
||||
int i=0;
|
||||
for (; i < 9; i++) {
|
||||
if (fork()) { break; } // Generate 9 processes
|
||||
if (i == 8) { return 0; }
|
||||
}
|
||||
|
||||
int input[3] = {-1, -1, -1};
|
||||
int output[3] = {-1, -1, -1};
|
||||
|
||||
char id = 'A'+i;
|
||||
switch (id) {
|
||||
case 'A': {// A
|
||||
input[0] = 11;
|
||||
output[0] = 0;
|
||||
output[1] = 1;
|
||||
output[2] = 2;
|
||||
} break;
|
||||
case 'B': {// B
|
||||
input[0] = 0;
|
||||
output[0] = 3;
|
||||
} break;
|
||||
case 'C': {// C
|
||||
input[0] = 1;
|
||||
output[0] = 4;
|
||||
output[1] = 5;
|
||||
} break;
|
||||
case 'D': {// D
|
||||
input[0] = 2;
|
||||
output[0] = 6;
|
||||
} break;
|
||||
case 'E': {// E
|
||||
input[0] = 4;
|
||||
output[0] = 7;
|
||||
} break;
|
||||
case 'F': {// F
|
||||
input[0] = 5;
|
||||
output[0] = 8;
|
||||
} break;
|
||||
case 'G': {// G
|
||||
input[0] = 7;
|
||||
input[1] = 8;
|
||||
output[0] = 9;
|
||||
} break;
|
||||
case 'H': {// H
|
||||
input[0] = 6;
|
||||
output[0] = 10;
|
||||
} break;
|
||||
case 'I': {// I
|
||||
input[0] = 3;
|
||||
input[1] = 9;
|
||||
input[2] = 10;
|
||||
output[0] = 11;
|
||||
} break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE* in_stream[3];
|
||||
FILE* out_stream[3];
|
||||
|
||||
for (int j=0; j < 3; j++) {
|
||||
if (input[j] != -1) {
|
||||
in_stream[j] = fdopen(fds[input[j]][0], "r");
|
||||
}
|
||||
if (output[j] != -1) {
|
||||
out_stream[j] = fdopen(fds[output[j]][1], "w");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printf("%c: got %d %d %d > %d %d %d\n", id, input[0], input[1], input[2], output[0], output[1], output[2]);
|
||||
sleep(1);
|
||||
|
||||
if (id == 'I') {
|
||||
int c;
|
||||
while (1) { // Get things from stdin
|
||||
c = getchar();
|
||||
for (int j=0; j < 3; j++) {
|
||||
if (output[j] != -1) {
|
||||
fputc(c, out_stream[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
while (1) {
|
||||
printf("%c listening...\n", id);
|
||||
|
||||
int c, d;
|
||||
d = -1;
|
||||
for (int j=0; j < 3; j++) {
|
||||
if (input[j] != -1) {
|
||||
c = fgetc(in_stream[j]);
|
||||
if (d != -1 && c != d) {
|
||||
fprintf(stderr, "%c got two different chars: %c vs %c\n", id, c, d);
|
||||
}
|
||||
d = c;
|
||||
}
|
||||
}
|
||||
printf("%c received %c\n", id, c);
|
||||
for (int j=0; j < 3; j++) {
|
||||
if (output[j] != -1) {
|
||||
printf("%c transmits %c to %d\n", id, c, output[j]);
|
||||
fputc(c, out_stream[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j=0; j < 3; j++) {
|
||||
if (input[j] != -1) {
|
||||
fclose(in_stream[j]);
|
||||
}
|
||||
if (output[j] != -1) {
|
||||
fclose(out_stream[j]);
|
||||
}
|
||||
}
|
||||
}
|
12
TD/TD8/index.md
Normal file
12
TD/TD8/index.md
Normal file
@ -0,0 +1,12 @@
|
||||
# TD 8: Threads and synchronisation
|
||||
|
||||
## Reasoning operating systems: questions
|
||||
|
||||
1. Différent mécanismes pour différentes utilisations:
|
||||
- mutex locks pour gérer l'accès à une ressource
|
||||
- sémaphores pour gérer l'accès à une quantité de variables
|
||||
- variables de condition
|
||||
- spin lock: comme sémaphore mais avec du temps processus
|
||||
2. Cela indique quelles fourchettes sont utilisées,
|
||||
chaque philosophe n'utilisant que 2 fourchettes ou aucune à la fois
|
||||
3. Deadlock possible
|
69
TD/TD9/exercice1.c
Normal file
69
TD/TD9/exercice1.c
Normal file
@ -0,0 +1,69 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define N 50
|
||||
//#define SHOW_DETAILS
|
||||
|
||||
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
void* access_res(void* args) {
|
||||
int id = *(int*)args;
|
||||
*(int*)args = 0;
|
||||
|
||||
for (int i=0; i < INT_MAX; i++) {
|
||||
pthread_mutex_lock(&lock);
|
||||
*(int*)args += 1;
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
*(int*)args = -1;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main() {
|
||||
pthread_t tid[N];
|
||||
int args[N]; // Reuse it for the number of accesses
|
||||
|
||||
for (int i=0; i < N; i++) {
|
||||
args[i] = i;
|
||||
pthread_create(&(tid[i]), NULL, &access_res, (void*)&(args[i]));
|
||||
}
|
||||
|
||||
bool is_end = false;
|
||||
while (!is_end) {
|
||||
#ifdef SHOW_DETAILS
|
||||
printf("Accesses:\n");
|
||||
#endif
|
||||
int max, min, avg;
|
||||
max = avg = 0;
|
||||
min = INT_MAX;
|
||||
for (int i=0; i < N; i++) {
|
||||
#ifdef SHOW_DETAILS
|
||||
printf("%d ", args[i]);
|
||||
#endif
|
||||
if (args[i] == -1)
|
||||
is_end = true;
|
||||
|
||||
if (args[i] > max)
|
||||
max = args[i];
|
||||
|
||||
if (args[i] < min)
|
||||
min = args[i];
|
||||
|
||||
avg += args[i]/N;
|
||||
}
|
||||
#ifdef SHOW_DETAILS
|
||||
printf("\n");
|
||||
#endif
|
||||
printf("min max avg : %d %d %d\n", min, max, avg);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
for (int i=0; i < N; i++) {
|
||||
pthread_join(tid[i], NULL);
|
||||
}
|
||||
}
|
63
TD/TD9/exercice2.c
Normal file
63
TD/TD9/exercice2.c
Normal file
@ -0,0 +1,63 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
|
||||
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_mutex_t mutex3 = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
|
||||
void* process_fun(void* arg) {
|
||||
int id = *(int*)arg;
|
||||
bool success = false;
|
||||
pthread_mutex_t* mutexs[3];
|
||||
if (id == 0) { // Gives deadlock sometimes
|
||||
mutexs[0] = &mutex1;
|
||||
mutexs[1] = &mutex2;
|
||||
mutexs[2] = &mutex3;
|
||||
} else if (id == 1) {
|
||||
mutexs[0] = &mutex2;
|
||||
mutexs[1] = &mutex1;
|
||||
mutexs[2] = &mutex3;
|
||||
} else if (id == 2) {
|
||||
mutexs[0] = &mutex1;
|
||||
mutexs[1] = &mutex2;
|
||||
mutexs[2] = &mutex3;
|
||||
}
|
||||
|
||||
while (!success) {
|
||||
bool csucc = true;
|
||||
for (int i=0; i < 3; i++) {
|
||||
if (pthread_mutex_trylock(mutexs[i]) != 0) {
|
||||
for (int j=0; j < i; j++) {
|
||||
pthread_mutex_unlock(mutexs[i]);
|
||||
}
|
||||
csucc = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
success = csucc;
|
||||
}
|
||||
printf("I have access\n");
|
||||
pthread_mutex_unlock(mutexs[0]);
|
||||
pthread_mutex_unlock(mutexs[1]);
|
||||
pthread_mutex_unlock(mutexs[2]);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main() {
|
||||
pthread_t tid[3];
|
||||
int args[3];
|
||||
|
||||
for (int i=0; i < 3; i++) {
|
||||
args[i] = i;
|
||||
pthread_create(&(tid[i]), NULL, &process_fun, &(args[i]));
|
||||
}
|
||||
|
||||
for (int i=0; i < 3; i++) {
|
||||
pthread_join(tid[i], NULL);
|
||||
}
|
||||
}
|
8
TD/TD9/index.md
Normal file
8
TD/TD9/index.md
Normal file
@ -0,0 +1,8 @@
|
||||
# Deadlocks
|
||||
|
||||
## Reasoning operating systems
|
||||
|
||||
1. Les processus 1 et 4 sont en deadlock.
|
||||
2. On n'a pas le graphe des tâches qui vont arriver en avance. Donc c'est plus compliqué dans un monde réel
|
||||
3. 1/6 : same order is deadlock free
|
||||
|
Loading…
Reference in New Issue
Block a user