All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] lockdep: Add nr_save_trace_invocations counter
@ 2010-04-22 20:15 John Kacur
  2010-04-23  2:58 ` Yong Zhang
  0 siblings, 1 reply; 21+ messages in thread
From: John Kacur @ 2010-04-22 20:15 UTC (permalink / raw)
  To: Peter Zijlstra, LKML
  Cc: linux-rt-users, Sven-Thorsten Dietrich, Clark Williams,
	Luis Claudio R. Goncalves, Ingo Molnar, Thomas Gleixner,
	Gregory Haskins

NOT FOR INCLUSION

I created this patch as a result of Peter Zilstra's request to get more 
info from lockdep. This patch is not for inclusion, at least in its 
present form, because it adds some redunant info to /proc/lockdep_stats

However, some of the fields are new, and it is worth examining, and / or 
applying if you are looking at the MAX_STACK_TRACE_ENTRIES too big 
problem.

I generated this patch against a recent tip/master but it applies without 
conflicts to the latest rt kernel as well. Comments are welcome, in fact 
they are appreciated.

>From 5181c0296dd1549e4e706ff25a4cd81a1d90137d Mon Sep 17 00:00:00 2001
From: John Kacur <jkacur@redhat.com>
Date: Thu, 22 Apr 2010 17:02:42 +0200
Subject: [PATCH] lockdep: Add nr_save_trace_invocations counter

Add the nr_save_trace_invocations counter which counts the number of
time save_trace() is invoked when relevant for trace enteries.

This means, those invocations from mark_lock() and add_lock_to_list()

When called from mark_lock() we break it down into LOCKSTATE categories.

Signed-off-by: John Kacur <jkacur@redhat.com>
---
 kernel/lockdep.c           |   20 ++++++++++++++++++++
 kernel/lockdep_internals.h |    2 ++
 kernel/lockdep_proc.c      |   23 +++++++++++++++++++++++
 3 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 78325f8..f921576 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -371,6 +371,10 @@ static int verbose(struct lock_class *class)
 unsigned long nr_stack_trace_entries;
 static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES];
 
+/* Calls to save_trace() from mark_lock() and add_lock_to_list() only*/
+unsigned long nr_save_trace_invocations;
+unsigned long nr_save_trace_invocations_type[LOCK_USAGE_STATES];
+
 static int save_trace(struct stack_trace *trace)
 {
 	trace->nr_entries = 0;
@@ -410,6 +414,19 @@ static int save_trace(struct stack_trace *trace)
 	return 1;
 }
 
+/*
+ * This function is only called from mark_lock() and add_lock_to_list()
+ * which are only called when holding the graph_lock. This counter
+ * piggybacks off of that lock
+ */
+static void inc_save_trace_invocations(enum lock_usage_bit new_bit)
+{
+	nr_save_trace_invocations++;
+	if (WARN_ON(new_bit >= LOCK_USAGE_STATES))
+		return;
+	nr_save_trace_invocations_type[new_bit]++;
+}
+
 unsigned int nr_hardirq_chains;
 unsigned int nr_softirq_chains;
 unsigned int nr_process_chains;
@@ -449,6 +466,7 @@ static const char *usage_str[] =
 #define LOCKDEP_STATE(__STATE) __USAGE(__STATE)
 #include "lockdep_states.h"
 #undef LOCKDEP_STATE
+#undef __USAGE
 	[LOCK_USED] = "INITIAL USE",
 };
 
@@ -816,6 +834,7 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
 	if (!entry)
 		return 0;
 
+	nr_save_trace_invocations++;
 	if (!save_trace(&entry->trace))
 		return 0;
 
@@ -2615,6 +2634,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
 
 	hlock_class(this)->usage_mask |= new_mask;
 
+	inc_save_trace_invocations(new_bit);
 	if (!save_trace(hlock_class(this)->usage_traces + new_bit))
 		return 0;
 
diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h
index 8d7d4b6..6149358 100644
--- a/kernel/lockdep_internals.h
+++ b/kernel/lockdep_internals.h
@@ -84,6 +84,8 @@ extern unsigned long nr_list_entries;
 extern unsigned long nr_lock_chains;
 extern int nr_chain_hlocks;
 extern unsigned long nr_stack_trace_entries;
+extern unsigned long nr_save_trace_invocations;
+extern unsigned long nr_save_trace_invocations_type[LOCK_USAGE_STATES];
 
 extern unsigned int nr_hardirq_chains;
 extern unsigned int nr_softirq_chains;
diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c
index 59b76c8..ef5f372 100644
--- a/kernel/lockdep_proc.c
+++ b/kernel/lockdep_proc.c
@@ -215,8 +215,24 @@ static void lockdep_stats_debug_show(struct seq_file *m)
 #endif
 }
 
+#define __USAGE(__STATE)	\
+[LOCK_USED_IN_##__STATE] = "LOCK_USED_IN_"__stringify(__STATE),	\
+[LOCK_ENABLED_##__STATE] = "LOCK_ENABLED_"__stringify(__STATE), \
+[LOCK_USED_IN_##__STATE##_READ] = "LOCK_USED_IN_"__stringify(__STATE)"_READ", \
+[LOCK_ENABLED_##__STATE##_READ] = "LOCK_ENABLED_"__stringify(__STATE)"_READ",
+
+static const char *lockstate_tostr[] =
+{
+#define LOCKDEP_STATE(__STATE) __USAGE(__STATE)
+#include "lockdep_states.h"
+#undef LOCKDEP_STATE
+#undef __USAGE
+	[LOCK_USED] = "LOCK_USED",
+};
+
 static int lockdep_stats_show(struct seq_file *m, void *v)
 {
+	int bit;
 	struct lock_class *class;
 	unsigned long nr_unused = 0, nr_uncategorized = 0,
 		      nr_irq_safe = 0, nr_irq_unsafe = 0,
@@ -307,6 +323,13 @@ static int lockdep_stats_show(struct seq_file *m, void *v)
 			nr_process_chains);
 	seq_printf(m, " stack-trace entries:           %11lu [max: %lu]\n",
 			nr_stack_trace_entries, MAX_STACK_TRACE_ENTRIES);
+	seq_printf(m, " stack-trace invocations: %lu\n",
+			nr_save_trace_invocations);
+
+	for (bit=0; bit < LOCK_USAGE_STATES; bit++)
+		seq_printf(m, "\t%s: %lu\n", lockstate_tostr[bit],
+			       nr_save_trace_invocations_type[bit]);	
+
 	seq_printf(m, " combined max dependencies:     %11u\n",
 			(nr_hardirq_chains + 1) *
 			(nr_softirq_chains + 1) *
-- 
1.6.6.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH] lockdep: Add nr_save_trace_invocations counter
  2010-04-22 20:15 [PATCH] lockdep: Add nr_save_trace_invocations counter John Kacur
@ 2010-04-23  2:58 ` Yong Zhang
  2010-04-23  6:52   ` Peter Zijlstra
  2010-04-23  7:24   ` John Kacur
  0 siblings, 2 replies; 21+ messages in thread
From: Yong Zhang @ 2010-04-23  2:58 UTC (permalink / raw)
  To: John Kacur
  Cc: Peter Zijlstra, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins

On Thu, Apr 22, 2010 at 10:15:48PM +0200, John Kacur wrote:
> NOT FOR INCLUSION
> 
> I created this patch as a result of Peter Zilstra's request to get more 
> info from lockdep. This patch is not for inclusion, at least in its 
> present form, because it adds some redunant info to /proc/lockdep_stats
> 
> However, some of the fields are new, and it is worth examining, and / or 
> applying if you are looking at the MAX_STACK_TRACE_ENTRIES too big 
> problem.
> 
> I generated this patch against a recent tip/master but it applies without 
> conflicts to the latest rt kernel as well. Comments are welcome, in fact 
> they are appreciated.
> 
> >From 5181c0296dd1549e4e706ff25a4cd81a1d90137d Mon Sep 17 00:00:00 2001
> From: John Kacur <jkacur@redhat.com>
> Date: Thu, 22 Apr 2010 17:02:42 +0200
> Subject: [PATCH] lockdep: Add nr_save_trace_invocations counter
> 
> Add the nr_save_trace_invocations counter which counts the number of
> time save_trace() is invoked when relevant for trace enteries.
> 
> This means, those invocations from mark_lock() and add_lock_to_list()
> 
> When called from mark_lock() we break it down into LOCKSTATE categories.
> 
> Signed-off-by: John Kacur <jkacur@redhat.com>

Just take a rough look at it. I don't think this can give more info.

> +/* Calls to save_trace() from mark_lock() and add_lock_to_list() only*/
> +unsigned long nr_save_trace_invocations;

It will equal to nr_list_entries.

> +unsigned long nr_save_trace_invocations_type[LOCK_USAGE_STATES];

And each item in this array will equal to nr_hardirq_[un]safe,
nr_softirq_[un]safe and such things under lockdep_stats_show(). Right?

Thanks,
Yong

> +
>  static int save_trace(struct stack_trace *trace)
>  {
>  	trace->nr_entries = 0;
> @@ -410,6 +414,19 @@ static int save_trace(struct stack_trace *trace)
>  	return 1;
>  }
>  
> +/*
> + * This function is only called from mark_lock() and add_lock_to_list()
> + * which are only called when holding the graph_lock. This counter
> + * piggybacks off of that lock
> + */
> +static void inc_save_trace_invocations(enum lock_usage_bit new_bit)
> +{
> +	nr_save_trace_invocations++;
> +	if (WARN_ON(new_bit >= LOCK_USAGE_STATES))
> +		return;
> +	nr_save_trace_invocations_type[new_bit]++;
> +}
> +
>  unsigned int nr_hardirq_chains;
>  unsigned int nr_softirq_chains;
>  unsigned int nr_process_chains;
> @@ -449,6 +466,7 @@ static const char *usage_str[] =
>  #define LOCKDEP_STATE(__STATE) __USAGE(__STATE)
>  #include "lockdep_states.h"
>  #undef LOCKDEP_STATE
> +#undef __USAGE
>  	[LOCK_USED] = "INITIAL USE",
>  };
>  
> @@ -816,6 +834,7 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
>  	if (!entry)
>  		return 0;
>  
> +	nr_save_trace_invocations++;
>  	if (!save_trace(&entry->trace))
>  		return 0;
>  
> @@ -2615,6 +2634,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
>  
>  	hlock_class(this)->usage_mask |= new_mask;
>  
> +	inc_save_trace_invocations(new_bit);
>  	if (!save_trace(hlock_class(this)->usage_traces + new_bit))
>  		return 0;
>  
> diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h
> index 8d7d4b6..6149358 100644
> --- a/kernel/lockdep_internals.h
> +++ b/kernel/lockdep_internals.h
> @@ -84,6 +84,8 @@ extern unsigned long nr_list_entries;
>  extern unsigned long nr_lock_chains;
>  extern int nr_chain_hlocks;
>  extern unsigned long nr_stack_trace_entries;
> +extern unsigned long nr_save_trace_invocations;
> +extern unsigned long nr_save_trace_invocations_type[LOCK_USAGE_STATES];
>  
>  extern unsigned int nr_hardirq_chains;
>  extern unsigned int nr_softirq_chains;
> diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c
> index 59b76c8..ef5f372 100644
> --- a/kernel/lockdep_proc.c
> +++ b/kernel/lockdep_proc.c
> @@ -215,8 +215,24 @@ static void lockdep_stats_debug_show(struct seq_file *m)
>  #endif
>  }
>  
> +#define __USAGE(__STATE)	\
> +[LOCK_USED_IN_##__STATE] = "LOCK_USED_IN_"__stringify(__STATE),	\
> +[LOCK_ENABLED_##__STATE] = "LOCK_ENABLED_"__stringify(__STATE), \
> +[LOCK_USED_IN_##__STATE##_READ] = "LOCK_USED_IN_"__stringify(__STATE)"_READ", \
> +[LOCK_ENABLED_##__STATE##_READ] = "LOCK_ENABLED_"__stringify(__STATE)"_READ",
> +
> +static const char *lockstate_tostr[] =
> +{
> +#define LOCKDEP_STATE(__STATE) __USAGE(__STATE)
> +#include "lockdep_states.h"
> +#undef LOCKDEP_STATE
> +#undef __USAGE
> +	[LOCK_USED] = "LOCK_USED",
> +};
> +
>  static int lockdep_stats_show(struct seq_file *m, void *v)
>  {
> +	int bit;
>  	struct lock_class *class;
>  	unsigned long nr_unused = 0, nr_uncategorized = 0,
>  		      nr_irq_safe = 0, nr_irq_unsafe = 0,
> @@ -307,6 +323,13 @@ static int lockdep_stats_show(struct seq_file *m, void *v)
>  			nr_process_chains);
>  	seq_printf(m, " stack-trace entries:           %11lu [max: %lu]\n",
>  			nr_stack_trace_entries, MAX_STACK_TRACE_ENTRIES);
> +	seq_printf(m, " stack-trace invocations: %lu\n",
> +			nr_save_trace_invocations);
> +
> +	for (bit=0; bit < LOCK_USAGE_STATES; bit++)
> +		seq_printf(m, "\t%s: %lu\n", lockstate_tostr[bit],
> +			       nr_save_trace_invocations_type[bit]);	
> +
>  	seq_printf(m, " combined max dependencies:     %11u\n",
>  			(nr_hardirq_chains + 1) *
>  			(nr_softirq_chains + 1) *
> -- 
> 1.6.6.1
> 
> --
> 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/

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] lockdep: Add nr_save_trace_invocations counter
  2010-04-23  2:58 ` Yong Zhang
@ 2010-04-23  6:52   ` Peter Zijlstra
  2010-04-23  8:03     ` Yong Zhang
  2010-04-23  7:24   ` John Kacur
  1 sibling, 1 reply; 21+ messages in thread
From: Peter Zijlstra @ 2010-04-23  6:52 UTC (permalink / raw)
  To: Yong Zhang
  Cc: John Kacur, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins

On Fri, 2010-04-23 at 10:58 +0800, Yong Zhang wrote:
> 
> > +unsigned long nr_save_trace_invocations_type[LOCK_USAGE_STATES];
> 
> And each item in this array will equal to nr_hardirq_[un]safe,
> nr_softirq_[un]safe and such things under lockdep_stats_show(). Right?

Well, the stats for RECLAIM_FS as missing, so at the very least we need
to re-write lockdep_stats_show() to use the lockdep_states.h magic.




^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] lockdep: Add nr_save_trace_invocations counter
  2010-04-23  2:58 ` Yong Zhang
  2010-04-23  6:52   ` Peter Zijlstra
@ 2010-04-23  7:24   ` John Kacur
  2010-04-23  8:00     ` Yong Zhang
  2010-04-23  8:05     ` Peter Zijlstra
  1 sibling, 2 replies; 21+ messages in thread
From: John Kacur @ 2010-04-23  7:24 UTC (permalink / raw)
  To: Yong Zhang
  Cc: Peter Zijlstra, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins


 
On Fri, 23 Apr 2010, Yong Zhang wrote:

> On Thu, Apr 22, 2010 at 10:15:48PM +0200, John Kacur wrote:
> > NOT FOR INCLUSION
> > 
> > I created this patch as a result of Peter Zilstra's request to get more 
> > info from lockdep. This patch is not for inclusion, at least in its 
> > present form, because it adds some redunant info to /proc/lockdep_stats
> > 
> > However, some of the fields are new, and it is worth examining, and / or 
> > applying if you are looking at the MAX_STACK_TRACE_ENTRIES too big 
> > problem.
> > 
> > I generated this patch against a recent tip/master but it applies without 
> > conflicts to the latest rt kernel as well. Comments are welcome, in fact 
> > they are appreciated.
> > 
> > >From 5181c0296dd1549e4e706ff25a4cd81a1d90137d Mon Sep 17 00:00:00 2001
> > From: John Kacur <jkacur@redhat.com>
> > Date: Thu, 22 Apr 2010 17:02:42 +0200
> > Subject: [PATCH] lockdep: Add nr_save_trace_invocations counter
> > 
> > Add the nr_save_trace_invocations counter which counts the number of
> > time save_trace() is invoked when relevant for trace enteries.
> > 
> > This means, those invocations from mark_lock() and add_lock_to_list()
> > 
> > When called from mark_lock() we break it down into LOCKSTATE categories.
> > 
> > Signed-off-by: John Kacur <jkacur@redhat.com>
> 
> Just take a rough look at it. I don't think this can give more info.
> 
> > +/* Calls to save_trace() from mark_lock() and add_lock_to_list() only*/
> > +unsigned long nr_save_trace_invocations;
> 
> It will equal to nr_list_entries.
> 
> > +unsigned long nr_save_trace_invocations_type[LOCK_USAGE_STATES];
> 
> And each item in this array will equal to nr_hardirq_[un]safe,
> nr_softirq_[un]safe and such things under lockdep_stats_show(). Right?
> 
> Thanks,
> Yong
> 

Hi Yong

Some context here - Peter asked me to see if we could get some more 
detailed stats on why some configurations reach the 
MAX_STACK_TRACE_ENTRIES limit - whether the limit was really too low for 
some circumstances, or whether we were counting somethings unnecessarily.

In any case, I stamped a big NOT FOR INCLUSION on my mail, because I 
noticed that somethings were redundant - albeit, obtained in a slightly 
different manner, however, not everything is redundant.

In particular, nr_save_trace_invocations is NOT equal to nr_list_entries.
You will see that reported in /proc/lockdep_stats as
direct dependencies:                  8752 [max: 16384]
I have
stack-trace invocations: 10888
from the same run.

Still trying to figure out what the meaning is of that though to be 
honest.

Here is a portion of the lockdep_stats, with all of the new fields and the 
redundant ones.

stack-trace invocations: 10888
	LOCK_USED_IN_HARDIRQ: 15
	LOCK_USED_IN_HARDIRQ_READ: 0
	LOCK_ENABLED_HARDIRQ: 543
	LOCK_ENABLED_HARDIRQ_READ: 28
	LOCK_USED_IN_SOFTIRQ: 0
	LOCK_USED_IN_SOFTIRQ_READ: 0
	LOCK_ENABLED_SOFTIRQ: 543
	LOCK_ENABLED_SOFTIRQ_READ: 28
	LOCK_USED_IN_RECLAIM_FS: 5
	LOCK_USED_IN_RECLAIM_FS_READ: 0
	LOCK_ENABLED_RECLAIM_FS: 95
	LOCK_ENABLED_RECLAIM_FS_READ: 8
	LOCK_USED: 871
 combined max dependencies:          139841
 hardirq-safe locks:                     15
 hardirq-unsafe locks:                  543
 softirq-safe locks:                      0
 softirq-unsafe locks:                  543
 irq-safe locks:                         15
 irq-unsafe locks:                      543
 hardirq-read-safe locks:                 0
 hardirq-read-unsafe locks:              28
 softirq-read-safe locks:                 0
 softirq-read-unsafe locks:              28
 irq-read-safe locks:                     0
 irq-read-unsafe locks:                  28

So, you see that all of the reclaim fields are new,
        LOCK_USED_IN_RECLAIM_FS: 5
        LOCK_USED_IN_RECLAIM_FS_READ: 0
        LOCK_ENABLED_RECLAIM_FS: 95
        LOCK_ENABLED_RECLAIM_FS_READ: 8

I can create a patch for inclusion that adds the reclaim fields, the 
question is, is the nr_save_trace_invocations a useful stat for us or not?

Thanks

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] lockdep: Add nr_save_trace_invocations counter
  2010-04-23  7:24   ` John Kacur
@ 2010-04-23  8:00     ` Yong Zhang
  2010-04-23  8:05     ` Peter Zijlstra
  1 sibling, 0 replies; 21+ messages in thread
From: Yong Zhang @ 2010-04-23  8:00 UTC (permalink / raw)
  To: John Kacur
  Cc: Peter Zijlstra, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins

On Fri, Apr 23, 2010 at 09:24:55AM +0200, John Kacur wrote:
> Some context here - Peter asked me to see if we could get some more 
> detailed stats on why some configurations reach the 
> MAX_STACK_TRACE_ENTRIES limit - whether the limit was really too low for 
> some circumstances, or whether we were counting somethings unnecessarily.
> 
> In any case, I stamped a big NOT FOR INCLUSION on my mail, because I 
> noticed that somethings were redundant - albeit, obtained in a slightly 
> different manner, however, not everything is redundant.
> 
> In particular, nr_save_trace_invocations is NOT equal to nr_list_entries.
> You will see that reported in /proc/lockdep_stats as
> direct dependencies:                  8752 [max: 16384]
> I have
> stack-trace invocations: 10888
> from the same run.

I missed that nr_save_trace_invocations is also increased in
inc_save_trace_invocations().
So nr_save_trace_invocations = nr_list_entries + sum of
nr_save_trace_invocations_type[].

> 
> Still trying to figure out what the meaning is of that though to be 
> honest.
> 
> Here is a portion of the lockdep_stats, with all of the new fields and the 
> redundant ones.
> 
> stack-trace invocations: 10888
> 	LOCK_USED_IN_HARDIRQ: 15
> 	LOCK_USED_IN_HARDIRQ_READ: 0
> 	LOCK_ENABLED_HARDIRQ: 543
> 	LOCK_ENABLED_HARDIRQ_READ: 28
> 	LOCK_USED_IN_SOFTIRQ: 0
> 	LOCK_USED_IN_SOFTIRQ_READ: 0
> 	LOCK_ENABLED_SOFTIRQ: 543
> 	LOCK_ENABLED_SOFTIRQ_READ: 28
> 	LOCK_USED_IN_RECLAIM_FS: 5
> 	LOCK_USED_IN_RECLAIM_FS_READ: 0
> 	LOCK_ENABLED_RECLAIM_FS: 95
> 	LOCK_ENABLED_RECLAIM_FS_READ: 8
> 	LOCK_USED: 871
>  combined max dependencies:          139841
>  hardirq-safe locks:                     15
>  hardirq-unsafe locks:                  543
>  softirq-safe locks:                      0
>  softirq-unsafe locks:                  543
>  irq-safe locks:                         15
>  irq-unsafe locks:                      543
>  hardirq-read-safe locks:                 0
>  hardirq-read-unsafe locks:              28
>  softirq-read-safe locks:                 0
>  softirq-read-unsafe locks:              28
>  irq-read-safe locks:                     0
>  irq-read-unsafe locks:                  28
> 
> So, you see that all of the reclaim fields are new,
>         LOCK_USED_IN_RECLAIM_FS: 5
>         LOCK_USED_IN_RECLAIM_FS_READ: 0
>         LOCK_ENABLED_RECLAIM_FS: 95
>         LOCK_ENABLED_RECLAIM_FS_READ: 8

Yes, indeed, data in lockdep_stats_show() is out of time.
So as Peter has said in another thread, we should add sample for RECLAIM_FS.

> 
> I can create a patch for inclusion that adds the reclaim fields, the 
> question is, is the nr_save_trace_invocations a useful stat for us or not?

Actually it's just a summation of the samples.
I don't think it's necessary.

Thanks,
Yong

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] lockdep: Add nr_save_trace_invocations counter
  2010-04-23  6:52   ` Peter Zijlstra
@ 2010-04-23  8:03     ` Yong Zhang
  0 siblings, 0 replies; 21+ messages in thread
From: Yong Zhang @ 2010-04-23  8:03 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: John Kacur, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins

On Fri, Apr 23, 2010 at 08:52:05AM +0200, Peter Zijlstra wrote:
> On Fri, 2010-04-23 at 10:58 +0800, Yong Zhang wrote:
> > 
> > > +unsigned long nr_save_trace_invocations_type[LOCK_USAGE_STATES];
> > 
> > And each item in this array will equal to nr_hardirq_[un]safe,
> > nr_softirq_[un]safe and such things under lockdep_stats_show(). Right?
> 
> Well, the stats for RECLAIM_FS as missing, so at the very least we need
> to re-write lockdep_stats_show() to use the lockdep_states.h magic.

Yeah, it's a good start point and will keep thing unifying in the future.

Thanks,
Yong

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] lockdep: Add nr_save_trace_invocations counter
  2010-04-23  7:24   ` John Kacur
  2010-04-23  8:00     ` Yong Zhang
@ 2010-04-23  8:05     ` Peter Zijlstra
  2010-04-23  8:31         ` John Kacur
  1 sibling, 1 reply; 21+ messages in thread
From: Peter Zijlstra @ 2010-04-23  8:05 UTC (permalink / raw)
  To: John Kacur
  Cc: Yong Zhang, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins

On Fri, 2010-04-23 at 09:24 +0200, John Kacur wrote:
> direct dependencies:                  8752 [max: 16384]
> I have
> stack-trace invocations: 10888
> from the same run.
> 
> Still trying to figure out what the meaning is of that though to be 
> honest.
> 
> Here is a portion of the lockdep_stats, with all of the new fields and the 
> redundant ones.
> 
> stack-trace invocations: 10888
>         LOCK_USED_IN_HARDIRQ: 15
>         LOCK_USED_IN_HARDIRQ_READ: 0
>         LOCK_ENABLED_HARDIRQ: 543
>         LOCK_ENABLED_HARDIRQ_READ: 28
>         LOCK_USED_IN_SOFTIRQ: 0
>         LOCK_USED_IN_SOFTIRQ_READ: 0
>         LOCK_ENABLED_SOFTIRQ: 543
>         LOCK_ENABLED_SOFTIRQ_READ: 28
>         LOCK_USED_IN_RECLAIM_FS: 5
>         LOCK_USED_IN_RECLAIM_FS_READ: 0
>         LOCK_ENABLED_RECLAIM_FS: 95
>         LOCK_ENABLED_RECLAIM_FS_READ: 8
>         LOCK_USED: 871 

8752+871+8+95+5+28+543+28+543+15=10888

So you get a stack-trace for each direct-dependency, and you get a
stack-trace for each LOCK_state, the sum seems to match the total
invocations.

Non of these numbers look strange.. 


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] lockdep: Add nr_save_trace_invocations counter
  2010-04-23  8:05     ` Peter Zijlstra
@ 2010-04-23  8:31         ` John Kacur
  0 siblings, 0 replies; 21+ messages in thread
From: John Kacur @ 2010-04-23  8:31 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Yong Zhang, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins

On Fri, Apr 23, 2010 at 10:05 AM, Peter Zijlstra <peterz@infradead.org> wrote:
> On Fri, 2010-04-23 at 09:24 +0200, John Kacur wrote:
>> direct dependencies:                  8752 [max: 16384]
>> I have
>> stack-trace invocations: 10888
>> from the same run.
>>
>> Still trying to figure out what the meaning is of that though to be
>> honest.
>>
>> Here is a portion of the lockdep_stats, with all of the new fields and the
>> redundant ones.
>>
>> stack-trace invocations: 10888
>>         LOCK_USED_IN_HARDIRQ: 15
>>         LOCK_USED_IN_HARDIRQ_READ: 0
>>         LOCK_ENABLED_HARDIRQ: 543
>>         LOCK_ENABLED_HARDIRQ_READ: 28
>>         LOCK_USED_IN_SOFTIRQ: 0
>>         LOCK_USED_IN_SOFTIRQ_READ: 0
>>         LOCK_ENABLED_SOFTIRQ: 543
>>         LOCK_ENABLED_SOFTIRQ_READ: 28
>>         LOCK_USED_IN_RECLAIM_FS: 5
>>         LOCK_USED_IN_RECLAIM_FS_READ: 0
>>         LOCK_ENABLED_RECLAIM_FS: 95
>>         LOCK_ENABLED_RECLAIM_FS_READ: 8
>>         LOCK_USED: 871
>
> 8752+871+8+95+5+28+543+28+543+15=10888
>
> So you get a stack-trace for each direct-dependency, and you get a
> stack-trace for each LOCK_state, the sum seems to match the total
> invocations.
>
> Non of these numbers look strange..
>

As I told Peter privately the laptop that triggered the
MAX_STACK_TRACE_ENTRIES every time, has met an
unfortunate early demise. However, I think it was the config - not the
hardware. On this machine where the above
numbers come from, I believe I have less debug options configured -
but it is running the exact same kernel as
the laptop was. (2.6.33.2-rt13)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] lockdep: Add nr_save_trace_invocations counter
@ 2010-04-23  8:31         ` John Kacur
  0 siblings, 0 replies; 21+ messages in thread
From: John Kacur @ 2010-04-23  8:31 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Yong Zhang, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins

On Fri, Apr 23, 2010 at 10:05 AM, Peter Zijlstra <peterz@infradead.org> wrote:
> On Fri, 2010-04-23 at 09:24 +0200, John Kacur wrote:
>> direct dependencies:                  8752 [max: 16384]
>> I have
>> stack-trace invocations: 10888
>> from the same run.
>>
>> Still trying to figure out what the meaning is of that though to be
>> honest.
>>
>> Here is a portion of the lockdep_stats, with all of the new fields and the
>> redundant ones.
>>
>> stack-trace invocations: 10888
>>         LOCK_USED_IN_HARDIRQ: 15
>>         LOCK_USED_IN_HARDIRQ_READ: 0
>>         LOCK_ENABLED_HARDIRQ: 543
>>         LOCK_ENABLED_HARDIRQ_READ: 28
>>         LOCK_USED_IN_SOFTIRQ: 0
>>         LOCK_USED_IN_SOFTIRQ_READ: 0
>>         LOCK_ENABLED_SOFTIRQ: 543
>>         LOCK_ENABLED_SOFTIRQ_READ: 28
>>         LOCK_USED_IN_RECLAIM_FS: 5
>>         LOCK_USED_IN_RECLAIM_FS_READ: 0
>>         LOCK_ENABLED_RECLAIM_FS: 95
>>         LOCK_ENABLED_RECLAIM_FS_READ: 8
>>         LOCK_USED: 871
>
> 8752+871+8+95+5+28+543+28+543+15=10888
>
> So you get a stack-trace for each direct-dependency, and you get a
> stack-trace for each LOCK_state, the sum seems to match the total
> invocations.
>
> Non of these numbers look strange..
>

As I told Peter privately the laptop that triggered the
MAX_STACK_TRACE_ENTRIES every time, has met an
unfortunate early demise. However, I think it was the config - not the
hardware. On this machine where the above
numbers come from, I believe I have less debug options configured -
but it is running the exact same kernel as
the laptop was. (2.6.33.2-rt13)
--
To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] lockdep: Add nr_save_trace_invocations counter
  2010-04-23  8:31         ` John Kacur
  (?)
@ 2010-04-23  8:49         ` Yong Zhang
  2010-04-23  9:40           ` John Kacur
  -1 siblings, 1 reply; 21+ messages in thread
From: Yong Zhang @ 2010-04-23  8:49 UTC (permalink / raw)
  To: John Kacur
  Cc: Peter Zijlstra, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins

On Fri, Apr 23, 2010 at 10:31:16AM +0200, John Kacur wrote:
> > 8752+871+8+95+5+28+543+28+543+15=10888
> >
> > So you get a stack-trace for each direct-dependency, and you get a
> > stack-trace for each LOCK_state, the sum seems to match the total
> > invocations.
> >
> > Non of these numbers look strange..
> >
> 
> As I told Peter privately the laptop that triggered the
> MAX_STACK_TRACE_ENTRIES every time, has met an
> unfortunate early demise. However, I think it was the config - not the
> hardware. On this machine where the above
> numbers come from, I believe I have less debug options configured -
> but it is running the exact same kernel as
> the laptop was. (2.6.33.2-rt13)

Through a rough computation:
MAX_STACK_TRACE_ENTRIES/10888 = 24
That means the average stack deepth is about 24.
So I'm thinking if we can take a check on the biggest deepth?
Could this make sense?

Thanks,
Yong


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] lockdep: Add nr_save_trace_invocations counter
  2010-04-23  8:49         ` Yong Zhang
@ 2010-04-23  9:40           ` John Kacur
  0 siblings, 0 replies; 21+ messages in thread
From: John Kacur @ 2010-04-23  9:40 UTC (permalink / raw)
  To: Yong Zhang
  Cc: Peter Zijlstra, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins

On Fri, Apr 23, 2010 at 10:49 AM, Yong Zhang <yong.zhang@windriver.com> wrote:
> On Fri, Apr 23, 2010 at 10:31:16AM +0200, John Kacur wrote:
>> > 8752+871+8+95+5+28+543+28+543+15=10888
>> >
>> > So you get a stack-trace for each direct-dependency, and you get a
>> > stack-trace for each LOCK_state, the sum seems to match the total
>> > invocations.
>> >
>> > Non of these numbers look strange..
>> >
>>
>> As I told Peter privately the laptop that triggered the
>> MAX_STACK_TRACE_ENTRIES every time, has met an
>> unfortunate early demise. However, I think it was the config - not the
>> hardware. On this machine where the above
>> numbers come from, I believe I have less debug options configured -
>> but it is running the exact same kernel as
>> the laptop was. (2.6.33.2-rt13)
>
> Through a rough computation:
> MAX_STACK_TRACE_ENTRIES/10888 = 24
> That means the average stack deepth is about 24.
> So I'm thinking if we can take a check on the biggest deepth?
> Could this make sense?
>

Hi Yong, yes that makes sense, I'll see if I can provide a patch for that too.

Thanks

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] lockdep: reduce stack_trace usage
  2010-04-23  8:31         ` John Kacur
  (?)
  (?)
@ 2010-04-23 13:40         ` Yong Zhang
  2010-04-26  6:24           ` Yong Zhang
                             ` (2 more replies)
  -1 siblings, 3 replies; 21+ messages in thread
From: Yong Zhang @ 2010-04-23 13:40 UTC (permalink / raw)
  To: John Kacur
  Cc: Peter Zijlstra, Yong Zhang, LKML, linux-rt-users,
	Sven-Thorsten Dietrich, Clark Williams,
	Luis Claudio R. Goncalves, Ingo Molnar, Thomas Gleixner,
	Gregory Haskins, David S. Miller

On Fri, Apr 23, 2010 at 10:31:16AM +0200, John Kacur wrote:
> > Non of these numbers look strange..
> >
> 
> As I told Peter privately the laptop that triggered the
> MAX_STACK_TRACE_ENTRIES every time, has met an
> unfortunate early demise. However, I think it was the config - not the
> hardware. On this machine where the above
> numbers come from, I believe I have less debug options configured -
> but it is running the exact same kernel as
> the laptop was. (2.6.33.2-rt13)

Hi John,

(checking mail at home).
I find some place which can be hacked. Below is the patch.
But I don't even compile it. Can you test it to see if it can smooth
your problem.

---cut here ---
>From 6b9d513b7c417c0805ef0acc1cb3227bddba0889 Mon Sep 17 00:00:00 2001
From: Yong Zhang <yong.zhang0@gmail.com>
Date: Fri, 23 Apr 2010 21:13:54 +0800
Subject: [PATCH] lockdep: reduce stack_trace usage

When calling check_prevs_add(), if all validations passed
add_lock_to_list() will add new lock to dependency tree and
alloc stack_trace for each list_entry. But at this time,
we are always on the same stack, so stack_trace for each
list_entry has the same value. This is redundant and eats up
lots of memory which could lead to warning on low
MAX_STACK_TRACE_ENTRIES.
Using one copy of stack_trace instead.

Signed-off-by: Yong Zhang <yong.zhang0@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: David S. Miller <davem@davemloft.net>
---
 kernel/lockdep.c |   20 ++++++++++++--------
 1 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 2594e1c..097d5fb 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -818,7 +818,8 @@ static struct lock_list *alloc_list_entry(void)
  * Add a new dependency to the head of the list:
  */
 static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
-			    struct list_head *head, unsigned long ip, int distance)
+			    struct list_head *head, unsigned long ip,
+			    int distance, struct stack_trace *trace)
 {
 	struct lock_list *entry;
 	/*
@@ -829,11 +830,9 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
 	if (!entry)
 		return 0;
 
-	if (!save_trace(&entry->trace))
-		return 0;
-
 	entry->class = this;
 	entry->distance = distance;
+	entry->trace = *trace;
 	/*
 	 * Since we never remove from the dependency list, the list can
 	 * be walked lockless by other CPUs, it's only allocation
@@ -1635,7 +1634,7 @@ check_deadlock(struct task_struct *curr, struct held_lock *next,
  */
 static int
 check_prev_add(struct task_struct *curr, struct held_lock *prev,
-	       struct held_lock *next, int distance)
+	       struct held_lock *next, int distance, struct stack_trace *trace)
 {
 	struct lock_list *entry;
 	int ret;
@@ -1694,14 +1693,14 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
 	 */
 	ret = add_lock_to_list(hlock_class(prev), hlock_class(next),
 			       &hlock_class(prev)->locks_after,
-			       next->acquire_ip, distance);
+			       next->acquire_ip, distance, trace);
 
 	if (!ret)
 		return 0;
 
 	ret = add_lock_to_list(hlock_class(next), hlock_class(prev),
 			       &hlock_class(next)->locks_before,
-			       next->acquire_ip, distance);
+			       next->acquire_ip, distance, trace);
 	if (!ret)
 		return 0;
 
