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

Peter Zijlstra <[email protected]> Mon, 3 Aug 2026 17:06:59 +0200
Newsgroups org.kernel.vger.rust-for-linux,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
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.