diff --git a/src/scheduler.c b/src/scheduler.c index bbf1d11447b5d77e4fac24e6d59869e450e030a8..be4e9ceb755cbe5d181ace3884682eccfed8207c 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -1,6 +1,7 @@ /******************************************************************************* * This file is part of SWIFT. * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk) + * Matthieu Schaller (matthieu.schaller@durham.ac.uk) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published @@ -792,6 +793,7 @@ void scheduler_reset(struct scheduler *s, int size) { s->nr_tasks = 0; s->tasks_next = 0; s->waiting = 0; + s->mask = 0; /* Set the task pointers in the queues. */ for (k = 0; k < s->nr_queues; k++) s->queues[k].tasks = s->tasks; @@ -902,13 +904,16 @@ void scheduler_start(struct scheduler *s, unsigned int mask) { struct task *t, *tasks = s->tasks; // ticks tic; + /* Store the mask */ + s->mask = mask; + /* Run through the tasks and set their waits. */ // tic = getticks(); for (k = nr_tasks - 1; k >= 0; k--) { t = &tasks[tid[k]]; t->wait = 0; t->rid = -1; - if (!((1 << t->type) & mask) || t->skip) continue; + if (!((1 << t->type) & s->mask) || t->skip) continue; for (j = 0; j < t->nr_unlock_tasks; j++) atomic_inc(&t->unlock_tasks[j]->wait); } @@ -916,13 +921,13 @@ void scheduler_start(struct scheduler *s, unsigned int mask) { // CPU_TPS * 1000 ); /* Don't enqueue link tasks directly. */ - mask &= ~(1 << task_type_link); + s->mask &= ~(1 << task_type_link); /* Loop over the tasks and enqueue whoever is ready. */ // tic = getticks(); for (k = 0; k < nr_tasks; k++) { t = &tasks[tid[k]]; - if (((1 << t->type) & mask) && !t->skip) { + if (((1 << t->type) & s->mask) && !t->skip) { if (t->wait == 0) { scheduler_enqueue(s, t); pthread_cond_broadcast(&s->sleep_cond); @@ -948,14 +953,16 @@ void scheduler_enqueue(struct scheduler *s, struct task *t) { int err; #endif - /* Ignore skipped tasks. */ - if (t->skip || atomic_cas(&t->rid, -1, 0) != -1) return; + /* Ignore skipped tasks and tasks not in the mask. */ + if (t->skip || ((1 << t->type) & ~(s->mask) && t->type != task_type_link) || + atomic_cas(&t->rid, -1, 0) != -1) + return; /* If this is an implicit task, just pretend it's done. */ if (t->implicit) { for (int j = 0; j < t->nr_unlock_tasks; j++) { struct task *t2 = t->unlock_tasks[j]; - if (atomic_dec(&t2->wait) == 1 && !t2->skip) scheduler_enqueue(s, t2); + if (atomic_dec(&t2->wait) == 1) scheduler_enqueue(s, t2); } } @@ -1055,19 +1062,13 @@ struct task *scheduler_done(struct scheduler *s, struct task *t) { /* Loop through the dependencies and add them to a queue if they are ready. */ - for (k = 0; k < t->nr_unlock_tasks; k++) { - t2 = t->unlock_tasks[k]; - if ((res = atomic_dec(&t2->wait)) < 1) error("Negative wait!"); - if (res == 1 && !t2->skip) { - if (0 && !t2->implicit && t2->ci->super == super && - (next == NULL || t2->weight > next->weight) && task_lock(t2)) { - if (next != NULL) { - task_unlock(next); - scheduler_enqueue(s, next); - } - next = t2; - } else - scheduler_enqueue(s, t2); + for (int k = 0; k < t->nr_unlock_tasks; k++) { + struct task *t2 = t->unlock_tasks[k]; + int res = atomic_dec(&t2->wait); + if (res < 1) { + error("Negative wait!"); + } else if (res == 1) { + scheduler_enqueue(s, t2); } } @@ -1075,16 +1076,15 @@ struct task *scheduler_done(struct scheduler *s, struct task *t) { if (!t->implicit) { t->toc = getticks(); pthread_mutex_lock(&s->sleep_mutex); - if (next == NULL) atomic_dec(&s->waiting); + atomic_dec(&s->waiting); pthread_cond_broadcast(&s->sleep_cond); pthread_mutex_unlock(&s->sleep_mutex); } - /* Start the clock on the follow-up task. */ - if (next != NULL) next->tic = getticks(); - - /* Return the next best task. */ - return next; + /* Return the next best task. Note that we currently do not + implement anything that does this, as getting it to respect + priorities is too tricky and currently unnecessary. */ + return NULL; } /** @@ -1104,26 +1104,29 @@ struct task *scheduler_unlock(struct scheduler *s, struct task *t) { /* Loop through the dependencies and add them to a queue if they are ready. */ - for (k = 0; k < t->nr_unlock_tasks; k++) { - t2 = t->unlock_tasks[k]; - if ((res = atomic_dec(&t2->wait)) < 1) error("Negative wait!"); - if (res == 1 && !t2->skip) scheduler_enqueue(s, t2); + for (int k = 0; k < t->nr_unlock_tasks; k++) { + struct task *t2 = t->unlock_tasks[k]; + int res = atomic_dec(&t2->wait); + if (res < 1) { + error("Negative wait!"); + } else if (res == 1) { + scheduler_enqueue(s, t2); + } } /* Task definitely done. */ if (!t->implicit) { t->toc = getticks(); pthread_mutex_lock(&s->sleep_mutex); - if (next == NULL) atomic_dec(&s->waiting); + atomic_dec(&s->waiting); pthread_cond_broadcast(&s->sleep_cond); pthread_mutex_unlock(&s->sleep_mutex); } - /* Start the clock on the follow-up task. */ - if (next != NULL) next->tic = getticks(); - - /* Return the next best task. */ - return next; + /* Return the next best task. Note that we currently do not + implement anything that does this, as getting it to respect + priorities is too tricky and currently unnecessary. */ + return NULL; } /** diff --git a/src/scheduler.h b/src/scheduler.h index fd30c76f56ec7ffceba8af10a96127ca2ffc0135..82371f9c3d1b88e613ead7df7246ae44e700dfdf 100644 --- a/src/scheduler.h +++ b/src/scheduler.h @@ -1,6 +1,7 @@ /******************************************************************************* * This file is part of SWIFT. * Copyright (c) 2013 Pedro Gonnet (pedro.gonnet@durham.ac.uk) + * Matthieu Schaller (matthieu.schaller@durham.ac.uk) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published @@ -50,6 +51,9 @@ struct scheduler { /* Scheduler flags. */ unsigned int flags; + /* Scheduler mask */ + unsigned int mask; + /* Number of queues in this scheduler. */ int nr_queues;