Skip to content
Snippets Groups Projects
Commit 5446b651 authored by Matthieu Schaller's avatar Matthieu Schaller
Browse files

Updated the scheduler to skip tasks not in the mask.

parent d298ee47
No related branches found
No related tags found
2 merge requests!136Master,!79First version of the multiple time-stepping
/******************************************************************************* /*******************************************************************************
* This file is part of SWIFT. * This file is part of SWIFT.
* Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk) * 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 * 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 * 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) { ...@@ -792,6 +793,7 @@ void scheduler_reset(struct scheduler *s, int size) {
s->nr_tasks = 0; s->nr_tasks = 0;
s->tasks_next = 0; s->tasks_next = 0;
s->waiting = 0; s->waiting = 0;
s->mask = 0;
/* Set the task pointers in the queues. */ /* Set the task pointers in the queues. */
for (k = 0; k < s->nr_queues; k++) s->queues[k].tasks = s->tasks; 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) { ...@@ -902,13 +904,16 @@ void scheduler_start(struct scheduler *s, unsigned int mask) {
struct task *t, *tasks = s->tasks; struct task *t, *tasks = s->tasks;
// ticks tic; // ticks tic;
/* Store the mask */
s->mask = mask;
/* Run through the tasks and set their waits. */ /* Run through the tasks and set their waits. */
// tic = getticks(); // tic = getticks();
for (k = nr_tasks - 1; k >= 0; k--) { for (k = nr_tasks - 1; k >= 0; k--) {
t = &tasks[tid[k]]; t = &tasks[tid[k]];
t->wait = 0; t->wait = 0;
t->rid = -1; 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++) for (j = 0; j < t->nr_unlock_tasks; j++)
atomic_inc(&t->unlock_tasks[j]->wait); atomic_inc(&t->unlock_tasks[j]->wait);
} }
...@@ -916,13 +921,13 @@ void scheduler_start(struct scheduler *s, unsigned int mask) { ...@@ -916,13 +921,13 @@ void scheduler_start(struct scheduler *s, unsigned int mask) {
// CPU_TPS * 1000 ); // CPU_TPS * 1000 );
/* Don't enqueue link tasks directly. */ /* 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. */ /* Loop over the tasks and enqueue whoever is ready. */
// tic = getticks(); // tic = getticks();
for (k = 0; k < nr_tasks; k++) { for (k = 0; k < nr_tasks; k++) {
t = &tasks[tid[k]]; t = &tasks[tid[k]];
if (((1 << t->type) & mask) && !t->skip) { if (((1 << t->type) & s->mask) && !t->skip) {
if (t->wait == 0) { if (t->wait == 0) {
scheduler_enqueue(s, t); scheduler_enqueue(s, t);
pthread_cond_broadcast(&s->sleep_cond); pthread_cond_broadcast(&s->sleep_cond);
...@@ -948,14 +953,16 @@ void scheduler_enqueue(struct scheduler *s, struct task *t) { ...@@ -948,14 +953,16 @@ void scheduler_enqueue(struct scheduler *s, struct task *t) {
int err; int err;
#endif #endif
/* Ignore skipped tasks. */ /* Ignore skipped tasks and tasks not in the mask. */
if (t->skip || atomic_cas(&t->rid, -1, 0) != -1) return; 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 this is an implicit task, just pretend it's done. */
if (t->implicit) { if (t->implicit) {
for (int j = 0; j < t->nr_unlock_tasks; j++) { for (int j = 0; j < t->nr_unlock_tasks; j++) {
struct task *t2 = t->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) { ...@@ -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 /* Loop through the dependencies and add them to a queue if
they are ready. */ they are ready. */
for (k = 0; k < t->nr_unlock_tasks; k++) { for (int k = 0; k < t->nr_unlock_tasks; k++) {
t2 = t->unlock_tasks[k]; struct task *t2 = t->unlock_tasks[k];
if ((res = atomic_dec(&t2->wait)) < 1) error("Negative wait!"); int res = atomic_dec(&t2->wait);
if (res == 1 && !t2->skip) { if (res < 1) {
if (0 && !t2->implicit && t2->ci->super == super && error("Negative wait!");
(next == NULL || t2->weight > next->weight) && task_lock(t2)) { } else if (res == 1) {
if (next != NULL) { scheduler_enqueue(s, t2);
task_unlock(next);
scheduler_enqueue(s, next);
}
next = t2;
} else
scheduler_enqueue(s, t2);
} }
} }
...@@ -1075,16 +1076,15 @@ struct task *scheduler_done(struct scheduler *s, struct task *t) { ...@@ -1075,16 +1076,15 @@ struct task *scheduler_done(struct scheduler *s, struct task *t) {
if (!t->implicit) { if (!t->implicit) {
t->toc = getticks(); t->toc = getticks();
pthread_mutex_lock(&s->sleep_mutex); pthread_mutex_lock(&s->sleep_mutex);
if (next == NULL) atomic_dec(&s->waiting); atomic_dec(&s->waiting);
pthread_cond_broadcast(&s->sleep_cond); pthread_cond_broadcast(&s->sleep_cond);
pthread_mutex_unlock(&s->sleep_mutex); pthread_mutex_unlock(&s->sleep_mutex);
} }
/* Start the clock on the follow-up task. */ /* Return the next best task. Note that we currently do not
if (next != NULL) next->tic = getticks(); implement anything that does this, as getting it to respect
priorities is too tricky and currently unnecessary. */
/* Return the next best task. */ return NULL;
return next;
} }
/** /**
...@@ -1104,26 +1104,29 @@ struct task *scheduler_unlock(struct scheduler *s, struct task *t) { ...@@ -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 /* Loop through the dependencies and add them to a queue if
they are ready. */ they are ready. */
for (k = 0; k < t->nr_unlock_tasks; k++) { for (int k = 0; k < t->nr_unlock_tasks; k++) {
t2 = t->unlock_tasks[k]; struct task *t2 = t->unlock_tasks[k];
if ((res = atomic_dec(&t2->wait)) < 1) error("Negative wait!"); int res = atomic_dec(&t2->wait);
if (res == 1 && !t2->skip) scheduler_enqueue(s, t2); if (res < 1) {
error("Negative wait!");
} else if (res == 1) {
scheduler_enqueue(s, t2);
}
} }
/* Task definitely done. */ /* Task definitely done. */
if (!t->implicit) { if (!t->implicit) {
t->toc = getticks(); t->toc = getticks();
pthread_mutex_lock(&s->sleep_mutex); pthread_mutex_lock(&s->sleep_mutex);
if (next == NULL) atomic_dec(&s->waiting); atomic_dec(&s->waiting);
pthread_cond_broadcast(&s->sleep_cond); pthread_cond_broadcast(&s->sleep_cond);
pthread_mutex_unlock(&s->sleep_mutex); pthread_mutex_unlock(&s->sleep_mutex);
} }
/* Start the clock on the follow-up task. */ /* Return the next best task. Note that we currently do not
if (next != NULL) next->tic = getticks(); implement anything that does this, as getting it to respect
priorities is too tricky and currently unnecessary. */
/* Return the next best task. */ return NULL;
return next;
} }
/** /**
......
/******************************************************************************* /*******************************************************************************
* This file is part of SWIFT. * This file is part of SWIFT.
* Copyright (c) 2013 Pedro Gonnet (pedro.gonnet@durham.ac.uk) * 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 * 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 * it under the terms of the GNU Lesser General Public License as published
...@@ -50,6 +51,9 @@ struct scheduler { ...@@ -50,6 +51,9 @@ struct scheduler {
/* Scheduler flags. */ /* Scheduler flags. */
unsigned int flags; unsigned int flags;
/* Scheduler mask */
unsigned int mask;
/* Number of queues in this scheduler. */ /* Number of queues in this scheduler. */
int nr_queues; int nr_queues;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment