Re: [PATCH] softirq: WARN_ON !preemptible() not check softirq cnt in bh disable on RT
From: Sebastian Andrzej Siewior
Date: Wed Mar 11 2026 - 06:17:53 EST
On 2026-03-10 19:55:34 [+0800], Xin Zhao wrote:
> In RT-Linux, when enabling CONFIG_PREEMPT_RT_NEEDS_BH_LOCK, calling
> __local_bh_disable_ip() when !preemptible() is illegal because it uses
> local_lock, which might sleep. The only exception is during the
> cgroup_init() logic in start_kernel() while preemption is disabled,
> cgroup_init() calls cgroup_idr_alloc(), which calls spin_lock_bh().
> It is sufficient to only exclude the system startup phase in macro
> DEBUG_LOCKS_WARN_ON.
No, cgroup_init() should not be quoted as an exception. It is okay to
exclude cases while the scheduler is not active because here lock
contention can not happen.
> Although the original check of this_cpu_read(softirq_ctrl.cnt) can also
> prevent the WARN_ON print during the boot process, it may hide some issues
> that should be exposed immediately. Because softirq_ctrl.cnt maybe 0 when
> __local_bh_disabled_ip() is called in !preemptible() context.
That is actually the point. If it is known that the call chain does not
origin from bh-disabled context the it is fine. Well, not fine if you
stick to the details but good enough if you don't to constantly complain
to everyone about the little things which don't make a difference.
> In RT-Linux, __local_bh_disable_ip() will be used by numerous _bh variants
> locks and local_bh_disable(). Since locks call __might_resched() check, we
> analyze the scenario of using local_bh_disable() in !preemptible() context.
>
> If CONFIG_PREEMPT_RT_NEEDS_BH_LOCK is not enabled, __local_bh_disable_ip()
> does not enter the local_lock lock and thus using local_bh_disable() in
> !preemptible() context does not lead to might sleep problem, but using
> local_bh_disable() in !preemptible() state is not meaningful in RT-Linux.
but it does not cause a locking or scheduling problem either.
> In non RT-Linux, we use local_irq_save() followed by local_bh_disable() to
> keep soft interrupts disabled after restoring interrupts. However, in
> RT-Linux, when CONFIG_PREEMPT_RT_NEEDS_BH_LOCK is not enabled,
> local_bh_disable() merely increments the softirq_ctrl.cnt counter without
> actually disabling the soft interrupt behavior, because other tasks on the
> CPU can preempt the task that wants to disable soft interrupts and execute
> soft interrupt-related logic.
> Consider the sequence diagram below:
> Task A Task B
> __local_bh_enable_ip()
> __do_softirq()
> handle_softirqs()
> ...
> local_irq_enable();
> ...
> local_irq_save()
> local_bh_disable()
> local_irq_restore()
> h->action(); -- it is serving softirq
> local_bh_enable()
Okay. How is this a problem? You can enter this scenario event even
without disabling interrupts within Task A.
> Signed-off-by: Xin Zhao <jackzxcui1989@xxxxxxx>
Sebastian