* [PATCH] genirq: Fix the possible synchronize_irq() wait-forever
@ 2014-02-24 3:29 Chuansheng Liu
2014-02-27 9:58 ` [tip:irq/urgent] genirq: Remove racy waitqueue_active check tip-bot for Chuansheng Liu
0 siblings, 1 reply; 2+ messages in thread
From: Chuansheng Liu @ 2014-02-24 3:29 UTC (permalink / raw)
To: tglx; +Cc: linux-kernel, Chuansheng Liu, Xiaoming Wang
We hit one rare case below:
T1 calling disable_irq(), but hanging at synchronize_irq()
always;
The corresponding irq thread is in sleeping state;
And all CPUs are in idle state;
After analysis, we found there is one possible scenerio which
causes T1 is waiting there forever:
CPU0 CPU1
synchronize_irq()
wait_event()
spin_lock()
atomic_dec_and_test(&threads_active)
insert the __wait into queue
spin_unlock()
if(waitqueue_active)
atomic_read(&threads_active)
wait_up()
Here after inserted the __wait into queue on CPU0, and before
test if queue is empty on CPU1, there is no barrier, it maybe
cause it is not visible for CPU1 immediately, although CPU0 has
updated the queue list.
It is similar for CPU0 atomic_read() threads_active also.
So we need one smp_mb() before waitqueue_active or something like
that.
Thomas shared one good option that removing waitqueue_active()
judgement directly, it will make things to be simple and clear.
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Xiaoming Wang <xiaoming.wang@intel.com>
Signed-off-by: Chuansheng Liu <chuansheng.liu@intel.com>
---
kernel/irq/manage.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 481a13c..d3bf660 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -802,8 +802,7 @@ static irqreturn_t irq_thread_fn(struct irq_desc *desc,
static void wake_threads_waitq(struct irq_desc *desc)
{
- if (atomic_dec_and_test(&desc->threads_active) &&
- waitqueue_active(&desc->wait_for_threads))
+ if (atomic_dec_and_test(&desc->threads_active))
wake_up(&desc->wait_for_threads);
}
--
1.9.rc0
^ permalink raw reply [flat|nested] 2+ messages in thread
* [tip:irq/urgent] genirq: Remove racy waitqueue_active check
2014-02-24 3:29 [PATCH] genirq: Fix the possible synchronize_irq() wait-forever Chuansheng Liu
@ 2014-02-27 9:58 ` tip-bot for Chuansheng Liu
0 siblings, 0 replies; 2+ messages in thread
From: tip-bot for Chuansheng Liu @ 2014-02-27 9:58 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, xiaoming.wang, hpa, mingo, tglx, chuansheng.liu
Commit-ID: c685689fd24d310343ac33942e9a54a974ae9c43
Gitweb: http://git.kernel.org/tip/c685689fd24d310343ac33942e9a54a974ae9c43
Author: Chuansheng Liu <chuansheng.liu@intel.com>
AuthorDate: Mon, 24 Feb 2014 11:29:50 +0800
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitDate: Thu, 27 Feb 2014 10:54:16 +0100
genirq: Remove racy waitqueue_active check
We hit one rare case below:
T1 calling disable_irq(), but hanging at synchronize_irq()
always;
The corresponding irq thread is in sleeping state;
And all CPUs are in idle state;
After analysis, we found there is one possible scenerio which
causes T1 is waiting there forever:
CPU0 CPU1
synchronize_irq()
wait_event()
spin_lock()
atomic_dec_and_test(&threads_active)
insert the __wait into queue
spin_unlock()
if(waitqueue_active)
atomic_read(&threads_active)
wake_up()
Here after inserted the __wait into queue on CPU0, and before
test if queue is empty on CPU1, there is no barrier, it maybe
cause it is not visible for CPU1 immediately, although CPU0 has
updated the queue list.
It is similar for CPU0 atomic_read() threads_active also.
So we'd need one smp_mb() before waitqueue_active.that, but removing
the waitqueue_active() check solves it as wel l and it makes
things simple and clear.
Signed-off-by: Chuansheng Liu <chuansheng.liu@intel.com>
Cc: Xiaoming Wang <xiaoming.wang@intel.com>
Link: http://lkml.kernel.org/r/1393212590-32543-1-git-send-email-chuansheng.liu@intel.com
Cc: stable@vger.kernel.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 481a13c..d3bf660 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -802,8 +802,7 @@ static irqreturn_t irq_thread_fn(struct irq_desc *desc,
static void wake_threads_waitq(struct irq_desc *desc)
{
- if (atomic_dec_and_test(&desc->threads_active) &&
- waitqueue_active(&desc->wait_for_threads))
+ if (atomic_dec_and_test(&desc->threads_active))
wake_up(&desc->wait_for_threads);
}
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2014-02-27 9:58 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-24 3:29 [PATCH] genirq: Fix the possible synchronize_irq() wait-forever Chuansheng Liu
2014-02-27 9:58 ` [tip:irq/urgent] genirq: Remove racy waitqueue_active check tip-bot for Chuansheng Liu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome