From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
To: Boqun Feng <boqun.feng@gmail.com>
Cc: linux-kernel@vger.kernel.org,
Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@kernel.org>,
Josh Triplett <josh@joshtriplett.org>,
Steven Rostedt <rostedt@goodmis.org>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
Lai Jiangshan <jiangshanlai@gmail.com>,
sasha.levin@oracle.com
Subject: Re: [RFC 6/6] RCU: Track rcu_dereference() in RCU read-side critical section
Date: Mon, 15 Feb 2016 20:08:40 -0800 [thread overview]
Message-ID: <20160216040840.GP6719@linux.vnet.ibm.com> (raw)
In-Reply-To: <20160216030143.GA27347@fixme-laptop>
On Tue, Feb 16, 2016 at 11:01:43AM +0800, Boqun Feng wrote:
> On Mon, Feb 15, 2016 at 05:05:53PM -0800, Paul E. McKenney wrote:
> > On Thu, Feb 04, 2016 at 12:45:12AM +0800, Boqun Feng wrote:
> > > The variables protected by an RCU read-side critical section are
> > > sometimes hard to figure out, especially when the critical section is
> > > long or has some function calls in it. However, figuring out which
> > > variable a RCU read-side critical section protects could save
> > > us a lot of time for code reviewing, bug fixing or performance tuning.
> > >
> > > This patch therefore uses the LOCKED_ACCESS to collect the information
> > > of relationship between rcu_dereference*() and rcu_read_lock*() by
> > > doing:
> > >
> > > Step 0: define a locked_access_class for RCU.
> > >
> > > Step 1: set the content of rcu_*_lock_key and __srcu_key to the
> > > address of the locked_access_class for RCU.
> > >
> > > Step 2: add locked_access_point() in __rcu_dereference_check()
> > >
> > > After that we can figure out not only in which RCU read-side critical
> > > section but also after which rcu_read_lock*() called an
> > > rcu_dereference*() is called.
> > >
> > > This feature is controlled by a config option RCU_LOCKED_ACCESS.
> > >
> > > Also clean up the initialization code of lockdep_maps for different
> > > flavors of RCU a little bit.
> > >
> > > Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
> > > ---
> > > include/linux/rcupdate.h | 8 ++++++++
> > > include/linux/srcu.h | 8 +++++++-
> > > kernel/locking/lockdep.c | 3 +++
> > > kernel/rcu/update.c | 31 +++++++++++++++++--------------
> > > lib/Kconfig.debug | 12 ++++++++++++
> > > 5 files changed, 47 insertions(+), 15 deletions(-)
> > >
> > > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
> > > index 14e6f47..4bab658 100644
> > > --- a/include/linux/rcupdate.h
> > > +++ b/include/linux/rcupdate.h
> > > @@ -610,6 +610,13 @@ static inline void rcu_preempt_sleep_check(void)
> > > #define rcu_dereference_sparse(p, space)
> > > #endif /* #else #ifdef __CHECKER__ */
> > >
> > > +#ifdef CONFIG_RCU_LOCKED_ACCESS
> > > +extern struct locked_access_class rcu_laclass;
> > > +#define rcu_dereference_access() \
> > > + locked_access_point(&rcu_laclass, LOCKED_ACCESS_TYPE_READ)
> > > +#else /* #ifdef CONFIG_LOCKED_ACCESS */
> > > +#define rcu_dereference_access()
> > > +#endif /* #else #ifdef CONFIG_LOCKED_ACCESS */
> > > #define __rcu_access_pointer(p, space) \
> > > ({ \
> > > typeof(*p) *_________p1 = (typeof(*p) *__force)READ_ONCE(p); \
> > > @@ -622,6 +629,7 @@ static inline void rcu_preempt_sleep_check(void)
> > > typeof(*p) *________p1 = (typeof(*p) *__force)lockless_dereference(p); \
> > > RCU_LOCKDEP_WARN(!(c), "suspicious rcu_dereference_check() usage"); \
> > > rcu_dereference_sparse(p, space); \
> > > + rcu_dereference_access(); \
> > > ((typeof(*p) __force __kernel *)(________p1)); \
> > > })
> > > #define __rcu_dereference_protected(p, c, space) \
> > > diff --git a/include/linux/srcu.h b/include/linux/srcu.h
> > > index f5f80c5..ff048a2 100644
> > > --- a/include/linux/srcu.h
> > > +++ b/include/linux/srcu.h
> > > @@ -64,12 +64,18 @@ struct srcu_struct {
> > >
> > > #ifdef CONFIG_DEBUG_LOCK_ALLOC
> > >
> > > +# ifdef CONFIG_RCU_LOCKED_ACCESS
> > > +# define RCU_KEY { .laclass = &rcu_laclass }
> > > +# else
> > > +# define RCU_KEY { 0 }
> > > +# endif
> > > +
> > > int __init_srcu_struct(struct srcu_struct *sp, const char *name,
> > > struct lock_class_key *key);
> > >
> > > #define init_srcu_struct(sp) \
> > > ({ \
> > > - static struct lock_class_key __srcu_key; \
> > > + static struct lock_class_key __srcu_key = RCU_KEY; \
> >
> > This gets me the following for the TASKS01, TINY02, TREE02, TREE05,
> > TREE06, and TREE08 configurations:
> >
> > CC mm/mmap.o
> > In file included from /home/paulmck/public_git/linux-rcu/include/linux/notifier.h:15:0,
> > from /home/paulmck/public_git/linux-rcu/arch/x86/include/asm/kdebug.h:4,
> > from /home/paulmck/public_git/linux-rcu/include/linux/kdebug.h:4,
> > from /home/paulmck/public_git/linux-rcu/kernel/notifier.c:1:
> > /home/paulmck/public_git/linux-rcu/kernel/notifier.c: In function ‘srcu_init_notifier_head’:
> > /home/paulmck/public_git/linux-rcu/include/linux/srcu.h:78:16: warning: missing braces around initializer [-Wmissing-braces]
> > static struct lock_class_key __srcu_key = RCU_KEY; \
> > ^
> > /home/paulmck/public_git/linux-rcu/kernel/notifier.c:526:6: note: in expansion of macro ‘init_srcu_struct’
> > if (init_srcu_struct(&nh->srcu) < 0)
> > ^
> > /home/paulmck/public_git/linux-rcu/include/linux/srcu.h:78:16: warning: (near initialization for ‘__srcu_key.subkeys’) [-Wmissing-braces]
> > static struct lock_class_key __srcu_key = RCU_KEY; \
> > ^
> > /home/paulmck/public_git/linux-rcu/kernel/notifier.c:526:6: note: in expansion of macro ‘init_srcu_struct’
> > if (init_srcu_struct(&nh->srcu) < 0)
> > ^
> >
> > These have the following in their .config files:
> >
> > CONFIG_DEBUG_LOCK_ALLOC=y
> >
> > However, none of your new Kconfig options are set, which needs to be
> > tested because this will be the common case. Several of them have
> > CONFIG_PROVE_LOCKING=y, but others do not.
> >
>
> Oh.. this is embarrassing ;-(
>
> Hmm.. when CONFIG_RCU_LOCKED_ACCESS=n and CONFIG_DEBUG_LOCK_ALLOC=y,
> this line becomes:
>
> static struct lock_class_key __srcu_key = { 0 };
>
> IIUC, "={ 0 }" is the unverisal zero initializer in C, could be used for
> zero initialising any structure or array, so it's OK here, right?
>
> And may I ask your compiler's version? Because looks to me this may
> be a compiler bug according to:
>
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64709
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) (KSIC)
> Also I can't reproduce this with CONFIG_RCU_LOCKED_ACCESS=n and
> CONFIG_DEBUG_LOCK_ALLOC=y on my machine, whose gcc version is 5.3.0.
>
> Of course I can use a different way here and do not need a "={ 0 }"
> here, because __srcu_key is static, and I just want to make sure we know
> what's going on here before we use a workaround, or I just want to know
> if I'm a bad C programmer ;-)
Well, it is quite possible that your code is correct in theory, but
we do need to make it so that compilers can deal with it. It would
not be the first compiler-bug workaround in RCU...
Thanx, Paul
> Regards,
> Boqun
>
> > I have dequeued these for the moment. Please send an updated patch
> > series when you have this fixed.
> >
> > Thanx, Paul
> >
> > > \
> > > __init_srcu_struct((sp), #sp, &__srcu_key); \
> > > })
> > > diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
> > > index 996c2d5..36bd0cc 100644
> > > --- a/kernel/locking/lockdep.c
> > > +++ b/kernel/locking/lockdep.c
> > > @@ -4623,5 +4623,8 @@ void locked_access(struct locked_access_class *laclass,
> > > correlate_locked_access(laclass, acqchain, loc, type);
> > > }
> > > EXPORT_SYMBOL(locked_access);
> > > +#ifdef CONFIG_RCU_LOCKED_ACCESS
> > > +DEFINE_LACLASS(rcu);
> > > +#endif
> > >
> > > #endif /* CONFIG_LOCKED_ACCESS */
> > > diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c
> > > index 76b94e1..ba2ded6 100644
> > > --- a/kernel/rcu/update.c
> > > +++ b/kernel/rcu/update.c
> > > @@ -235,20 +235,23 @@ EXPORT_SYMBOL_GPL(__rcu_read_unlock);
> > > #endif /* #ifdef CONFIG_PREEMPT_RCU */
> > >
> > > #ifdef CONFIG_DEBUG_LOCK_ALLOC
> > > -static struct lock_class_key rcu_lock_key;
> > > -struct lockdep_map rcu_lock_map =
> > > - STATIC_LOCKDEP_MAP_INIT("rcu_read_lock", &rcu_lock_key);
> > > -EXPORT_SYMBOL_GPL(rcu_lock_map);
> > > -
> > > -static struct lock_class_key rcu_bh_lock_key;
> > > -struct lockdep_map rcu_bh_lock_map =
> > > - STATIC_LOCKDEP_MAP_INIT("rcu_read_lock_bh", &rcu_bh_lock_key);
> > > -EXPORT_SYMBOL_GPL(rcu_bh_lock_map);
> > > -
> > > -static struct lock_class_key rcu_sched_lock_key;
> > > -struct lockdep_map rcu_sched_lock_map =
> > > - STATIC_LOCKDEP_MAP_INIT("rcu_read_lock_sched", &rcu_sched_lock_key);
> > > -EXPORT_SYMBOL_GPL(rcu_sched_lock_map);
> > > +
> > > +# ifdef CONFIG_RCU_LOCKED_ACCESS
> > > +# define RCU_KEY { .laclass = &rcu_laclass }
> > > +# else
> > > +# define RCU_KEY { 0 }
> > > +# endif
> > > +
> > > +#define DEFINE_RCU_LOCKDEP_MAP(flavor) \
> > > + static struct lock_class_key rcu##flavor##_lock_key = RCU_KEY; \
> > > + struct lockdep_map rcu##flavor##_lock_map = \
> > > + STATIC_LOCKDEP_MAP_INIT("rcu" #flavor "_read_lock", \
> > > + &rcu##flavor##_lock_key); \
> > > + EXPORT_SYMBOL_GPL(rcu##flavor##_lock_map)
> > > +
> > > +DEFINE_RCU_LOCKDEP_MAP();
> > > +DEFINE_RCU_LOCKDEP_MAP(_bh);
> > > +DEFINE_RCU_LOCKDEP_MAP(_sched);
> > >
> > > static struct lock_class_key rcu_callback_key;
> > > struct lockdep_map rcu_callback_map =
> > > diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> > > index 178f288..b6003d4 100644
> > > --- a/lib/Kconfig.debug
> > > +++ b/lib/Kconfig.debug
> > > @@ -1410,6 +1410,18 @@ config RCU_EQS_DEBUG
> > > Say N here if you need ultimate kernel/user switch latencies
> > > Say Y if you are unsure
> > >
> > > +config RCU_LOCKED_ACCESS
> > > + bool "Track data access in RCU read-side critical sections"
> > > + depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
> > > + select LOCKED_ACCESS
> > > + default n
> > > + help
> > > + Track data acces in RCU read-side critical sections,
> > > + by doing so, one can examine which rcu_dereference() and its
> > > + friends are called in which RCU read-side critical sections,
> > > + and even more detailed, after which rcu_read_lock() and
> > > + its friends are called.
> > > +
> > > endmenu # "RCU Debugging"
> > >
> > > config DEBUG_BLOCK_EXT_DEVT
> > > --
> > > 2.7.0
> > >
> >
next prev parent reply other threads:[~2016-02-16 4:08 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-03 16:45 [RFC 0/6] Track RCU dereferences in RCU read-side critical sections Boqun Feng
2016-02-03 16:45 ` [RFC 1/6] lockdep: Add helper functions of irq_context Boqun Feng
2016-02-03 16:45 ` [RFC 2/6] lockdep: LOCKED_ACCESS: Introduce locked access class and acqchain Boqun Feng
2016-02-03 16:45 ` [RFC 3/6] lockdep: LOCKED_ACCESS: Maintain the keys of acqchains Boqun Feng
2016-02-03 16:45 ` [RFC 4/6] lockdep: LOCKED_ACCESS: Introduce locked_access_point() Boqun Feng
2016-02-03 16:45 ` [RFC 5/6] lockdep: LOCKED_ACCESS: Add proc interface for locked access class Boqun Feng
2016-02-03 16:45 ` [RFC 6/6] RCU: Track rcu_dereference() in RCU read-side critical section Boqun Feng
2016-02-16 1:05 ` Paul E. McKenney
2016-02-16 3:01 ` Boqun Feng
2016-02-16 4:08 ` Paul E. McKenney [this message]
2016-02-16 4:59 ` Boqun Feng
2016-02-16 5:55 ` Josh Triplett
2016-02-15 18:03 ` [RFC 0/6] Track RCU dereferences in RCU read-side critical sections Paul E. McKenney
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=20160216040840.GP6719@linux.vnet.ibm.com \
--to=paulmck@linux.vnet.ibm.com \
--cc=boqun.feng@gmail.com \
--cc=jiangshanlai@gmail.com \
--cc=josh@joshtriplett.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mingo@kernel.org \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=sasha.levin@oracle.com \
/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.