1 commit 443cd507ce7f78c6f8742b72736585c031d5a921
2 Author: Huang, Ying <ying.huang@intel.com>
3 Date: Fri Jun 20 16:39:21 2008 +0800
5 lockdep: add lock_class information to lock_chain and output it
7 This patch records array of lock_class into lock_chain, and export
8 lock_chain information via /proc/lockdep_chains.
10 It is based on x86/master branch of git-x86 tree, and has been tested
13 Signed-off-by: Huang Ying <ying.huang@intel.com>
14 Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
15 Signed-off-by: Ingo Molnar <mingo@elte.hu>
17 diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
18 index 4c4d236..b26fbc7 100644
19 --- a/include/linux/lockdep.h
20 +++ b/include/linux/lockdep.h
21 @@ -182,6 +182,9 @@ struct lock_list {
22 * We record lock dependency chains, so that we can cache them:
28 struct list_head entry;
31 diff --git a/kernel/lockdep.c b/kernel/lockdep.c
32 index 81a4e4a..a796f1f 100644
33 --- a/kernel/lockdep.c
34 +++ b/kernel/lockdep.c
35 @@ -1458,7 +1458,14 @@ out_bug:
38 unsigned long nr_lock_chains;
39 -static struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS];
40 +struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS];
41 +atomic_t nr_chain_hlocks;
42 +static u16 chain_hlocks[MAX_LOCKDEP_CHAIN_HLOCKS];
44 +struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i)
46 + return lock_classes + chain_hlocks[chain->base + i];
50 * Look up a dependency chain. If the key is not present yet then
51 @@ -1466,9 +1473,14 @@ static struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS];
52 * validated. If the key is already hashed, return 0.
54 -static inline int lookup_chain_cache(u64 chain_key)
55 +static inline int lookup_chain_cache(struct task_struct *curr,
56 + struct held_lock *hlock,
59 + struct lock_class *class = hlock->class;
60 struct list_head *hash_head = chainhashentry(chain_key);
61 struct lock_chain *chain;
62 + struct held_lock *hlock_curr, *hlock_next;
65 if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
67 @@ -1517,6 +1529,26 @@ cache_hit:
69 chain = lock_chains + nr_lock_chains++;
70 chain->chain_key = chain_key;
71 + chain->irq_context = hlock->irq_context;
72 + /* Find the first held_lock of current chain */
74 + for (i = curr->lockdep_depth - 1; i >= 0; i--) {
75 + hlock_curr = curr->held_locks + i;
76 + if (hlock_curr->irq_context != hlock_next->irq_context)
81 + chain->depth = curr->lockdep_depth + 1 - i;
82 + n = atomic_add_return(chain->depth, &nr_chain_hlocks);
83 + if (unlikely(n < MAX_LOCKDEP_CHAIN_HLOCKS)) {
84 + chain->base = n - chain->depth;
85 + for (j = 0; j < chain->depth - 1; j++, i++) {
86 + int lock_id = curr->held_locks[i].class - lock_classes;
87 + chain_hlocks[chain->base + j] = lock_id;
89 + chain_hlocks[chain->base + j] = class - lock_classes;
91 list_add_tail_rcu(&chain->entry, hash_head);
92 debug_atomic_inc(&chain_lookup_misses);
94 @@ -1538,7 +1570,7 @@ static int validate_chain(struct task_struct *curr, struct lockdep_map *lock,
95 * (If lookup_chain_cache() returns with 1 it acquires
98 - if (!trylock && (check == 2) && lookup_chain_cache(chain_key)) {
99 + if (!trylock && (check == 2) && lookup_chain_cache(curr, hlock, chain_key)) {
101 * Check whether last held lock:
103 diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h
104 index 8ce09bc..db09b17 100644
105 --- a/kernel/lockdep_internals.h
106 +++ b/kernel/lockdep_internals.h
108 #define MAX_LOCKDEP_CHAINS_BITS 14
109 #define MAX_LOCKDEP_CHAINS (1UL << MAX_LOCKDEP_CHAINS_BITS)
111 +#define MAX_LOCKDEP_CHAIN_HLOCKS (MAX_LOCKDEP_CHAINS*5)
114 * Stack-trace: tightly packed array of stack backtrace
115 * addresses. Protected by the hash_lock.
117 #define MAX_STACK_TRACE_ENTRIES 262144UL
119 extern struct list_head all_lock_classes;
120 +extern struct lock_chain lock_chains[];
123 get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4);
125 extern const char * __get_key_name(struct lockdep_subclass_key *key, char *str);
127 +struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i);
129 extern unsigned long nr_lock_classes;
130 extern unsigned long nr_list_entries;
131 extern unsigned long nr_lock_chains;
132 +extern atomic_t nr_chain_hlocks;
133 extern unsigned long nr_stack_trace_entries;
135 extern unsigned int nr_hardirq_chains;
136 diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c
137 index 688c5f1..14d052c 100644
138 --- a/kernel/lockdep_proc.c
139 +++ b/kernel/lockdep_proc.c
140 @@ -178,6 +178,110 @@ static const struct file_operations proc_lockdep_operations = {
141 .release = seq_release,
144 +static void print_name(struct seq_file *m, struct lock_class *class)
147 + const char *name = class->name;
150 + name = __get_key_name(class->key, str);
151 + seq_printf(m, "%s", name);
153 + seq_printf(m, "%s", name);
154 + if (class->name_version > 1)
155 + seq_printf(m, "#%d", class->name_version);
156 + if (class->subclass)
157 + seq_printf(m, "/%d", class->subclass);
161 +static void *lc_next(struct seq_file *m, void *v, loff_t *pos)
163 + struct lock_chain *chain;
167 + if (v == SEQ_START_TOKEN)
168 + chain = m->private;
172 + if (*pos < nr_lock_chains)
173 + chain = lock_chains + *pos;
181 +static void *lc_start(struct seq_file *m, loff_t *pos)
184 + return SEQ_START_TOKEN;
186 + if (*pos < nr_lock_chains)
187 + return lock_chains + *pos;
192 +static void lc_stop(struct seq_file *m, void *v)
196 +static int lc_show(struct seq_file *m, void *v)
198 + struct lock_chain *chain = v;
199 + struct lock_class *class;
202 + if (v == SEQ_START_TOKEN) {
203 + seq_printf(m, "all lock chains:\n");
207 + seq_printf(m, "irq_context: %d\n", chain->irq_context);
209 + for (i = 0; i < chain->depth; i++) {
210 + class = lock_chain_get_class(chain, i);
211 + seq_printf(m, "[%p] ", class->key);
212 + print_name(m, class);
220 +static const struct seq_operations lockdep_chains_ops = {
227 +static int lockdep_chains_open(struct inode *inode, struct file *file)
229 + int res = seq_open(file, &lockdep_chains_ops);
231 + struct seq_file *m = file->private_data;
233 + if (nr_lock_chains)
234 + m->private = lock_chains;
241 +static const struct file_operations proc_lockdep_chains_operations = {
242 + .open = lockdep_chains_open,
244 + .llseek = seq_lseek,
245 + .release = seq_release,
248 static void lockdep_stats_debug_show(struct seq_file *m)
250 #ifdef CONFIG_DEBUG_LOCKDEP
251 @@ -294,5 +381,7 @@ static int lockdep_stats_show(struct seq_file *m, void *v)
253 seq_printf(m, " dependency chains: %11lu [max: %lu]\n",
254 nr_lock_chains, MAX_LOCKDEP_CHAINS);
255 + seq_printf(m, " dependency chain hlocks: %11d [max: %lu]\n",
256 + atomic_read(&nr_chain_hlocks), MAX_LOCKDEP_CHAIN_HLOCKS);
258 #ifdef CONFIG_TRACE_IRQFLAGS
259 @@ -661,6 +750,9 @@ static const struct file_operations proc_lock_stat_operations = {
260 entry = create_proc_entry("lockdep", S_IRUSR, NULL);
262 entry->proc_fops = &proc_lockdep_operations;
263 + entry = create_proc_entry("lockdep_chains", S_IRUSR, NULL);
265 + entry->proc_fops = &proc_lockdep_chains_operations;
267 entry = create_proc_entry("lockdep_stats", S_IRUSR, NULL);