nohz fix
Ingo Molnar
maintainerLinus,
Please pull the latest timers-urgent-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers-urgent-for-linus
# HEAD: 24b91e360ef521a2808771633d76ebc68bd5604b nohz: Fix collision between tick and other hrtimers
This fixes an old NOHZ race where we incorrectly calculate the next timer interrupt in certain circumstances where hrtimers are pending, that can cause hard to reproduce stalled-values artifacts in /proc/stat.
Thanks,
Ingo
------------------>
Frederic Weisbecker (1):
nohz: Fix collision between tick and other hrtimers
kernel/time/tick-sched.c | 9 +++++++-- kernel/time/tick-sched.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-)
kernel/time/tick-sched.c +7 -2
@@ -767,7 +767,7 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts, tick = expires;/* Skip reprogram of event if its not changed */ -if (ts->tick_stopped && (expires == dev->next_event)) +if (ts->tick_stopped && (expires == ts->next_tick)) goto out;/*
@@ -787,6 +787,8 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts,trace_tick_stop (1 ,TICK_DEP_MASK_NONE ); } + ts->next_tick = tick; +/* * If the expiration time == KTIME_MAX, then we simply stop * the tick timer.
@@ -802,7 +804,10 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts,else tick_program_event (tick,1 ); out: -/* Update the estimated sleep length */ +/* +* Update the estimated sleep length until the next timer +* (not only the tick). +*/ ts->sleep_length =ktime_sub (dev->next_event, now);return tick; }
kernel/time/tick-sched.h +2 -0
@@ -27,6 +27,7 @@ enum tick_nohz_mode {* timer is modified for nohz sleeps. This is necessary * to resume the tick timer operation in the timeline * when the CPU returns from nohz sleep. +* @next_tick: Next tick to be fired when in dynticks mode. * @tick_stopped: Indicator that the idle tick has been stopped * @idle_jiffies: jiffies at the entry to idle for idle time accounting * @idle_calls: Total number of idle calls
@@ -44,6 +45,7 @@ struct tick_sched {unsigned long check_clocks;enum tick_nohz_mode nohz_mode;ktime_t last_tick; +ktime_t next_tick;int inidle;int tick_stopped;unsigned long idle_jiffies;