[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1310662707.27864.38.camel@gandalf.stny.rr.com>
Date: Thu, 14 Jul 2011 12:58:27 -0400
From: Steven Rostedt <rostedt@...dmis.org>
To: Sergey Senozhatsky <sergey.senozhatsky@...il.com>
Cc: Peter Zijlstra <a.p.zijlstra@...llo.nl>,
Ingo Molnar <mingo@...e.hu>,
Thomas Gleixner <tglx@...utronix.de>,
Andrew Morton <akpm@...ux-foundation.org>,
"Paul E. McKenney" <paulmck@...ux.vnet.ibm.com>,
Dipankar Sarma <dipankar@...ibm.com>,
linux-kernel@...r.kernel.org
Subject: Re: INFO: possible circular locking dependency detected
On Thu, 2011-07-14 at 17:49 +0300, Sergey Senozhatsky wrote:
> [ 4172.371363] Chain exists of:
> [ 4172.371363] rcu_node_level_0 --> sync_rcu_preempt_exp_wq.lock --> &p->pi_lock
> [ 4172.371370]
> [ 4172.371371] Possible unsafe locking scenario:
> [ 4172.371372]
> [ 4172.371374] CPU0 CPU1
> [ 4172.371375] ---- ----
> [ 4172.371377] lock(&p->pi_lock);
> [ 4172.371380] lock(sync_rcu_preempt_exp_wq.lock);
> [ 4172.371384] lock(&p->pi_lock);
> [ 4172.371387] lock(rcu_node_level_0);
> [ 4172.371390]
> [ 4172.371390] *** DEADLOCK ***
Here's what I found:
Note: rcu_node_level_0 == rnp->lock from rcu_init_one()
static char *buf[] = { "rcu_node_level_0",
"rcu_node_level_1",
"rcu_node_level_2",
"rcu_node_level_3" }; /* Match MAX_RCU_LVLS */
[..]
raw_spin_lock_init(&rnp->lock);
lockdep_set_class_and_name(&rnp->lock,
&rcu_node_class[i], buf[i]);
We have this call chain:
rcu_report_exp_rnp() {
raw_spin_lock_irqsave(&rnp->lock, flags);
wake_up(&sync_rcu_preempt_exp_wq);
__wake_up() {
/* q == sync_rcu_preempt_exp_wq */
spin_lock_irqsave(&q->lock, flags);
try_to_wake_up() {
raw_spin_lock_irqsave(&p->pi_lock, flags);
Which gives us the noted lock chain:
rcu_node_level_0 --> sync_rcu_preempt_exp_wq.lock --> &p->pi_lock
But then we have:
try_to_wake_up() {
raw_spin_lock_irqsave(&p->pi_lock, flags);
select_task_rq_fair() {
rcu_read_unlock() {
rcu_read_unlock_special() {
raw_spin_lock(&rnp->lock);
Now we have the call chain of &p->pi_lock -> rcu_node_level_O
But to call this we have:
void __rcu_read_unlock(void)
{
struct task_struct *t = current;
barrier(); /* needed if we ever invoke rcu_read_unlock in rcutree.c */
--t->rcu_read_lock_nesting;
barrier(); /* decrement before load of ->rcu_read_unlock_special */
if (t->rcu_read_lock_nesting == 0 &&
unlikely(ACCESS_ONCE(t->rcu_read_unlock_special)))
rcu_read_unlock_special(t);
Thus the question is, how did we get rcu_read_unlock_special set here?
-- Steve
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists