History

timers: Improve get_next_timer_interrupt()

Gilad reported at http://lkml.kernel.org/r/1336056962-10465-2-git-send-email-gilad@benyossef.com "Current timer code fails to correctly return a value meaning that there is no future timer event, with the result that the timer keeps getting re-armed in HZ one shot mode even when we could turn it off, generating unneeded interrupts. What is happening is that when __next_timer_interrupt() wishes to return a value that signifies "there is no future timer event", it returns (base->timer_jiffies + NEXT_TIMER_MAX_DELTA). However, the code in tick_nohz_stop_sched_tick(), which called __next_timer_interrupt() via get_next_timer_interrupt(), compares the return value to (last_jiffies + NEXT_TIMER_MAX_DELTA) to see if the timer needs to be re-armed. base->timer_jiffies != last_jiffies and so tick_nohz_stop_sched_tick() interperts the return value as indication that there is a distant future event 12 days from now and programs the timer to fire next after KTIME_MAX nsecs instead of avoiding to arm it. This ends up causing a needless interrupt once every KTIME_MAX nsecs." Fix this by using the new active timer accounting. This avoids scans when no active timer is enqueued completely, so we don't have to rely on base->timer_next and base->timer_jiffies anymore.

Thomas Gleixner committed 14 years ago

Commit e40468a1 parent 99d5f3a1 file · +8 −5Browse files

Unified · Split

kernel/timer.c+8−5
@@ -1326,18 +1326,21 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now, · 1325 unmodified lines
13261326 unsigned long get_next_timer_interrupt(unsigned long now)
13271327 {
13281328 struct tvec_base *base = __this_cpu_read(tvec_bases);
1329− unsigned long expires;
1329+ unsigned long expires = now + NEXT_TIMER_MAX_DELTA;
13301330
13311331 /*
13321332 * Pretend that there is no timer pending if the cpu is offline.
13331333 * Possible pending timers will be migrated later to an active cpu.
13341334 */
13351335 if (cpu_is_offline(smp_processor_id()))
1336− return now + NEXT_TIMER_MAX_DELTA;
1336+ return expires;
1337+
13371338 spin_lock(&base->lock);
1338− if (time_before_eq(base->next_timer, base->timer_jiffies))
1339− base->next_timer = __next_timer_interrupt(base);
1340− expires = base->next_timer;
1339+ if (base->active_timers) {
1340+ if (time_before_eq(base->next_timer, base->timer_jiffies))
1341+ base->next_timer = __next_timer_interrupt(base);
1342+ expires = base->next_timer;
1343+ }
13411344 spin_unlock(&base->lock);
13421345
13431346 if (time_before_eq(expires, now))