@@ -1732,6 +1731,7 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
 {
 	int depth = curr->lockdep_depth;
 	struct held_lock *hlock;
+	struct stack_trace trace;
 
 	/*
 	 * Debugging checks.
@@ -1748,6 +1748,9 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
 			curr->held_locks[depth-1].irq_context)
 		goto out_bug;
 
+	if (!save_trace(&trace))
+		return 0;
+
 	for (;;) {
 		int distance = curr->lockdep_depth - depth + 1;
 		hlock = curr->held_locks + depth-1;
@@ -1756,7 +1759,8 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
 		 * added:
 		 */
 		if (hlock->read != 2) {
-			if (!check_prev_add(curr, hlock, next, distance))
+			if (!check_prev_add(curr, hlock, next,
+						distance, &trace))
 				return 0;
 			/*
 			 * Stop after the first non-trylock entry,
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH] lockdep: reduce stack_trace usage
  2010-04-23 13:40         ` [PATCH] lockdep: reduce stack_trace usage Yong Zhang
@ 2010-04-26  6:24           ` Yong Zhang
  2010-05-03 12:11           ` Peter Zijlstra
  2010-05-04  6:57           ` [PATCH V2] " Yong Zhang
  2 siblings, 0 replies; 21+ messages in thread
From: Yong Zhang @ 2010-04-26  6:24 UTC (permalink / raw)
  To: John Kacur, Peter Zijlstra
  Cc: LKML, linux-rt-users, Sven-Thorsten Dietrich, Clark Williams,
	Luis Claudio R. Goncalves, Ingo Molnar, Thomas Gleixner,
	Gregory Haskins, David S. Miller, Yong Zhang

On Fri, Apr 23, 2010 at 09:40:44PM +0800, Yong Zhang wrote:
> Hi John,
> 
> (checking mail at home).
> I find some place which can be hacked. Below is the patch.
> But I don't even compile it. Can you test it to see if it can smooth
> your problem.
> 
> ---cut here ---
> >From 6b9d513b7c417c0805ef0acc1cb3227bddba0889 Mon Sep 17 00:00:00 2001
> From: Yong Zhang <yong.zhang0@gmail.com>
> Date: Fri, 23 Apr 2010 21:13:54 +0800
> Subject: [PATCH] lockdep: reduce stack_trace usage
> 
> When calling check_prevs_add(), if all validations passed
> add_lock_to_list() will add new lock to dependency tree and
> alloc stack_trace for each list_entry. But at this time,
> we are always on the same stack, so stack_trace for each
> list_entry has the same value. This is redundant and eats up
> lots of memory which could lead to warning on low
> MAX_STACK_TRACE_ENTRIES.
> Using one copy of stack_trace instead.

With the following test patch running on my machine:
> cat /proc/lockdep_stats 
 lock-classes:                          564 [max: 8191]
 direct dependencies:                  2626 [max: 16384]
 indirect dependencies:                5951
 all direct dependencies:             48226
 dependency chains:                    2576 [max: 32768]
 dependency chain hlocks:              6740 [max: 163840]
 in-hardirq chains:                      18
 in-softirq chains:                     163
 in-process chains:                    2395
 stack-trace entries:                 63076 [max: 262144]
 duplicated stack-trace entries:       7592         <=========
 combined max dependencies:         7465936
 hardirq-safe locks:                     30
 hardirq-unsafe locks:                  380
 softirq-safe locks:                     82
 softirq-unsafe locks:                  305
 irq-safe locks:                         90
 irq-unsafe locks:                      380
 hardirq-read-safe locks:                 0
 hardirq-read-unsafe locks:              51
 softirq-read-safe locks:                11
 softirq-read-unsafe locks:              40
 irq-read-safe locks:                    11
 irq-read-unsafe locks:                  51
 uncategorized locks:                   112
 unused locks:                            1
 max locking depth:                      15
 max bfs queue depth:                    83
 debug_locks:                             1

We can see that about 12% stack_trace usage can be reduced.

Thanks,
Yong

------lockdep-duplicated-stack_trace-detect.patch------
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 2594e1c..dfd37ea 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -369,6 +369,7 @@ static int verbose(struct lock_class *class)
  * addresses. Protected by the graph_lock.
  */
 unsigned long nr_stack_trace_entries;
+unsigned long nr_duplicated_stack_trace_entries;
 static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES];
 
 static int save_trace(struct stack_trace *trace)
@@ -818,9 +819,14 @@ static struct lock_list *alloc_list_entry(void)
  * Add a new dependency to the head of the list:
  */
 static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
-			    struct list_head *head, unsigned long ip, int distance)
+			    struct list_head *head, unsigned long ip,
+			    int distance, struct held_lock *next)
 {
 	struct lock_list *entry;
+	static struct held_lock *hlock;
+	static struct stack_trace trace;
+	int i;
+
 	/*
 	 * Lock not present yet - get a new dependency struct and
 	 * add it to the list:
@@ -834,6 +840,20 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
 
 	entry->class = this;
 	entry->distance = distance;
+
+	if (hlock != next) {
+		hlock = next;
+		trace = entry->trace;
+	} else if (trace.nr_entries == entry->trace.nr_entries &&
+		 trace.max_entries == entry->trace.max_entries) {
+		 /* start from 2 to skip the stack introduced by lockdep */
+		 for (i=2; i<trace.nr_entries; i++) {
+			if (trace.entries[i] != entry->trace.entries[i])
+				goto no_duplicated;
+		}
+		nr_duplicated_stack_trace_entries += trace.nr_entries;
+	}
+no_duplicated:
 	/*
 	 * Since we never remove from the dependency list, the list can
 	 * be walked lockless by other CPUs, it's only allocation
@@ -1694,14 +1714,14 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
 	 */
 	ret = add_lock_to_list(hlock_class(prev), hlock_class(next),
 			       &hlock_class(prev)->locks_after,
-			       next->acquire_ip, distance);
+			       next->acquire_ip, distance, next);
 
 	if (!ret)
 		return 0;
 
 	ret = add_lock_to_list(hlock_class(next), hlock_class(prev),
 			       &hlock_class(next)->locks_before,
-			       next->acquire_ip, distance);
+			       next->acquire_ip, distance, next);
 	if (!ret)
 		return 0;
 
diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h
index a2ee95a..d00fe7b 100644
--- a/kernel/lockdep_internals.h
+++ b/kernel/lockdep_internals.h
@@ -84,6 +84,7 @@ extern unsigned long nr_list_entries;
 extern unsigned long nr_lock_chains;
 extern int nr_chain_hlocks;
 extern unsigned long nr_stack_trace_entries;
+extern unsigned long nr_duplicated_stack_trace_entries;
 
 extern unsigned int nr_hardirq_chains;
 extern unsigned int nr_softirq_chains;
diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c
index d4aba4f..32cb9a3 100644
--- a/kernel/lockdep_proc.c
+++ b/kernel/lockdep_proc.c
@@ -307,6 +307,8 @@ static int lockdep_stats_show(struct seq_file *m, void *v)
 			nr_process_chains);
 	seq_printf(m, " stack-trace entries:           %11lu [max: %lu]\n",
 			nr_stack_trace_entries, MAX_STACK_TRACE_ENTRIES);
