Skip to content

Commit f80e214

Browse files
committed
hrtimer: Unbreak hrtimer_force_reprogram()
Since the recent consoliation of reprogramming functions, hrtimer_force_reprogram() is affected by a check whether the new expiry time is past the current expiry time. This breaks the NOHZ logic as that relies on the fact that the tick hrtimer is moved into the future. That means cpu_base->expires_next becomes stale and subsequent reprogramming attempts fail as well until the situation is cleaned up by an hrtimer interrupts. For some yet unknown reason this leads to a complete stall, so for now partially revert the offending commit to a known working state. The root cause for the stall is still investigated and will be fixed in a subsequent commit. Fixes: b14bca9 ("hrtimer: Consolidate reprogramming code") Reported-by: Mike Galbraith <efault@gmx.de> Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Mike Galbraith <efault@gmx.de> Link: https://lore.kernel.org/r/8735recskh.ffs@tglx
1 parent 9482fd7 commit f80e214

File tree

1 file changed

+20
-20
lines changed

1 file changed

+20
-20
lines changed

kernel/time/hrtimer.c

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -652,24 +652,10 @@ static inline int hrtimer_hres_active(void)
652652
return __hrtimer_hres_active(this_cpu_ptr(&hrtimer_bases));
653653
}
654654

655-
static void
656-
__hrtimer_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal,
657-
struct hrtimer *next_timer, ktime_t expires_next)
655+
static void __hrtimer_reprogram(struct hrtimer_cpu_base *cpu_base,
656+
struct hrtimer *next_timer,
657+
ktime_t expires_next)
658658
{
659-
/*
660-
* If the hrtimer interrupt is running, then it will reevaluate the
661-
* clock bases and reprogram the clock event device.
662-
*/
663-
if (cpu_base->in_hrtirq)
664-
return;
665-
666-
if (expires_next > cpu_base->expires_next)
667-
return;
668-
669-
if (skip_equal && expires_next == cpu_base->expires_next)
670-
return;
671-
672-
cpu_base->next_timer = next_timer;
673659
cpu_base->expires_next = expires_next;
674660

675661
/*
@@ -707,8 +693,10 @@ hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal)
707693

708694
expires_next = hrtimer_update_next_event(cpu_base);
709695

710-
__hrtimer_reprogram(cpu_base, skip_equal, cpu_base->next_timer,
711-
expires_next);
696+
if (skip_equal && expires_next == cpu_base->expires_next)
697+
return;
698+
699+
__hrtimer_reprogram(cpu_base, cpu_base->next_timer, expires_next);
712700
}
713701

714702
/* High resolution timer related functions */
@@ -863,7 +851,19 @@ static void hrtimer_reprogram(struct hrtimer *timer, bool reprogram)
863851
if (base->cpu_base != cpu_base)
864852
return;
865853

866-
__hrtimer_reprogram(cpu_base, true, timer, expires);
854+
if (expires >= cpu_base->expires_next)
855+
return;
856+
857+
/*
858+
* If the hrtimer interrupt is running, then it will reevaluate the
859+
* clock bases and reprogram the clock event device.
860+
*/
861+
if (cpu_base->in_hrtirq)
862+
return;
863+
864+
cpu_base->next_timer = timer;
865+
866+
__hrtimer_reprogram(cpu_base, timer, expires);
867867
}
868868

869869
static bool update_needs_ipi(struct hrtimer_cpu_base *cpu_base,

0 commit comments

Comments
 (0)