mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
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 <anna-maria@linutronix.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Frederic Weisbecker <frederic@kernel.org> Link: https://lore.kernel.org/r/20231201092654.34614-13-anna-maria@linutronix.de
This commit is contained in:
parent
bb8caad508
commit
da65f29dad
@ -1922,8 +1922,8 @@ static u64 cmp_next_hrtimer_event(u64 basem, u64 expires)
|
||||
u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
|
||||
{
|
||||
struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
|
||||
unsigned long nextevt = basej + NEXT_TIMER_MAX_DELTA;
|
||||
u64 expires = KTIME_MAX;
|
||||
unsigned long nextevt;
|
||||
bool was_idle;
|
||||
|
||||
/*
|
||||
@ -1936,7 +1936,6 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
|
||||
raw_spin_lock(&base->lock);
|
||||
if (base->next_expiry_recalc)
|
||||
next_expiry_recalc(base);
|
||||
nextevt = base->next_expiry;
|
||||
|
||||
/*
|
||||
* 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)
|
||||
__forward_timer_base(base, basej);
|
||||
|
||||
if (base->timers_pending) {
|
||||
nextevt = base->next_expiry;
|
||||
|
||||
/* If we missed a tick already, force 0 delta */
|
||||
if (time_before(nextevt, basej))
|
||||
nextevt = basej;
|
||||
expires = basem + (u64)(nextevt - basej) * TICK_NSEC;
|
||||
} else {
|
||||
/*
|
||||
* Move next_expiry for the empty base into the future to
|
||||
* prevent a unnecessary raise of the timer softirq when the
|
||||
* next_expiry value will be reached even if there is no timer
|
||||
* pending.
|
||||
*/
|
||||
base->next_expiry = nextevt;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user