aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern B. Brandenburg <bbb@cs.unc.edu>2010-03-02 11:51:07 -0500
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-29 17:27:44 -0400
commit7a4affe47db86075eb36519049d047f6facab378 (patch)
treeed71e435d8cc2ceab5f77ce430777ee2e56cab2e
parent0c1a489cb92c996d50adfb84fee5edd7205e0c1b (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.c21
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
266static void psnedf_task_block(struct task_struct *t) 275static 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
285static void psnedf_task_exit(struct task_struct * t) 284static void psnedf_task_exit(struct task_struct * t)