diff options
author | Peter Zijlstra <peterz@infradead.org> | 2017-02-02 10:55:06 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2017-02-24 02:58:33 -0500 |
commit | 8cb68b343a66cf19834472012590490d34d31703 (patch) | |
tree | 9fb6c71ddb2c046c0aaceb748248d94cc74a351d | |
parent | 2bfe01eff4307409b95859e860261d0907149b61 (diff) |
sched/core: Fix update_rq_clock() splat on hotplug (and suspend/resume)
The hotplug code still triggers the warning about using a stale
rq->clock value.
Fix things up to actually run update_rq_clock() in a place where we
record the 'UPDATED' flag, and then modify the annotation to retain
this flag over the rq->lock fiddling that happens as a result of
actually migrating all the tasks elsewhere.
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Tested-by: Mike Galbraith <efault@gmx.de>
Tested-by: Sachin Sant <sachinp@linux.vnet.ibm.com>
Tested-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ross Zwisler <zwisler@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: 4d25b35ea372 ("sched/fair: Restore previous rq_flags when migrating tasks in hotplug")
Link: http://lkml.kernel.org/r/20170202155506.GX6515@twins.programming.kicks-ass.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | kernel/sched/core.c | 14 |
1 files changed, 4 insertions, 10 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 34e2291a9a6c..2d6e828a0471 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
@@ -5557,7 +5557,7 @@ static void migrate_tasks(struct rq *dead_rq) | |||
5557 | { | 5557 | { |
5558 | struct rq *rq = dead_rq; | 5558 | struct rq *rq = dead_rq; |
5559 | struct task_struct *next, *stop = rq->stop; | 5559 | struct task_struct *next, *stop = rq->stop; |
5560 | struct rq_flags rf, old_rf; | 5560 | struct rq_flags rf; |
5561 | int dest_cpu; | 5561 | int dest_cpu; |
5562 | 5562 | ||
5563 | /* | 5563 | /* |
@@ -5576,7 +5576,9 @@ static void migrate_tasks(struct rq *dead_rq) | |||
5576 | * class method both need to have an up-to-date | 5576 | * class method both need to have an up-to-date |
5577 | * value of rq->clock[_task] | 5577 | * value of rq->clock[_task] |
5578 | */ | 5578 | */ |
5579 | rq_pin_lock(rq, &rf); | ||
5579 | update_rq_clock(rq); | 5580 | update_rq_clock(rq); |
5581 | rq_unpin_lock(rq, &rf); | ||
5580 | 5582 | ||
5581 | for (;;) { | 5583 | for (;;) { |
5582 | /* | 5584 | /* |
@@ -5589,7 +5591,7 @@ static void migrate_tasks(struct rq *dead_rq) | |||
5589 | /* | 5591 | /* |
5590 | * pick_next_task() assumes pinned rq->lock: | 5592 | * pick_next_task() assumes pinned rq->lock: |
5591 | */ | 5593 | */ |
5592 | rq_pin_lock(rq, &rf); | 5594 | rq_repin_lock(rq, &rf); |
5593 | next = pick_next_task(rq, &fake_task, &rf); | 5595 | next = pick_next_task(rq, &fake_task, &rf); |
5594 | BUG_ON(!next); | 5596 | BUG_ON(!next); |
5595 | next->sched_class->put_prev_task(rq, next); | 5597 | next->sched_class->put_prev_task(rq, next); |
@@ -5618,13 +5620,6 @@ static void migrate_tasks(struct rq *dead_rq) | |||
5618 | continue; | 5620 | continue; |
5619 | } | 5621 | } |
5620 | 5622 | ||
5621 | /* | ||
5622 | * __migrate_task() may return with a different | ||
5623 | * rq->lock held and a new cookie in 'rf', but we need | ||
5624 | * to preserve rf::clock_update_flags for 'dead_rq'. | ||
5625 | */ | ||
5626 | old_rf = rf; | ||
5627 | |||
5628 | /* Find suitable destination for @next, with force if needed. */ | 5623 | /* Find suitable destination for @next, with force if needed. */ |
5629 | dest_cpu = select_fallback_rq(dead_rq->cpu, next); | 5624 | dest_cpu = select_fallback_rq(dead_rq->cpu, next); |
5630 | 5625 | ||
@@ -5633,7 +5628,6 @@ static void migrate_tasks(struct rq *dead_rq) | |||
5633 | raw_spin_unlock(&rq->lock); | 5628 | raw_spin_unlock(&rq->lock); |
5634 | rq = dead_rq; | 5629 | rq = dead_rq; |
5635 | raw_spin_lock(&rq->lock); | 5630 | raw_spin_lock(&rq->lock); |
5636 | rf = old_rf; | ||
5637 | } | 5631 | } |
5638 | raw_spin_unlock(&next->pi_lock); | 5632 | raw_spin_unlock(&next->pi_lock); |
5639 | } | 5633 | } |