From 5bcd520f1685aea2524c5653297b9011cb3161a9 Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Wed, 22 Sep 2010 23:20:18 -0400 Subject: EDF-WM: handle race between wake_up() and schedule() A job that temporarily blocked without being descheduled might have its slices advanced to the next CPU. In this case, we need to force a rescheduling + migration. --- litmus/sched_edf_wm.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/litmus/sched_edf_wm.c b/litmus/sched_edf_wm.c index c3d241a42566..baf03f7ca6ac 100644 --- a/litmus/sched_edf_wm.c +++ b/litmus/sched_edf_wm.c @@ -323,8 +323,7 @@ static struct task_struct* wm_schedule(struct task_struct * prev) rt_domain_t *edf = &dom->domain; struct task_struct *next, *migrate = NULL; - int out_of_time, sleep, preempt, - exists, blocks, resched; + int out_of_time, sleep, preempt, wrong_cpu, exists, blocks, resched; raw_spin_lock(&dom->slock); @@ -336,6 +335,7 @@ static struct task_struct* wm_schedule(struct task_struct * prev) /* (0) Determine state */ exists = dom->scheduled != NULL; + wrong_cpu = exists && get_partition(dom->scheduled) != dom->cpu; blocks = exists && !is_running(dom->scheduled); out_of_time = exists && budget_enforced(dom->scheduled) @@ -349,11 +349,25 @@ static struct task_struct* wm_schedule(struct task_struct * prev) */ resched = preempt; + + if (exists) + TRACE_TASK(prev, + "blocks:%d out_of_time:%d sleep:%d preempt:%d " + "wrong_cpu:%d state:%d sig:%d\n", + blocks, out_of_time, sleep, preempt, wrong_cpu, + prev->state, signal_pending(prev)); + /* If a task blocks we have no choice but to reschedule. */ if (blocks) resched = 1; + /* This can happen if sliced task was moved to the next slice + * by the wake_up() code path while still being scheduled. + */ + if (wrong_cpu) + resched = 1; + /* Any task that is preemptable and either exhausts its execution * budget or wants to sleep completes. We may have to reschedule after * this. -- cgit v1.2.2