Commit df60a8441866153d691ae69b77934904c2de5e0d
Committed by
Ingo Molnar
1 parent
2df8b1d656
Exists in
master
and in
7 other branches
lockdep: fix build if CONFIG_PROVE_LOCKING not defined
If CONFIG_PROVE_LOCKING not defined, then no dependency information is available. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Showing 1 changed file with 6 additions and 6 deletions Inline Diff
kernel/lockdep_proc.c
1 | /* | 1 | /* |
2 | * kernel/lockdep_proc.c | 2 | * kernel/lockdep_proc.c |
3 | * | 3 | * |
4 | * Runtime locking correctness validator | 4 | * Runtime locking correctness validator |
5 | * | 5 | * |
6 | * Started by Ingo Molnar: | 6 | * Started by Ingo Molnar: |
7 | * | 7 | * |
8 | * Copyright (C) 2006,2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> | 8 | * Copyright (C) 2006,2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> |
9 | * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> | 9 | * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> |
10 | * | 10 | * |
11 | * Code for /proc/lockdep and /proc/lockdep_stats: | 11 | * Code for /proc/lockdep and /proc/lockdep_stats: |
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/proc_fs.h> | 15 | #include <linux/proc_fs.h> |
16 | #include <linux/seq_file.h> | 16 | #include <linux/seq_file.h> |
17 | #include <linux/kallsyms.h> | 17 | #include <linux/kallsyms.h> |
18 | #include <linux/debug_locks.h> | 18 | #include <linux/debug_locks.h> |
19 | #include <linux/vmalloc.h> | 19 | #include <linux/vmalloc.h> |
20 | #include <linux/sort.h> | 20 | #include <linux/sort.h> |
21 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
22 | #include <asm/div64.h> | 22 | #include <asm/div64.h> |
23 | 23 | ||
24 | #include "lockdep_internals.h" | 24 | #include "lockdep_internals.h" |
25 | 25 | ||
26 | static void *l_next(struct seq_file *m, void *v, loff_t *pos) | 26 | static void *l_next(struct seq_file *m, void *v, loff_t *pos) |
27 | { | 27 | { |
28 | struct lock_class *class; | 28 | struct lock_class *class; |
29 | 29 | ||
30 | (*pos)++; | 30 | (*pos)++; |
31 | 31 | ||
32 | if (v == SEQ_START_TOKEN) | 32 | if (v == SEQ_START_TOKEN) |
33 | class = m->private; | 33 | class = m->private; |
34 | else { | 34 | else { |
35 | class = v; | 35 | class = v; |
36 | 36 | ||
37 | if (class->lock_entry.next != &all_lock_classes) | 37 | if (class->lock_entry.next != &all_lock_classes) |
38 | class = list_entry(class->lock_entry.next, | 38 | class = list_entry(class->lock_entry.next, |
39 | struct lock_class, lock_entry); | 39 | struct lock_class, lock_entry); |
40 | else | 40 | else |
41 | class = NULL; | 41 | class = NULL; |
42 | } | 42 | } |
43 | 43 | ||
44 | return class; | 44 | return class; |
45 | } | 45 | } |
46 | 46 | ||
47 | static void *l_start(struct seq_file *m, loff_t *pos) | 47 | static void *l_start(struct seq_file *m, loff_t *pos) |
48 | { | 48 | { |
49 | struct lock_class *class; | 49 | struct lock_class *class; |
50 | loff_t i = 0; | 50 | loff_t i = 0; |
51 | 51 | ||
52 | if (*pos == 0) | 52 | if (*pos == 0) |
53 | return SEQ_START_TOKEN; | 53 | return SEQ_START_TOKEN; |
54 | 54 | ||
55 | list_for_each_entry(class, &all_lock_classes, lock_entry) { | 55 | list_for_each_entry(class, &all_lock_classes, lock_entry) { |
56 | if (++i == *pos) | 56 | if (++i == *pos) |
57 | return class; | 57 | return class; |
58 | } | 58 | } |
59 | return NULL; | 59 | return NULL; |
60 | } | 60 | } |
61 | 61 | ||
62 | static void l_stop(struct seq_file *m, void *v) | 62 | static void l_stop(struct seq_file *m, void *v) |
63 | { | 63 | { |
64 | } | 64 | } |
65 | 65 | ||
66 | static void print_name(struct seq_file *m, struct lock_class *class) | 66 | static void print_name(struct seq_file *m, struct lock_class *class) |
67 | { | 67 | { |
68 | char str[128]; | 68 | char str[128]; |
69 | const char *name = class->name; | 69 | const char *name = class->name; |
70 | 70 | ||
71 | if (!name) { | 71 | if (!name) { |
72 | name = __get_key_name(class->key, str); | 72 | name = __get_key_name(class->key, str); |
73 | seq_printf(m, "%s", name); | 73 | seq_printf(m, "%s", name); |
74 | } else{ | 74 | } else{ |
75 | seq_printf(m, "%s", name); | 75 | seq_printf(m, "%s", name); |
76 | if (class->name_version > 1) | 76 | if (class->name_version > 1) |
77 | seq_printf(m, "#%d", class->name_version); | 77 | seq_printf(m, "#%d", class->name_version); |
78 | if (class->subclass) | 78 | if (class->subclass) |
79 | seq_printf(m, "/%d", class->subclass); | 79 | seq_printf(m, "/%d", class->subclass); |
80 | } | 80 | } |
81 | } | 81 | } |
82 | 82 | ||
83 | static int l_show(struct seq_file *m, void *v) | 83 | static int l_show(struct seq_file *m, void *v) |
84 | { | 84 | { |
85 | unsigned long nr_forward_deps, nr_backward_deps; | ||
86 | struct lock_class *class = v; | 85 | struct lock_class *class = v; |
87 | struct lock_list *entry; | 86 | struct lock_list *entry; |
88 | char c1, c2, c3, c4; | 87 | char c1, c2, c3, c4; |
89 | 88 | ||
90 | if (v == SEQ_START_TOKEN) { | 89 | if (v == SEQ_START_TOKEN) { |
91 | seq_printf(m, "all lock classes:\n"); | 90 | seq_printf(m, "all lock classes:\n"); |
92 | return 0; | 91 | return 0; |
93 | } | 92 | } |
94 | 93 | ||
95 | seq_printf(m, "%p", class->key); | 94 | seq_printf(m, "%p", class->key); |
96 | #ifdef CONFIG_DEBUG_LOCKDEP | 95 | #ifdef CONFIG_DEBUG_LOCKDEP |
97 | seq_printf(m, " OPS:%8ld", class->ops); | 96 | seq_printf(m, " OPS:%8ld", class->ops); |
98 | #endif | 97 | #endif |
99 | nr_forward_deps = lockdep_count_forward_deps(class); | 98 | #ifdef CONFIG_PROVE_LOCKING |
100 | seq_printf(m, " FD:%5ld", nr_forward_deps); | 99 | seq_printf(m, " FD:%5ld", lockdep_count_forward_deps(class)); |
100 | seq_printf(m, " BD:%5ld", lockdep_count_backward_deps(class)); | ||
101 | #endif | ||
101 | 102 | ||
102 | nr_backward_deps = lockdep_count_backward_deps(class); | ||
103 | seq_printf(m, " BD:%5ld", nr_backward_deps); | ||
104 | |||
105 | get_usage_chars(class, &c1, &c2, &c3, &c4); | 103 | get_usage_chars(class, &c1, &c2, &c3, &c4); |
106 | seq_printf(m, " %c%c%c%c", c1, c2, c3, c4); | 104 | seq_printf(m, " %c%c%c%c", c1, c2, c3, c4); |
107 | 105 | ||
108 | seq_printf(m, ": "); | 106 | seq_printf(m, ": "); |
109 | print_name(m, class); | 107 | print_name(m, class); |
110 | seq_puts(m, "\n"); | 108 | seq_puts(m, "\n"); |
111 | 109 | ||
112 | list_for_each_entry(entry, &class->locks_after, entry) { | 110 | list_for_each_entry(entry, &class->locks_after, entry) { |
113 | if (entry->distance == 1) { | 111 | if (entry->distance == 1) { |
114 | seq_printf(m, " -> [%p] ", entry->class->key); | 112 | seq_printf(m, " -> [%p] ", entry->class->key); |
115 | print_name(m, entry->class); | 113 | print_name(m, entry->class); |
116 | seq_puts(m, "\n"); | 114 | seq_puts(m, "\n"); |
117 | } | 115 | } |
118 | } | 116 | } |
119 | seq_puts(m, "\n"); | 117 | seq_puts(m, "\n"); |
120 | 118 | ||
121 | return 0; | 119 | return 0; |
122 | } | 120 | } |
123 | 121 | ||
124 | static const struct seq_operations lockdep_ops = { | 122 | static const struct seq_operations lockdep_ops = { |
125 | .start = l_start, | 123 | .start = l_start, |
126 | .next = l_next, | 124 | .next = l_next, |
127 | .stop = l_stop, | 125 | .stop = l_stop, |
128 | .show = l_show, | 126 | .show = l_show, |
129 | }; | 127 | }; |
130 | 128 | ||
131 | static int lockdep_open(struct inode *inode, struct file *file) | 129 | static int lockdep_open(struct inode *inode, struct file *file) |
132 | { | 130 | { |
133 | int res = seq_open(file, &lockdep_ops); | 131 | int res = seq_open(file, &lockdep_ops); |
134 | if (!res) { | 132 | if (!res) { |
135 | struct seq_file *m = file->private_data; | 133 | struct seq_file *m = file->private_data; |
136 | 134 | ||
137 | if (!list_empty(&all_lock_classes)) | 135 | if (!list_empty(&all_lock_classes)) |
138 | m->private = list_entry(all_lock_classes.next, | 136 | m->private = list_entry(all_lock_classes.next, |
139 | struct lock_class, lock_entry); | 137 | struct lock_class, lock_entry); |
140 | else | 138 | else |
141 | m->private = NULL; | 139 | m->private = NULL; |
142 | } | 140 | } |
143 | return res; | 141 | return res; |
144 | } | 142 | } |
145 | 143 | ||
146 | static const struct file_operations proc_lockdep_operations = { | 144 | static const struct file_operations proc_lockdep_operations = { |
147 | .open = lockdep_open, | 145 | .open = lockdep_open, |
148 | .read = seq_read, | 146 | .read = seq_read, |
149 | .llseek = seq_lseek, | 147 | .llseek = seq_lseek, |
150 | .release = seq_release, | 148 | .release = seq_release, |
151 | }; | 149 | }; |
152 | 150 | ||
153 | #ifdef CONFIG_PROVE_LOCKING | 151 | #ifdef CONFIG_PROVE_LOCKING |
154 | static void *lc_next(struct seq_file *m, void *v, loff_t *pos) | 152 | static void *lc_next(struct seq_file *m, void *v, loff_t *pos) |
155 | { | 153 | { |
156 | struct lock_chain *chain; | 154 | struct lock_chain *chain; |
157 | 155 | ||
158 | (*pos)++; | 156 | (*pos)++; |
159 | 157 | ||
160 | if (v == SEQ_START_TOKEN) | 158 | if (v == SEQ_START_TOKEN) |
161 | chain = m->private; | 159 | chain = m->private; |
162 | else { | 160 | else { |
163 | chain = v; | 161 | chain = v; |
164 | 162 | ||
165 | if (*pos < nr_lock_chains) | 163 | if (*pos < nr_lock_chains) |
166 | chain = lock_chains + *pos; | 164 | chain = lock_chains + *pos; |
167 | else | 165 | else |
168 | chain = NULL; | 166 | chain = NULL; |
169 | } | 167 | } |
170 | 168 | ||
171 | return chain; | 169 | return chain; |
172 | } | 170 | } |
173 | 171 | ||
174 | static void *lc_start(struct seq_file *m, loff_t *pos) | 172 | static void *lc_start(struct seq_file *m, loff_t *pos) |
175 | { | 173 | { |
176 | if (*pos == 0) | 174 | if (*pos == 0) |
177 | return SEQ_START_TOKEN; | 175 | return SEQ_START_TOKEN; |
178 | 176 | ||
179 | if (*pos < nr_lock_chains) | 177 | if (*pos < nr_lock_chains) |
180 | return lock_chains + *pos; | 178 | return lock_chains + *pos; |
181 | 179 | ||
182 | return NULL; | 180 | return NULL; |
183 | } | 181 | } |
184 | 182 | ||
185 | static void lc_stop(struct seq_file *m, void *v) | 183 | static void lc_stop(struct seq_file *m, void *v) |
186 | { | 184 | { |
187 | } | 185 | } |
188 | 186 | ||
189 | static int lc_show(struct seq_file *m, void *v) | 187 | static int lc_show(struct seq_file *m, void *v) |
190 | { | 188 | { |
191 | struct lock_chain *chain = v; | 189 | struct lock_chain *chain = v; |
192 | struct lock_class *class; | 190 | struct lock_class *class; |
193 | int i; | 191 | int i; |
194 | 192 | ||
195 | if (v == SEQ_START_TOKEN) { | 193 | if (v == SEQ_START_TOKEN) { |
196 | seq_printf(m, "all lock chains:\n"); | 194 | seq_printf(m, "all lock chains:\n"); |
197 | return 0; | 195 | return 0; |
198 | } | 196 | } |
199 | 197 | ||
200 | seq_printf(m, "irq_context: %d\n", chain->irq_context); | 198 | seq_printf(m, "irq_context: %d\n", chain->irq_context); |
201 | 199 | ||
202 | for (i = 0; i < chain->depth; i++) { | 200 | for (i = 0; i < chain->depth; i++) { |
203 | class = lock_chain_get_class(chain, i); | 201 | class = lock_chain_get_class(chain, i); |
204 | if (!class->key) | 202 | if (!class->key) |
205 | continue; | 203 | continue; |
206 | 204 | ||
207 | seq_printf(m, "[%p] ", class->key); | 205 | seq_printf(m, "[%p] ", class->key); |
208 | print_name(m, class); | 206 | print_name(m, class); |
209 | seq_puts(m, "\n"); | 207 | seq_puts(m, "\n"); |
210 | } | 208 | } |
211 | seq_puts(m, "\n"); | 209 | seq_puts(m, "\n"); |
212 | 210 | ||
213 | return 0; | 211 | return 0; |
214 | } | 212 | } |
215 | 213 | ||
216 | static const struct seq_operations lockdep_chains_ops = { | 214 | static const struct seq_operations lockdep_chains_ops = { |
217 | .start = lc_start, | 215 | .start = lc_start, |
218 | .next = lc_next, | 216 | .next = lc_next, |
219 | .stop = lc_stop, | 217 | .stop = lc_stop, |
220 | .show = lc_show, | 218 | .show = lc_show, |
221 | }; | 219 | }; |
222 | 220 | ||
223 | static int lockdep_chains_open(struct inode *inode, struct file *file) | 221 | static int lockdep_chains_open(struct inode *inode, struct file *file) |
224 | { | 222 | { |
225 | int res = seq_open(file, &lockdep_chains_ops); | 223 | int res = seq_open(file, &lockdep_chains_ops); |
226 | if (!res) { | 224 | if (!res) { |
227 | struct seq_file *m = file->private_data; | 225 | struct seq_file *m = file->private_data; |
228 | 226 | ||
229 | if (nr_lock_chains) | 227 | if (nr_lock_chains) |
230 | m->private = lock_chains; | 228 | m->private = lock_chains; |
231 | else | 229 | else |
232 | m->private = NULL; | 230 | m->private = NULL; |
233 | } | 231 | } |
234 | return res; | 232 | return res; |
235 | } | 233 | } |
236 | 234 | ||
237 | static const struct file_operations proc_lockdep_chains_operations = { | 235 | static const struct file_operations proc_lockdep_chains_operations = { |
238 | .open = lockdep_chains_open, | 236 | .open = lockdep_chains_open, |
239 | .read = seq_read, | 237 | .read = seq_read, |
240 | .llseek = seq_lseek, | 238 | .llseek = seq_lseek, |
241 | .release = seq_release, | 239 | .release = seq_release, |
242 | }; | 240 | }; |
243 | #endif /* CONFIG_PROVE_LOCKING */ | 241 | #endif /* CONFIG_PROVE_LOCKING */ |
244 | 242 | ||
245 | static void lockdep_stats_debug_show(struct seq_file *m) | 243 | static void lockdep_stats_debug_show(struct seq_file *m) |
246 | { | 244 | { |
247 | #ifdef CONFIG_DEBUG_LOCKDEP | 245 | #ifdef CONFIG_DEBUG_LOCKDEP |
248 | unsigned int hi1 = debug_atomic_read(&hardirqs_on_events), | 246 | unsigned int hi1 = debug_atomic_read(&hardirqs_on_events), |
249 | hi2 = debug_atomic_read(&hardirqs_off_events), | 247 | hi2 = debug_atomic_read(&hardirqs_off_events), |
250 | hr1 = debug_atomic_read(&redundant_hardirqs_on), | 248 | hr1 = debug_atomic_read(&redundant_hardirqs_on), |
251 | hr2 = debug_atomic_read(&redundant_hardirqs_off), | 249 | hr2 = debug_atomic_read(&redundant_hardirqs_off), |
252 | si1 = debug_atomic_read(&softirqs_on_events), | 250 | si1 = debug_atomic_read(&softirqs_on_events), |
253 | si2 = debug_atomic_read(&softirqs_off_events), | 251 | si2 = debug_atomic_read(&softirqs_off_events), |
254 | sr1 = debug_atomic_read(&redundant_softirqs_on), | 252 | sr1 = debug_atomic_read(&redundant_softirqs_on), |
255 | sr2 = debug_atomic_read(&redundant_softirqs_off); | 253 | sr2 = debug_atomic_read(&redundant_softirqs_off); |
256 | 254 | ||
257 | seq_printf(m, " chain lookup misses: %11u\n", | 255 | seq_printf(m, " chain lookup misses: %11u\n", |
258 | debug_atomic_read(&chain_lookup_misses)); | 256 | debug_atomic_read(&chain_lookup_misses)); |
259 | seq_printf(m, " chain lookup hits: %11u\n", | 257 | seq_printf(m, " chain lookup hits: %11u\n", |
260 | debug_atomic_read(&chain_lookup_hits)); | 258 | debug_atomic_read(&chain_lookup_hits)); |
261 | seq_printf(m, " cyclic checks: %11u\n", | 259 | seq_printf(m, " cyclic checks: %11u\n", |
262 | debug_atomic_read(&nr_cyclic_checks)); | 260 | debug_atomic_read(&nr_cyclic_checks)); |
263 | seq_printf(m, " cyclic-check recursions: %11u\n", | 261 | seq_printf(m, " cyclic-check recursions: %11u\n", |
264 | debug_atomic_read(&nr_cyclic_check_recursions)); | 262 | debug_atomic_read(&nr_cyclic_check_recursions)); |
265 | seq_printf(m, " find-mask forwards checks: %11u\n", | 263 | seq_printf(m, " find-mask forwards checks: %11u\n", |
266 | debug_atomic_read(&nr_find_usage_forwards_checks)); | 264 | debug_atomic_read(&nr_find_usage_forwards_checks)); |
267 | seq_printf(m, " find-mask forwards recursions: %11u\n", | 265 | seq_printf(m, " find-mask forwards recursions: %11u\n", |
268 | debug_atomic_read(&nr_find_usage_forwards_recursions)); | 266 | debug_atomic_read(&nr_find_usage_forwards_recursions)); |
269 | seq_printf(m, " find-mask backwards checks: %11u\n", | 267 | seq_printf(m, " find-mask backwards checks: %11u\n", |
270 | debug_atomic_read(&nr_find_usage_backwards_checks)); | 268 | debug_atomic_read(&nr_find_usage_backwards_checks)); |
271 | seq_printf(m, " find-mask backwards recursions:%11u\n", | 269 | seq_printf(m, " find-mask backwards recursions:%11u\n", |
272 | debug_atomic_read(&nr_find_usage_backwards_recursions)); | 270 | debug_atomic_read(&nr_find_usage_backwards_recursions)); |
273 | 271 | ||
274 | seq_printf(m, " hardirq on events: %11u\n", hi1); | 272 | seq_printf(m, " hardirq on events: %11u\n", hi1); |
275 | seq_printf(m, " hardirq off events: %11u\n", hi2); | 273 | seq_printf(m, " hardirq off events: %11u\n", hi2); |
276 | seq_printf(m, " redundant hardirq ons: %11u\n", hr1); | 274 | seq_printf(m, " redundant hardirq ons: %11u\n", hr1); |
277 | seq_printf(m, " redundant hardirq offs: %11u\n", hr2); | 275 | seq_printf(m, " redundant hardirq offs: %11u\n", hr2); |
278 | seq_printf(m, " softirq on events: %11u\n", si1); | 276 | seq_printf(m, " softirq on events: %11u\n", si1); |
279 | seq_printf(m, " softirq off events: %11u\n", si2); | 277 | seq_printf(m, " softirq off events: %11u\n", si2); |
280 | seq_printf(m, " redundant softirq ons: %11u\n", sr1); | 278 | seq_printf(m, " redundant softirq ons: %11u\n", sr1); |
281 | seq_printf(m, " redundant softirq offs: %11u\n", sr2); | 279 | seq_printf(m, " redundant softirq offs: %11u\n", sr2); |
282 | #endif | 280 | #endif |
283 | } | 281 | } |
284 | 282 | ||
285 | static int lockdep_stats_show(struct seq_file *m, void *v) | 283 | static int lockdep_stats_show(struct seq_file *m, void *v) |
286 | { | 284 | { |
287 | struct lock_class *class; | 285 | struct lock_class *class; |
288 | unsigned long nr_unused = 0, nr_uncategorized = 0, | 286 | unsigned long nr_unused = 0, nr_uncategorized = 0, |
289 | nr_irq_safe = 0, nr_irq_unsafe = 0, | 287 | nr_irq_safe = 0, nr_irq_unsafe = 0, |
290 | nr_softirq_safe = 0, nr_softirq_unsafe = 0, | 288 | nr_softirq_safe = 0, nr_softirq_unsafe = 0, |
291 | nr_hardirq_safe = 0, nr_hardirq_unsafe = 0, | 289 | nr_hardirq_safe = 0, nr_hardirq_unsafe = 0, |
292 | nr_irq_read_safe = 0, nr_irq_read_unsafe = 0, | 290 | nr_irq_read_safe = 0, nr_irq_read_unsafe = 0, |
293 | nr_softirq_read_safe = 0, nr_softirq_read_unsafe = 0, | 291 | nr_softirq_read_safe = 0, nr_softirq_read_unsafe = 0, |
294 | nr_hardirq_read_safe = 0, nr_hardirq_read_unsafe = 0, | 292 | nr_hardirq_read_safe = 0, nr_hardirq_read_unsafe = 0, |
295 | sum_forward_deps = 0, factor = 0; | 293 | sum_forward_deps = 0, factor = 0; |
296 | 294 | ||
297 | list_for_each_entry(class, &all_lock_classes, lock_entry) { | 295 | list_for_each_entry(class, &all_lock_classes, lock_entry) { |
298 | 296 | ||
299 | if (class->usage_mask == 0) | 297 | if (class->usage_mask == 0) |
300 | nr_unused++; | 298 | nr_unused++; |
301 | if (class->usage_mask == LOCKF_USED) | 299 | if (class->usage_mask == LOCKF_USED) |
302 | nr_uncategorized++; | 300 | nr_uncategorized++; |
303 | if (class->usage_mask & LOCKF_USED_IN_IRQ) | 301 | if (class->usage_mask & LOCKF_USED_IN_IRQ) |
304 | nr_irq_safe++; | 302 | nr_irq_safe++; |
305 | if (class->usage_mask & LOCKF_ENABLED_IRQS) | 303 | if (class->usage_mask & LOCKF_ENABLED_IRQS) |
306 | nr_irq_unsafe++; | 304 | nr_irq_unsafe++; |
307 | if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ) | 305 | if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ) |
308 | nr_softirq_safe++; | 306 | nr_softirq_safe++; |
309 | if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS) | 307 | if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS) |
310 | nr_softirq_unsafe++; | 308 | nr_softirq_unsafe++; |
311 | if (class->usage_mask & LOCKF_USED_IN_HARDIRQ) | 309 | if (class->usage_mask & LOCKF_USED_IN_HARDIRQ) |
312 | nr_hardirq_safe++; | 310 | nr_hardirq_safe++; |
313 | if (class->usage_mask & LOCKF_ENABLED_HARDIRQS) | 311 | if (class->usage_mask & LOCKF_ENABLED_HARDIRQS) |
314 | nr_hardirq_unsafe++; | 312 | nr_hardirq_unsafe++; |
315 | if (class->usage_mask & LOCKF_USED_IN_IRQ_READ) | 313 | if (class->usage_mask & LOCKF_USED_IN_IRQ_READ) |
316 | nr_irq_read_safe++; | 314 | nr_irq_read_safe++; |
317 | if (class->usage_mask & LOCKF_ENABLED_IRQS_READ) | 315 | if (class->usage_mask & LOCKF_ENABLED_IRQS_READ) |
318 | nr_irq_read_unsafe++; | 316 | nr_irq_read_unsafe++; |
319 | if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ_READ) | 317 | if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ_READ) |
320 | nr_softirq_read_safe++; | 318 | nr_softirq_read_safe++; |
321 | if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS_READ) | 319 | if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS_READ) |
322 | nr_softirq_read_unsafe++; | 320 | nr_softirq_read_unsafe++; |
323 | if (class->usage_mask & LOCKF_USED_IN_HARDIRQ_READ) | 321 | if (class->usage_mask & LOCKF_USED_IN_HARDIRQ_READ) |
324 | nr_hardirq_read_safe++; | 322 | nr_hardirq_read_safe++; |
325 | if (class->usage_mask & LOCKF_ENABLED_HARDIRQS_READ) | 323 | if (class->usage_mask & LOCKF_ENABLED_HARDIRQS_READ) |
326 | nr_hardirq_read_unsafe++; | 324 | nr_hardirq_read_unsafe++; |
327 | 325 | ||
326 | #ifdef CONFIG_PROVE_LOCKING | ||
328 | sum_forward_deps += lockdep_count_forward_deps(class); | 327 | sum_forward_deps += lockdep_count_forward_deps(class); |
328 | #endif | ||
329 | } | 329 | } |
330 | #ifdef CONFIG_DEBUG_LOCKDEP | 330 | #ifdef CONFIG_DEBUG_LOCKDEP |
331 | DEBUG_LOCKS_WARN_ON(debug_atomic_read(&nr_unused_locks) != nr_unused); | 331 | DEBUG_LOCKS_WARN_ON(debug_atomic_read(&nr_unused_locks) != nr_unused); |
332 | #endif | 332 | #endif |
333 | seq_printf(m, " lock-classes: %11lu [max: %lu]\n", | 333 | seq_printf(m, " lock-classes: %11lu [max: %lu]\n", |
334 | nr_lock_classes, MAX_LOCKDEP_KEYS); | 334 | nr_lock_classes, MAX_LOCKDEP_KEYS); |
335 | seq_printf(m, " direct dependencies: %11lu [max: %lu]\n", | 335 | seq_printf(m, " direct dependencies: %11lu [max: %lu]\n", |
336 | nr_list_entries, MAX_LOCKDEP_ENTRIES); | 336 | nr_list_entries, MAX_LOCKDEP_ENTRIES); |
337 | seq_printf(m, " indirect dependencies: %11lu\n", | 337 | seq_printf(m, " indirect dependencies: %11lu\n", |
338 | sum_forward_deps); | 338 | sum_forward_deps); |
339 | 339 | ||
340 | /* | 340 | /* |
341 | * Total number of dependencies: | 341 | * Total number of dependencies: |
342 | * | 342 | * |
343 | * All irq-safe locks may nest inside irq-unsafe locks, | 343 | * All irq-safe locks may nest inside irq-unsafe locks, |
344 | * plus all the other known dependencies: | 344 | * plus all the other known dependencies: |
345 | */ | 345 | */ |
346 | seq_printf(m, " all direct dependencies: %11lu\n", | 346 | seq_printf(m, " all direct dependencies: %11lu\n", |
347 | nr_irq_unsafe * nr_irq_safe + | 347 | nr_irq_unsafe * nr_irq_safe + |
348 | nr_hardirq_unsafe * nr_hardirq_safe + | 348 | nr_hardirq_unsafe * nr_hardirq_safe + |
349 | nr_list_entries); | 349 | nr_list_entries); |
350 | 350 | ||
351 | /* | 351 | /* |
352 | * Estimated factor between direct and indirect | 352 | * Estimated factor between direct and indirect |
353 | * dependencies: | 353 | * dependencies: |
354 | */ | 354 | */ |
355 | if (nr_list_entries) | 355 | if (nr_list_entries) |
356 | factor = sum_forward_deps / nr_list_entries; | 356 | factor = sum_forward_deps / nr_list_entries; |
357 | 357 | ||
358 | #ifdef CONFIG_PROVE_LOCKING | 358 | #ifdef CONFIG_PROVE_LOCKING |
359 | seq_printf(m, " dependency chains: %11lu [max: %lu]\n", | 359 | seq_printf(m, " dependency chains: %11lu [max: %lu]\n", |
360 | nr_lock_chains, MAX_LOCKDEP_CHAINS); | 360 | nr_lock_chains, MAX_LOCKDEP_CHAINS); |
361 | seq_printf(m, " dependency chain hlocks: %11d [max: %lu]\n", | 361 | seq_printf(m, " dependency chain hlocks: %11d [max: %lu]\n", |
362 | nr_chain_hlocks, MAX_LOCKDEP_CHAIN_HLOCKS); | 362 | nr_chain_hlocks, MAX_LOCKDEP_CHAIN_HLOCKS); |
363 | #endif | 363 | #endif |
364 | 364 | ||
365 | #ifdef CONFIG_TRACE_IRQFLAGS | 365 | #ifdef CONFIG_TRACE_IRQFLAGS |
366 | seq_printf(m, " in-hardirq chains: %11u\n", | 366 | seq_printf(m, " in-hardirq chains: %11u\n", |
367 | nr_hardirq_chains); | 367 | nr_hardirq_chains); |
368 | seq_printf(m, " in-softirq chains: %11u\n", | 368 | seq_printf(m, " in-softirq chains: %11u\n", |
369 | nr_softirq_chains); | 369 | nr_softirq_chains); |
370 | #endif | 370 | #endif |
371 | seq_printf(m, " in-process chains: %11u\n", | 371 | seq_printf(m, " in-process chains: %11u\n", |
372 | nr_process_chains); | 372 | nr_process_chains); |
373 | seq_printf(m, " stack-trace entries: %11lu [max: %lu]\n", | 373 | seq_printf(m, " stack-trace entries: %11lu [max: %lu]\n", |
374 | nr_stack_trace_entries, MAX_STACK_TRACE_ENTRIES); | 374 | nr_stack_trace_entries, MAX_STACK_TRACE_ENTRIES); |
375 | seq_printf(m, " combined max dependencies: %11u\n", | 375 | seq_printf(m, " combined max dependencies: %11u\n", |
376 | (nr_hardirq_chains + 1) * | 376 | (nr_hardirq_chains + 1) * |
377 | (nr_softirq_chains + 1) * | 377 | (nr_softirq_chains + 1) * |
378 | (nr_process_chains + 1) | 378 | (nr_process_chains + 1) |
379 | ); | 379 | ); |
380 | seq_printf(m, " hardirq-safe locks: %11lu\n", | 380 | seq_printf(m, " hardirq-safe locks: %11lu\n", |
381 | nr_hardirq_safe); | 381 | nr_hardirq_safe); |
382 | seq_printf(m, " hardirq-unsafe locks: %11lu\n", | 382 | seq_printf(m, " hardirq-unsafe locks: %11lu\n", |
383 | nr_hardirq_unsafe); | 383 | nr_hardirq_unsafe); |
384 | seq_printf(m, " softirq-safe locks: %11lu\n", | 384 | seq_printf(m, " softirq-safe locks: %11lu\n", |
385 | nr_softirq_safe); | 385 | nr_softirq_safe); |
386 | seq_printf(m, " softirq-unsafe locks: %11lu\n", | 386 | seq_printf(m, " softirq-unsafe locks: %11lu\n", |
387 | nr_softirq_unsafe); | 387 | nr_softirq_unsafe); |
388 | seq_printf(m, " irq-safe locks: %11lu\n", | 388 | seq_printf(m, " irq-safe locks: %11lu\n", |
389 | nr_irq_safe); | 389 | nr_irq_safe); |
390 | seq_printf(m, " irq-unsafe locks: %11lu\n", | 390 | seq_printf(m, " irq-unsafe locks: %11lu\n", |
391 | nr_irq_unsafe); | 391 | nr_irq_unsafe); |
392 | 392 | ||
393 | seq_printf(m, " hardirq-read-safe locks: %11lu\n", | 393 | seq_printf(m, " hardirq-read-safe locks: %11lu\n", |
394 | nr_hardirq_read_safe); | 394 | nr_hardirq_read_safe); |
395 | seq_printf(m, " hardirq-read-unsafe locks: %11lu\n", | 395 | seq_printf(m, " hardirq-read-unsafe locks: %11lu\n", |
396 | nr_hardirq_read_unsafe); | 396 | nr_hardirq_read_unsafe); |
397 | seq_printf(m, " softirq-read-safe locks: %11lu\n", | 397 | seq_printf(m, " softirq-read-safe locks: %11lu\n", |
398 | nr_softirq_read_safe); | 398 | nr_softirq_read_safe); |
399 | seq_printf(m, " softirq-read-unsafe locks: %11lu\n", | 399 | seq_printf(m, " softirq-read-unsafe locks: %11lu\n", |
400 | nr_softirq_read_unsafe); | 400 | nr_softirq_read_unsafe); |
401 | seq_printf(m, " irq-read-safe locks: %11lu\n", | 401 | seq_printf(m, " irq-read-safe locks: %11lu\n", |
402 | nr_irq_read_safe); | 402 | nr_irq_read_safe); |
403 | seq_printf(m, " irq-read-unsafe locks: %11lu\n", | 403 | seq_printf(m, " irq-read-unsafe locks: %11lu\n", |
404 | nr_irq_read_unsafe); | 404 | nr_irq_read_unsafe); |
405 | 405 | ||
406 | seq_printf(m, " uncategorized locks: %11lu\n", | 406 | seq_printf(m, " uncategorized locks: %11lu\n", |
407 | nr_uncategorized); | 407 | nr_uncategorized); |
408 | seq_printf(m, " unused locks: %11lu\n", | 408 | seq_printf(m, " unused locks: %11lu\n", |
409 | nr_unused); | 409 | nr_unused); |
410 | seq_printf(m, " max locking depth: %11u\n", | 410 | seq_printf(m, " max locking depth: %11u\n", |
411 | max_lockdep_depth); | 411 | max_lockdep_depth); |
412 | seq_printf(m, " max recursion depth: %11u\n", | 412 | seq_printf(m, " max recursion depth: %11u\n", |
413 | max_recursion_depth); | 413 | max_recursion_depth); |
414 | lockdep_stats_debug_show(m); | 414 | lockdep_stats_debug_show(m); |
415 | seq_printf(m, " debug_locks: %11u\n", | 415 | seq_printf(m, " debug_locks: %11u\n", |
416 | debug_locks); | 416 | debug_locks); |
417 | 417 | ||
418 | return 0; | 418 | return 0; |
419 | } | 419 | } |
420 | 420 | ||
421 | static int lockdep_stats_open(struct inode *inode, struct file *file) | 421 | static int lockdep_stats_open(struct inode *inode, struct file *file) |
422 | { | 422 | { |
423 | return single_open(file, lockdep_stats_show, NULL); | 423 | return single_open(file, lockdep_stats_show, NULL); |
424 | } | 424 | } |
425 | 425 | ||
426 | static const struct file_operations proc_lockdep_stats_operations = { | 426 | static const struct file_operations proc_lockdep_stats_operations = { |
427 | .open = lockdep_stats_open, | 427 | .open = lockdep_stats_open, |
428 | .read = seq_read, | 428 | .read = seq_read, |
429 | .llseek = seq_lseek, | 429 | .llseek = seq_lseek, |
430 | .release = single_release, | 430 | .release = single_release, |
431 | }; | 431 | }; |
432 | 432 | ||
433 | #ifdef CONFIG_LOCK_STAT | 433 | #ifdef CONFIG_LOCK_STAT |
434 | 434 | ||
435 | struct lock_stat_data { | 435 | struct lock_stat_data { |
436 | struct lock_class *class; | 436 | struct lock_class *class; |
437 | struct lock_class_stats stats; | 437 | struct lock_class_stats stats; |
438 | }; | 438 | }; |
439 | 439 | ||
440 | struct lock_stat_seq { | 440 | struct lock_stat_seq { |
441 | struct lock_stat_data *iter; | 441 | struct lock_stat_data *iter; |
442 | struct lock_stat_data *iter_end; | 442 | struct lock_stat_data *iter_end; |
443 | struct lock_stat_data stats[MAX_LOCKDEP_KEYS]; | 443 | struct lock_stat_data stats[MAX_LOCKDEP_KEYS]; |
444 | }; | 444 | }; |
445 | 445 | ||
446 | /* | 446 | /* |
447 | * sort on absolute number of contentions | 447 | * sort on absolute number of contentions |
448 | */ | 448 | */ |
449 | static int lock_stat_cmp(const void *l, const void *r) | 449 | static int lock_stat_cmp(const void *l, const void *r) |
450 | { | 450 | { |
451 | const struct lock_stat_data *dl = l, *dr = r; | 451 | const struct lock_stat_data *dl = l, *dr = r; |
452 | unsigned long nl, nr; | 452 | unsigned long nl, nr; |
453 | 453 | ||
454 | nl = dl->stats.read_waittime.nr + dl->stats.write_waittime.nr; | 454 | nl = dl->stats.read_waittime.nr + dl->stats.write_waittime.nr; |
455 | nr = dr->stats.read_waittime.nr + dr->stats.write_waittime.nr; | 455 | nr = dr->stats.read_waittime.nr + dr->stats.write_waittime.nr; |
456 | 456 | ||
457 | return nr - nl; | 457 | return nr - nl; |
458 | } | 458 | } |
459 | 459 | ||
460 | static void seq_line(struct seq_file *m, char c, int offset, int length) | 460 | static void seq_line(struct seq_file *m, char c, int offset, int length) |
461 | { | 461 | { |
462 | int i; | 462 | int i; |
463 | 463 | ||
464 | for (i = 0; i < offset; i++) | 464 | for (i = 0; i < offset; i++) |
465 | seq_puts(m, " "); | 465 | seq_puts(m, " "); |
466 | for (i = 0; i < length; i++) | 466 | for (i = 0; i < length; i++) |
467 | seq_printf(m, "%c", c); | 467 | seq_printf(m, "%c", c); |
468 | seq_puts(m, "\n"); | 468 | seq_puts(m, "\n"); |
469 | } | 469 | } |
470 | 470 | ||
471 | static void snprint_time(char *buf, size_t bufsiz, s64 nr) | 471 | static void snprint_time(char *buf, size_t bufsiz, s64 nr) |
472 | { | 472 | { |
473 | unsigned long rem; | 473 | unsigned long rem; |
474 | 474 | ||
475 | rem = do_div(nr, 1000); /* XXX: do_div_signed */ | 475 | rem = do_div(nr, 1000); /* XXX: do_div_signed */ |
476 | snprintf(buf, bufsiz, "%lld.%02d", (long long)nr, ((int)rem+5)/10); | 476 | snprintf(buf, bufsiz, "%lld.%02d", (long long)nr, ((int)rem+5)/10); |
477 | } | 477 | } |
478 | 478 | ||
479 | static void seq_time(struct seq_file *m, s64 time) | 479 | static void seq_time(struct seq_file *m, s64 time) |
480 | { | 480 | { |
481 | char num[15]; | 481 | char num[15]; |
482 | 482 | ||
483 | snprint_time(num, sizeof(num), time); | 483 | snprint_time(num, sizeof(num), time); |
484 | seq_printf(m, " %14s", num); | 484 | seq_printf(m, " %14s", num); |
485 | } | 485 | } |
486 | 486 | ||
487 | static void seq_lock_time(struct seq_file *m, struct lock_time *lt) | 487 | static void seq_lock_time(struct seq_file *m, struct lock_time *lt) |
488 | { | 488 | { |
489 | seq_printf(m, "%14lu", lt->nr); | 489 | seq_printf(m, "%14lu", lt->nr); |
490 | seq_time(m, lt->min); | 490 | seq_time(m, lt->min); |
491 | seq_time(m, lt->max); | 491 | seq_time(m, lt->max); |
492 | seq_time(m, lt->total); | 492 | seq_time(m, lt->total); |
493 | } | 493 | } |
494 | 494 | ||
495 | static void seq_stats(struct seq_file *m, struct lock_stat_data *data) | 495 | static void seq_stats(struct seq_file *m, struct lock_stat_data *data) |
496 | { | 496 | { |
497 | char name[39]; | 497 | char name[39]; |
498 | struct lock_class *class; | 498 | struct lock_class *class; |
499 | struct lock_class_stats *stats; | 499 | struct lock_class_stats *stats; |
500 | int i, namelen; | 500 | int i, namelen; |
501 | 501 | ||
502 | class = data->class; | 502 | class = data->class; |
503 | stats = &data->stats; | 503 | stats = &data->stats; |
504 | 504 | ||
505 | namelen = 38; | 505 | namelen = 38; |
506 | if (class->name_version > 1) | 506 | if (class->name_version > 1) |
507 | namelen -= 2; /* XXX truncates versions > 9 */ | 507 | namelen -= 2; /* XXX truncates versions > 9 */ |
508 | if (class->subclass) | 508 | if (class->subclass) |
509 | namelen -= 2; | 509 | namelen -= 2; |
510 | 510 | ||
511 | if (!class->name) { | 511 | if (!class->name) { |
512 | char str[KSYM_NAME_LEN]; | 512 | char str[KSYM_NAME_LEN]; |
513 | const char *key_name; | 513 | const char *key_name; |
514 | 514 | ||
515 | key_name = __get_key_name(class->key, str); | 515 | key_name = __get_key_name(class->key, str); |
516 | snprintf(name, namelen, "%s", key_name); | 516 | snprintf(name, namelen, "%s", key_name); |
517 | } else { | 517 | } else { |
518 | snprintf(name, namelen, "%s", class->name); | 518 | snprintf(name, namelen, "%s", class->name); |
519 | } | 519 | } |
520 | namelen = strlen(name); | 520 | namelen = strlen(name); |
521 | if (class->name_version > 1) { | 521 | if (class->name_version > 1) { |
522 | snprintf(name+namelen, 3, "#%d", class->name_version); | 522 | snprintf(name+namelen, 3, "#%d", class->name_version); |
523 | namelen += 2; | 523 | namelen += 2; |
524 | } | 524 | } |
525 | if (class->subclass) { | 525 | if (class->subclass) { |
526 | snprintf(name+namelen, 3, "/%d", class->subclass); | 526 | snprintf(name+namelen, 3, "/%d", class->subclass); |
527 | namelen += 2; | 527 | namelen += 2; |
528 | } | 528 | } |
529 | 529 | ||
530 | if (stats->write_holdtime.nr) { | 530 | if (stats->write_holdtime.nr) { |
531 | if (stats->read_holdtime.nr) | 531 | if (stats->read_holdtime.nr) |
532 | seq_printf(m, "%38s-W:", name); | 532 | seq_printf(m, "%38s-W:", name); |
533 | else | 533 | else |
534 | seq_printf(m, "%40s:", name); | 534 | seq_printf(m, "%40s:", name); |
535 | 535 | ||
536 | seq_printf(m, "%14lu ", stats->bounces[bounce_contended_write]); | 536 | seq_printf(m, "%14lu ", stats->bounces[bounce_contended_write]); |
537 | seq_lock_time(m, &stats->write_waittime); | 537 | seq_lock_time(m, &stats->write_waittime); |
538 | seq_printf(m, " %14lu ", stats->bounces[bounce_acquired_write]); | 538 | seq_printf(m, " %14lu ", stats->bounces[bounce_acquired_write]); |
539 | seq_lock_time(m, &stats->write_holdtime); | 539 | seq_lock_time(m, &stats->write_holdtime); |
540 | seq_puts(m, "\n"); | 540 | seq_puts(m, "\n"); |
541 | } | 541 | } |
542 | 542 | ||
543 | if (stats->read_holdtime.nr) { | 543 | if (stats->read_holdtime.nr) { |
544 | seq_printf(m, "%38s-R:", name); | 544 | seq_printf(m, "%38s-R:", name); |
545 | seq_printf(m, "%14lu ", stats->bounces[bounce_contended_read]); | 545 | seq_printf(m, "%14lu ", stats->bounces[bounce_contended_read]); |
546 | seq_lock_time(m, &stats->read_waittime); | 546 | seq_lock_time(m, &stats->read_waittime); |
547 | seq_printf(m, " %14lu ", stats->bounces[bounce_acquired_read]); | 547 | seq_printf(m, " %14lu ", stats->bounces[bounce_acquired_read]); |
548 | seq_lock_time(m, &stats->read_holdtime); | 548 | seq_lock_time(m, &stats->read_holdtime); |
549 | seq_puts(m, "\n"); | 549 | seq_puts(m, "\n"); |
550 | } | 550 | } |
551 | 551 | ||
552 | if (stats->read_waittime.nr + stats->write_waittime.nr == 0) | 552 | if (stats->read_waittime.nr + stats->write_waittime.nr == 0) |
553 | return; | 553 | return; |
554 | 554 | ||
555 | if (stats->read_holdtime.nr) | 555 | if (stats->read_holdtime.nr) |
556 | namelen += 2; | 556 | namelen += 2; |
557 | 557 | ||
558 | for (i = 0; i < ARRAY_SIZE(class->contention_point); i++) { | 558 | for (i = 0; i < ARRAY_SIZE(class->contention_point); i++) { |
559 | char sym[KSYM_SYMBOL_LEN]; | 559 | char sym[KSYM_SYMBOL_LEN]; |
560 | char ip[32]; | 560 | char ip[32]; |
561 | 561 | ||
562 | if (class->contention_point[i] == 0) | 562 | if (class->contention_point[i] == 0) |
563 | break; | 563 | break; |
564 | 564 | ||
565 | if (!i) | 565 | if (!i) |
566 | seq_line(m, '-', 40-namelen, namelen); | 566 | seq_line(m, '-', 40-namelen, namelen); |
567 | 567 | ||
568 | sprint_symbol(sym, class->contention_point[i]); | 568 | sprint_symbol(sym, class->contention_point[i]); |
569 | snprintf(ip, sizeof(ip), "[<%p>]", | 569 | snprintf(ip, sizeof(ip), "[<%p>]", |
570 | (void *)class->contention_point[i]); | 570 | (void *)class->contention_point[i]); |
571 | seq_printf(m, "%40s %14lu %29s %s\n", name, | 571 | seq_printf(m, "%40s %14lu %29s %s\n", name, |
572 | stats->contention_point[i], | 572 | stats->contention_point[i], |
573 | ip, sym); | 573 | ip, sym); |
574 | } | 574 | } |
575 | if (i) { | 575 | if (i) { |
576 | seq_puts(m, "\n"); | 576 | seq_puts(m, "\n"); |
577 | seq_line(m, '.', 0, 40 + 1 + 10 * (14 + 1)); | 577 | seq_line(m, '.', 0, 40 + 1 + 10 * (14 + 1)); |
578 | seq_puts(m, "\n"); | 578 | seq_puts(m, "\n"); |
579 | } | 579 | } |
580 | } | 580 | } |
581 | 581 | ||
582 | static void seq_header(struct seq_file *m) | 582 | static void seq_header(struct seq_file *m) |
583 | { | 583 | { |
584 | seq_printf(m, "lock_stat version 0.2\n"); | 584 | seq_printf(m, "lock_stat version 0.2\n"); |
585 | seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1)); | 585 | seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1)); |
586 | seq_printf(m, "%40s %14s %14s %14s %14s %14s %14s %14s %14s " | 586 | seq_printf(m, "%40s %14s %14s %14s %14s %14s %14s %14s %14s " |
587 | "%14s %14s\n", | 587 | "%14s %14s\n", |
588 | "class name", | 588 | "class name", |
589 | "con-bounces", | 589 | "con-bounces", |
590 | "contentions", | 590 | "contentions", |
591 | "waittime-min", | 591 | "waittime-min", |
592 | "waittime-max", | 592 | "waittime-max", |
593 | "waittime-total", | 593 | "waittime-total", |
594 | "acq-bounces", | 594 | "acq-bounces", |
595 | "acquisitions", | 595 | "acquisitions", |
596 | "holdtime-min", | 596 | "holdtime-min", |
597 | "holdtime-max", | 597 | "holdtime-max", |
598 | "holdtime-total"); | 598 | "holdtime-total"); |
599 | seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1)); | 599 | seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1)); |
600 | seq_printf(m, "\n"); | 600 | seq_printf(m, "\n"); |
601 | } | 601 | } |
602 | 602 | ||
603 | static void *ls_start(struct seq_file *m, loff_t *pos) | 603 | static void *ls_start(struct seq_file *m, loff_t *pos) |
604 | { | 604 | { |
605 | struct lock_stat_seq *data = m->private; | 605 | struct lock_stat_seq *data = m->private; |
606 | 606 | ||
607 | if (*pos == 0) | 607 | if (*pos == 0) |
608 | return SEQ_START_TOKEN; | 608 | return SEQ_START_TOKEN; |
609 | 609 | ||
610 | data->iter = data->stats + *pos; | 610 | data->iter = data->stats + *pos; |
611 | if (data->iter >= data->iter_end) | 611 | if (data->iter >= data->iter_end) |
612 | data->iter = NULL; | 612 | data->iter = NULL; |
613 | 613 | ||
614 | return data->iter; | 614 | return data->iter; |
615 | } | 615 | } |
616 | 616 | ||
617 | static void *ls_next(struct seq_file *m, void *v, loff_t *pos) | 617 | static void *ls_next(struct seq_file *m, void *v, loff_t *pos) |
618 | { | 618 | { |
619 | struct lock_stat_seq *data = m->private; | 619 | struct lock_stat_seq *data = m->private; |
620 | 620 | ||
621 | (*pos)++; | 621 | (*pos)++; |
622 | 622 | ||
623 | if (v == SEQ_START_TOKEN) | 623 | if (v == SEQ_START_TOKEN) |
624 | data->iter = data->stats; | 624 | data->iter = data->stats; |
625 | else { | 625 | else { |
626 | data->iter = v; | 626 | data->iter = v; |
627 | data->iter++; | 627 | data->iter++; |
628 | } | 628 | } |
629 | 629 | ||
630 | if (data->iter == data->iter_end) | 630 | if (data->iter == data->iter_end) |
631 | data->iter = NULL; | 631 | data->iter = NULL; |
632 | 632 | ||
633 | return data->iter; | 633 | return data->iter; |
634 | } | 634 | } |
635 | 635 | ||
636 | static void ls_stop(struct seq_file *m, void *v) | 636 | static void ls_stop(struct seq_file *m, void *v) |
637 | { | 637 | { |
638 | } | 638 | } |
639 | 639 | ||
640 | static int ls_show(struct seq_file *m, void *v) | 640 | static int ls_show(struct seq_file *m, void *v) |
641 | { | 641 | { |
642 | if (v == SEQ_START_TOKEN) | 642 | if (v == SEQ_START_TOKEN) |
643 | seq_header(m); | 643 | seq_header(m); |
644 | else | 644 | else |
645 | seq_stats(m, v); | 645 | seq_stats(m, v); |
646 | 646 | ||
647 | return 0; | 647 | return 0; |
648 | } | 648 | } |
649 | 649 | ||
650 | static struct seq_operations lockstat_ops = { | 650 | static struct seq_operations lockstat_ops = { |
651 | .start = ls_start, | 651 | .start = ls_start, |
652 | .next = ls_next, | 652 | .next = ls_next, |
653 | .stop = ls_stop, | 653 | .stop = ls_stop, |
654 | .show = ls_show, | 654 | .show = ls_show, |
655 | }; | 655 | }; |
656 | 656 | ||
657 | static int lock_stat_open(struct inode *inode, struct file *file) | 657 | static int lock_stat_open(struct inode *inode, struct file *file) |
658 | { | 658 | { |
659 | int res; | 659 | int res; |
660 | struct lock_class *class; | 660 | struct lock_class *class; |
661 | struct lock_stat_seq *data = vmalloc(sizeof(struct lock_stat_seq)); | 661 | struct lock_stat_seq *data = vmalloc(sizeof(struct lock_stat_seq)); |
662 | 662 | ||
663 | if (!data) | 663 | if (!data) |
664 | return -ENOMEM; | 664 | return -ENOMEM; |
665 | 665 | ||
666 | res = seq_open(file, &lockstat_ops); | 666 | res = seq_open(file, &lockstat_ops); |
667 | if (!res) { | 667 | if (!res) { |
668 | struct lock_stat_data *iter = data->stats; | 668 | struct lock_stat_data *iter = data->stats; |
669 | struct seq_file *m = file->private_data; | 669 | struct seq_file *m = file->private_data; |
670 | 670 | ||
671 | data->iter = iter; | 671 | data->iter = iter; |
672 | list_for_each_entry(class, &all_lock_classes, lock_entry) { | 672 | list_for_each_entry(class, &all_lock_classes, lock_entry) { |
673 | iter->class = class; | 673 | iter->class = class; |
674 | iter->stats = lock_stats(class); | 674 | iter->stats = lock_stats(class); |
675 | iter++; | 675 | iter++; |
676 | } | 676 | } |
677 | data->iter_end = iter; | 677 | data->iter_end = iter; |
678 | 678 | ||
679 | sort(data->stats, data->iter_end - data->iter, | 679 | sort(data->stats, data->iter_end - data->iter, |
680 | sizeof(struct lock_stat_data), | 680 | sizeof(struct lock_stat_data), |
681 | lock_stat_cmp, NULL); | 681 | lock_stat_cmp, NULL); |
682 | 682 | ||
683 | m->private = data; | 683 | m->private = data; |
684 | } else | 684 | } else |
685 | vfree(data); | 685 | vfree(data); |
686 | 686 | ||
687 | return res; | 687 | return res; |
688 | } | 688 | } |
689 | 689 | ||
690 | static ssize_t lock_stat_write(struct file *file, const char __user *buf, | 690 | static ssize_t lock_stat_write(struct file *file, const char __user *buf, |
691 | size_t count, loff_t *ppos) | 691 | size_t count, loff_t *ppos) |
692 | { | 692 | { |
693 | struct lock_class *class; | 693 | struct lock_class *class; |
694 | char c; | 694 | char c; |
695 | 695 | ||
696 | if (count) { | 696 | if (count) { |
697 | if (get_user(c, buf)) | 697 | if (get_user(c, buf)) |
698 | return -EFAULT; | 698 | return -EFAULT; |
699 | 699 | ||
700 | if (c != '0') | 700 | if (c != '0') |
701 | return count; | 701 | return count; |
702 | 702 | ||
703 | list_for_each_entry(class, &all_lock_classes, lock_entry) | 703 | list_for_each_entry(class, &all_lock_classes, lock_entry) |
704 | clear_lock_stats(class); | 704 | clear_lock_stats(class); |
705 | } | 705 | } |
706 | return count; | 706 | return count; |
707 | } | 707 | } |
708 | 708 | ||
709 | static int lock_stat_release(struct inode *inode, struct file *file) | 709 | static int lock_stat_release(struct inode *inode, struct file *file) |
710 | { | 710 | { |
711 | struct seq_file *seq = file->private_data; | 711 | struct seq_file *seq = file->private_data; |
712 | 712 | ||
713 | vfree(seq->private); | 713 | vfree(seq->private); |
714 | seq->private = NULL; | 714 | seq->private = NULL; |
715 | return seq_release(inode, file); | 715 | return seq_release(inode, file); |
716 | } | 716 | } |
717 | 717 | ||
718 | static const struct file_operations proc_lock_stat_operations = { | 718 | static const struct file_operations proc_lock_stat_operations = { |
719 | .open = lock_stat_open, | 719 | .open = lock_stat_open, |
720 | .write = lock_stat_write, | 720 | .write = lock_stat_write, |
721 | .read = seq_read, | 721 | .read = seq_read, |
722 | .llseek = seq_lseek, | 722 | .llseek = seq_lseek, |
723 | .release = lock_stat_release, | 723 | .release = lock_stat_release, |
724 | }; | 724 | }; |
725 | #endif /* CONFIG_LOCK_STAT */ | 725 | #endif /* CONFIG_LOCK_STAT */ |
726 | 726 | ||
727 | static int __init lockdep_proc_init(void) | 727 | static int __init lockdep_proc_init(void) |
728 | { | 728 | { |
729 | proc_create("lockdep", S_IRUSR, NULL, &proc_lockdep_operations); | 729 | proc_create("lockdep", S_IRUSR, NULL, &proc_lockdep_operations); |
730 | #ifdef CONFIG_PROVE_LOCKING | 730 | #ifdef CONFIG_PROVE_LOCKING |
731 | proc_create("lockdep_chains", S_IRUSR, NULL, | 731 | proc_create("lockdep_chains", S_IRUSR, NULL, |
732 | &proc_lockdep_chains_operations); | 732 | &proc_lockdep_chains_operations); |
733 | #endif | 733 | #endif |
734 | proc_create("lockdep_stats", S_IRUSR, NULL, | 734 | proc_create("lockdep_stats", S_IRUSR, NULL, |
735 | &proc_lockdep_stats_operations); | 735 | &proc_lockdep_stats_operations); |
736 | 736 | ||
737 | #ifdef CONFIG_LOCK_STAT | 737 | #ifdef CONFIG_LOCK_STAT |
738 | proc_create("lock_stat", S_IRUSR, NULL, &proc_lock_stat_operations); | 738 | proc_create("lock_stat", S_IRUSR, NULL, &proc_lock_stat_operations); |
739 | #endif | 739 | #endif |
740 | 740 | ||
741 | return 0; | 741 | return 0; |
742 | } | 742 | } |