NOHZ: fix thinko in the timer restart code path

commit fb02fbc14d (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>
This commit is contained in:
Thomas Gleixner 2008-10-21 20:17:35 +02:00
parent 2515ddc6db
commit c4bd822e7b

View File

@ -567,11 +567,21 @@ static void tick_nohz_switch_to_nohz(void)
static void tick_nohz_kick_tick(int cpu) static void tick_nohz_kick_tick(int cpu)
{ {
struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
ktime_t delta, now;
if (!ts->tick_stopped) if (!ts->tick_stopped)
return; return;
tick_nohz_restart(ts, ktime_get()); /*
* Do not touch the tick device, when the next expiry is either
* already reached or less/equal than the tick period.
*/
now = ktime_get();
delta = ktime_sub(ts->sched_timer.expires, now);
if (delta.tv64 <= tick_period.tv64)
return;
tick_nohz_restart(ts, now);
} }
#else #else