aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/sched/core.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 0902e4d72671..9b786704d34b 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5183,24 +5183,47 @@ static void migrate_tasks(struct rq *dead_rq)
5183 break; 5183 break;
5184 5184
5185 /* 5185 /*
5186 * Ensure rq->lock covers the entire task selection 5186 * pick_next_task assumes pinned rq->lock.
5187 * until the migration.
5188 */ 5187 */
5189 lockdep_pin_lock(&rq->lock); 5188 lockdep_pin_lock(&rq->lock);
5190 next = pick_next_task(rq, &fake_task); 5189 next = pick_next_task(rq, &fake_task);
5191 BUG_ON(!next); 5190 BUG_ON(!next);
5192 next->sched_class->put_prev_task(rq, next); 5191 next->sched_class->put_prev_task(rq, next);
5193 5192
5193 /*
5194 * Rules for changing task_struct::cpus_allowed are holding
5195 * both pi_lock and rq->lock, such that holding either
5196 * stabilizes the mask.
5197 *
5198 * Drop rq->lock is not quite as disastrous as it usually is
5199 * because !cpu_active at this point, which means load-balance
5200 * will not interfere. Also, stop-machine.
5201 */
5202 lockdep_unpin_lock(&rq->lock);
5203 raw_spin_unlock(&rq->lock);
5204 raw_spin_lock(&next->pi_lock);
5205 raw_spin_lock(&rq->lock);
5206
5207 /*
5208 * Since we're inside stop-machine, _nothing_ should have
5209 * changed the task, WARN if weird stuff happened, because in
5210 * that case the above rq->lock drop is a fail too.
5211 */
5212 if (WARN_ON(task_rq(next) != rq || !task_on_rq_queued(next))) {
5213 raw_spin_unlock(&next->pi_lock);
5214 continue;
5215 }
5216
5194 /* Find suitable destination for @next, with force if needed. */ 5217 /* Find suitable destination for @next, with force if needed. */
5195 dest_cpu = select_fallback_rq(dead_rq->cpu, next); 5218 dest_cpu = select_fallback_rq(dead_rq->cpu, next);
5196 5219
5197 lockdep_unpin_lock(&rq->lock);
5198 rq = __migrate_task(rq, next, dest_cpu); 5220 rq = __migrate_task(rq, next, dest_cpu);
5199 if (rq != dead_rq) { 5221 if (rq != dead_rq) {
5200 raw_spin_unlock(&rq->lock); 5222 raw_spin_unlock(&rq->lock);
5201 rq = dead_rq; 5223 rq = dead_rq;
5202 raw_spin_lock(&rq->lock); 5224 raw_spin_lock(&rq->lock);
5203 } 5225 }
5226 raw_spin_unlock(&next->pi_lock);
5204 } 5227 }
5205 5228
5206 rq->stop = stop; 5229 rq->stop = stop;