Commit c4bd822e7b12a9008241d76db45b665f2fef180c

Authored by Thomas Gleixner
1 parent 2515ddc6db

NOHZ: fix thinko in the timer restart code path

commit fb02fbc14d17837b4b7b02dbb36142c16a7bf208 (NOHZ: restart tick
device from irq_enter())

solves the problem of stale jiffies when long running softirqs happen
in a long idle sleep period, but it has a major thinko in it:

When the interrupt which came in _is_ the timer interrupt which should
expire ts->sched_timer then we cancel and rearm the timer _before_ it
gets expired in hrtimer_interrupt() to the next period. That means the
call back function is not called. This game can go on for ever :(

Prevent this by making sure to only rearm the timer when the expiry
time is more than one tick_period away. Otherwise keep it running as
it is either already expired or will expiry at the right point to
update jiffies.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Venkatesch Pallipadi <venkatesh.pallipadi@intel.com>

Showing 1 changed file with 11 additions and 1 deletions Side-by-side Diff

kernel/time/tick-sched.c
... ... @@ -567,11 +567,21 @@
567 567 static void tick_nohz_kick_tick(int cpu)
568 568 {
569 569 struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
  570 + ktime_t delta, now;
570 571  
571 572 if (!ts->tick_stopped)
572 573 return;
573 574  
574   - tick_nohz_restart(ts, ktime_get());
  575 + /*
  576 + * Do not touch the tick device, when the next expiry is either
  577 + * already reached or less/equal than the tick period.
  578 + */
  579 + now = ktime_get();
  580 + delta = ktime_sub(ts->sched_timer.expires, now);
  581 + if (delta.tv64 <= tick_period.tv64)
  582 + return;
  583 +
  584 + tick_nohz_restart(ts, now);
575 585 }
576 586  
577 587 #else