diff --git a/includes/sched.h b/includes/sched.h index 32738ec..fca019b 100644 --- a/includes/sched.h +++ b/includes/sched.h @@ -1,6 +1,5 @@ #pragma once -#include #include struct scheduler; diff --git a/src/quicksort.c b/src/quicksort.c index f59b6b7..10257b0 100644 --- a/src/quicksort.c +++ b/src/quicksort.c @@ -1,5 +1,7 @@ #include "../includes/quicksort.h" +#include + int partition(int *a, int lo, int hi) { diff --git a/src/sched.c b/src/sched.c index 8ac16fe..9a96a2c 100644 --- a/src/sched.c +++ b/src/sched.c @@ -1,6 +1,7 @@ #include "../includes/sched.h" #include +#include #include #include #include @@ -11,9 +12,6 @@ struct task_info { }; struct scheduler { - /* Indicateurs de changement d'état */ - pthread_cond_t *cond; - /* Taille des piles */ int qlen; @@ -23,9 +21,6 @@ struct scheduler { /* Nombre de threads instanciés */ int nthreads; - /* Nombre de threads en attente */ - int nthsleep; - /* Piles de tâches */ struct task_info **tasks; @@ -54,7 +49,6 @@ int current_thread(struct scheduler *); int sched_init(int nthreads, int qlen, taskfunc f, void *closure) { - sched.cond = NULL; sched.mutex = NULL; sched.tasks = NULL; sched.threads = NULL; @@ -74,8 +68,6 @@ sched_init(int nthreads, int qlen, taskfunc f, void *closure) } sched.nthreads = nthreads; - sched.nthsleep = 0; - // Initialisation des mutex de chaque processus if(!(sched.mutex = malloc(sched.nthreads * sizeof(pthread_mutex_t)))) { perror("Mutexes"); @@ -88,18 +80,6 @@ sched_init(int nthreads, int qlen, taskfunc f, void *closure) } } - // Initialisation des variables de conditions de chaque processus - if(!(sched.cond = malloc(sched.nthreads * sizeof(pthread_cond_t)))) { - perror("Variable conditions"); - 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 sched_init_cleanup(-1); - } - } - // Initialisation du curseur suivant l'état de la pile de chaque processus if(!(sched.top = malloc(sched.nthreads * sizeof(int)))) { perror("Cursor top stack\n"); @@ -121,6 +101,12 @@ sched_init(int nthreads, int qlen, taskfunc f, void *closure) } } + // Ajoute la tâche initiale + if(sched_spawn_core(f, closure, &sched, 0) < 0) { + fprintf(stderr, "Can't create the initial task\n"); + return sched_init_cleanup(-1); + } + if(!(sched.threads = malloc(sched.nthreads * sizeof(pthread_t *)))) { perror("Threads"); return sched_init_cleanup(-1); @@ -144,12 +130,6 @@ sched_init(int nthreads, int qlen, taskfunc f, void *closure) } } - // Ajoute la tâche initiale - if(sched_spawn_core(f, closure, &sched, 0) < 0) { - fprintf(stderr, "Can't create the initial task\n"); - return sched_init_cleanup(-1); - } - for(int i = 0; i < nthreads; ++i) { if((pthread_join(sched.threads[i], NULL) != 0)) { fprintf(stderr, "Can't wait the thread %d\n", i); @@ -172,11 +152,6 @@ sched_init_cleanup(int ret_code) sched.mutex = NULL; } - if(sched.cond) { - free(sched.cond); - sched.cond = NULL; - } - if(sched.tasks) { for(int i = 0; i < sched.nthreads; ++i) { if(sched.tasks[i]) { @@ -231,9 +206,12 @@ current_thread(struct scheduler *s) int sched_spawn_core(taskfunc f, void *closure, struct scheduler *s, int core) { + // printf("%d locking (a)\n", core); pthread_mutex_lock(&s->mutex[core]); + // printf("%d locked (a)\n", core); if(s->top[core] + 1 >= s->qlen) { + // printf("%d unlock (a)\n", core); pthread_mutex_unlock(&s->mutex[core]); errno = EAGAIN; fprintf(stderr, "Stack is full\n"); @@ -243,7 +221,7 @@ sched_spawn_core(taskfunc f, void *closure, struct scheduler *s, int core) s->top[core]++; s->tasks[core][s->top[core]] = (struct task_info){closure, f}; - pthread_cond_signal(&s->cond[core]); + // printf("%d unlock (a)\n", core); pthread_mutex_unlock(&s->mutex[core]); return 0; @@ -262,40 +240,39 @@ sched_worker(void *arg) } while(1) { + // printf("%d locking (b)\n", curr_th); pthread_mutex_lock(&s->mutex[curr_th]); + // printf("%d locked (b)\n", curr_th); // Si rien à faire if(s->top[curr_th] == -1) { - if(s->nthsleep + 1 == s->nthreads) { - // Signal a tout les threads que il n'y a plus rien à faire - pthread_cond_broadcast(&s->cond[curr_th]); - pthread_mutex_unlock(&s->mutex[curr_th]); - - break; - } - // Cherche un thread (avec le + de tâches en attente) à voler int stolen = -1; - for(int i = 0, size = -1; i < s->nthreads; ++i) { + /* for(int i = 0, size = -1; i < s->nthreads; ++i) { if(i == curr_th) { // On ne se vole pas soi-même continue; } + printf("%d locking (c)\n", i); pthread_mutex_lock(&s->mutex[i]); + printf("%d locked (c)\n", i); if(s->top[i] > size) { stolen = i; size = s->top[i]; } + printf("%d unlock (c)\n", i); pthread_mutex_unlock(&s->mutex[i]); - } + } */ // Vole une tâche à un autre thread if(stolen >= 0) { struct task_info theft; + // printf("%d locking (d)\n", stolen); pthread_mutex_lock(&s->mutex[stolen]); + // printf("%d locked (d)\n", stolen); // Actuellement on prend la tâche la plus ancienne en // inversant la première et la dernière @@ -304,8 +281,10 @@ sched_worker(void *arg) s->tasks[stolen][0] = s->tasks[stolen][s->top[stolen]]; s->top[stolen]--; + // printf("%d unlock (d)\n", stolen); pthread_mutex_unlock(&s->mutex[stolen]); + // printf("%d unlock (b)\n", curr_th); pthread_mutex_unlock(&s->mutex[curr_th]); // Rajoute la tâche sur notre pile @@ -314,18 +293,16 @@ sched_worker(void *arg) continue; } - s->nthsleep++; - pthread_cond_wait(&s->cond[curr_th], &s->mutex[curr_th]); - s->nthsleep--; pthread_mutex_unlock(&s->mutex[curr_th]); - - continue; + // printf("%d se tire car R à faire\n", curr_th); + break; } // Extrait la tâche de la pile taskfunc f = s->tasks[curr_th][s->top[curr_th]].f; void *closure = s->tasks[curr_th][s->top[curr_th]].closure; s->top[curr_th]--; + // printf("%d unlock (b)\n", curr_th); pthread_mutex_unlock(&s->mutex[curr_th]); // Exécute la tâche