Commit c4bd822e7b12a9008241d76db45b665f2fef180c
1 parent
2515ddc6db
Exists in
master
and in
20 other branches
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 |