+	seq_printf(m, " duplicated stack-trace entries:%11lu\n",
+			nr_duplicated_stack_trace_entries);
 	seq_printf(m, " combined max dependencies:     %11u\n",
 			(nr_hardirq_chains + 1) *
 			(nr_softirq_chains + 1) *
> 
> Signed-off-by: Yong Zhang <yong.zhang0@gmail.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: David S. Miller <davem@davemloft.net>
> ---
>  kernel/lockdep.c |   20 ++++++++++++--------
>  1 files changed, 12 insertions(+), 8 deletions(-)
> 
> diff --git a/kernel/lockdep.c b/kernel/lockdep.c
> index 2594e1c..097d5fb 100644
> --- a/kernel/lockdep.c
> +++ b/kernel/lockdep.c
> @@ -818,7 +818,8 @@ static struct lock_list *alloc_list_entry(void)
>   * Add a new dependency to the head of the list:
>   */
>  static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
> -			    struct list_head *head, unsigned long ip, int distance)
> +			    struct list_head *head, unsigned long ip,
> +			    int distance, struct stack_trace *trace)
>  {
>  	struct lock_list *entry;
>  	/*
> @@ -829,11 +830,9 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
>  	if (!entry)
>  		return 0;
>  
> -	if (!save_trace(&entry->trace))
> -		return 0;
> -
>  	entry->class = this;
>  	entry->distance = distance;
> +	entry->trace = *trace;
>  	/*
>  	 * Since we never remove from the dependency list, the list can
>  	 * be walked lockless by other CPUs, it's only allocation
> @@ -1635,7 +1634,7 @@ check_deadlock(struct task_struct *curr, struct held_lock *next,
>   */
>  static int
>  check_prev_add(struct task_struct *curr, struct held_lock *prev,
> -	       struct held_lock *next, int distance)
> +	       struct held_lock *next, int distance, struct stack_trace *trace)
>  {
>  	struct lock_list *entry;
>  	int ret;
> @@ -1694,14 +1693,14 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
>  	 */
>  	ret = add_lock_to_list(hlock_class(prev), hlock_class(next),
>  			       &hlock_class(prev)->locks_after,
> -			       next->acquire_ip, distance);
> +			       next->acquire_ip, distance, trace);
>  
>  	if (!ret)
>  		return 0;
>  
>  	ret = add_lock_to_list(hlock_class(next), hlock_class(prev),
>  			       &hlock_class(next)->locks_before,
> -			       next->acquire_ip, distance);
> +			       next->acquire_ip, distance, trace);
>  	if (!ret)
>  		return 0;
>  
> @@ -1732,6 +1731,7 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
>  {
>  	int depth = curr->lockdep_depth;
>  	struct held_lock *hlock;
> +	struct stack_trace trace;
>  
>  	/*
>  	 * Debugging checks.
> @@ -1748,6 +1748,9 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
>  			curr->held_locks[depth-1].irq_context)
>  		goto out_bug;
>  
> +	if (!save_trace(&trace))
> +		return 0;
> +
>  	for (;;) {
>  		int distance = curr->lockdep_depth - depth + 1;
>  		hlock = curr->held_locks + depth-1;
> @@ -1756,7 +1759,8 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
>  		 * added:
>  		 */
>  		if (hlock->read != 2) {
> -			if (!check_prev_add(curr, hlock, next, distance))
> +			if (!check_prev_add(curr, hlock, next,
> +						distance, &trace))
>  				return 0;
>  			/*
>  			 * Stop after the first non-trylock entry,
> -- 
> 1.6.3.3

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH] lockdep: reduce stack_trace usage
  2010-04-23 13:40         ` [PATCH] lockdep: reduce stack_trace usage Yong Zhang
  2010-04-26  6:24           ` Yong Zhang
@ 2010-05-03 12:11           ` Peter Zijlstra
  2010-05-04  6:37             ` Yong Zhang
  2010-05-04  6:57           ` [PATCH V2] " Yong Zhang
  2 siblings, 1 reply; 21+ messages in thread
From: Peter Zijlstra @ 2010-05-03 12:11 UTC (permalink / raw)
  To: Yong Zhang
  Cc: John Kacur, Yong Zhang, LKML, linux-rt-users,
	Sven-Thorsten Dietrich, Clark Williams,
	Luis Claudio R. Goncalves, Ingo Molnar, Thomas Gleixner,
	Gregory Haskins, David S. Miller

On Fri, 2010-04-23 at 21:40 +0800, Yong Zhang wrote:

> From 6b9d513b7c417c0805ef0acc1cb3227bddba0889 Mon Sep 17 00:00:00 2001
> From: Yong Zhang <yong.zhang0@gmail.com>
> Date: Fri, 23 Apr 2010 21:13:54 +0800
> Subject: [PATCH] lockdep: reduce stack_trace usage
> 
> When calling check_prevs_add(), if all validations passed
> add_lock_to_list() will add new lock to dependency tree and
> alloc stack_trace for each list_entry. But at this time,
> we are always on the same stack, so stack_trace for each
> list_entry has the same value. This is redundant and eats up
> lots of memory which could lead to warning on low
> MAX_STACK_TRACE_ENTRIES.
> Using one copy of stack_trace instead.

OK, I like the idea, but I'm a little confused as to why you pull
save_trace() up two functions, from what I can see we can now end up
saving a trace where we previously would not have done one (the whole
recursive lock mess.

So please respin this with save_trace() in check_prev_add() right before
the first add_lock_to_list().

> Signed-off-by: Yong Zhang <yong.zhang0@gmail.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: David S. Miller <davem@davemloft.net>
> ---
>  kernel/lockdep.c |   20 ++++++++++++--------
>  1 files changed, 12 insertions(+), 8 deletions(-)
> 
> diff --git a/kernel/lockdep.c b/kernel/lockdep.c
> index 2594e1c..097d5fb 100644
> --- a/kernel/lockdep.c
> +++ b/kernel/lockdep.c
> @@ -818,7 +818,8 @@ static struct lock_list *alloc_list_entry(void)
>   * Add a new dependency to the head of the list:
>   */
>  static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
> -			    struct list_head *head, unsigned long ip, int distance)
> +			    struct list_head *head, unsigned long ip,
> +			    int distance, struct stack_trace *trace)
>  {
>  	struct lock_list *entry;
>  	/*
> @@ -829,11 +830,9 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
>  	if (!entry)
>  		return 0;
>  
> -	if (!save_trace(&entry->trace))
> -		return 0;
> -
>  	entry->class = this;
>  	entry->distance = distance;
> +	entry->trace = *trace;
>  	/*
>  	 * Since we never remove from the dependency list, the list can
>  	 * be walked lockless by other CPUs, it's only allocation
> @@ -1635,7 +1634,7 @@ check_deadlock(struct task_struct *curr, struct held_lock *next,
>   */
>  static int
>  check_prev_add(struct task_struct *curr, struct held_lock *prev,
> -	       struct held_lock *next, int distance)
> +	       struct held_lock *next, int distance, struct stack_trace *trace)
>  {
>  	struct lock_list *entry;
>  	int ret;
> @@ -1694,14 +1693,14 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
>  	 */
>  	ret = add_lock_to_list(hlock_class(prev), hlock_class(next),
>  			       &hlock_class(prev)->locks_after,
> -			       next->acquire_ip, distance);
> +			       next->acquire_ip, distance, trace);
>  
>  	if (!ret)
>  		return 0;
>  
>  	ret = add_lock_to_list(hlock_class(next), hlock_class(prev),
>  			       &hlock_class(next)->locks_before,
> -			       next->acquire_ip, distance);
> +			       next->acquire_ip, distance, trace);
>  	if (!ret)
>  		return 0;
>  
> @@ -1732,6 +1731,7 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
>  {
>  	int depth = curr->lockdep_depth;
>  	struct held_lock *hlock;
> +	struct stack_trace trace;
>  
>  	/*
>  	 * Debugging checks.
> @@ -1748,6 +1748,9 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
>  			curr->held_locks[depth-1].irq_context)
>  		goto out_bug;
>  
> +	if (!save_trace(&trace))
> +		return 0;
> +
>  	for (;;) {
>  		int distance = curr->lockdep_depth - depth + 1;
>  		hlock = curr->held_locks + depth-1;
> @@ -1756,7 +1759,8 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
>  		 * added:
>  		 */
>  		if (hlock->read != 2) {
> -			if (!check_prev_add(curr, hlock, next, distance))
> +			if (!check_prev_add(curr, hlock, next,
> +						distance, &trace))
>  				return 0;
>  			/*
>  			 * Stop after the first non-trylock entry,


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] lockdep: reduce stack_trace usage
  2010-05-03 12:11           ` Peter Zijlstra
@ 2010-05-04  6:37             ` Yong Zhang
  0 siblings, 0 replies; 21+ messages in thread
From: Yong Zhang @ 2010-05-04  6:37 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Yong Zhang, John Kacur, LKML, linux-rt-users,
	Sven-Thorsten Dietrich, Clark Williams,
	Luis Claudio R. Goncalves, Ingo Molnar, Thomas Gleixner,
	Gregory Haskins, David S. Miller

On Mon, May 03, 2010 at 02:11:29PM +0200, Peter Zijlstra wrote:
> OK, I like the idea, but I'm a little confused as to why you pull
> save_trace() up two functions,

I also want to avoid adding redundant trace in case of trylock.
On my machine, I catched about 150 trylock dependences.

> from what I can see we can now end up
> saving a trace where we previously would not have done one (the whole
> recursive lock mess.

Oh, Yes, this patch will not give result as expected. Thank you for pointing
it. I will respin it in V2.

> 
> So please respin this with save_trace() in check_prev_add() right before
> the first add_lock_to_list().

No problem. 
BTW, in case of trylock dependence, I will let check_prevs_add() carry a flag
to check_prev_add(). Thus, we can save more redundant trace. How do you
think about it?

Thanks,
Yong

> 
> > Signed-off-by: Yong Zhang <yong.zhang0@gmail.com>
> > Cc: Peter Zijlstra <peterz@infradead.org>
> > Cc: Ingo Molnar <mingo@redhat.com>
> > Cc: David S. Miller <davem@davemloft.net>
> > ---
> >  kernel/lockdep.c |   20 ++++++++++++--------
> >  1 files changed, 12 insertions(+), 8 deletions(-)
> > 
> > diff --git a/kernel/lockdep.c b/kernel/lockdep.c
> > index 2594e1c..097d5fb 100644
> > --- a/kernel/lockdep.c
> > +++ b/kernel/lockdep.c
> > @@ -818,7 +818,8 @@ static struct lock_list *alloc_list_entry(void)
> >   * Add a new dependency to the head of the list:
> >   */
> >  static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
> > -			    struct list_head *head, unsigned long ip, int distance)
> > +			    struct list_head *head, unsigned long ip,
> > +			    int distance, struct stack_trace *trace)
> >  {
> >  	struct lock_list *entry;
> >  	/*
> > @@ -829,11 +830,9 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
> >  	if (!entry)
> >  		return 0;
> >  
> > -	if (!save_trace(&entry->trace))
> > -		return 0;
> > -
> >  	entry->class = this;
> >  	entry->distance = distance;
> > +	entry->trace = *trace;
> >  	/*
> >  	 * Since we never remove from the dependency list, the list can
> >  	 * be walked lockless by other CPUs, it's only allocation
> > @@ -1635,7 +1634,7 @@ check_deadlock(struct task_struct *curr, struct held_lock *next,
> >   */
> >  static int
> >  check_prev_add(struct task_struct *curr, struct held_lock *prev,
> > -	       struct held_lock *next, int distance)
> > +	       struct held_lock *next, int distance, struct stack_trace *trace)
> >  {
> >  	struct lock_list *entry;
> >  	int ret;
> > @@ -1694,14 +1693,14 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
> >  	 */
> >  	ret = add_lock_to_list(hlock_class(prev), hlock_class(next),
> >  			       &hlock_class(prev)->locks_after,
> > -			       next->acquire_ip, distance);
> > +			       next->acquire_ip, distance, trace);
> >  
> >  	if (!ret)
> >  		return 0;
> >  
> >  	ret = add_lock_to_list(hlock_class(next), hlock_class(prev),
> >  			       &hlock_class(next)->locks_before,
> > -			       next->acquire_ip, distance);
> > +			       next->acquire_ip, distance, trace);
> >  	if (!ret)
> >  		return 0;
> >  
> > @@ -1732,6 +1731,7 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
> >  {
> >  	int depth = curr->lockdep_depth;
> >  	struct held_lock *hlock;
> > +	struct stack_trace trace;
> >  
> >  	/*
> >  	 * Debugging checks.
> > @@ -1748,6 +1748,9 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
> >  			curr->held_locks[depth-1].irq_context)
> >  		goto out_bug;
> >  
> > +	if (!save_trace(&trace))
> > +		return 0;
> > +
> >  	for (;;) {
> >  		int distance = curr->lockdep_depth - depth + 1;
> >  		hlock = curr->held_locks + depth-1;
> > @@ -1756,7 +1759,8 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
> >  		 * added:
> >  		 */
> >  		if (hlock->read != 2) {
> > -			if (!check_prev_add(curr, hlock, next, distance))
> > +			if (!check_prev_add(curr, hlock, next,
> > +						distance, &trace))
> >  				return 0;
> >  			/*
> >  			 * Stop after the first non-trylock entry,

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH V2] lockdep: reduce stack_trace usage
  2010-04-23 13:40         ` [PATCH] lockdep: reduce stack_trace usage Yong Zhang
  2010-04-26  6:24           ` Yong Zhang
  2010-05-03 12:11           ` Peter Zijlstra
@ 2010-05-04  6:57           ` Yong Zhang
  2010-05-04 12:56             ` Peter Zijlstra
  2010-05-07 18:40             ` [tip:core/locking] lockdep: Reduce " tip-bot for Yong Zhang
  2 siblings, 2 replies; 21+ messages in thread
From: Yong Zhang @ 2010-05-04  6:57 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: John Kacur, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins, David S. Miller, Yong Zhang

>From 04395389820e89c0bd4bb57b939ec1882e0bb5da Mon Sep 17 00:00:00 2001
From: Yong Zhang <yong.zhang@windriver.com>
Date: Tue, 4 May 2010 14:16:48 +0800
Subject: [PATCH] lockdep: Reduce stack_trace usage

When calling check_prevs_add(), if all validations passed
add_lock_to_list() will add new lock to dependency tree and
alloc stack_trace for each list_entry. But at this time,
we are always on the same stack, so stack_trace for each
list_entry has the same value. This is redundant and eats up
lots of memory which could lead to warning on low
MAX_STACK_TRACE_ENTRIES.
Using one copy of stack_trace instead.

V2: As suggested by Peter Zijlstra, move save_trace() from
    check_prevs_add() to check_prev_add().
    Add tracking for trylock dependence which is also redundant.

Signed-off-by: Yong Zhang <yong.zhang0@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: David S. Miller <davem@davemloft.net>
---
 kernel/lockdep.c |   22 ++++++++++++++--------
 1 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 2594e1c..56e0ff9 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -818,7 +818,8 @@ static struct lock_list *alloc_list_entry(void)
  * Add a new dependency to the head of the list:
  */
 static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
-			    struct list_head *head, unsigned long ip, int distance)
+			    struct list_head *head, unsigned long ip,
+			    int distance, struct stack_trace *trace)
 {
 	struct lock_list *entry;
 	/*
@@ -829,11 +830,9 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
 	if (!entry)
 		return 0;
 
-	if (!save_trace(&entry->trace))
-		return 0;
-
 	entry->class = this;
 	entry->distance = distance;
+	entry->trace = *trace;
 	/*
 	 * Since we never remove from the dependency list, the list can
 	 * be walked lockless by other CPUs, it's only allocation
@@ -1635,12 +1634,13 @@ check_deadlock(struct task_struct *curr, struct held_lock *next,
  */
 static int
 check_prev_add(struct task_struct *curr, struct held_lock *prev,
-	       struct held_lock *next, int distance)
+	       struct held_lock *next, int distance, int trylock_loop)
 {
 	struct lock_list *entry;
 	int ret;
 	struct lock_list this;
 	struct lock_list *uninitialized_var(target_entry);
+	static struct stack_trace trace;
 
 	/*
 	 * Prove that the new <prev> -> <next> dependency would not
@@ -1688,20 +1688,23 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
 		}
 	}
 
+	if (!trylock_loop && !save_trace(&trace))
+		return 0;
+
 	/*
 	 * Ok, all validations passed, add the new lock
 	 * to the previous lock's dependency list:
 	 */
 	ret = add_lock_to_list(hlock_class(prev), hlock_class(next),
 			       &hlock_class(prev)->locks_after,
-			       next->acquire_ip, distance);
+			       next->acquire_ip, distance, &trace);
 
 	if (!ret)
 		return 0;
 
 	ret = add_lock_to_list(hlock_class(next), hlock_class(prev),
 			       &hlock_class(next)->locks_before,
-			       next->acquire_ip, distance);
+			       next->acquire_ip, distance, &trace);
 	if (!ret)
 		return 0;
 
