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.
* 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;
}
/**
......
/*******************************************************************************
* 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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment