* [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC
@ 2015-05-21 10:04 Denys Vlasenko
2015-05-21 12:52 ` Paul E. McKenney
2015-05-21 13:45 ` Steven Rostedt
0 siblings, 2 replies; 13+ messages in thread
From: Denys Vlasenko @ 2015-05-21 10:04 UTC (permalink / raw)
To: Paul E. McKenney
Cc: Denys Vlasenko, Josh Triplett, Steven Rostedt, Mathieu Desnoyers,
Lai Jiangshan, linux-kernel, Tejun Heo, Oleg Nesterov
DEBUG_LOCK_ALLOC=y is not a production setting, but it is
not very unusual either. Many developers routinely
use kernels built with it enabled.
Apart from being selected by hand, it is also auto-selected by
PROVE_LOCKING "Lock debugging: prove locking correctness" and
LOCK_STAT "Lock usage statistics" config options.
LOCK STAT is necessary for "perf lock" to work.
I wouldn't spend too much time optimizing it, but this particular
function has a very large cost in code size: when it is deinlined,
code size decreases by 830,000 bytes:
text data bss dec hex filename
85674192 22294776 20627456 128596424 7aa39c8 vmlinux.before
84837612 22294424 20627456 127759492 79d7484 vmlinux
(with this config: http://busybox.net/~vda/kernel_config)
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
CC: Josh Triplett <josh@joshtriplett.org>
CC: Steven Rostedt <rostedt@goodmis.org>
CC: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: Lai Jiangshan <laijs@cn.fujitsu.com>
CC: linux-kernel@vger.kernel.org
CC: Tejun Heo <tj@kernel.org>
CC: Oleg Nesterov <oleg@redhat.com>
---
include/linux/rcupdate.h | 40 ++-----------------------------------
kernel/rcu/update.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+), 38 deletions(-)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 7809749..6024a65 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -439,46 +439,10 @@ int rcu_read_lock_bh_held(void);
* If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an
* RCU-sched read-side critical section. In absence of
* CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side
- * critical section unless it can prove otherwise. Note that disabling
- * of preemption (including disabling irqs) counts as an RCU-sched
- * read-side critical section. This is useful for debug checks in functions
- * that required that they be called within an RCU-sched read-side
- * critical section.
- *
- * Check debug_lockdep_rcu_enabled() to prevent false positives during boot
- * and while lockdep is disabled.
- *
- * Note that if the CPU is in the idle loop from an RCU point of
- * view (ie: that we are in the section between rcu_idle_enter() and
- * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU
- * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs
- * that are in such a section, considering these as in extended quiescent
- * state, so such a CPU is effectively never in an RCU read-side critical
- * section regardless of what RCU primitives it invokes. This state of
- * affairs is required --- we need to keep an RCU-free window in idle
- * where the CPU may possibly enter into low power mode. This way we can
- * notice an extended quiescent state to other CPUs that started a grace
- * period. Otherwise we would delay any grace period as long as we run in
- * the idle task.
- *
- * Similarly, we avoid claiming an SRCU read lock held if the current
- * CPU is offline.
+ * critical section unless it can prove otherwise.
*/
#ifdef CONFIG_PREEMPT_COUNT
-static inline int rcu_read_lock_sched_held(void)
-{
- int lockdep_opinion = 0;
-
- if (!debug_lockdep_rcu_enabled())
- return 1;
- if (!rcu_is_watching())
- return 0;
- if (!rcu_lockdep_current_cpu_online())
- return 0;
- if (debug_locks)
- lockdep_opinion = lock_is_held(&rcu_sched_lock_map);
- return lockdep_opinion || preempt_count() != 0 || irqs_disabled();
-}
+int rcu_read_lock_sched_held(void);
#else /* #ifdef CONFIG_PREEMPT_COUNT */
static inline int rcu_read_lock_sched_held(void)
{
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c
index e0d31a3..e02218f 100644
--- a/kernel/rcu/update.c
+++ b/kernel/rcu/update.c
@@ -62,6 +62,58 @@ MODULE_ALIAS("rcupdate");
module_param(rcu_expedited, int, 0);
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+/**
+ * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section?
+ *
+ * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an
+ * RCU-sched read-side critical section. In absence of
+ * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side
+ * critical section unless it can prove otherwise. Note that disabling
+ * of preemption (including disabling irqs) counts as an RCU-sched
+ * read-side critical section. This is useful for debug checks in functions
+ * that required that they be called within an RCU-sched read-side
+ * critical section.
+ *
+ * Check debug_lockdep_rcu_enabled() to prevent false positives during boot
+ * and while lockdep is disabled.
+ *
+ * Note that if the CPU is in the idle loop from an RCU point of
+ * view (ie: that we are in the section between rcu_idle_enter() and
+ * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU
+ * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs
+ * that are in such a section, considering these as in extended quiescent
+ * state, so such a CPU is effectively never in an RCU read-side critical
+ * section regardless of what RCU primitives it invokes. This state of
+ * affairs is required --- we need to keep an RCU-free window in idle
+ * where the CPU may possibly enter into low power mode. This way we can
+ * notice an extended quiescent state to other CPUs that started a grace
+ * period. Otherwise we would delay any grace period as long as we run in
+ * the idle task.
+ *
+ * Similarly, we avoid claiming an SRCU read lock held if the current
+ * CPU is offline.
+ */
+#ifdef CONFIG_PREEMPT_COUNT
+int rcu_read_lock_sched_held(void)
+{
+ int lockdep_opinion = 0;
+
+ if (!debug_lockdep_rcu_enabled())
+ return 1;
+ if (!rcu_is_watching())
+ return 0;
+ if (!rcu_lockdep_current_cpu_online())
+ return 0;
+ if (debug_locks)
+ lockdep_opinion = lock_is_held(&rcu_sched_lock_map);
+ return lockdep_opinion || preempt_count() != 0 || irqs_disabled();
+}
+EXPORT_SYMBOL(rcu_read_lock_sched_held);
+#else
+/* !CONFIG_PREEMPT_COUNT - the function is inlined to always return 1 */
+#endif
+
#ifdef CONFIG_PREEMPT_RCU
/*
--
1.8.1.4
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC 2015-05-21 10:04 [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC Denys Vlasenko @ 2015-05-21 12:52 ` Paul E. McKenney 2015-05-21 13:09 ` Steven Rostedt 2015-05-21 13:45 ` Steven Rostedt 1 sibling, 1 reply; 13+ messages in thread From: Paul E. McKenney @ 2015-05-21 12:52 UTC (permalink / raw) To: Denys Vlasenko Cc: Josh Triplett, Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, linux-kernel, Tejun Heo, Oleg Nesterov On Thu, May 21, 2015 at 12:04:07PM +0200, Denys Vlasenko wrote: > DEBUG_LOCK_ALLOC=y is not a production setting, but it is > not very unusual either. Many developers routinely > use kernels built with it enabled. > > Apart from being selected by hand, it is also auto-selected by > PROVE_LOCKING "Lock debugging: prove locking correctness" and > LOCK_STAT "Lock usage statistics" config options. > LOCK STAT is necessary for "perf lock" to work. > > I wouldn't spend too much time optimizing it, but this particular > function has a very large cost in code size: when it is deinlined, > code size decreases by 830,000 bytes: > > text data bss dec hex filename > 85674192 22294776 20627456 128596424 7aa39c8 vmlinux.before > 84837612 22294424 20627456 127759492 79d7484 vmlinux > > (with this config: http://busybox.net/~vda/kernel_config) OK, I'll bite... I do see the numbers above, but is this really a problem for anyone? As you say, DEBUG_LOCK_ALLOC=y is not a production setting. Thanx, Paul > Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com> > CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> > CC: Josh Triplett <josh@joshtriplett.org> > CC: Steven Rostedt <rostedt@goodmis.org> > CC: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> > CC: Lai Jiangshan <laijs@cn.fujitsu.com> > CC: linux-kernel@vger.kernel.org > CC: Tejun Heo <tj@kernel.org> > CC: Oleg Nesterov <oleg@redhat.com> > --- > include/linux/rcupdate.h | 40 ++----------------------------------- > kernel/rcu/update.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 54 insertions(+), 38 deletions(-) > > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h > index 7809749..6024a65 100644 > --- a/include/linux/rcupdate.h > +++ b/include/linux/rcupdate.h > @@ -439,46 +439,10 @@ int rcu_read_lock_bh_held(void); > * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an > * RCU-sched read-side critical section. In absence of > * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side > - * critical section unless it can prove otherwise. Note that disabling > - * of preemption (including disabling irqs) counts as an RCU-sched > - * read-side critical section. This is useful for debug checks in functions > - * that required that they be called within an RCU-sched read-side > - * critical section. > - * > - * Check debug_lockdep_rcu_enabled() to prevent false positives during boot > - * and while lockdep is disabled. > - * > - * Note that if the CPU is in the idle loop from an RCU point of > - * view (ie: that we are in the section between rcu_idle_enter() and > - * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU > - * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs > - * that are in such a section, considering these as in extended quiescent > - * state, so such a CPU is effectively never in an RCU read-side critical > - * section regardless of what RCU primitives it invokes. This state of > - * affairs is required --- we need to keep an RCU-free window in idle > - * where the CPU may possibly enter into low power mode. This way we can > - * notice an extended quiescent state to other CPUs that started a grace > - * period. Otherwise we would delay any grace period as long as we run in > - * the idle task. > - * > - * Similarly, we avoid claiming an SRCU read lock held if the current > - * CPU is offline. > + * critical section unless it can prove otherwise. > */ > #ifdef CONFIG_PREEMPT_COUNT > -static inline int rcu_read_lock_sched_held(void) > -{ > - int lockdep_opinion = 0; > - > - if (!debug_lockdep_rcu_enabled()) > - return 1; > - if (!rcu_is_watching()) > - return 0; > - if (!rcu_lockdep_current_cpu_online()) > - return 0; > - if (debug_locks) > - lockdep_opinion = lock_is_held(&rcu_sched_lock_map); > - return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); > -} > +int rcu_read_lock_sched_held(void); > #else /* #ifdef CONFIG_PREEMPT_COUNT */ > static inline int rcu_read_lock_sched_held(void) > { > diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c > index e0d31a3..e02218f 100644 > --- a/kernel/rcu/update.c > +++ b/kernel/rcu/update.c > @@ -62,6 +62,58 @@ MODULE_ALIAS("rcupdate"); > > module_param(rcu_expedited, int, 0); > > +#ifdef CONFIG_DEBUG_LOCK_ALLOC > +/** > + * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section? > + * > + * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an > + * RCU-sched read-side critical section. In absence of > + * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side > + * critical section unless it can prove otherwise. Note that disabling > + * of preemption (including disabling irqs) counts as an RCU-sched > + * read-side critical section. This is useful for debug checks in functions > + * that required that they be called within an RCU-sched read-side > + * critical section. > + * > + * Check debug_lockdep_rcu_enabled() to prevent false positives during boot > + * and while lockdep is disabled. > + * > + * Note that if the CPU is in the idle loop from an RCU point of > + * view (ie: that we are in the section between rcu_idle_enter() and > + * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU > + * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs > + * that are in such a section, considering these as in extended quiescent > + * state, so such a CPU is effectively never in an RCU read-side critical > + * section regardless of what RCU primitives it invokes. This state of > + * affairs is required --- we need to keep an RCU-free window in idle > + * where the CPU may possibly enter into low power mode. This way we can > + * notice an extended quiescent state to other CPUs that started a grace > + * period. Otherwise we would delay any grace period as long as we run in > + * the idle task. > + * > + * Similarly, we avoid claiming an SRCU read lock held if the current > + * CPU is offline. > + */ > +#ifdef CONFIG_PREEMPT_COUNT > +int rcu_read_lock_sched_held(void) > +{ > + int lockdep_opinion = 0; > + > + if (!debug_lockdep_rcu_enabled()) > + return 1; > + if (!rcu_is_watching()) > + return 0; > + if (!rcu_lockdep_current_cpu_online()) > + return 0; > + if (debug_locks) > + lockdep_opinion = lock_is_held(&rcu_sched_lock_map); > + return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); > +} > +EXPORT_SYMBOL(rcu_read_lock_sched_held); > +#else > +/* !CONFIG_PREEMPT_COUNT - the function is inlined to always return 1 */ > +#endif > + > #ifdef CONFIG_PREEMPT_RCU > > /* > -- > 1.8.1.4 > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC 2015-05-21 12:52 ` Paul E. McKenney @ 2015-05-21 13:09 ` Steven Rostedt 2015-05-21 13:25 ` Paul E. McKenney 0 siblings, 1 reply; 13+ messages in thread From: Steven Rostedt @ 2015-05-21 13:09 UTC (permalink / raw) To: Paul E. McKenney Cc: Denys Vlasenko, Josh Triplett, Mathieu Desnoyers, Lai Jiangshan, linux-kernel, Tejun Heo, Oleg Nesterov On Thu, 21 May 2015 05:52:24 -0700 "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> wrote: > On Thu, May 21, 2015 at 12:04:07PM +0200, Denys Vlasenko wrote: > > DEBUG_LOCK_ALLOC=y is not a production setting, but it is > > not very unusual either. Many developers routinely > > use kernels built with it enabled. > > > > Apart from being selected by hand, it is also auto-selected by > > PROVE_LOCKING "Lock debugging: prove locking correctness" and > > LOCK_STAT "Lock usage statistics" config options. > > LOCK STAT is necessary for "perf lock" to work. > > > > I wouldn't spend too much time optimizing it, but this particular > > function has a very large cost in code size: when it is deinlined, > > code size decreases by 830,000 bytes: > > > > text data bss dec hex filename > > 85674192 22294776 20627456 128596424 7aa39c8 vmlinux.before > > 84837612 22294424 20627456 127759492 79d7484 vmlinux > > > > (with this config: http://busybox.net/~vda/kernel_config) > > OK, I'll bite... I do see the numbers above, but is this really a > problem for anyone? As you say, DEBUG_LOCK_ALLOC=y is not a production > setting. > Correct, and because it's not a production setting it should be fine as a call and not a static inline. The i$ hit probably neglects the saving of it being inlined too. It's not a big deal either way, but it may make building the kernel a bit faster ;-) -- Steve ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC 2015-05-21 13:09 ` Steven Rostedt @ 2015-05-21 13:25 ` Paul E. McKenney 2015-05-21 13:41 ` Steven Rostedt 0 siblings, 1 reply; 13+ messages in thread From: Paul E. McKenney @ 2015-05-21 13:25 UTC (permalink / raw) To: Steven Rostedt Cc: Denys Vlasenko, Josh Triplett, Mathieu Desnoyers, Lai Jiangshan, linux-kernel, Tejun Heo, Oleg Nesterov On Thu, May 21, 2015 at 09:09:43AM -0400, Steven Rostedt wrote: > On Thu, 21 May 2015 05:52:24 -0700 > "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> wrote: > > > On Thu, May 21, 2015 at 12:04:07PM +0200, Denys Vlasenko wrote: > > > DEBUG_LOCK_ALLOC=y is not a production setting, but it is > > > not very unusual either. Many developers routinely > > > use kernels built with it enabled. > > > > > > Apart from being selected by hand, it is also auto-selected by > > > PROVE_LOCKING "Lock debugging: prove locking correctness" and > > > LOCK_STAT "Lock usage statistics" config options. > > > LOCK STAT is necessary for "perf lock" to work. > > > > > > I wouldn't spend too much time optimizing it, but this particular > > > function has a very large cost in code size: when it is deinlined, > > > code size decreases by 830,000 bytes: > > > > > > text data bss dec hex filename > > > 85674192 22294776 20627456 128596424 7aa39c8 vmlinux.before > > > 84837612 22294424 20627456 127759492 79d7484 vmlinux > > > > > > (with this config: http://busybox.net/~vda/kernel_config) > > > > OK, I'll bite... I do see the numbers above, but is this really a > > problem for anyone? As you say, DEBUG_LOCK_ALLOC=y is not a production > > setting. > > > > Correct, and because it's not a production setting it should be fine as > a call and not a static inline. The i$ hit probably neglects the saving > of it being inlined too. > > It's not a big deal either way, but it may make building the kernel a > bit faster ;-) OK, if you believe that it is valuable enough to give it a Reviewed-by, I will queue it. ;-) Thanx, Paul ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC 2015-05-21 13:25 ` Paul E. McKenney @ 2015-05-21 13:41 ` Steven Rostedt 0 siblings, 0 replies; 13+ messages in thread From: Steven Rostedt @ 2015-05-21 13:41 UTC (permalink / raw) To: Paul E. McKenney Cc: Denys Vlasenko, Josh Triplett, Mathieu Desnoyers, Lai Jiangshan, linux-kernel, Tejun Heo, Oleg Nesterov On Thu, 21 May 2015 06:25:28 -0700 "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> wrote: > OK, if you believe that it is valuable enough to give it a Reviewed-by, > I will queue it. ;-) Let me take a closer look at the patch first. -- Steve ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC 2015-05-21 10:04 [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC Denys Vlasenko 2015-05-21 12:52 ` Paul E. McKenney @ 2015-05-21 13:45 ` Steven Rostedt 2015-05-21 15:09 ` Denys Vlasenko 1 sibling, 1 reply; 13+ messages in thread From: Steven Rostedt @ 2015-05-21 13:45 UTC (permalink / raw) To: Denys Vlasenko Cc: Paul E. McKenney, Josh Triplett, Mathieu Desnoyers, Lai Jiangshan, linux-kernel, Tejun Heo, Oleg Nesterov On Thu, 21 May 2015 12:04:07 +0200 Denys Vlasenko <dvlasenk@redhat.com> wrote: > DEBUG_LOCK_ALLOC=y is not a production setting, but it is > not very unusual either. Many developers routinely > use kernels built with it enabled. > > Apart from being selected by hand, it is also auto-selected by > PROVE_LOCKING "Lock debugging: prove locking correctness" and > LOCK_STAT "Lock usage statistics" config options. > LOCK STAT is necessary for "perf lock" to work. > > I wouldn't spend too much time optimizing it, but this particular > function has a very large cost in code size: when it is deinlined, > code size decreases by 830,000 bytes: > > text data bss dec hex filename > 85674192 22294776 20627456 128596424 7aa39c8 vmlinux.before > 84837612 22294424 20627456 127759492 79d7484 vmlinux > > (with this config: http://busybox.net/~vda/kernel_config) > > Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com> > CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> > CC: Josh Triplett <josh@joshtriplett.org> > CC: Steven Rostedt <rostedt@goodmis.org> > CC: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> > CC: Lai Jiangshan <laijs@cn.fujitsu.com> > CC: linux-kernel@vger.kernel.org > CC: Tejun Heo <tj@kernel.org> > CC: Oleg Nesterov <oleg@redhat.com> > --- > include/linux/rcupdate.h | 40 ++----------------------------------- > kernel/rcu/update.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 54 insertions(+), 38 deletions(-) > > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h > index 7809749..6024a65 100644 > --- a/include/linux/rcupdate.h > +++ b/include/linux/rcupdate.h > @@ -439,46 +439,10 @@ int rcu_read_lock_bh_held(void); > * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an > * RCU-sched read-side critical section. In absence of > * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side > - * critical section unless it can prove otherwise. Note that disabling > - * of preemption (including disabling irqs) counts as an RCU-sched > - * read-side critical section. This is useful for debug checks in functions > - * that required that they be called within an RCU-sched read-side > - * critical section. > - * > - * Check debug_lockdep_rcu_enabled() to prevent false positives during boot > - * and while lockdep is disabled. > - * > - * Note that if the CPU is in the idle loop from an RCU point of > - * view (ie: that we are in the section between rcu_idle_enter() and > - * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU > - * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs > - * that are in such a section, considering these as in extended quiescent > - * state, so such a CPU is effectively never in an RCU read-side critical > - * section regardless of what RCU primitives it invokes. This state of > - * affairs is required --- we need to keep an RCU-free window in idle > - * where the CPU may possibly enter into low power mode. This way we can > - * notice an extended quiescent state to other CPUs that started a grace > - * period. Otherwise we would delay any grace period as long as we run in > - * the idle task. > - * > - * Similarly, we avoid claiming an SRCU read lock held if the current > - * CPU is offline. > + * critical section unless it can prove otherwise. > */ > #ifdef CONFIG_PREEMPT_COUNT > -static inline int rcu_read_lock_sched_held(void) > -{ > - int lockdep_opinion = 0; > - > - if (!debug_lockdep_rcu_enabled()) > - return 1; > - if (!rcu_is_watching()) > - return 0; > - if (!rcu_lockdep_current_cpu_online()) > - return 0; > - if (debug_locks) > - lockdep_opinion = lock_is_held(&rcu_sched_lock_map); > - return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); > -} > +int rcu_read_lock_sched_held(void); > #else /* #ifdef CONFIG_PREEMPT_COUNT */ > static inline int rcu_read_lock_sched_held(void) > { > diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c > index e0d31a3..e02218f 100644 > --- a/kernel/rcu/update.c > +++ b/kernel/rcu/update.c > @@ -62,6 +62,58 @@ MODULE_ALIAS("rcupdate"); > > module_param(rcu_expedited, int, 0); > > +#ifdef CONFIG_DEBUG_LOCK_ALLOC > +/** > + * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section? > + * > + * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an > + * RCU-sched read-side critical section. In absence of > + * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side > + * critical section unless it can prove otherwise. Note that disabling > + * of preemption (including disabling irqs) counts as an RCU-sched > + * read-side critical section. This is useful for debug checks in functions > + * that required that they be called within an RCU-sched read-side > + * critical section. > + * > + * Check debug_lockdep_rcu_enabled() to prevent false positives during boot > + * and while lockdep is disabled. > + * > + * Note that if the CPU is in the idle loop from an RCU point of > + * view (ie: that we are in the section between rcu_idle_enter() and > + * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU > + * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs > + * that are in such a section, considering these as in extended quiescent > + * state, so such a CPU is effectively never in an RCU read-side critical > + * section regardless of what RCU primitives it invokes. This state of > + * affairs is required --- we need to keep an RCU-free window in idle > + * where the CPU may possibly enter into low power mode. This way we can > + * notice an extended quiescent state to other CPUs that started a grace > + * period. Otherwise we would delay any grace period as long as we run in > + * the idle task. > + * > + * Similarly, we avoid claiming an SRCU read lock held if the current > + * CPU is offline. > + */ > +#ifdef CONFIG_PREEMPT_COUNT > +int rcu_read_lock_sched_held(void) > +{ > + int lockdep_opinion = 0; > + > + if (!debug_lockdep_rcu_enabled()) > + return 1; > + if (!rcu_is_watching()) > + return 0; > + if (!rcu_lockdep_current_cpu_online()) > + return 0; > + if (debug_locks) > + lockdep_opinion = lock_is_held(&rcu_sched_lock_map); > + return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); > +} > +EXPORT_SYMBOL(rcu_read_lock_sched_held); > +#else > +/* !CONFIG_PREEMPT_COUNT - the function is inlined to always return 1 */ Nuke the #else. It's not needed and this is a common enough practice to have the static inline foo() { } when disabled that we do not need to comment about it here. > +#endif Hmm, you added two #ifdef, and one #endif. How does this even compile?? -- Steve > + > #ifdef CONFIG_PREEMPT_RCU > > /* ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC 2015-05-21 13:45 ` Steven Rostedt @ 2015-05-21 15:09 ` Denys Vlasenko 2015-05-21 15:26 ` Paul E. McKenney 0 siblings, 1 reply; 13+ messages in thread From: Denys Vlasenko @ 2015-05-21 15:09 UTC (permalink / raw) To: Steven Rostedt Cc: Paul E. McKenney, Josh Triplett, Mathieu Desnoyers, Lai Jiangshan, linux-kernel, Tejun Heo, Oleg Nesterov On 05/21/2015 03:45 PM, Steven Rostedt wrote: > On Thu, 21 May 2015 12:04:07 +0200 > Denys Vlasenko <dvlasenk@redhat.com> wrote: > >> DEBUG_LOCK_ALLOC=y is not a production setting, but it is >> not very unusual either. Many developers routinely >> use kernels built with it enabled. >> >> Apart from being selected by hand, it is also auto-selected by >> PROVE_LOCKING "Lock debugging: prove locking correctness" and >> LOCK_STAT "Lock usage statistics" config options. >> LOCK STAT is necessary for "perf lock" to work. >> >> I wouldn't spend too much time optimizing it, but this particular >> function has a very large cost in code size: when it is deinlined, >> code size decreases by 830,000 bytes: >> >> text data bss dec hex filename >> 85674192 22294776 20627456 128596424 7aa39c8 vmlinux.before >> 84837612 22294424 20627456 127759492 79d7484 vmlinux >> >> (with this config: http://busybox.net/~vda/kernel_config) >> >> Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com> >> CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> >> CC: Josh Triplett <josh@joshtriplett.org> >> CC: Steven Rostedt <rostedt@goodmis.org> >> CC: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> >> CC: Lai Jiangshan <laijs@cn.fujitsu.com> >> CC: linux-kernel@vger.kernel.org >> CC: Tejun Heo <tj@kernel.org> >> CC: Oleg Nesterov <oleg@redhat.com> >> --- >> include/linux/rcupdate.h | 40 ++----------------------------------- >> kernel/rcu/update.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 54 insertions(+), 38 deletions(-) >> >> diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h >> index 7809749..6024a65 100644 >> --- a/include/linux/rcupdate.h >> +++ b/include/linux/rcupdate.h >> @@ -439,46 +439,10 @@ int rcu_read_lock_bh_held(void); >> * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an >> * RCU-sched read-side critical section. In absence of >> * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side >> - * critical section unless it can prove otherwise. Note that disabling >> - * of preemption (including disabling irqs) counts as an RCU-sched >> - * read-side critical section. This is useful for debug checks in functions >> - * that required that they be called within an RCU-sched read-side >> - * critical section. >> - * >> - * Check debug_lockdep_rcu_enabled() to prevent false positives during boot >> - * and while lockdep is disabled. >> - * >> - * Note that if the CPU is in the idle loop from an RCU point of >> - * view (ie: that we are in the section between rcu_idle_enter() and >> - * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU >> - * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs >> - * that are in such a section, considering these as in extended quiescent >> - * state, so such a CPU is effectively never in an RCU read-side critical >> - * section regardless of what RCU primitives it invokes. This state of >> - * affairs is required --- we need to keep an RCU-free window in idle >> - * where the CPU may possibly enter into low power mode. This way we can >> - * notice an extended quiescent state to other CPUs that started a grace >> - * period. Otherwise we would delay any grace period as long as we run in >> - * the idle task. >> - * >> - * Similarly, we avoid claiming an SRCU read lock held if the current >> - * CPU is offline. >> + * critical section unless it can prove otherwise. >> */ >> #ifdef CONFIG_PREEMPT_COUNT >> -static inline int rcu_read_lock_sched_held(void) >> -{ >> - int lockdep_opinion = 0; >> - >> - if (!debug_lockdep_rcu_enabled()) >> - return 1; >> - if (!rcu_is_watching()) >> - return 0; >> - if (!rcu_lockdep_current_cpu_online()) >> - return 0; >> - if (debug_locks) >> - lockdep_opinion = lock_is_held(&rcu_sched_lock_map); >> - return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); >> -} >> +int rcu_read_lock_sched_held(void); >> #else /* #ifdef CONFIG_PREEMPT_COUNT */ >> static inline int rcu_read_lock_sched_held(void) >> { >> diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c >> index e0d31a3..e02218f 100644 >> --- a/kernel/rcu/update.c >> +++ b/kernel/rcu/update.c >> @@ -62,6 +62,58 @@ MODULE_ALIAS("rcupdate"); >> >> module_param(rcu_expedited, int, 0); >> >> +#ifdef CONFIG_DEBUG_LOCK_ALLOC >> +/** >> + * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section? >> + * >> + * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an >> + * RCU-sched read-side critical section. In absence of >> + * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side >> + * critical section unless it can prove otherwise. Note that disabling >> + * of preemption (including disabling irqs) counts as an RCU-sched >> + * read-side critical section. This is useful for debug checks in functions >> + * that required that they be called within an RCU-sched read-side >> + * critical section. >> + * >> + * Check debug_lockdep_rcu_enabled() to prevent false positives during boot >> + * and while lockdep is disabled. >> + * >> + * Note that if the CPU is in the idle loop from an RCU point of >> + * view (ie: that we are in the section between rcu_idle_enter() and >> + * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU >> + * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs >> + * that are in such a section, considering these as in extended quiescent >> + * state, so such a CPU is effectively never in an RCU read-side critical >> + * section regardless of what RCU primitives it invokes. This state of >> + * affairs is required --- we need to keep an RCU-free window in idle >> + * where the CPU may possibly enter into low power mode. This way we can >> + * notice an extended quiescent state to other CPUs that started a grace >> + * period. Otherwise we would delay any grace period as long as we run in >> + * the idle task. >> + * >> + * Similarly, we avoid claiming an SRCU read lock held if the current >> + * CPU is offline. >> + */ >> +#ifdef CONFIG_PREEMPT_COUNT >> +int rcu_read_lock_sched_held(void) >> +{ >> + int lockdep_opinion = 0; >> + >> + if (!debug_lockdep_rcu_enabled()) >> + return 1; >> + if (!rcu_is_watching()) >> + return 0; >> + if (!rcu_lockdep_current_cpu_online()) >> + return 0; >> + if (debug_locks) >> + lockdep_opinion = lock_is_held(&rcu_sched_lock_map); >> + return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); >> +} >> +EXPORT_SYMBOL(rcu_read_lock_sched_held); >> +#else >> +/* !CONFIG_PREEMPT_COUNT - the function is inlined to always return 1 */ > > Nuke the #else. It's not needed and this is a common enough practice to > have the static inline foo() { } when disabled that we do not need to > comment about it here. Sending patch v2 in a few minutes. >> +#endif > > Hmm, you added two #ifdef, and one #endif. How does this even compile?? Er... it... doesn't. There was "#if defined CONFIG_DEBUG_LOCK_ALLOC && defined CONFIG_PREEMPT_COUNT" but then I split it into two #ifs to have a nice explanatory empty #else clause. And I did not test it after that edit ("what could possibly go wrong?"). Sorry. Patch v2 I'm sending _is_ tested. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC 2015-05-21 15:09 ` Denys Vlasenko @ 2015-05-21 15:26 ` Paul E. McKenney 2015-05-21 21:53 ` Denys Vlasenko 0 siblings, 1 reply; 13+ messages in thread From: Paul E. McKenney @ 2015-05-21 15:26 UTC (permalink / raw) To: Denys Vlasenko Cc: Steven Rostedt, Josh Triplett, Mathieu Desnoyers, Lai Jiangshan, linux-kernel, Tejun Heo, Oleg Nesterov On Thu, May 21, 2015 at 05:09:27PM +0200, Denys Vlasenko wrote: > On 05/21/2015 03:45 PM, Steven Rostedt wrote: > > On Thu, 21 May 2015 12:04:07 +0200 > > Denys Vlasenko <dvlasenk@redhat.com> wrote: > > > >> DEBUG_LOCK_ALLOC=y is not a production setting, but it is > >> not very unusual either. Many developers routinely > >> use kernels built with it enabled. > >> > >> Apart from being selected by hand, it is also auto-selected by > >> PROVE_LOCKING "Lock debugging: prove locking correctness" and > >> LOCK_STAT "Lock usage statistics" config options. > >> LOCK STAT is necessary for "perf lock" to work. > >> > >> I wouldn't spend too much time optimizing it, but this particular > >> function has a very large cost in code size: when it is deinlined, > >> code size decreases by 830,000 bytes: > >> > >> text data bss dec hex filename > >> 85674192 22294776 20627456 128596424 7aa39c8 vmlinux.before > >> 84837612 22294424 20627456 127759492 79d7484 vmlinux > >> > >> (with this config: http://busybox.net/~vda/kernel_config) > >> > >> Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com> > >> CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> > >> CC: Josh Triplett <josh@joshtriplett.org> > >> CC: Steven Rostedt <rostedt@goodmis.org> > >> CC: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> > >> CC: Lai Jiangshan <laijs@cn.fujitsu.com> > >> CC: linux-kernel@vger.kernel.org > >> CC: Tejun Heo <tj@kernel.org> > >> CC: Oleg Nesterov <oleg@redhat.com> > >> --- > >> include/linux/rcupdate.h | 40 ++----------------------------------- > >> kernel/rcu/update.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ > >> 2 files changed, 54 insertions(+), 38 deletions(-) > >> > >> diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h > >> index 7809749..6024a65 100644 > >> --- a/include/linux/rcupdate.h > >> +++ b/include/linux/rcupdate.h > >> @@ -439,46 +439,10 @@ int rcu_read_lock_bh_held(void); > >> * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an > >> * RCU-sched read-side critical section. In absence of > >> * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side > >> - * critical section unless it can prove otherwise. Note that disabling > >> - * of preemption (including disabling irqs) counts as an RCU-sched > >> - * read-side critical section. This is useful for debug checks in functions > >> - * that required that they be called within an RCU-sched read-side > >> - * critical section. > >> - * > >> - * Check debug_lockdep_rcu_enabled() to prevent false positives during boot > >> - * and while lockdep is disabled. > >> - * > >> - * Note that if the CPU is in the idle loop from an RCU point of > >> - * view (ie: that we are in the section between rcu_idle_enter() and > >> - * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU > >> - * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs > >> - * that are in such a section, considering these as in extended quiescent > >> - * state, so such a CPU is effectively never in an RCU read-side critical > >> - * section regardless of what RCU primitives it invokes. This state of > >> - * affairs is required --- we need to keep an RCU-free window in idle > >> - * where the CPU may possibly enter into low power mode. This way we can > >> - * notice an extended quiescent state to other CPUs that started a grace > >> - * period. Otherwise we would delay any grace period as long as we run in > >> - * the idle task. > >> - * > >> - * Similarly, we avoid claiming an SRCU read lock held if the current > >> - * CPU is offline. > >> + * critical section unless it can prove otherwise. > >> */ > >> #ifdef CONFIG_PREEMPT_COUNT > >> -static inline int rcu_read_lock_sched_held(void) > >> -{ > >> - int lockdep_opinion = 0; > >> - > >> - if (!debug_lockdep_rcu_enabled()) > >> - return 1; > >> - if (!rcu_is_watching()) > >> - return 0; > >> - if (!rcu_lockdep_current_cpu_online()) > >> - return 0; > >> - if (debug_locks) > >> - lockdep_opinion = lock_is_held(&rcu_sched_lock_map); > >> - return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); > >> -} > >> +int rcu_read_lock_sched_held(void); > >> #else /* #ifdef CONFIG_PREEMPT_COUNT */ > >> static inline int rcu_read_lock_sched_held(void) > >> { > >> diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c > >> index e0d31a3..e02218f 100644 > >> --- a/kernel/rcu/update.c > >> +++ b/kernel/rcu/update.c > >> @@ -62,6 +62,58 @@ MODULE_ALIAS("rcupdate"); > >> > >> module_param(rcu_expedited, int, 0); > >> > >> +#ifdef CONFIG_DEBUG_LOCK_ALLOC > >> +/** > >> + * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section? > >> + * > >> + * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an > >> + * RCU-sched read-side critical section. In absence of > >> + * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side > >> + * critical section unless it can prove otherwise. Note that disabling > >> + * of preemption (including disabling irqs) counts as an RCU-sched > >> + * read-side critical section. This is useful for debug checks in functions > >> + * that required that they be called within an RCU-sched read-side > >> + * critical section. > >> + * > >> + * Check debug_lockdep_rcu_enabled() to prevent false positives during boot > >> + * and while lockdep is disabled. > >> + * > >> + * Note that if the CPU is in the idle loop from an RCU point of > >> + * view (ie: that we are in the section between rcu_idle_enter() and > >> + * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU > >> + * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs > >> + * that are in such a section, considering these as in extended quiescent > >> + * state, so such a CPU is effectively never in an RCU read-side critical > >> + * section regardless of what RCU primitives it invokes. This state of > >> + * affairs is required --- we need to keep an RCU-free window in idle > >> + * where the CPU may possibly enter into low power mode. This way we can > >> + * notice an extended quiescent state to other CPUs that started a grace > >> + * period. Otherwise we would delay any grace period as long as we run in > >> + * the idle task. > >> + * > >> + * Similarly, we avoid claiming an SRCU read lock held if the current > >> + * CPU is offline. > >> + */ > >> +#ifdef CONFIG_PREEMPT_COUNT > >> +int rcu_read_lock_sched_held(void) > >> +{ > >> + int lockdep_opinion = 0; > >> + > >> + if (!debug_lockdep_rcu_enabled()) > >> + return 1; > >> + if (!rcu_is_watching()) > >> + return 0; > >> + if (!rcu_lockdep_current_cpu_online()) > >> + return 0; > >> + if (debug_locks) > >> + lockdep_opinion = lock_is_held(&rcu_sched_lock_map); > >> + return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); > >> +} > >> +EXPORT_SYMBOL(rcu_read_lock_sched_held); > >> +#else > >> +/* !CONFIG_PREEMPT_COUNT - the function is inlined to always return 1 */ > > > > Nuke the #else. It's not needed and this is a common enough practice to > > have the static inline foo() { } when disabled that we do not need to > > comment about it here. > > Sending patch v2 in a few minutes. > > >> +#endif > > > > Hmm, you added two #ifdef, and one #endif. How does this even compile?? > > Er... it... doesn't. > > There was "#if defined CONFIG_DEBUG_LOCK_ALLOC && defined CONFIG_PREEMPT_COUNT" > but then I split it into two #ifs to have a nice explanatory empty > #else clause. And I did not test it after that edit > ("what could possibly go wrong?"). Sorry. > > Patch v2 I'm sending _is_ tested. Boot/run as well as build? Thanx, Paul ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC 2015-05-21 15:26 ` Paul E. McKenney @ 2015-05-21 21:53 ` Denys Vlasenko 2015-05-26 15:18 ` Paul E. McKenney 0 siblings, 1 reply; 13+ messages in thread From: Denys Vlasenko @ 2015-05-21 21:53 UTC (permalink / raw) To: paulmck Cc: Steven Rostedt, Josh Triplett, Mathieu Desnoyers, Lai Jiangshan, linux-kernel, Tejun Heo, Oleg Nesterov On 05/21/2015 05:26 PM, Paul E. McKenney wrote: > On Thu, May 21, 2015 at 05:09:27PM +0200, Denys Vlasenko wrote: >> On 05/21/2015 03:45 PM, Steven Rostedt wrote: >>> On Thu, 21 May 2015 12:04:07 +0200 >>> Denys Vlasenko <dvlasenk@redhat.com> wrote: >>> >>>> DEBUG_LOCK_ALLOC=y is not a production setting, but it is >>>> not very unusual either. Many developers routinely >>>> use kernels built with it enabled. >>>> >>>> Apart from being selected by hand, it is also auto-selected by >>>> PROVE_LOCKING "Lock debugging: prove locking correctness" and >>>> LOCK_STAT "Lock usage statistics" config options. >>>> LOCK STAT is necessary for "perf lock" to work. >>>> >>>> I wouldn't spend too much time optimizing it, but this particular >>>> function has a very large cost in code size: when it is deinlined, >>>> code size decreases by 830,000 bytes: >>>> >>>> text data bss dec hex filename >>>> 85674192 22294776 20627456 128596424 7aa39c8 vmlinux.before >>>> 84837612 22294424 20627456 127759492 79d7484 vmlinux >>>> >>>> (with this config: http://busybox.net/~vda/kernel_config) >>>> >>>> Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com> >>>> CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> >>>> CC: Josh Triplett <josh@joshtriplett.org> >>>> CC: Steven Rostedt <rostedt@goodmis.org> >>>> CC: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> >>>> CC: Lai Jiangshan <laijs@cn.fujitsu.com> >>>> CC: linux-kernel@vger.kernel.org >>>> CC: Tejun Heo <tj@kernel.org> >>>> CC: Oleg Nesterov <oleg@redhat.com> >>>> --- >>>> include/linux/rcupdate.h | 40 ++----------------------------------- >>>> kernel/rcu/update.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ >>>> 2 files changed, 54 insertions(+), 38 deletions(-) >>>> >>>> diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h >>>> index 7809749..6024a65 100644 >>>> --- a/include/linux/rcupdate.h >>>> +++ b/include/linux/rcupdate.h >>>> @@ -439,46 +439,10 @@ int rcu_read_lock_bh_held(void); >>>> * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an >>>> * RCU-sched read-side critical section. In absence of >>>> * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side >>>> - * critical section unless it can prove otherwise. Note that disabling >>>> - * of preemption (including disabling irqs) counts as an RCU-sched >>>> - * read-side critical section. This is useful for debug checks in functions >>>> - * that required that they be called within an RCU-sched read-side >>>> - * critical section. >>>> - * >>>> - * Check debug_lockdep_rcu_enabled() to prevent false positives during boot >>>> - * and while lockdep is disabled. >>>> - * >>>> - * Note that if the CPU is in the idle loop from an RCU point of >>>> - * view (ie: that we are in the section between rcu_idle_enter() and >>>> - * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU >>>> - * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs >>>> - * that are in such a section, considering these as in extended quiescent >>>> - * state, so such a CPU is effectively never in an RCU read-side critical >>>> - * section regardless of what RCU primitives it invokes. This state of >>>> - * affairs is required --- we need to keep an RCU-free window in idle >>>> - * where the CPU may possibly enter into low power mode. This way we can >>>> - * notice an extended quiescent state to other CPUs that started a grace >>>> - * period. Otherwise we would delay any grace period as long as we run in >>>> - * the idle task. >>>> - * >>>> - * Similarly, we avoid claiming an SRCU read lock held if the current >>>> - * CPU is offline. >>>> + * critical section unless it can prove otherwise. >>>> */ >>>> #ifdef CONFIG_PREEMPT_COUNT >>>> -static inline int rcu_read_lock_sched_held(void) >>>> -{ >>>> - int lockdep_opinion = 0; >>>> - >>>> - if (!debug_lockdep_rcu_enabled()) >>>> - return 1; >>>> - if (!rcu_is_watching()) >>>> - return 0; >>>> - if (!rcu_lockdep_current_cpu_online()) >>>> - return 0; >>>> - if (debug_locks) >>>> - lockdep_opinion = lock_is_held(&rcu_sched_lock_map); >>>> - return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); >>>> -} >>>> +int rcu_read_lock_sched_held(void); >>>> #else /* #ifdef CONFIG_PREEMPT_COUNT */ >>>> static inline int rcu_read_lock_sched_held(void) >>>> { >>>> diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c >>>> index e0d31a3..e02218f 100644 >>>> --- a/kernel/rcu/update.c >>>> +++ b/kernel/rcu/update.c >>>> @@ -62,6 +62,58 @@ MODULE_ALIAS("rcupdate"); >>>> >>>> module_param(rcu_expedited, int, 0); >>>> >>>> +#ifdef CONFIG_DEBUG_LOCK_ALLOC >>>> +/** >>>> + * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section? >>>> + * >>>> + * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an >>>> + * RCU-sched read-side critical section. In absence of >>>> + * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side >>>> + * critical section unless it can prove otherwise. Note that disabling >>>> + * of preemption (including disabling irqs) counts as an RCU-sched >>>> + * read-side critical section. This is useful for debug checks in functions >>>> + * that required that they be called within an RCU-sched read-side >>>> + * critical section. >>>> + * >>>> + * Check debug_lockdep_rcu_enabled() to prevent false positives during boot >>>> + * and while lockdep is disabled. >>>> + * >>>> + * Note that if the CPU is in the idle loop from an RCU point of >>>> + * view (ie: that we are in the section between rcu_idle_enter() and >>>> + * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU >>>> + * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs >>>> + * that are in such a section, considering these as in extended quiescent >>>> + * state, so such a CPU is effectively never in an RCU read-side critical >>>> + * section regardless of what RCU primitives it invokes. This state of >>>> + * affairs is required --- we need to keep an RCU-free window in idle >>>> + * where the CPU may possibly enter into low power mode. This way we can >>>> + * notice an extended quiescent state to other CPUs that started a grace >>>> + * period. Otherwise we would delay any grace period as long as we run in >>>> + * the idle task. >>>> + * >>>> + * Similarly, we avoid claiming an SRCU read lock held if the current >>>> + * CPU is offline. >>>> + */ >>>> +#ifdef CONFIG_PREEMPT_COUNT >>>> +int rcu_read_lock_sched_held(void) >>>> +{ >>>> + int lockdep_opinion = 0; >>>> + >>>> + if (!debug_lockdep_rcu_enabled()) >>>> + return 1; >>>> + if (!rcu_is_watching()) >>>> + return 0; >>>> + if (!rcu_lockdep_current_cpu_online()) >>>> + return 0; >>>> + if (debug_locks) >>>> + lockdep_opinion = lock_is_held(&rcu_sched_lock_map); >>>> + return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); >>>> +} >>>> +EXPORT_SYMBOL(rcu_read_lock_sched_held); >>>> +#else >>>> +/* !CONFIG_PREEMPT_COUNT - the function is inlined to always return 1 */ >>> >>> Nuke the #else. It's not needed and this is a common enough practice to >>> have the static inline foo() { } when disabled that we do not need to >>> comment about it here. >> >> Sending patch v2 in a few minutes. >> >>>> +#endif >>> >>> Hmm, you added two #ifdef, and one #endif. How does this even compile?? >> >> Er... it... doesn't. >> >> There was "#if defined CONFIG_DEBUG_LOCK_ALLOC && defined CONFIG_PREEMPT_COUNT" >> but then I split it into two #ifs to have a nice explanatory empty >> #else clause. And I did not test it after that edit >> ("what could possibly go wrong?"). Sorry. >> >> Patch v2 I'm sending _is_ tested. > > Boot/run as well as build? I did not even dare to try booting 128 megabyte allyesconfig monstrosity, before you asked. It took me 4 hours of rebuilds to figure out that CONFIG_CMDLINE_BOOL needs to be disabled for my qemu boot to succeed :) :) So, yes, patched allyesconfig kernel seems to boot... it takes 250 seconds in qemu. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC 2015-05-21 21:53 ` Denys Vlasenko @ 2015-05-26 15:18 ` Paul E. McKenney 2015-05-26 15:37 ` Steven Rostedt 0 siblings, 1 reply; 13+ messages in thread From: Paul E. McKenney @ 2015-05-26 15:18 UTC (permalink / raw) To: Denys Vlasenko Cc: Steven Rostedt, Josh Triplett, Mathieu Desnoyers, Lai Jiangshan, linux-kernel, Tejun Heo, Oleg Nesterov On Thu, May 21, 2015 at 11:53:21PM +0200, Denys Vlasenko wrote: > On 05/21/2015 05:26 PM, Paul E. McKenney wrote: > > On Thu, May 21, 2015 at 05:09:27PM +0200, Denys Vlasenko wrote: > >> On 05/21/2015 03:45 PM, Steven Rostedt wrote: > >>> On Thu, 21 May 2015 12:04:07 +0200 > >>> Denys Vlasenko <dvlasenk@redhat.com> wrote: > >>> > >>>> DEBUG_LOCK_ALLOC=y is not a production setting, but it is > >>>> not very unusual either. Many developers routinely > >>>> use kernels built with it enabled. > >>>> > >>>> Apart from being selected by hand, it is also auto-selected by > >>>> PROVE_LOCKING "Lock debugging: prove locking correctness" and > >>>> LOCK_STAT "Lock usage statistics" config options. > >>>> LOCK STAT is necessary for "perf lock" to work. > >>>> > >>>> I wouldn't spend too much time optimizing it, but this particular > >>>> function has a very large cost in code size: when it is deinlined, > >>>> code size decreases by 830,000 bytes: > >>>> > >>>> text data bss dec hex filename > >>>> 85674192 22294776 20627456 128596424 7aa39c8 vmlinux.before > >>>> 84837612 22294424 20627456 127759492 79d7484 vmlinux > >>>> > >>>> (with this config: http://busybox.net/~vda/kernel_config) > >>>> > >>>> Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com> > >>>> CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> > >>>> CC: Josh Triplett <josh@joshtriplett.org> > >>>> CC: Steven Rostedt <rostedt@goodmis.org> > >>>> CC: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> > >>>> CC: Lai Jiangshan <laijs@cn.fujitsu.com> > >>>> CC: linux-kernel@vger.kernel.org > >>>> CC: Tejun Heo <tj@kernel.org> > >>>> CC: Oleg Nesterov <oleg@redhat.com> > >>>> --- > >>>> include/linux/rcupdate.h | 40 ++----------------------------------- > >>>> kernel/rcu/update.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ > >>>> 2 files changed, 54 insertions(+), 38 deletions(-) > >>>> > >>>> diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h > >>>> index 7809749..6024a65 100644 > >>>> --- a/include/linux/rcupdate.h > >>>> +++ b/include/linux/rcupdate.h > >>>> @@ -439,46 +439,10 @@ int rcu_read_lock_bh_held(void); > >>>> * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an > >>>> * RCU-sched read-side critical section. In absence of > >>>> * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side > >>>> - * critical section unless it can prove otherwise. Note that disabling > >>>> - * of preemption (including disabling irqs) counts as an RCU-sched > >>>> - * read-side critical section. This is useful for debug checks in functions > >>>> - * that required that they be called within an RCU-sched read-side > >>>> - * critical section. > >>>> - * > >>>> - * Check debug_lockdep_rcu_enabled() to prevent false positives during boot > >>>> - * and while lockdep is disabled. > >>>> - * > >>>> - * Note that if the CPU is in the idle loop from an RCU point of > >>>> - * view (ie: that we are in the section between rcu_idle_enter() and > >>>> - * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU > >>>> - * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs > >>>> - * that are in such a section, considering these as in extended quiescent > >>>> - * state, so such a CPU is effectively never in an RCU read-side critical > >>>> - * section regardless of what RCU primitives it invokes. This state of > >>>> - * affairs is required --- we need to keep an RCU-free window in idle > >>>> - * where the CPU may possibly enter into low power mode. This way we can > >>>> - * notice an extended quiescent state to other CPUs that started a grace > >>>> - * period. Otherwise we would delay any grace period as long as we run in > >>>> - * the idle task. > >>>> - * > >>>> - * Similarly, we avoid claiming an SRCU read lock held if the current > >>>> - * CPU is offline. > >>>> + * critical section unless it can prove otherwise. > >>>> */ > >>>> #ifdef CONFIG_PREEMPT_COUNT > >>>> -static inline int rcu_read_lock_sched_held(void) > >>>> -{ > >>>> - int lockdep_opinion = 0; > >>>> - > >>>> - if (!debug_lockdep_rcu_enabled()) > >>>> - return 1; > >>>> - if (!rcu_is_watching()) > >>>> - return 0; > >>>> - if (!rcu_lockdep_current_cpu_online()) > >>>> - return 0; > >>>> - if (debug_locks) > >>>> - lockdep_opinion = lock_is_held(&rcu_sched_lock_map); > >>>> - return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); > >>>> -} > >>>> +int rcu_read_lock_sched_held(void); > >>>> #else /* #ifdef CONFIG_PREEMPT_COUNT */ > >>>> static inline int rcu_read_lock_sched_held(void) > >>>> { > >>>> diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c > >>>> index e0d31a3..e02218f 100644 > >>>> --- a/kernel/rcu/update.c > >>>> +++ b/kernel/rcu/update.c > >>>> @@ -62,6 +62,58 @@ MODULE_ALIAS("rcupdate"); > >>>> > >>>> module_param(rcu_expedited, int, 0); > >>>> > >>>> +#ifdef CONFIG_DEBUG_LOCK_ALLOC > >>>> +/** > >>>> + * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section? > >>>> + * > >>>> + * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an > >>>> + * RCU-sched read-side critical section. In absence of > >>>> + * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side > >>>> + * critical section unless it can prove otherwise. Note that disabling > >>>> + * of preemption (including disabling irqs) counts as an RCU-sched > >>>> + * read-side critical section. This is useful for debug checks in functions > >>>> + * that required that they be called within an RCU-sched read-side > >>>> + * critical section. > >>>> + * > >>>> + * Check debug_lockdep_rcu_enabled() to prevent false positives during boot > >>>> + * and while lockdep is disabled. > >>>> + * > >>>> + * Note that if the CPU is in the idle loop from an RCU point of > >>>> + * view (ie: that we are in the section between rcu_idle_enter() and > >>>> + * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU > >>>> + * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs > >>>> + * that are in such a section, considering these as in extended quiescent > >>>> + * state, so such a CPU is effectively never in an RCU read-side critical > >>>> + * section regardless of what RCU primitives it invokes. This state of > >>>> + * affairs is required --- we need to keep an RCU-free window in idle > >>>> + * where the CPU may possibly enter into low power mode. This way we can > >>>> + * notice an extended quiescent state to other CPUs that started a grace > >>>> + * period. Otherwise we would delay any grace period as long as we run in > >>>> + * the idle task. > >>>> + * > >>>> + * Similarly, we avoid claiming an SRCU read lock held if the current > >>>> + * CPU is offline. > >>>> + */ > >>>> +#ifdef CONFIG_PREEMPT_COUNT > >>>> +int rcu_read_lock_sched_held(void) > >>>> +{ > >>>> + int lockdep_opinion = 0; > >>>> + > >>>> + if (!debug_lockdep_rcu_enabled()) > >>>> + return 1; > >>>> + if (!rcu_is_watching()) > >>>> + return 0; > >>>> + if (!rcu_lockdep_current_cpu_online()) > >>>> + return 0; > >>>> + if (debug_locks) > >>>> + lockdep_opinion = lock_is_held(&rcu_sched_lock_map); > >>>> + return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); > >>>> +} > >>>> +EXPORT_SYMBOL(rcu_read_lock_sched_held); > >>>> +#else > >>>> +/* !CONFIG_PREEMPT_COUNT - the function is inlined to always return 1 */ > >>> > >>> Nuke the #else. It's not needed and this is a common enough practice to > >>> have the static inline foo() { } when disabled that we do not need to > >>> comment about it here. > >> > >> Sending patch v2 in a few minutes. > >> > >>>> +#endif > >>> > >>> Hmm, you added two #ifdef, and one #endif. How does this even compile?? > >> > >> Er... it... doesn't. > >> > >> There was "#if defined CONFIG_DEBUG_LOCK_ALLOC && defined CONFIG_PREEMPT_COUNT" > >> but then I split it into two #ifs to have a nice explanatory empty > >> #else clause. And I did not test it after that edit > >> ("what could possibly go wrong?"). Sorry. > >> > >> Patch v2 I'm sending _is_ tested. > > > > Boot/run as well as build? > > I did not even dare to try booting 128 megabyte allyesconfig monstrosity, > before you asked. > > It took me 4 hours of rebuilds to figure out that CONFIG_CMDLINE_BOOL needs to be > disabled for my qemu boot to succeed :) :) Just make sure you retain the .config file to allow you to more easily test future changes! ;-) > So, yes, patched allyesconfig kernel seems to boot... it takes 250 seconds in qemu. Steve, are you OK with Denys's most recent patch? Thanx, Paul ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC 2015-05-26 15:18 ` Paul E. McKenney @ 2015-05-26 15:37 ` Steven Rostedt 2015-05-26 15:47 ` Denys Vlasenko 2015-05-26 15:51 ` Paul E. McKenney 0 siblings, 2 replies; 13+ messages in thread From: Steven Rostedt @ 2015-05-26 15:37 UTC (permalink / raw) To: Paul E. McKenney Cc: Denys Vlasenko, Josh Triplett, Mathieu Desnoyers, Lai Jiangshan, linux-kernel, Tejun Heo, Oleg Nesterov On Tue, 26 May 2015 08:18:03 -0700 "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> wrote: > Steve, are you OK with Denys's most recent patch? The only comment I believe I had on it was the use of parenthesis around the CONFIG names for defined(), as that seems to be the common method used in the kernel. -- Steve ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC 2015-05-26 15:37 ` Steven Rostedt @ 2015-05-26 15:47 ` Denys Vlasenko 2015-05-26 15:51 ` Paul E. McKenney 1 sibling, 0 replies; 13+ messages in thread From: Denys Vlasenko @ 2015-05-26 15:47 UTC (permalink / raw) To: Steven Rostedt, Paul E. McKenney Cc: Josh Triplett, Mathieu Desnoyers, Lai Jiangshan, linux-kernel, Tejun Heo, Oleg Nesterov On 05/26/2015 05:37 PM, Steven Rostedt wrote: > On Tue, 26 May 2015 08:18:03 -0700 > "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> wrote: > >> Steve, are you OK with Denys's most recent patch? > > The only comment I believe I had on it was the use of parenthesis > around the CONFIG names for defined(), as that seems to be the common > method used in the kernel. I'm sending patch v3 with this change ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC 2015-05-26 15:37 ` Steven Rostedt 2015-05-26 15:47 ` Denys Vlasenko @ 2015-05-26 15:51 ` Paul E. McKenney 1 sibling, 0 replies; 13+ messages in thread From: Paul E. McKenney @ 2015-05-26 15:51 UTC (permalink / raw) To: Steven Rostedt Cc: Denys Vlasenko, Josh Triplett, Mathieu Desnoyers, Lai Jiangshan, linux-kernel, Tejun Heo, Oleg Nesterov On Tue, May 26, 2015 at 11:37:14AM -0400, Steven Rostedt wrote: > On Tue, 26 May 2015 08:18:03 -0700 > "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> wrote: > > > Steve, are you OK with Denys's most recent patch? > > The only comment I believe I had on it was the use of parenthesis > around the CONFIG names for defined(), as that seems to be the common > method used in the kernel. So it sounds the next step is for Denys to send an update with the parentheses. Thanx, Paul ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2015-05-26 15:52 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-05-21 10:04 [PATCH] rcu: Deinline rcu_read_lock_sched_held() if DEBUG_LOCK_ALLOC Denys Vlasenko 2015-05-21 12:52 ` Paul E. McKenney 2015-05-21 13:09 ` Steven Rostedt 2015-05-21 13:25 ` Paul E. McKenney 2015-05-21 13:41 ` Steven Rostedt 2015-05-21 13:45 ` Steven Rostedt 2015-05-21 15:09 ` Denys Vlasenko 2015-05-21 15:26 ` Paul E. McKenney 2015-05-21 21:53 ` Denys Vlasenko 2015-05-26 15:18 ` Paul E. McKenney 2015-05-26 15:37 ` Steven Rostedt 2015-05-26 15:47 ` Denys Vlasenko 2015-05-26 15:51 ` Paul E. McKenney
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox