summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCon Kolivas <kernel@kolivas.org>2016-10-14 08:40:22 +1100
committerCon Kolivas <kernel@kolivas.org>2016-10-14 16:56:14 +1100
commit121b4e98923ec804af2304f789f3acede490d17a (patch)
tree5c1f0250f65421559341cdf4063f6f2ebce15a7b
parent74ccb93e82205c1dc4624f4f793458e0040ca28c (diff)
Double lock and differentiate rq from new_rq in wake_up_new_task, altering correct current task under lock.
-rw-r--r--kernel/sched/MuQSS.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/kernel/sched/MuQSS.c b/kernel/sched/MuQSS.c
index 9515ebdfc053..4ecee0f56c0b 100644
--- a/kernel/sched/MuQSS.c
+++ b/kernel/sched/MuQSS.c
@@ -2165,16 +2165,21 @@ static inline void init_schedstats(void) {}
void wake_up_new_task(struct task_struct *p)
{
struct task_struct *parent, *rq_curr;
+ struct rq *rq, *new_rq;
unsigned long flags;
- struct rq *rq;
parent = p->parent;
raw_spin_lock_irqsave(&p->pi_lock, flags);
p->state = TASK_RUNNING;
- if (unlikely(needs_other_cpu(p, task_cpu(p))))
+ /* Task_rq can't change yet on a new task */
+ new_rq = rq = task_rq(p);
+ if (unlikely(needs_other_cpu(p, task_cpu(p)))) {
set_task_cpu(p, valid_task_cpu(p));
- rq = __task_rq_lock(p);
+ new_rq = task_rq(p);
+ }
+
+ double_rq_lock(rq, new_rq);
update_clocks(rq);
rq_curr = rq->curr;
@@ -2210,9 +2215,11 @@ void wake_up_new_task(struct task_struct *p)
time_slice_expired(p, rq);
if (suitable_idle_cpus(p))
resched_best_idle(p, task_cpu(p));
+ else if (unlikely(rq != new_rq))
+ try_preempt(p, new_rq);
} else {
p->time_slice = rq->rq_time_slice;
- if (rq_curr == parent && !suitable_idle_cpus(p)) {
+ if (rq_curr == parent && rq == new_rq && !suitable_idle_cpus(p)) {
/*
* The VM isn't cloned, so we're in a good position to
* do child-runs-first in anticipation of an exec. This
@@ -2220,13 +2227,14 @@ void wake_up_new_task(struct task_struct *p)
*/
__set_tsk_resched(rq_curr);
} else
- try_preempt(p, rq);
+ try_preempt(p, new_rq);
}
} else {
time_slice_expired(p, rq);
- try_preempt(p, rq);
+ try_preempt(p, new_rq);
}
- task_rq_unlock(rq, p, &flags);
+ double_rq_unlock(rq, new_rq);
+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
}
#ifdef CONFIG_PREEMPT_NOTIFIERS