Perhaps this makes things more clear...
----
<edited output - real one is waaaay to big>
$ cat /proc/lock_stat
T class name contentions waittime-min waittime-max waittime-total acquisitions holdtime-min holdtime-max holdtime-total
------------------------------------------------------------------------------------------------------------------------------------------------------------------
X dcache_lock 543 478 23751 427570 166757 217 572426 90179147
dcache_lock 192 [<ffffffff802a5980>] d_instantiate+0x2a/0xad
dcache_lock 215 [<ffffffff8033b7a1>] _atomic_dec_and_lock+0x39/0x58
dcache_lock 2 [<ffffffff802a4703>] d_rehash+0x1b/0x44
dcache_lock 1 [<ffffffff802a5c53>] d_alloc+0x170/0x1d0
W tasklist_lock 9 1322 12870 21729 7543 593 125518 25759730
R tasklist_lock 36 1742 10475 76717 6104 417 56540 9121541
tasklist_lock 42 [<ffffffff80235240>] do_wait+0x7b/0xaa1
tasklist_lock 0 [<ffffffff802406a3>] sys_setpriority+0x4a/0x1ca
tasklist_lock 0 [<ffffffff80231786>] copy_process+0x116b/0x1689
tasklist_lock 0 [<ffffffff802361ac>] do_exit+0x4d2/0x878
X nl_table_wait.lock 0 0 0 0 1133 365 103424 581560
X cpufreq_driver_lock 0 0 0 0 122 438 44040 136777
X net_todo_run_mutex 0 0 0 0 121 636 42205 112073
Signed-off-by: Peter Zijlstra <[email protected]>
---
kernel/lockdep_proc.c | 241 ++++++++++++++++++++++++++------------------------
1 file changed, 129 insertions(+), 112 deletions(-)
Index: linux-2.6/kernel/lockdep_proc.c
===================================================================
--- linux-2.6.orig/kernel/lockdep_proc.c 2007-05-23 12:08:18.000000000 +0200
+++ linux-2.6/kernel/lockdep_proc.c 2007-05-23 15:14:03.000000000 +0200
@@ -15,6 +15,8 @@
#include <linux/seq_file.h>
#include <linux/kallsyms.h>
#include <linux/debug_locks.h>
+#include <linux/vmalloc.h>
+#include <linux/sort.h>
#include <asm/uaccess.h>
#include <asm/div64.h>
@@ -345,49 +347,145 @@ static const struct file_operations proc
};
#ifdef CONFIG_LOCK_STAT
-static int lock_contentions_show(struct seq_file *m, void *v)
-{
- char sym[KSYM_SYMBOL_LEN];
+
+struct lock_stat_data {
struct lock_class *class;
struct lock_class_stats stats;
- int i;
+};
+
+/*
+ * sort on absolute number of contentions
+ */
+int lock_stat_cmp(const void *l, const void *r)
+{
+ const struct lock_stat_data *dl = l, *dr = r;
+ unsigned long nl, nr;
+
+ nl = dl->stats.read_waittime.nr + dl->stats.write_waittime.nr;
+ nr = dr->stats.read_waittime.nr + dr->stats.write_waittime.nr;
+
+ return nr - nl;
+}
+
+static int lock_stat_show(struct seq_file *m, void *v)
+{
+ struct lock_class *class;
+ struct lock_stat_data *stat, *stat_end;
+ struct lock_stat_data *stat_snapshot =
+ vmalloc(sizeof(struct lock_stat_data) * MAX_LOCKDEP_KEYS);
+
+ if (!stat_snapshot) {
+ seq_printf(m, "-ENOMEM\n");
+ return 0;
+ }
+
+ stat_end = stat_snapshot;
list_for_each_entry(class, &all_lock_classes, lock_entry) {
- stats = lock_stats(class);
+ stat_end->class = class;
+ stat_end->stats = lock_stats(class);
+ stat_end++;
+ }
- if (stats.read_contentions || stats.write_contentions) {
- seq_printf(m, "%s: %lu %lu", class->name,
- stats.write_contentions,
- stats.read_contentions);
-
- for (i = 0; i < ARRAY_SIZE(class->contention_point);
- i++) {
- if (class->contention_point[i] == 0)
- break;
- sprint_symbol(sym, class->contention_point[i]);
- seq_printf(m, " %lu [<%p>] %s",
- stats.contention_point[i],
- (void *)class->contention_point[i],
- sym);
- }
- seq_printf(m, "\n");
+ sort(stat_snapshot, stat_end - stat_snapshot,
+ sizeof(struct lock_stat_data),
+ lock_stat_cmp, NULL);
+
+ seq_printf(m, "%1s %40s %14s %14s %14s %14s %14s %14s %14s %14s\n",
+ "T",
+ "class name",
+ "contentions",
+ "waittime-min",
+ "waittime-max",
+ "waittime-total",
+ "acquisitions",
+ "holdtime-min",
+ "holdtime-max",
+ "holdtime-total");
+ seq_printf(m, "-" "-"
+ "----------------------------------------" "-"
+ "--------------" "-"
+ "--------------" "-"
+ "--------------" "-"
+ "--------------" "-"
+ "--------------" "-"
+ "--------------" "-"
+ "--------------" "-"
+ "--------------" "\n");
+
+ for (stat = stat_snapshot; stat != stat_end; stat++) {
+ struct lock_class_stats *stats = &stat->stats;
+ int i;
+
+ class = stat->class;
+
+ if (stats->write_waittime.nr ||
+ stats->write_holdtime.nr)
+ seq_printf(m, "%c %40s %14lu %14llu %14llu %14llu"
+ " %14lu %14llu %14llu %14llu\n",
+ (stats->read_holdtime.nr ? 'W' : 'X'),
+ class->name,
+ stats->write_waittime.nr,
+ stats->write_waittime.min,
+ stats->write_waittime.max,
+ stats->write_waittime.total,
+ stats->write_holdtime.nr,
+ stats->write_holdtime.min,
+ stats->write_holdtime.max,
+ stats->write_holdtime.total);
+
+ if (stats->read_waittime.nr ||
+ stats->read_holdtime.nr)
+ seq_printf(m, "%c %40s %14lu %14llu %14llu %14llu"
+ " %14lu %14llu %14llu %14llu\n",
+ 'R',
+ class->name,
+ stats->read_waittime.nr,
+ stats->read_waittime.min,
+ stats->read_waittime.max,
+ stats->read_waittime.total,
+ stats->read_holdtime.nr,
+ stats->read_holdtime.min,
+ stats->read_holdtime.max,
+ stats->read_holdtime.total);
+
+ for (i = 0; i < ARRAY_SIZE(class->contention_point); i++) {
+ char sym[KSYM_SYMBOL_LEN];
+ char ip[32];
+
+ if (class->contention_point[i] == 0)
+ break;
+
+ if (!i)
+ seq_printf(m, "\n");
+
+ sprint_symbol(sym, class->contention_point[i]);
+ snprintf(ip, sizeof(ip), "[<%p>]",
+ (void *)class->contention_point[i]);
+ seq_printf(m, " %40s %14lu %29s %s\n",
+ class->name,
+ stats->contention_point[i],
+ ip, sym);
}
+ if (i)
+ seq_printf(m, "\n");
}
+ vfree(stat_snapshot);
+
return 0;
}
-static int lock_contentions_open(struct inode *inode, struct file *file)
+static int lock_stat_open(struct inode *inode, struct file *file)
{
- return single_open(file, lock_contentions_show, NULL);
+ return single_open(file, lock_stat_show, NULL);
}
-ssize_t lock_contentions_write(struct file *file, const char __user *buf,
+ssize_t lock_stat_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct lock_class *class;
char c;
- int i;
if (count) {
if (get_user(c, buf))
@@ -402,83 +501,9 @@ ssize_t lock_contentions_write(struct fi
return count;
}
-static const struct file_operations proc_lock_contentions_operations = {
- .open = lock_contentions_open,
- .write = lock_contentions_write,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-static void print_time(struct seq_file *m, struct lock_time *lt)
-{
- seq_printf(m, " %lu %llu %llu %llu",
- lt->nr, lt->min, lt->max, lt->total);
-}
-
-static int lock_waittime_show(struct seq_file *m, void *v)
-{
- struct lock_class *class;
- struct lock_class_stats stats;
-
- list_for_each_entry(class, &all_lock_classes, lock_entry) {
- stats = lock_stats(class);
-
- if (stats.read_contentions || stats.write_contentions) {
- seq_printf(m, "%s: %lu %lu", class->name,
- stats.write_contentions,
- stats.read_contentions);
- print_time(m, &stats.write_waittime);
- print_time(m, &stats.read_waittime);
- seq_printf(m, "\n");
- }
- }
-
- return 0;
-}
-
-static int lock_waittime_open(struct inode *inode, struct file *file)
-{
- return single_open(file, lock_waittime_show, NULL);
-}
-
-static const struct file_operations proc_lock_waittime_operations = {
- .open = lock_waittime_open,
- .write = lock_contentions_write,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-static int lock_holdtime_show(struct seq_file *m, void *v)
-{
- struct lock_class *class;
- struct lock_class_stats stats;
-
- list_for_each_entry(class, &all_lock_classes, lock_entry) {
- stats = lock_stats(class);
-
- if (stats.read_contentions || stats.write_contentions) {
- seq_printf(m, "%s: %lu %lu", class->name,
- stats.write_contentions,
- stats.read_contentions);
- print_time(m, &stats.write_holdtime);
- print_time(m, &stats.read_holdtime);
- seq_printf(m, "\n");
- }
- }
-
- return 0;
-}
-
-static int lock_holdtime_open(struct inode *inode, struct file *file)
-{
- return single_open(file, lock_holdtime_show, NULL);
-}
-
-static const struct file_operations proc_lock_holdtime_operations = {
- .open = lock_holdtime_open,
- .write = lock_contentions_write,
+static const struct file_operations proc_lock_stat_operations = {
+ .open = lock_stat_open,
+ .write = lock_stat_write,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
@@ -498,17 +523,9 @@ static int __init lockdep_proc_init(void
entry->proc_fops = &proc_lockdep_stats_operations;
#ifdef CONFIG_LOCK_STAT
- entry = create_proc_entry("lock_contentions", S_IRUSR, NULL);
- if (entry)
- entry->proc_fops = &proc_lock_contentions_operations;
-
- entry = create_proc_entry("lock_waittime", S_IRUSR, NULL);
- if (entry)
- entry->proc_fops = &proc_lock_waittime_operations;
-
- entry = create_proc_entry("lock_holdtime", S_IRUSR, NULL);
+ entry = create_proc_entry("lock_stat", S_IRUSR, NULL);
if (entry)
- entry->proc_fops = &proc_lock_holdtime_operations;
+ entry->proc_fops = &proc_lock_stat_operations;
#endif
return 0;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]