diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2008-10-21 14:17:35 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2008-10-21 14:53:24 -0400 |
| commit | c4bd822e7b12a9008241d76db45b665f2fef180c (patch) | |
| tree | bd4b7b4e2e7db065c971eb264196f02e0b01ecff | |
| parent | 2515ddc6db8eb49a79f0fe5e67ff09ac7c81eab4 (diff) | |
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>
| -rw-r--r-- | kernel/time/tick-sched.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 0581c11fe6c6..727c1ae0517a 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
| @@ -567,11 +567,21 @@ static void tick_nohz_switch_to_nohz(void) | |||
| 567 | static void tick_nohz_kick_tick(int cpu) | 567 | static void tick_nohz_kick_tick(int cpu) |
| 568 | { | 568 | { |
| 569 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | 569 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); |
| 570 | ktime_t delta, now; | ||
| 570 | 571 | ||
| 571 | if (!ts->tick_stopped) | 572 | if (!ts->tick_stopped) |
| 572 | return; | 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 | #else | 587 | #else |
