Re: [PATCH v4 05/17] irq & spin_lock: Add counted interrupt disabling/enabling
Boqun Feng <[email protected]> Wed, 5 Aug 2026 06:53:30 -0700
| Newsgroups | org.kernel.vger.rust-for-linux,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On Wed, Aug 05, 2026 at 12:19:25AM -0700, Boqun Feng wrote:
> On Wed, Aug 05, 2026 at 12:39:36PM +0530, Shrikanth Hegde wrote:
> >
> >
> > On 8/5/26 12:37 PM, Boqun Feng wrote:
> > > On Wed, Aug 05, 2026 at 08:36:45AM +0200, Peter Zijlstra wrote:
> > > > On Tue, Aug 04, 2026 at 02:08:11PM -0700, Boqun Feng wrote:
> > > >
> > > > > > > + /* Interrupts can happen here, but it's OK, see __irq_exit_rcu(). */
> > > > > > > +
> > > > > > > + if ((new_count & HARDIRQ_DISABLE_MASK) == HARDIRQ_DISABLE_OFFSET)
> > > > > > > + _local_interrupt_disable();
> > > > > > > +}
> > > > > >
> > > > > > Maximum nesting possible is 256 right? Whats is stopping here to do more than that?
> > > > >
> > > > > Yes. Currently similar as softirq, we don't detect the overflow.
> > > > >
> > > > > > Should there be a warn_on?
> > > > >
> > > > > A simple warn_on could be problematic because warn_on() itself may take
> > > > > an irq-disabling lock, and that may trigger another overflow on top of
> > > > > the existing overflow. It's a bit tricky to do a proper detection. But
> > > > > I'm open to ideas.
> > > >
> > > > DEBUG_PREEMPT's preempt_count_add() does:
> > > >
> > > > DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >= PREEMPT_MASK - 10);
> > > >
> > >
> > > Yeah, but this is behind a kconfig (DEBUG_PREEMPT), so not sure whether
> > > it's what Shrikanth asked here.
> > >
> >
> > I was suggesting to have a mechanism which allows to debug it/
> > find the callers.
> >
>
> Ok, I can reuse the DEBUG_PREEMPT kconfig and the DEBUG_LOCKS_WARN_ON()
> here, but it'll be similar to the detection here, not a 256 maximum
> nesting but a 256 - 10 value (and I'm not going to explain why we think
> 10 is a good buffer, unless you think we should have a discussion about
> it ;-) )
>
Something as below? Going to send it to kernel build bot and see if it
works for all configs.
----------------->8
diff --git a/include/linux/interrupt_rc.h b/include/linux/interrupt_rc.h
index b9a7f05ecf42..39f30bc65548 100644
--- a/include/linux/interrupt_rc.h
+++ b/include/linux/interrupt_rc.h
@@ -12,6 +12,7 @@
*/
#include <linux/irqflags.h>
+#include <linux/debug_locks.h>
#include <linux/preempt.h>
#include <linux/processor.h>
#include <linux/smp.h>
@@ -63,6 +64,12 @@ static inline void local_interrupt_disable(void)
new_count = hardirq_disable_enter();
+ /* Is hardirq disable count overflow soon? */
+ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT))
+ DEBUG_LOCKS_WARN_ON((new_count & HARDIRQ_DISABLE_MASK) +
+ (10 << HARDIRQ_DISABLE_SHIFT) >
+ HARDIRQ_DISABLE_MASK);
+
/* Interrupts can happen here, but it's OK, see __irq_exit_rcu(). */
if ((new_count & HARDIRQ_DISABLE_MASK) == HARDIRQ_DISABLE_OFFSET)
@@ -73,6 +80,11 @@ static inline void local_interrupt_enable(void)
{
int new_count;
+ /* Unpaired local_interrupt_enable()? Warn and abort. */
+ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT) &&
+ DEBUG_LOCKS_WARN_ON((preempt_count() & HARDIRQ_DISABLE_MASK) == 0))
+ return;
+
new_count = hardirq_disable_exit();
if ((new_count & HARDIRQ_DISABLE_MASK) == 0) >