diff options
author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2010-03-02 11:51:07 -0500 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-29 17:27:44 -0400 |
commit | 7a4affe47db86075eb36519049d047f6facab378 (patch) | |
tree | ed71e435d8cc2ceab5f77ce430777ee2e56cab2e | |
parent | 0c1a489cb92c996d50adfb84fee5edd7205e0c1b (diff) |
Bugfix: PSN-EDF should only requeue tasks that are not scheduled
Requeue a task that is already scheduled will cause it to be effectively
in the runqueue twice since scheduled tasks are conceptually the head
of the queue. If a task is still scheduled, then schedule() will do the
right thing and do the requeuing if necessary.
This fixes crashes reported by Glenn and Andrea.
-rw-r--r-- | litmus/sched_psn_edf.c | 21 |
1 files changed, 10 insertions, 11 deletions
diff --git a/litmus/sched_psn_edf.c b/litmus/sched_psn_edf.c index 3a93124e24f6..d37f045768d5 100644 --- a/litmus/sched_psn_edf.c +++ b/litmus/sched_psn_edf.c | |||
@@ -258,28 +258,27 @@ static void psnedf_task_wake_up(struct task_struct *task) | |||
258 | release_at(task, now); | 258 | release_at(task, now); |
259 | sched_trace_task_release(task); | 259 | sched_trace_task_release(task); |
260 | } | 260 | } |
261 | requeue(task, edf); | 261 | |
262 | /* Only add to ready queue if it is not the currently-scheduled | ||
263 | * task. This could be the case if a task was woken up concurrently | ||
264 | * on a remote CPU before the executing CPU got around to actually | ||
265 | * de-scheduling the task, i.e., wake_up() raced with schedule() | ||
266 | * and won. | ||
267 | */ | ||
268 | if (pedf->scheduled != task) | ||
269 | requeue(task, edf); | ||
270 | |||
262 | spin_unlock_irqrestore(&pedf->slock, flags); | 271 | spin_unlock_irqrestore(&pedf->slock, flags); |
263 | TRACE_TASK(task, "wake up done\n"); | 272 | TRACE_TASK(task, "wake up done\n"); |
264 | } | 273 | } |
265 | 274 | ||
266 | static void psnedf_task_block(struct task_struct *t) | 275 | static void psnedf_task_block(struct task_struct *t) |
267 | { | 276 | { |
268 | psnedf_domain_t *pedf = task_pedf(t); | ||
269 | |||
270 | /* only running tasks can block, thus t is in no queue */ | 277 | /* only running tasks can block, thus t is in no queue */ |
271 | TRACE_TASK(t, "block at %llu, state=%d\n", litmus_clock(), t->state); | 278 | TRACE_TASK(t, "block at %llu, state=%d\n", litmus_clock(), t->state); |
272 | 279 | ||
273 | BUG_ON(!is_realtime(t)); | 280 | BUG_ON(!is_realtime(t)); |
274 | BUG_ON(is_queued(t)); | 281 | BUG_ON(is_queued(t)); |
275 | |||
276 | /* if this task is dead, then we need to reset pedf->schedule now | ||
277 | * as we might get rescheduled before task_exit executes | ||
278 | */ | ||
279 | if(unlikely(t->state == TASK_DEAD)) { | ||
280 | TRACE_TASK(t, "Dead, setting scheduled = NULL\n"); | ||
281 | pedf->scheduled = NULL; | ||
282 | } | ||
283 | } | 282 | } |
284 | 283 | ||
285 | static void psnedf_task_exit(struct task_struct * t) | 284 | static void psnedf_task_exit(struct task_struct * t) |