Skip to content

Commit da65f29

Browse files
anna-marialxKAGA-KOKO
authored andcommitted
timers: Fix nextevt calculation when no timers are pending
When no timer is queued into an empty timer base, the next_expiry will not be updated. It was originally calculated as base->clk + NEXT_TIMER_MAX_DELTA When the timer base stays empty long enough (> NEXT_TIMER_MAX_DELTA), the next_expiry value of the empty base suggests that there is a timer pending soon. This might be more a kind of a theoretical problem, but the fix doesn't hurt. Use only base->next_expiry value as nextevt when timers are pending. Otherwise nextevt will be jiffies + NEXT_TIMER_MAX_DELTA. As all information is in place, update base->next_expiry value of the empty timer base as well. Signed-off-by: Anna-Maria Behnsen <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Frederic Weisbecker <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent bb8caad commit da65f29

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

kernel/time/timer.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,8 +1922,8 @@ static u64 cmp_next_hrtimer_event(u64 basem, u64 expires)
19221922
u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
19231923
{
19241924
struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
1925+
unsigned long nextevt = basej + NEXT_TIMER_MAX_DELTA;
19251926
u64 expires = KTIME_MAX;
1926-
unsigned long nextevt;
19271927
bool was_idle;
19281928

19291929
/*
@@ -1936,7 +1936,6 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
19361936
raw_spin_lock(&base->lock);
19371937
if (base->next_expiry_recalc)
19381938
next_expiry_recalc(base);
1939-
nextevt = base->next_expiry;
19401939

19411940
/*
19421941
* We have a fresh next event. Check whether we can forward the
@@ -1945,10 +1944,20 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
19451944
__forward_timer_base(base, basej);
19461945

19471946
if (base->timers_pending) {
1947+
nextevt = base->next_expiry;
1948+
19481949
/* If we missed a tick already, force 0 delta */
19491950
if (time_before(nextevt, basej))
19501951
nextevt = basej;
19511952
expires = basem + (u64)(nextevt - basej) * TICK_NSEC;
1953+
} else {
1954+
/*
1955+
* Move next_expiry for the empty base into the future to
1956+
* prevent a unnecessary raise of the timer softirq when the
1957+
* next_expiry value will be reached even if there is no timer
1958+
* pending.
1959+
*/
1960+
base->next_expiry = nextevt;
19521961
}
19531962

19541963
/*

0 commit comments

Comments
 (0)