Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] lockdep: add graph depth information to /proc/lockdep

Generate locking graph information into /proc/lockdep, for lock hierarchy
documentation and visualization purposes.

sample output:

c089fd5c OPS: 138 FD: 14 BD: 1 --..: &tty->termios_mutex
-> [c07a3430] tty_ldisc_lock
-> [c07a37f0] &port_lock_key
-> [c07afdc0] &rq->rq_lock_key#2

The lock classes listed are all the first-hop lock dependencies that
lockdep has seen so far.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Jason Baron and committed by
Linus Torvalds
068135e6 381a2292

+42 -19
+1
include/linux/lockdep.h
··· 132 132 struct list_head entry; 133 133 struct lock_class *class; 134 134 struct stack_trace trace; 135 + int distance; 135 136 }; 136 137 137 138 /*
+12 -7
kernel/lockdep.c
··· 490 490 * Add a new dependency to the head of the list: 491 491 */ 492 492 static int add_lock_to_list(struct lock_class *class, struct lock_class *this, 493 - struct list_head *head, unsigned long ip) 493 + struct list_head *head, unsigned long ip, int distance) 494 494 { 495 495 struct lock_list *entry; 496 496 /* ··· 502 502 return 0; 503 503 504 504 entry->class = this; 505 + entry->distance = distance; 505 506 if (!save_trace(&entry->trace)) 506 507 return 0; 507 508 ··· 907 906 */ 908 907 static int 909 908 check_prev_add(struct task_struct *curr, struct held_lock *prev, 910 - struct held_lock *next) 909 + struct held_lock *next, int distance) 911 910 { 912 911 struct lock_list *entry; 913 912 int ret; ··· 985 984 * L2 added to its dependency list, due to the first chain.) 986 985 */ 987 986 list_for_each_entry(entry, &prev->class->locks_after, entry) { 988 - if (entry->class == next->class) 987 + if (entry->class == next->class) { 988 + if (distance == 1) 989 + entry->distance = 1; 989 990 return 2; 991 + } 990 992 } 991 993 992 994 /* ··· 997 993 * to the previous lock's dependency list: 998 994 */ 999 995 ret = add_lock_to_list(prev->class, next->class, 1000 - &prev->class->locks_after, next->acquire_ip); 996 + &prev->class->locks_after, next->acquire_ip, distance); 997 + 1001 998 if (!ret) 1002 999 return 0; 1003 1000 1004 1001 ret = add_lock_to_list(next->class, prev->class, 1005 - &next->class->locks_before, next->acquire_ip); 1002 + &next->class->locks_before, next->acquire_ip, distance); 1006 1003 if (!ret) 1007 1004 return 0; 1008 1005 ··· 1051 1046 goto out_bug; 1052 1047 1053 1048 for (;;) { 1049 + int distance = curr->lockdep_depth - depth + 1; 1054 1050 hlock = curr->held_locks + depth-1; 1055 1051 /* 1056 1052 * Only non-recursive-read entries get new dependencies 1057 1053 * added: 1058 1054 */ 1059 1055 if (hlock->read != 2) { 1060 - if (!check_prev_add(curr, hlock, next)) 1056 + if (!check_prev_add(curr, hlock, next, distance)) 1061 1057 return 0; 1062 1058 /* 1063 1059 * Stop after the first non-trylock entry, ··· 2785 2779 } 2786 2780 2787 2781 EXPORT_SYMBOL_GPL(debug_show_held_locks); 2788 -
+29 -12
kernel/lockdep_proc.c
··· 77 77 return ret; 78 78 } 79 79 80 + static void print_name(struct seq_file *m, struct lock_class *class) 81 + { 82 + char str[128]; 83 + const char *name = class->name; 84 + 85 + if (!name) { 86 + name = __get_key_name(class->key, str); 87 + seq_printf(m, "%s", name); 88 + } else{ 89 + seq_printf(m, "%s", name); 90 + if (class->name_version > 1) 91 + seq_printf(m, "#%d", class->name_version); 92 + if (class->subclass) 93 + seq_printf(m, "/%d", class->subclass); 94 + } 95 + } 96 + 80 97 static int l_show(struct seq_file *m, void *v) 81 98 { 82 99 unsigned long nr_forward_deps, nr_backward_deps; 83 100 struct lock_class *class = m->private; 84 - char str[128], c1, c2, c3, c4; 85 - const char *name; 101 + struct lock_list *entry; 102 + char c1, c2, c3, c4; 86 103 87 104 seq_printf(m, "%p", class->key); 88 105 #ifdef CONFIG_DEBUG_LOCKDEP ··· 114 97 get_usage_chars(class, &c1, &c2, &c3, &c4); 115 98 seq_printf(m, " %c%c%c%c", c1, c2, c3, c4); 116 99 117 - name = class->name; 118 - if (!name) { 119 - name = __get_key_name(class->key, str); 120 - seq_printf(m, ": %s", name); 121 - } else{ 122 - seq_printf(m, ": %s", name); 123 - if (class->name_version > 1) 124 - seq_printf(m, "#%d", class->name_version); 125 - if (class->subclass) 126 - seq_printf(m, "/%d", class->subclass); 100 + seq_printf(m, ": "); 101 + print_name(m, class); 102 + seq_puts(m, "\n"); 103 + 104 + list_for_each_entry(entry, &class->locks_after, entry) { 105 + if (entry->distance == 1) { 106 + seq_printf(m, " -> [%p] ", entry->class); 107 + print_name(m, entry->class); 108 + seq_puts(m, "\n"); 109 + } 127 110 } 128 111 seq_puts(m, "\n"); 129 112