summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2013-02-13 17:12:02 +0100
committerSteven Rostedt <rostedt@goodmis.org>2013-04-24 11:46:05 -0400
commitff8b37edfb6870659d75312a040f49ebd8fc3813 (patch)
treeea3336ca3c07b107a6c8680eea1083f2ad409d11
parentfe65a34575e1f1c1c7698a69a774980f85ede825 (diff)
downloadlinux-rt-ff8b37edfb6870659d75312a040f49ebd8fc3813.tar.gz
softirq: Fix nohz pending issue for real
We really need to iterate through all softirqs to find a potentially blocked runner. T1 runs softirq X (that cleared pending bit for X) Interrupt raises softirq Y T1 gets blocked on a lock and lock owner is not runnable T1 schedules out CPU goes idle and complains about pending softirq Y. Now iterating over all softirqs lets us find the runner for X and eliminate Y from the to warn about list as well. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--kernel/softirq.c13
1 files changed, 4 insertions, 9 deletions
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 385fceaf2f04..1a0145ab0ddf 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -100,20 +100,15 @@ void softirq_check_pending_idle(void)
{
static int rate_limit;
struct softirq_runner *sr = &__get_cpu_var(softirq_runners);
- u32 warnpending, pending = local_softirq_pending();
+ u32 warnpending = local_softirq_pending();
+ int i;
if (rate_limit >= 10)
return;
- warnpending = pending;
-
- while (pending) {
- struct task_struct *tsk;
- int i = __ffs(pending);
-
- pending &= ~(1 << i);
+ for (i = 0; i < NR_SOFTIRQS; i++) {
+ struct task_struct *tsk = sr->runner[i];
- tsk = sr->runner[i];
/*
* The wakeup code in rtmutex.c wakes up the task
* _before_ it sets pi_blocked_on to NULL under