diff --git a/src/sched.c b/src/sched.c index e31b8c5..8ac16fe 100644 --- a/src/sched.c +++ b/src/sched.c @@ -255,32 +255,66 @@ sched_worker(void *arg) struct scheduler *s = (struct scheduler *)arg; // Récupère le processus courant (index tableau) - int curr_th = current_thread(s); + int curr_th; + if((curr_th = current_thread(s)) < 0) { + fprintf(stderr, "Worker thread not tracked, exiting...\n"); + return NULL; + } while(1) { pthread_mutex_lock(&s->mutex[curr_th]); - // S'il on a rien à faire + // Si rien à faire if(s->top[curr_th] == -1) { - s->nthsleep++; - if(s->nthsleep == s->nthreads) { + if(s->nthsleep + 1 == s->nthreads) { // 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[curr_th]); pthread_mutex_unlock(&s->mutex[curr_th]); break; } - // TODO: Essayer de voler une tâche à un autre coeur - if(0) { - // TODO: - // - Trouver un coeur avec le + de tâches en attente - // - Prendre la tâche la plus ancienne (pas LIFO) - // - La rajouter sur notre pile + // Cherche un thread (avec le + de tâches en attente) à voler + int stolen = -1; + for(int i = 0, size = -1; i < s->nthreads; ++i) { + if(i == curr_th) { + // On ne se vole pas soi-même + continue; + } + + pthread_mutex_lock(&s->mutex[i]); + + if(s->top[i] > size) { + stolen = i; + size = s->top[i]; + } + + pthread_mutex_unlock(&s->mutex[i]); + } + + // Vole une tâche à un autre thread + if(stolen >= 0) { + struct task_info theft; + pthread_mutex_lock(&s->mutex[stolen]); + + // Actuellement on prend la tâche la plus ancienne en + // inversant la première et la dernière + // TODO: Récupérer la premiere tâche tout en respectant l'ordre + theft = s->tasks[stolen][0]; + s->tasks[stolen][0] = s->tasks[stolen][s->top[stolen]]; + s->top[stolen]--; + + pthread_mutex_unlock(&s->mutex[stolen]); + + pthread_mutex_unlock(&s->mutex[curr_th]); + + // Rajoute la tâche sur notre pile + sched_spawn_core(theft.f, theft.closure, s, curr_th); + continue; } + s->nthsleep++; pthread_cond_wait(&s->cond[curr_th], &s->mutex[curr_th]); s->nthsleep--; pthread_mutex_unlock(&s->mutex[curr_th]);