@@ -1731,6 +1734,7 @@ static int
 check_prevs_add(struct task_struct *curr, struct held_lock *next)
 {
 	int depth = curr->lockdep_depth;
+	int trylock_loop = 0;
 	struct held_lock *hlock;
 
 	/*
@@ -1756,7 +1760,8 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
 		 * added:
 		 */
 		if (hlock->read != 2) {
-			if (!check_prev_add(curr, hlock, next, distance))
+			if (!check_prev_add(curr, hlock, next,
+						distance, trylock_loop))
 				return 0;
 			/*
 			 * Stop after the first non-trylock entry,
@@ -1779,6 +1784,7 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
 		if (curr->held_locks[depth].irq_context !=
 				curr->held_locks[depth-1].irq_context)
 			break;
+		trylock_loop = 1;
 	}
 	return 1;
 out_bug:
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH V2] lockdep: reduce stack_trace usage
  2010-05-04  6:57           ` [PATCH V2] " Yong Zhang
@ 2010-05-04 12:56             ` Peter Zijlstra
  2010-05-05  1:31               ` Yong Zhang
  2010-05-07 18:40             ` [tip:core/locking] lockdep: Reduce " tip-bot for Yong Zhang
  1 sibling, 1 reply; 21+ messages in thread
From: Peter Zijlstra @ 2010-05-04 12:56 UTC (permalink / raw)
  To: Yong Zhang
  Cc: John Kacur, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins, David S. Miller, Yong Zhang

On Tue, 2010-05-04 at 14:57 +0800, Yong Zhang wrote:
> From 04395389820e89c0bd4bb57b939ec1882e0bb5da Mon Sep 17 00:00:00 2001
> From: Yong Zhang <yong.zhang@windriver.com>
> Date: Tue, 4 May 2010 14:16:48 +0800
> Subject: [PATCH] lockdep: Reduce stack_trace usage
> 
> When calling check_prevs_add(), if all validations passed
> add_lock_to_list() will add new lock to dependency tree and
> alloc stack_trace for each list_entry. But at this time,
> we are always on the same stack, so stack_trace for each
> list_entry has the same value. This is redundant and eats up
> lots of memory which could lead to warning on low
> MAX_STACK_TRACE_ENTRIES.
> Using one copy of stack_trace instead.

Right, this looks like it ought to do as intended.

I added the below snipped because I know I'll fail to remember and that
'static' qualifier is fairly easy to miss.

Thanks!

---

Index: linux-2.6/kernel/lockdep.c
===================================================================
--- linux-2.6.orig/kernel/lockdep.c
+++ linux-2.6/kernel/lockdep.c
@@ -1627,6 +1627,13 @@ check_prev_add(struct task_struct *curr,
 	int ret;
 	struct lock_list this;
 	struct lock_list *uninitialized_var(target_entry);
+	/*
+	 * Static variable, serialized by the graph_lock().
+	 *
+	 * We use this static variable to save the stack trace in case
+	 * we call into this function multiple times due to encountering
+	 * trylocks in the held lock stack.
+	 */
 	static struct stack_trace trace;
 
 	/*


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH V2] lockdep: reduce stack_trace usage
  2010-05-04 12:56             ` Peter Zijlstra
@ 2010-05-05  1:31               ` Yong Zhang
  2010-05-05  9:09                 ` Peter Zijlstra
  0 siblings, 1 reply; 21+ messages in thread
From: Yong Zhang @ 2010-05-05  1:31 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: John Kacur, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins, David S. Miller, Yong Zhang

On Tue, May 04, 2010 at 02:56:51PM +0200, Peter Zijlstra wrote:
> Right, this looks like it ought to do as intended.
> 
> I added the below snipped because I know I'll fail to remember and that
> 'static' qualifier is fairly easy to miss.

OK. Thanks for your comments.

BTW, do you need me resend the patch with your comments in?

Thanks,
Yong

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH V2] lockdep: reduce stack_trace usage
  2010-05-05  1:31               ` Yong Zhang
@ 2010-05-05  9:09                 ` Peter Zijlstra
  2010-05-05  9:18                   ` Yong Zhang
  0 siblings, 1 reply; 21+ messages in thread
From: Peter Zijlstra @ 2010-05-05  9:09 UTC (permalink / raw)
  To: Yong Zhang
  Cc: John Kacur, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins, David S. Miller, Yong Zhang

On Wed, 2010-05-05 at 09:31 +0800, Yong Zhang wrote:
> On Tue, May 04, 2010 at 02:56:51PM +0200, Peter Zijlstra wrote:
> > Right, this looks like it ought to do as intended.
> > 
> > I added the below snipped because I know I'll fail to remember and that
> > 'static' qualifier is fairly easy to miss.
> 
> OK. Thanks for your comments.
> 
> BTW, do you need me resend the patch with your comments in?

No, I've got it.


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH V2] lockdep: reduce stack_trace usage
  2010-05-05  9:09                 ` Peter Zijlstra
@ 2010-05-05  9:18                   ` Yong Zhang
  0 siblings, 0 replies; 21+ messages in thread
From: Yong Zhang @ 2010-05-05  9:18 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: John Kacur, LKML, linux-rt-users, Sven-Thorsten Dietrich,
	Clark Williams, Luis Claudio R. Goncalves, Ingo Molnar,
	Thomas Gleixner, Gregory Haskins, David S. Miller, Yong Zhang

On Wed, May 05, 2010 at 11:09:26AM +0200, Peter Zijlstra wrote:
> > BTW, do you need me resend the patch with your comments in?
> 
> No, I've got it.

That's great. Thank you. :)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [tip:core/locking] lockdep: Reduce stack_trace usage
  2010-05-04  6:57           ` [PATCH V2] " Yong Zhang
  2010-05-04 12:56             ` Peter Zijlstra
@ 2010-05-07 18:40             ` tip-bot for Yong Zhang
  1 sibling, 0 replies; 21+ messages in thread
From: tip-bot for Yong Zhang @ 2010-05-07 18:40 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, hpa, mingo, a.p.zijlstra, davem, yong.zhang, tglx,
	yong.zhang0, mingo

Commit-ID:  4726f2a617ebd868a4fdeb5679613b897e5f1676
Gitweb:     http://git.kernel.org/tip/4726f2a617ebd868a4fdeb5679613b897e5f1676
Author:     Yong Zhang <yong.zhang@windriver.com>
AuthorDate: Tue, 4 May 2010 14:16:48 +0800
Committer:  Ingo Molnar <mingo@elte.hu>
CommitDate: Fri, 7 May 2010 11:27:26 +0200

lockdep: Reduce stack_trace usage

When calling check_prevs_add(), if all validations passed
add_lock_to_list() will add new lock to dependency tree and
alloc stack_trace for each list_entry.

But at this time, we are always on the same stack, so stack_trace
for each list_entry has the same value. This is redundant and eats
up lots of memory which could lead to warning on low
MAX_STACK_TRACE_ENTRIES.

Use one copy of stack_trace instead.

V2: As suggested by Peter Zijlstra, move save_trace() from
    check_prevs_add() to check_prev_add().
    Add tracking for trylock dependence which is also redundant.

Signed-off-by: Yong Zhang <yong.zhang0@windriver.com>
Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <20100504065711.GC10784@windriver.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 kernel/lockdep.c |   29 +++++++++++++++++++++--------
 1 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 9cf7985..5108080 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -805,7 +805,8 @@ static struct lock_list *alloc_list_entry(void)
  * Add a new dependency to the head of the list:
  */
 static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
-			    struct list_head *head, unsigned long ip, int distance)
+			    struct list_head *head, unsigned long ip,
+			    int distance, struct stack_trace *trace)
 {
 	struct lock_list *entry;
 	/*
@@ -816,11 +817,9 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
 	if (!entry)
 		return 0;
 
-	if (!save_trace(&entry->trace))
-		return 0;
-
 	entry->class = this;
 	entry->distance = distance;
+	entry->trace = *trace;
 	/*
 	 * Since we never remove from the dependency list, the list can
 	 * be walked lockless by other CPUs, it's only allocation
@@ -1622,12 +1621,20 @@ check_deadlock(struct task_struct *curr, struct held_lock *next,
  */
 static int
 check_prev_add(struct task_struct *curr, struct held_lock *prev,
-	       struct held_lock *next, int distance)
+	       struct held_lock *next, int distance, int trylock_loop)
 {
 	struct lock_list *entry;
 	int ret;
 	struct lock_list this;
 	struct lock_list *uninitialized_var(target_entry);
+	/*
+	 * Static variable, serialized by the graph_lock().
+	 *
+	 * We use this static variable to save the stack trace in case
+	 * we call into this function multiple times due to encountering
+	 * trylocks in the held lock stack.
+	 */
+	static struct stack_trace trace;
 
 	/*
 	 * Prove that the new <prev> -> <next> dependency would not
@@ -1675,20 +1682,23 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
 		}
 	}
 
+	if (!trylock_loop && !save_trace(&trace))
+		return 0;
+
 	/*
 	 * Ok, all validations passed, add the new lock
 	 * to the previous lock's dependency list:
 	 */
 	ret = add_lock_to_list(hlock_class(prev), hlock_class(next),
 			       &hlock_class(prev)->locks_after,
-			       next->acquire_ip, distance);
+			       next->acquire_ip, distance, &trace);
 
 	if (!ret)
 		return 0;
 
 	ret = add_lock_to_list(hlock_class(next), hlock_class(prev),
 			       &hlock_class(next)->locks_before,
-			       next->acquire_ip, distance);
+			       next->acquire_ip, distance, &trace);
 	if (!ret)
 		return 0;
 
