Re: [PATCH 05/24] irq & spin_lock: Add counted interrupt disabling/enabling

From: Peter Zijlstra

Date: Mon Aug 03 2026 - 11:30:20 EST


On Mon, Aug 03, 2026 at 07:39:44AM -0700, Boqun Feng wrote:
> On Mon, Aug 03, 2026 at 04:21:06PM +0200, Peter Zijlstra wrote:

> > No; for one, you cannot elide the preempt_disable/enable() from this
> > thing.
> >
> > It has always been valid to do:
> >
> > raw_spin_lock_irq(lock);
> > ...
> > raw_spin_unlock(lock);
> > ...
> > local_irq_enable();
> >
> > And since raw_spin_unlock() does have the preemption thing,
>
> Good point!
>
> However, IIRC, the elision was trying to optimize two preempt_count
> accesses (one for irq disable, one for preempt disable) into one in
> raw_spin_lock_irq_disable() or raw_spin_unlock_irq_enable().

It is relatively easy to fold the increments in
raw_spin_lock_irq_disable(), the enable (see below) is going to be a
little more tricky.

> We may
> still want to do it in the future, if that's the case, we will still
> have should_resched() check in raw_spin_unlock_irq_enable()?

So if you have raw_spin_unlock_irq_enable() *and* you've managed to fold
the preempt_count() accesses of hardirq_disable_exit() and
preempt_enable(), then yes. Consider:

preempt_disable();

<IRQ happens, set TIF_NEED_RESCHED and folds PREEMPT_NEED_RESCHED>

raw_spin_lock_irq_disable(lock);
preempt_enable(); // can't reschedule
...
raw_spin_unlock_irq_enable(lock); // drops to 0 without an interrupt pending

So the folding of hardirq_disable_exit() and preempt_enable() needs to
take care of *both* special cases: 1) the local_irq_restore() and 2)
calling __preempt_schedule() when 0.