In idle or full dynticks mode, the tick can be stopped for few jiffies to avoid unnecessary events.
In highres mode, when the tick fires again we reprogram the 'tick-sched' hrtimer from tick_sched_timer() (by returning HRTIMER_RESTART to hrtimer core).
Because the tick was stopped earlier, irq_exit() would eventually call tick_nohz_full_stop_tick() and it will surely reprogram hrtimer again.
We can avoid double reprogramming of tick-sched hrtimer by returning 'HRTIMER_NORESTART' from tick_sched_timer() when 'tick_stopped' is set to '1'.
Similar piece of code was present initially when dynticks functionality was first added: 79bf2bb3.
But later commit fb02fbc removed this check to keep jiffies updated for the sake of long running softirqs, but was later again reverted in ae99286b due to spurious wakeups. However it was not entirely reverted. The long running softirqs were asked to fix themselves.
Introducing this change again shouldn't result in 'long running softirqs' issue discussed in fb02fbc, as tick_nohz_kick_tick() is still commented out.
Suggested-by: Frederic Weisbecker fweisbec@gmail.com Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- kernel/time/tick-sched.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index bb7b736..2604eec 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -1089,6 +1089,10 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer) if (regs) tick_sched_handle(ts, regs);
+ /* Do not restart, when we are in idle or full dynticks mode */ + if (unlikely(ts->tick_stopped)) + return HRTIMER_NORESTART; + hrtimer_forward(timer, now, tick_period);
return HRTIMER_RESTART;