From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
To: Steven Rostedt <rostedt@goodmis.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>,
Ed Tomlinson <edt@aei.ca>,
Sergey Senozhatsky <sergey.senozhatsky@gmail.com>,
Ingo Molnar <mingo@elte.hu>, Thomas Gleixner <tglx@linutronix.de>,
Andrew Morton <akpm@linux-foundation.org>,
Dipankar Sarma <dipankar@in.ibm.com>,
linux-kernel@vger.kernel.org
Subject: Re: INFO: possible circular locking dependency detected
Date: Fri, 15 Jul 2011 10:24:16 -0700 [thread overview]
Message-ID: <20110715172416.GE2327@linux.vnet.ibm.com> (raw)
In-Reply-To: <1310750204.27864.69.camel@gandalf.stny.rr.com>
On Fri, Jul 15, 2011 at 01:16:44PM -0400, Steven Rostedt wrote:
> On Fri, 2011-07-15 at 10:03 -0700, Paul E. McKenney wrote:
> > On Fri, Jul 15, 2011 at 12:55:57PM -0400, Steven Rostedt wrote:
> > > On Fri, 2011-07-15 at 15:07 +0200, Peter Zijlstra wrote:
> > >
> > > > OK, so the latter case cannot happen (rcu_preempt_check_callbacks only
> > > > sets NEED_QS when rcu_read_lock_nesting), we need two interrupts for
> > > > this to happen.
> > > >
> > > > rcu_read_lock()
> > > >
> > > > <IRQ>
> > > > |= RCU_READ_UNLOCK_NEED_QS
> > > >
> > > > rcu_read_unlock()
> > > > __rcu_read_unlock()
> > > > --rcu_read_lock_nesting;
> > > > <IRQ>
> > > > ttwu()
> > > > rcu_read_lock()
> > > > rcu_read_unlock()
> > > > rcu_read_unlock_special()
> > > > *BANG*
> > > > rcu_read_unlock_special()
> > > >
> > >
> > > What about this patch? Not even compiled tested.
> >
> > This runs afoul of the restriction that ->rcu_read_unlock_special must
> > be updated with irqs disabled, please see below.
>
> What about changing special into a local_t, then it could be updated
> atomically wrt interrupts (not for other CPUs).
I would like to avoid increasing the cost of the rcu_read_unlock()
fastpath. I still believe that it is possible to fix this without
increasing that cost.
> > I am also missing what the goal is -- I don't immediatly see how this
> > prevents the scenario that Ed ran into, for example.
>
> >From the example that Peter showed above:
>
> The interrupt happens after decrementing lock_nesting, and then when it
> did the rcu_read_unlock(), it would call special() because the ->special
> variable was set. My patch makes it so that ->special will *not* be set.
But the rcu_read_unlock() called from within the irq handler would
take a second snapshot of ->special. It could then enter
rcu_read_unlock_special().
> We will probably need to put a preempt_disable() in there too, to keep
> the ->special being zero and scheduled out.
But ->rcu_read_unlock_special is in the task structure, so would move
with the task. But yes, that sort of thing is one reason that I would
like to keep ->rcu_read_unlock_special modifications under irq-disable.
> > Thanx, Paul
> >
> > > -- Steve
> > >
> > > diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
> > > index 14dc7dd..e3545fa 100644
> > > --- a/kernel/rcutree_plugin.h
> > > +++ b/kernel/rcutree_plugin.h
> > > @@ -284,18 +284,17 @@ static struct list_head *rcu_next_node_entry(struct task_struct *t,
> > > * notify RCU core processing or task having blocked during the RCU
> > > * read-side critical section.
> > > */
> > > -static void rcu_read_unlock_special(struct task_struct *t)
> > > +static int rcu_read_unlock_special(struct task_struct *t, int special)
> > > {
> > > int empty;
> > > int empty_exp;
> > > unsigned long flags;
> > > struct list_head *np;
> > > struct rcu_node *rnp;
> > > - int special;
> > >
> > > /* NMI handlers cannot block and cannot safely manipulate state. */
> > > if (in_nmi())
> > > - return;
> > > + return special;
> > >
> > > local_irq_save(flags);
> > >
> > > @@ -303,7 +302,6 @@ static void rcu_read_unlock_special(struct task_struct *t)
> > > * If RCU core is waiting for this CPU to exit critical section,
> > > * let it know that we have done so.
> > > */
> > > - special = t->rcu_read_unlock_special;
> > > if (special & RCU_READ_UNLOCK_NEED_QS) {
> > > rcu_preempt_qs(smp_processor_id());
> > > }
> > > @@ -311,7 +309,7 @@ static void rcu_read_unlock_special(struct task_struct *t)
> > > /* Hardware IRQ handlers cannot block. */
> > > if (in_irq()) {
> > > local_irq_restore(flags);
> > > - return;
> > > + return special;
> > > }
> > >
> > > /* Clean up if blocked during RCU read-side critical section. */
> > > @@ -373,6 +371,7 @@ static void rcu_read_unlock_special(struct task_struct *t)
> > > } else {
> > > local_irq_restore(flags);
> > > }
> > > + return special;
> > > }
> > >
> > > /*
> > > @@ -385,13 +384,21 @@ static void rcu_read_unlock_special(struct task_struct *t)
> > > void __rcu_read_unlock(void)
> > > {
> > > struct task_struct *t = current;
> > > + int special;
> > >
> > > + special = ACCESS_ONCE(t->rcu_read_unlock_special);
> > > + /*
> > > + * Clear special here to prevent interrupts from seeing it
> > > + * enabled after decrementing lock_nesting and calling
> > > + * rcu_read_unlock_special().
> > > + */
> >
> > Any change to ->rcu_read_unlock_special from an irq handler that happens
> > here is lost. Changes to ->rcu_read_unlock_special must be done with
> > irqs disabled. And I hope to avoid irq disabling on the rcu_read_unlock()
> > fastpath.
>
> We can check if special changed afterwards. Hmm, would a xchg be bad to
> do?
I would really like to avoid that in the common rcu_read_unlock() fastpath.
> > > + t->rcu_read_unlock_special = 0;
> > > 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);
> > > + if (t->rcu_read_lock_nesting == 0 && special)
> > > + special = rcu_read_unlock_special(t, special);
> >
> > And changes to ->rcu_read_unlock_special from an irq handler that happens
> > here are also lost.
>
> How expensive is xchg?
>
> special = xchg(&t->rcu_read_lock_special, 0);
> [..]
> special = xchg(&t->rcu_read_lock_special, special);
> /* check special */
>
> Or is xchg too expensive for rcu_read_unlock()?
It is a bit expensive for that fastpath.
Thanx, Paul
> -- Steve
>
> >
> > > + t->rcu_read_unlock_special = special;
> > > #ifdef CONFIG_PROVE_LOCKING
> > > WARN_ON_ONCE(ACCESS_ONCE(t->rcu_read_lock_nesting) < 0);
> > > #endif /* #ifdef CONFIG_PROVE_LOCKING */
> > >
> > >
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
next prev parent reply other threads:[~2011-07-15 17:25 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-07-14 14:49 INFO: possible circular locking dependency detected Sergey Senozhatsky
2011-07-14 16:41 ` Peter Zijlstra
2011-07-14 16:57 ` Paul E. McKenney
2011-07-14 19:16 ` Sergey Senozhatsky
2011-07-14 19:15 ` Sergey Senozhatsky
2011-07-14 19:34 ` Paul E. McKenney
2011-07-14 19:38 ` Dave Jones
2011-07-14 20:33 ` Paul E. McKenney
2011-07-14 19:38 ` Sergey Senozhatsky
2011-07-14 16:58 ` Steven Rostedt
2011-07-14 17:02 ` Steven Rostedt
2011-07-14 17:05 ` Paul E. McKenney
2011-07-14 17:32 ` Steven Rostedt
2011-07-14 17:46 ` Steven Rostedt
2011-07-14 19:18 ` Paul E. McKenney
2011-07-14 19:41 ` Steven Rostedt
2011-07-14 20:33 ` Paul E. McKenney
2011-07-15 11:05 ` Ed Tomlinson
2011-07-15 11:29 ` Peter Zijlstra
2011-07-15 11:35 ` Ed Tomlinson
2011-07-15 11:39 ` Peter Zijlstra
2011-07-15 18:11 ` Paul E. McKenney
2011-07-15 12:42 ` Paul E. McKenney
2011-07-15 13:07 ` Peter Zijlstra
2011-07-15 14:36 ` Paul E. McKenney
2011-07-15 15:04 ` Peter Zijlstra
2011-07-15 15:59 ` Paul E. McKenney
2011-07-15 16:11 ` Peter Zijlstra
2011-07-15 16:56 ` Paul E. McKenney
2011-07-15 21:48 ` Ed Tomlinson
2011-07-15 22:04 ` Paul E. McKenney
2011-07-16 19:42 ` Ed Tomlinson
2011-07-17 0:02 ` Paul E. McKenney
2011-07-17 1:56 ` Ed Tomlinson
2011-07-17 14:28 ` Paul E. McKenney
2011-07-18 15:15 ` Paul E. McKenney
2011-07-18 9:29 ` Peter Zijlstra
2011-07-18 15:29 ` Paul E. McKenney
2011-07-15 16:55 ` Steven Rostedt
2011-07-15 17:03 ` Paul E. McKenney
2011-07-15 17:16 ` Steven Rostedt
2011-07-15 17:24 ` Paul E. McKenney [this message]
2011-07-15 17:42 ` Steven Rostedt
2011-07-15 18:33 ` Paul E. McKenney
-- strict thread matches above, loose matches on Subject: below --
2013-11-20 20:15 Alexei Starovoitov
2013-11-20 23:24 ` Casey Schaufler
2011-08-07 16:22 Justin P. Mattock
2011-08-11 20:57 ` Justin P. Mattock
2009-12-06 10:11 Richard Zidlicky
2009-10-10 23:09 John Kacur
2007-02-08 15:03 Pedro M. López
2006-10-16 14:05 alpha @ steudten Engineering
2006-10-16 14:32 ` Nick Piggin
2006-10-16 15:42 ` Randy Dunlap
2006-10-16 15:46 ` Nick Piggin
2006-10-19 6:02 ` Andrew Morton
2006-10-19 6:30 ` Nick Piggin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110715172416.GE2327@linux.vnet.ibm.com \
--to=paulmck@linux.vnet.ibm.com \
--cc=a.p.zijlstra@chello.nl \
--cc=akpm@linux-foundation.org \
--cc=dipankar@in.ibm.com \
--cc=edt@aei.ca \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=rostedt@goodmis.org \
--cc=sergey.senozhatsky@gmail.com \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.