Commit 5167e8d5 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar

sched/nohz: Rewrite and fix load-avg computation -- again

Thanks to Charles Wang for spotting the defects in the current code:

 - If we go idle during the sample window -- after sampling, we get a
   negative bias because we can negate our own sample.

 - If we wake up during the sample window we get a positive bias
   because we push the sample to a known active period.

So rewrite the entire nohz load-avg muck once again, now adding
copious documentation to the code.
Reported-and-tested-by: default avatarDoug Smythies <dsmythies@telus.net>
Reported-and-tested-by: default avatarCharles Wang <muming.wq@gmail.com>
Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: stable@kernel.org
Link: http://lkml.kernel.org/r/1340373782.18025.74.camel@twins
[ minor edits ]
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 164c33c6
...@@ -1909,6 +1909,14 @@ static inline int set_cpus_allowed_ptr(struct task_struct *p, ...@@ -1909,6 +1909,14 @@ static inline int set_cpus_allowed_ptr(struct task_struct *p,
} }
#endif #endif
#ifdef CONFIG_NO_HZ
void calc_load_enter_idle(void);
void calc_load_exit_idle(void);
#else
static inline void calc_load_enter_idle(void) { }
static inline void calc_load_exit_idle(void) { }
#endif /* CONFIG_NO_HZ */
#ifndef CONFIG_CPUMASK_OFFSTACK #ifndef CONFIG_CPUMASK_OFFSTACK
static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask) static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
{ {
......
This diff is collapsed.
...@@ -25,7 +25,6 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl ...@@ -25,7 +25,6 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl
static struct task_struct *pick_next_task_idle(struct rq *rq) static struct task_struct *pick_next_task_idle(struct rq *rq)
{ {
schedstat_inc(rq, sched_goidle); schedstat_inc(rq, sched_goidle);
calc_load_account_idle(rq);
return rq->idle; return rq->idle;
} }
......
...@@ -942,8 +942,6 @@ static inline u64 sched_avg_period(void) ...@@ -942,8 +942,6 @@ static inline u64 sched_avg_period(void)
return (u64)sysctl_sched_time_avg * NSEC_PER_MSEC / 2; return (u64)sysctl_sched_time_avg * NSEC_PER_MSEC / 2;
} }
void calc_load_account_idle(struct rq *this_rq);
#ifdef CONFIG_SCHED_HRTICK #ifdef CONFIG_SCHED_HRTICK
/* /*
......
...@@ -406,6 +406,7 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts) ...@@ -406,6 +406,7 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts)
*/ */
if (!ts->tick_stopped) { if (!ts->tick_stopped) {
select_nohz_load_balancer(1); select_nohz_load_balancer(1);
calc_load_enter_idle();
ts->idle_tick = hrtimer_get_expires(&ts->sched_timer); ts->idle_tick = hrtimer_get_expires(&ts->sched_timer);
ts->tick_stopped = 1; ts->tick_stopped = 1;
...@@ -597,6 +598,7 @@ void tick_nohz_idle_exit(void) ...@@ -597,6 +598,7 @@ void tick_nohz_idle_exit(void)
account_idle_ticks(ticks); account_idle_ticks(ticks);
#endif #endif
calc_load_exit_idle();
touch_softlockup_watchdog(); touch_softlockup_watchdog();
/* /*
* Cancel the scheduled timer and restore the tick * Cancel the scheduled timer and restore the tick
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment