scheduler fix
Linus,
Please pull the latest sched-urgent-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git sched-urgent-for-linus
# HEAD: d60585c5766e9620d5d83e2b25dc042c7bdada2c sched/core: Correct off by one bug in load migration calculation
Fix a CPU hotplug related corruption of the load average that got introduced in this merge window.
Thanks,
Ingo
------------------>
Thomas Gleixner (1):
sched/core: Correct off by one bug in load migration calculation
kernel/sched/core.c | 6 ++++-- kernel/sched/loadavg.c | 8 ++++---- kernel/sched/sched.h | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-)
kernel/sched/core.c +4 -2
@@ -5394,13 +5394,15 @@ void idle_task_exit(void)/* * 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. +* nr_active count is stable. We need to take the teardown thread which +* is calling this into account, so we hand in adjust = 1 to the load +* calculation. * * Also see the comment "Global load-average calculations". */ static void calc_load_migrate (struct rq *rq) { -long delta =calc_load_fold_active (rq); +long delta =calc_load_fold_active (rq,1 );if (delta)atomic_long_add (delta, &calc_load_tasks); }
kernel/sched/loadavg.c +4 -4
@@ -78,11 +78,11 @@ void get_avenrun(unsigned long *loads, unsigned long offset, int shift) loads[2 ] = (avenrun[2 ] + offset) << shift; } -long calc_load_fold_active (struct rq *this_rq) +long calc_load_fold_active (struct rq *this_rq,long adjust) {long nr_active, delta =0 ; - nr_active = this_rq->nr_running; + nr_active = this_rq->nr_running - adjust; nr_active += (long )this_rq->nr_uninterruptible;if (nr_active != this_rq->calc_load_active) {
@@ -188,7 +188,7 @@ void calc_load_enter_idle(void)* We're going into NOHZ mode, if there's any pending delta, fold it * into the pending idle delta. */ - delta =calc_load_fold_active (this_rq); + delta =calc_load_fold_active (this_rq,0 );if (delta) {int idx =calc_load_write_idx ();
@@ -389,7 +389,7 @@ void calc_global_load_tick(struct rq *this_rq)if (time_before (jiffies, this_rq->calc_load_update))return ; - delta =calc_load_fold_active (this_rq); + delta =calc_load_fold_active (this_rq,0 );if (delta)atomic_long_add (delta, &calc_load_tasks);
kernel/sched/sched.h +1 -1
@@ -28,7 +28,7 @@ extern unsigned long calc_load_update;extern atomic_long_t calc_load_tasks;extern void calc_global_load_tick (struct rq *this_rq); -extern long calc_load_fold_active (struct rq *this_rq); +extern long calc_load_fold_active (struct rq *this_rq,long adjust);#ifdef CONFIG_SMP extern void cpu_load_update_active (struct rq *this_rq);