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