45 lines
1.8 KiB
Diff
45 lines
1.8 KiB
Diff
Subject: rcu: rcutiny: Prevent RCU stall
|
|
From: Thomas Gleixner <tglx@linutronix.de>
|
|
Date: Tue, 16 Oct 2012 18:36:51 +0200
|
|
|
|
rcu_read_unlock_special() checks in_serving_softirq() and leaves early
|
|
when true. On RT this is obviously wrong as softirq processing context
|
|
can be preempted and therefor such a task can be on the gp_tasks
|
|
list. Leaving early here will leave the task on the list and therefor
|
|
block RCU processing forever.
|
|
|
|
This cannot happen on mainline because softirq processing context
|
|
cannot be preempted and therefor this can never happen at all.
|
|
|
|
In fact this check looks quite questionable in general. Neither irq
|
|
context nor softirq processing context in mainline can ever be
|
|
preempted in mainline so the special unlock case should not ever be
|
|
invoked in such context. Now the only explanation might be a
|
|
rcu_read_unlock() being interrupted and therefor leave the rcu nest
|
|
count at 0 before the special unlock bit has been cleared. That looks
|
|
fragile. At least it's missing a big fat comment. Paul ????
|
|
|
|
See mainline commits: ec433f0c5 and 8762705a for further enlightment.
|
|
|
|
Reported-by: Kristian Lehmann <krleit00@hs-esslingen.de>
|
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
Cc: stable-rt@vger.kernel.org
|
|
|
|
---
|
|
kernel/rcutiny_plugin.h | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
Index: linux-stable/kernel/rcutiny_plugin.h
|
|
===================================================================
|
|
--- linux-stable.orig/kernel/rcutiny_plugin.h
|
|
+++ linux-stable/kernel/rcutiny_plugin.h
|
|
@@ -560,7 +560,7 @@ void rcu_read_unlock_special(struct task
|
|
rcu_preempt_cpu_qs();
|
|
|
|
/* Hardware IRQ handlers cannot block. */
|
|
- if (in_irq() || in_serving_softirq()) {
|
|
+ if (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_OFFSET)) {
|
|
local_irq_restore(flags);
|
|
return;
|
|
}
|