55 lines
1.5 KiB
Diff
55 lines
1.5 KiB
Diff
Subject: softirq: Fix nohz pending issue for real
|
|
From: Thomas Gleixner <tglx@linutronix.de>
|
|
Date: Mon, 12 Nov 2012 22:07:34 +0100
|
|
|
|
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>
|
|
---
|
|
kernel/softirq.c | 13 ++++---------
|
|
1 file changed, 4 insertions(+), 9 deletions(-)
|
|
|
|
Index: linux-stable/kernel/softirq.c
|
|
===================================================================
|
|
--- linux-stable.orig/kernel/softirq.c
|
|
+++ linux-stable/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
|