mutex as allocation

This commit is contained in:
Mylloon 2024-04-21 14:42:36 +02:00
parent f5e7a51861
commit 4481d3d25d
Signed by: Anri
GPG key ID: A82D63DFF8D1317F

View file

@ -17,7 +17,7 @@ struct scheduler {
int qlen; int qlen;
/* Mutex qui protège la structure */ /* Mutex qui protège la structure */
pthread_mutex_t mutex; pthread_mutex_t *mutex;
/* Nombre de threads instanciés */ /* Nombre de threads instanciés */
int nthreads; int nthreads;
@ -39,7 +39,7 @@ static struct scheduler sched;
void *sched_worker(void *); void *sched_worker(void *);
/* Nettoie les opérations effectuées par l'initialisation de l'ordonnanceur */ /* Nettoie les opérations effectuées par l'initialisation de l'ordonnanceur */
int cleanup_init(int); int sched_init_cleanup(int);
int int
sched_init(int nthreads, int qlen, taskfunc f, void *closure) sched_init(int nthreads, int qlen, taskfunc f, void *closure)
@ -63,27 +63,35 @@ sched_init(int nthreads, int qlen, taskfunc f, void *closure)
sched.nthsleep = 0; sched.nthsleep = 0;
if(pthread_mutex_init(&sched.mutex, NULL) != 0) { // Initialisation des mutex de chaque processus
fprintf(stderr, "Can't init mutex\n"); if(!(sched.mutex = malloc(sched.nthreads * sizeof(pthread_mutex_t)))) {
return -1; perror("Mutexes");
return sched_init_cleanup(-1);
}
for(int i = 0; i < sched.nthreads; ++i) {
if(pthread_mutex_init(&sched.mutex[i], NULL) != 0) {
fprintf(stderr, "Can't init mutex for thread %d\n", i);
return sched_init_cleanup(-1);
}
} }
// Initialisation des variables de conditions de chaque processus // Initialisation des variables de conditions de chaque processus
if(!(sched.cond = malloc(sched.nthreads * sizeof(pthread_cond_t)))) { if(!(sched.cond = malloc(sched.nthreads * sizeof(pthread_cond_t)))) {
perror("Variable conditions"); perror("Variable conditions");
return cleanup_init(-1); return sched_init_cleanup(-1);
} }
for(int i = 0; i < sched.nthreads; ++i) { for(int i = 0; i < sched.nthreads; ++i) {
if(pthread_cond_init(&sched.cond[i], NULL) != 0) { if(pthread_cond_init(&sched.cond[i], NULL) != 0) {
fprintf(stderr, "Can't init condition variable for thread %d\n", i); fprintf(stderr, "Can't init condition variable for thread %d\n", i);
return cleanup_init(-1); return sched_init_cleanup(-1);
} }
} }
sched.top = -1; sched.top = -1;
if((sched.tasks = malloc(qlen * sizeof(struct task_info))) == NULL) { if((sched.tasks = malloc(qlen * sizeof(struct task_info))) == NULL) {
perror("Stack"); perror("Stack");
return cleanup_init(-1); return sched_init_cleanup(-1);
} }
pthread_t threads[nthreads]; pthread_t threads[nthreads];
@ -102,34 +110,43 @@ sched_init(int nthreads, int qlen, taskfunc f, void *closure)
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
return cleanup_init(-1); return sched_init_cleanup(-1);
} }
} }
if(sched_spawn(f, closure, &sched) < 0) { if(sched_spawn(f, closure, &sched) < 0) {
fprintf(stderr, "Can't create the initial task\n"); fprintf(stderr, "Can't create the initial task\n");
return cleanup_init(-1); return sched_init_cleanup(-1);
} }
for(int i = 0; i < nthreads; ++i) { for(int i = 0; i < nthreads; ++i) {
if((pthread_join(threads[i], NULL) != 0)) { if((pthread_join(threads[i], NULL) != 0)) {
fprintf(stderr, "Can't wait the thread %d\n", i); fprintf(stderr, "Can't wait the thread %d\n", i);
return cleanup_init(-1); return sched_init_cleanup(-1);
} }
} }
return cleanup_init(1); return sched_init_cleanup(1);
} }
int int
cleanup_init(int ret_code) sched_init_cleanup(int ret_code)
{ {
if(!sched.cond) { if(sched.mutex) {
for(int i = 0; i < sched.nthreads; ++i) {
pthread_mutex_destroy(&sched.mutex[i]);
}
free(sched.mutex);
sched.mutex = NULL;
}
if(sched.cond) {
free(sched.cond); free(sched.cond);
sched.cond = NULL; sched.cond = NULL;
} }
if(!sched.tasks) { if(sched.tasks) {
free(sched.tasks); free(sched.tasks);
sched.tasks = NULL; sched.tasks = NULL;
@ -141,10 +158,10 @@ cleanup_init(int ret_code)
int int
sched_spawn(taskfunc f, void *closure, struct scheduler *s) sched_spawn(taskfunc f, void *closure, struct scheduler *s)
{ {
pthread_mutex_lock(&s->mutex); pthread_mutex_lock(&s->mutex[0]);
if(s->top + 1 >= s->qlen) { if(s->top + 1 >= s->qlen) {
pthread_mutex_unlock(&s->mutex); pthread_mutex_unlock(&s->mutex[0]);
errno = EAGAIN; errno = EAGAIN;
fprintf(stderr, "Stack is full\n"); fprintf(stderr, "Stack is full\n");
return -1; return -1;
@ -153,7 +170,7 @@ sched_spawn(taskfunc f, void *closure, struct scheduler *s)
s->tasks[++s->top] = (struct task_info){closure, f}; s->tasks[++s->top] = (struct task_info){closure, f};
pthread_cond_signal(&s->cond[0]); pthread_cond_signal(&s->cond[0]);
pthread_mutex_unlock(&s->mutex); pthread_mutex_unlock(&s->mutex[0]);
return 0; return 0;
} }
@ -164,7 +181,7 @@ sched_worker(void *arg)
struct scheduler *s = (struct scheduler *)arg; struct scheduler *s = (struct scheduler *)arg;
while(1) { while(1) {
pthread_mutex_lock(&s->mutex); pthread_mutex_lock(&s->mutex[0]);
// S'il on a rien à faire // S'il on a rien à faire
if(s->top == -1) { if(s->top == -1) {
@ -173,14 +190,14 @@ sched_worker(void *arg)
// Signal a tout les threads que il n'y a plus rien à faire // Signal a tout les threads que il n'y a plus rien à faire
// si un thread attend une tâche // si un thread attend une tâche
pthread_cond_broadcast(&s->cond[0]); pthread_cond_broadcast(&s->cond[0]);
pthread_mutex_unlock(&s->mutex); pthread_mutex_unlock(&s->mutex[0]);
break; break;
} }
pthread_cond_wait(&s->cond[0], &s->mutex); pthread_cond_wait(&s->cond[0], &s->mutex[0]);
s->nthsleep--; s->nthsleep--;
pthread_mutex_unlock(&s->mutex); pthread_mutex_unlock(&s->mutex[0]);
continue; continue;
} }
@ -188,7 +205,7 @@ sched_worker(void *arg)
taskfunc f = s->tasks[s->top].f; taskfunc f = s->tasks[s->top].f;
void *closure = s->tasks[s->top].closure; void *closure = s->tasks[s->top].closure;
s->top--; s->top--;
pthread_mutex_unlock(&s->mutex); pthread_mutex_unlock(&s->mutex[0]);
// Exécute la tâche // Exécute la tâche
f(closure, s); f(closure, s);