tasklets: Prevent tasklet_unlock_spin_wait() deadlock on RT
authorThomas Gleixner <tglx@linutronix.de>
Tue, 9 Mar 2021 08:42:10 +0000 (09:42 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Wed, 17 Mar 2021 15:33:57 +0000 (16:33 +0100)
commiteb2dafbba8b824ee77f166629babd470dd0b1c0a
treec3a84b3625d79c8b129e05c252be3f7d3ab376f8
parent697d8c63c4a2991a22a896a5e6adcdbb28fefe56
tasklets: Prevent tasklet_unlock_spin_wait() deadlock on RT

tasklet_unlock_spin_wait() spin waits for the TASKLET_STATE_SCHED bit in
the tasklet state to be cleared. This works on !RT nicely because the
corresponding execution can only happen on a different CPU.

On RT softirq processing is preemptible, therefore a task preempting the
softirq processing thread can spin forever.

Prevent this by invoking local_bh_disable()/enable() inside the loop. In
case that the softirq processing thread was preempted by the current task,
current will block on the local lock which yields the CPU to the preempted
softirq processing thread. If the tasklet is processed on a different CPU
then the local_bh_disable()/enable() pair is just a waste of processor
cycles.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20210309084241.988908275@linutronix.de
include/linux/interrupt.h
kernel/softirq.c