@@ -1718,6 +1728,7 @@ static int
 check_prevs_add(struct task_struct *curr, struct held_lock *next)
 {
 	int depth = curr->lockdep_depth;
+	int trylock_loop = 0;
 	struct held_lock *hlock;
 
 	/*
@@ -1743,7 +1754,8 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
 		 * added:
 		 */
 		if (hlock->read != 2) {
-			if (!check_prev_add(curr, hlock, next, distance))
+			if (!check_prev_add(curr, hlock, next,
+						distance, trylock_loop))
 				return 0;
 			/*
 			 * Stop after the first non-trylock entry,
@@ -1766,6 +1778,7 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
 		if (curr->held_locks[depth].irq_context !=
 				curr->held_locks[depth-1].irq_context)
 			break;
+		trylock_loop = 1;
 	}
 	return 1;
 out_bug:

^ permalink raw reply related	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2010-05-07 18:41 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-22 20:15 [PATCH] lockdep: Add nr_save_trace_invocations counter John Kacur
2010-04-23  2:58 ` Yong Zhang
2010-04-23  6:52   ` Peter Zijlstra
2010-04-23  8:03     ` Yong Zhang
2010-04-23  7:24   ` John Kacur
2010-04-23  8:00     ` Yong Zhang
2010-04-23  8:05     ` Peter Zijlstra
2010-04-23  8:31       ` John Kacur
2010-04-23  8:31         ` John Kacur
2010-04-23  8:49         ` Yong Zhang
2010-04-23  9:40           ` John Kacur
2010-04-23 13:40         ` [PATCH] lockdep: reduce stack_trace usage Yong Zhang
2010-04-26  6:24           ` Yong Zhang
2010-05-03 12:11           ` Peter Zijlstra
2010-05-04  6:37             ` Yong Zhang
2010-05-04  6:57           ` [PATCH V2] " Yong Zhang
2010-05-04 12:56             ` Peter Zijlstra
2010-05-05  1:31               ` Yong Zhang
2010-05-05  9:09                 ` Peter Zijlstra
2010-05-05  9:18                   ` Yong Zhang
2010-05-07 18:40             ` [tip:core/locking] lockdep: Reduce " tip-bot for Yong Zhang

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.