|
@@ -5304,27 +5304,17 @@ void idle_task_exit(void)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * While a dead CPU has no uninterruptible tasks queued at this point,
|
|
|
- * it might still have a nonzero ->nr_uninterruptible counter, because
|
|
|
- * for performance reasons the counter is not stricly tracking tasks to
|
|
|
- * their home CPUs. So we just add the counter to another CPU's counter,
|
|
|
- * to keep the global sum constant after CPU-down:
|
|
|
- */
|
|
|
-static void migrate_nr_uninterruptible(struct rq *rq_src)
|
|
|
-{
|
|
|
- struct rq *rq_dest = cpu_rq(cpumask_any(cpu_active_mask));
|
|
|
-
|
|
|
- rq_dest->nr_uninterruptible += rq_src->nr_uninterruptible;
|
|
|
- rq_src->nr_uninterruptible = 0;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * remove the tasks which were accounted by rq from calc_load_tasks.
|
|
|
+ * Since this CPU is going 'away' for a while, fold any nr_active delta
|
|
|
+ * we might have. Assumes we're called after migrate_tasks() so that the
|
|
|
+ * nr_active count is stable.
|
|
|
+ *
|
|
|
+ * Also see the comment "Global load-average calculations".
|
|
|
*/
|
|
|
-static void calc_global_load_remove(struct rq *rq)
|
|
|
+static void calc_load_migrate(struct rq *rq)
|
|
|
{
|
|
|
- atomic_long_sub(rq->calc_load_active, &calc_load_tasks);
|
|
|
- rq->calc_load_active = 0;
|
|
|
+ long delta = calc_load_fold_active(rq);
|
|
|
+ if (delta)
|
|
|
+ atomic_long_add(delta, &calc_load_tasks);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -5617,9 +5607,18 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
|
|
|
migrate_tasks(cpu);
|
|
|
BUG_ON(rq->nr_running != 1); /* the migration thread */
|
|
|
raw_spin_unlock_irqrestore(&rq->lock, flags);
|
|
|
+ break;
|
|
|
|
|
|
- migrate_nr_uninterruptible(rq);
|
|
|
- calc_global_load_remove(rq);
|
|
|
+ case CPU_DEAD:
|
|
|
+ {
|
|
|
+ struct rq *dest_rq;
|
|
|
+
|
|
|
+ local_irq_save(flags);
|
|
|
+ dest_rq = cpu_rq(smp_processor_id());
|
|
|
+ raw_spin_lock(&dest_rq->lock);
|
|
|
+ calc_load_migrate(rq);
|
|
|
+ raw_spin_unlock_irqrestore(&dest_rq->lock, flags);
|
|
|
+ }
|
|
|
break;
|
|
|
#endif
|
|
|
}
|