From c00613f1fad38acec00ef2c009ae4e73110084ac Mon Sep 17 00:00:00 2001 From: Bjoern Brandenburg Date: Tue, 14 Aug 2012 20:38:55 +0200 Subject: Fix wake_up() preemptions under P-FP and PSN-EDF Due to some mistake in the past, PSN-EDF was missing a check for preemptions when a task resumes. P-FP adopted it by virtue of copy&paste. This patch makes sure that a preemption is triggered when a higher-priority task is added to the ready queue. --- litmus/sched_pfp.c | 12 ++++++++++-- litmus/sched_psn_edf.c | 21 ++++++++++++++------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/litmus/sched_pfp.c b/litmus/sched_pfp.c index 62be699629b1..b1d5b4326a0e 100644 --- a/litmus/sched_pfp.c +++ b/litmus/sched_pfp.c @@ -95,6 +95,12 @@ static void pfp_release_jobs(rt_domain_t* rt, struct bheap* tasks) raw_spin_unlock_irqrestore(&pfp->slock, flags); } +static void pfp_preempt_check(pfp_domain_t *pfp) +{ + if (fp_higher_prio(fp_prio_peek(&pfp->ready_queue), pfp->scheduled)) + preempt(pfp); +} + static void pfp_domain_init(pfp_domain_t* pfp, int cpu) { @@ -291,7 +297,7 @@ static void pfp_task_new(struct task_struct * t, int on_rq, int running) } else { requeue(t, pfp); /* maybe we have to reschedule */ - preempt(pfp); + pfp_preempt_check(pfp); } raw_spin_unlock_irqrestore(&pfp->slock, flags); } @@ -337,8 +343,10 @@ static void pfp_task_wake_up(struct task_struct *task) * and won. Also, don't requeue if it is still queued, which can * happen under the DPCP due wake-ups racing with migrations. */ - if (pfp->scheduled != task) + if (pfp->scheduled != task) { requeue(task, pfp); + pfp_preempt_check(pfp); + } out_unlock: raw_spin_unlock_irqrestore(&pfp->slock, flags); diff --git a/litmus/sched_psn_edf.c b/litmus/sched_psn_edf.c index b0c8126bd44a..8933e15605ae 100644 --- a/litmus/sched_psn_edf.c +++ b/litmus/sched_psn_edf.c @@ -133,6 +133,15 @@ static void unboost_priority(struct task_struct* t) #endif +static int psnedf_preempt_check(psnedf_domain_t *pedf) +{ + if (edf_preemption_needed(&pedf->domain, pedf->scheduled)) { + preempt(pedf); + return 1; + } else + return 0; +} + /* This check is trivial in partioned systems as we only have to consider * the CPU of the partition. */ @@ -143,11 +152,7 @@ static int psnedf_check_resched(rt_domain_t *edf) /* because this is a callback from rt_domain_t we already hold * the necessary lock for the ready queue */ - if (edf_preemption_needed(edf, pedf->scheduled)) { - preempt(pedf); - return 1; - } else - return 0; + return psnedf_preempt_check(pedf); } static void job_completion(struct task_struct* t, int forced) @@ -299,7 +304,7 @@ static void psnedf_task_new(struct task_struct * t, int on_rq, int running) } else { requeue(t, edf); /* maybe we have to reschedule */ - preempt(pedf); + psnedf_preempt_check(pedf); } raw_spin_unlock_irqrestore(&pedf->slock, flags); } @@ -335,8 +340,10 @@ static void psnedf_task_wake_up(struct task_struct *task) * de-scheduling the task, i.e., wake_up() raced with schedule() * and won. */ - if (pedf->scheduled != task) + if (pedf->scheduled != task) { requeue(task, edf); + psnedf_preempt_check(pedf); + } raw_spin_unlock_irqrestore(&pedf->slock, flags); TRACE_TASK(task, "wake up done\n"); -- cgit v1.2.2