Re: [PATCH v2 5/6] entry,hrtimer: Push reprogramming timers into the interrupt return path
From: Thomas Gleixner
Date: Mon Feb 02 2026 - 18:28:29 EST
On Mon, Feb 02 2026 at 17:33, Peter Zijlstra wrote:
> On Mon, Feb 02, 2026 at 03:37:13PM +0100, Thomas Gleixner wrote:
>> On Wed, Jan 21 2026 at 17:20, Peter Zijlstra wrote:
>> > while (ti_work & EXIT_TO_USER_MODE_WORK_LOOP) {
>> >
>> > + /*
>> > + * If hrtimer need re-arming, do so before enabling IRQs,
>> > + * except when a reschedule is needed, in that case schedule()
>> > + * will do this.
>> > + */
>> > + if ((ti_work & (_TIF_NEED_RESCHED |
>> > + _TIF_NEED_RESCHED_LAZY |
>> > + _TIF_HRTIMER_REARM)) == _TIF_HRTIMER_REARM)
>> > + hrtimer_rearm();
>>
>> Two things I'm not convinced that they are handled correctly:
>>
>> 1) Interrupts
>>
>> After reenabling interrupts and before reaching schedule() an
>> interrupt comes in and runs soft interrupt processing for a while
>> on the way back, which delays the update until that processing
>> completes.
>
> So the basic thing looks like:
>
> <USER-MODE>
> irqentry_enter()
> run_irq_on_irqstack_cond()
> if (user_mode() || hardirq_stack_inuse)
> irq_enter_rcu();
> func_c();
> irq_exit_rcu()
> __irq_exit_rcu()
> invoke_softirq()
> irqentry_exit()
> irqentry_exit_to_user_mode()
> irqentry_exit_to_user_mode_prepare()
> __exit_to_user_mode_prepare()
> exit_to_user_mode_loop()
> ...here...
>
> So a nested IRQ at this point will have !user_mode(), but I think it can
> still end up in softirqs due to that hardirq_stack_inuse. Should we
> perhaps make sure only user_mode() ends up in softirqs?
All interrupts independent of the mode they hit are ending up in
irq_exit_rcu() and therefore in __irq_exit_rcu()
run_irq_on_irqstack_cond()
if (user_mode() || hardirq_stack_inuse)
// Stay on user or hardirq stack
irq_enter_rcu();
func_c();
irq_exit_rcu()
else
// MAGIC ASM to switch to hardirq stack
call irq_enter_rcu
call func_c
call irq_exit_rcu
The only reason why invoke_softirq() won't be called is when the
interrupt hits into the softirq processing region of the previous
interrupt, which means it's already on the hardirq stack.
But looking at this there is already a problem without interrupt
nesting:
irq_enter_rcu();
timer_interrupt()
hrtimer_interrupt()
delay_rearm();
irq_exit_rcu()
__irq_exit_rcu()
invoke_softirq() <- Here
Soft interrupts can run for quite some time, which means this already
can cause timers being delayed for way too long. I think in
__irq_exit_rcu() you want to do:
if (!in_interrupt() && local_softirq_pending()) {
hrtimer_rearm();
invoke_softirq();
}
Thanks,
tglx