aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/lockdep.h11
-rw-r--r--kernel/fork.c2
-rw-r--r--kernel/lockdep.c47
-rw-r--r--kernel/lockdep_internals.h6
-rw-r--r--kernel/lockdep_proc.c97
-rw-r--r--kernel/mutex-debug.c2
-rw-r--r--kernel/mutex.c5
7 files changed, 151 insertions, 19 deletions
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 4c4d236ded18..2486eb4edbf1 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -182,6 +182,9 @@ struct lock_list {
182 * We record lock dependency chains, so that we can cache them: 182 * We record lock dependency chains, so that we can cache them:
183 */ 183 */
184struct lock_chain { 184struct lock_chain {
185 u8 irq_context;
186 u8 depth;
187 u16 base;
185 struct list_head entry; 188 struct list_head entry;
186 u64 chain_key; 189 u64 chain_key;
187}; 190};
@@ -276,14 +279,6 @@ extern void lockdep_init_map(struct lockdep_map *lock, const char *name,
276 (lock)->dep_map.key, sub) 279 (lock)->dep_map.key, sub)
277 280
278/* 281/*
279 * To initialize a lockdep_map statically use this macro.
280 * Note that _name must not be NULL.
281 */
282#define STATIC_LOCKDEP_MAP_INIT(_name, _key) \
283 { .name = (_name), .key = (void *)(_key), }
284
285
286/*
287 * Acquire a lock. 282 * Acquire a lock.
288 * 283 *
289 * Values for "read": 284 * Values for "read":
diff --git a/kernel/fork.c b/kernel/fork.c
index 16fd412c756d..4bd2f516401f 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -910,7 +910,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
910 910
911 rt_mutex_init_task(p); 911 rt_mutex_init_task(p);
912 912
913#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_LOCKDEP) 913#ifdef CONFIG_PROVE_LOCKING
914 DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled); 914 DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
915 DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); 915 DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
916#endif 916#endif
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 65548eff029e..d38a64362973 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -1462,7 +1462,14 @@ out_bug:
1462} 1462}
1463 1463
1464unsigned long nr_lock_chains; 1464unsigned long nr_lock_chains;
1465static struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS]; 1465struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS];
1466int nr_chain_hlocks;
1467static u16 chain_hlocks[MAX_LOCKDEP_CHAIN_HLOCKS];
1468
1469struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i)
1470{
1471 return lock_classes + chain_hlocks[chain->base + i];
1472}
1466 1473
1467/* 1474/*
1468 * Look up a dependency chain. If the key is not present yet then 1475 * Look up a dependency chain. If the key is not present yet then
@@ -1470,10 +1477,15 @@ static struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS];
1470 * validated. If the key is already hashed, return 0. 1477 * validated. If the key is already hashed, return 0.
1471 * (On return with 1 graph_lock is held.) 1478 * (On return with 1 graph_lock is held.)
1472 */ 1479 */
1473static inline int lookup_chain_cache(u64 chain_key, struct lock_class *class) 1480static inline int lookup_chain_cache(struct task_struct *curr,
1481 struct held_lock *hlock,
1482 u64 chain_key)
1474{ 1483{
1484 struct lock_class *class = hlock->class;
1475 struct list_head *hash_head = chainhashentry(chain_key); 1485 struct list_head *hash_head = chainhashentry(chain_key);
1476 struct lock_chain *chain; 1486 struct lock_chain *chain;
1487 struct held_lock *hlock_curr, *hlock_next;
1488 int i, j, n, cn;
1477 1489
1478 if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) 1490 if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
1479 return 0; 1491 return 0;
@@ -1521,6 +1533,32 @@ cache_hit:
1521 } 1533 }
1522 chain = lock_chains + nr_lock_chains++; 1534 chain = lock_chains + nr_lock_chains++;
1523 chain->chain_key = chain_key; 1535 chain->chain_key = chain_key;
1536 chain->irq_context = hlock->irq_context;
1537 /* Find the first held_lock of current chain */
1538 hlock_next = hlock;
1539 for (i = curr->lockdep_depth - 1; i >= 0; i--) {
1540 hlock_curr = curr->held_locks + i;
1541 if (hlock_curr->irq_context != hlock_next->irq_context)
1542 break;
1543 hlock_next = hlock;
1544 }
1545 i++;
1546 chain->depth = curr->lockdep_depth + 1 - i;
1547 cn = nr_chain_hlocks;
1548 while (cn + chain->depth <= MAX_LOCKDEP_CHAIN_HLOCKS) {
1549 n = cmpxchg(&nr_chain_hlocks, cn, cn + chain->depth);
1550 if (n == cn)
1551 break;
1552 cn = n;
1553 }
1554 if (likely(cn + chain->depth <= MAX_LOCKDEP_CHAIN_HLOCKS)) {
1555 chain->base = cn;
1556 for (j = 0; j < chain->depth - 1; j++, i++) {
1557 int lock_id = curr->held_locks[i].class - lock_classes;
1558 chain_hlocks[chain->base + j] = lock_id;
1559 }
1560 chain_hlocks[chain->base + j] = class - lock_classes;
1561 }
1524 list_add_tail_rcu(&chain->entry, hash_head); 1562 list_add_tail_rcu(&chain->entry, hash_head);
1525 debug_atomic_inc(&chain_lookup_misses); 1563 debug_atomic_inc(&chain_lookup_misses);
1526 inc_chains(); 1564 inc_chains();
@@ -1542,7 +1580,7 @@ static int validate_chain(struct task_struct *curr, struct lockdep_map *lock,
1542 * graph_lock for us) 1580 * graph_lock for us)
1543 */ 1581 */
1544 if (!hlock->trylock && (hlock->check == 2) && 1582 if (!hlock->trylock && (hlock->check == 2) &&
1545 lookup_chain_cache(chain_key, hlock->class)) { 1583 lookup_chain_cache(curr, hlock, chain_key)) {
1546 /* 1584 /*
1547 * Check whether last held lock: 1585 * Check whether last held lock:
1548 * 1586 *
@@ -2668,7 +2706,8 @@ __lock_release(struct lockdep_map *lock, int nested, unsigned long ip)
2668 */ 2706 */
2669static void check_flags(unsigned long flags) 2707static void check_flags(unsigned long flags)
2670{ 2708{
2671#if defined(CONFIG_DEBUG_LOCKDEP) && defined(CONFIG_TRACE_IRQFLAGS) 2709#if defined(CONFIG_PROVE_LOCKING) && defined(CONFIG_DEBUG_LOCKDEP) && \
2710 defined(CONFIG_TRACE_IRQFLAGS)
2672 if (!debug_locks) 2711 if (!debug_locks)
2673 return; 2712 return;
2674 2713
diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h
index 8ce09bc4613d..c3600a091a28 100644
--- a/kernel/lockdep_internals.h
+++ b/kernel/lockdep_internals.h
@@ -23,6 +23,8 @@
23#define MAX_LOCKDEP_CHAINS_BITS 14 23#define MAX_LOCKDEP_CHAINS_BITS 14
24#define MAX_LOCKDEP_CHAINS (1UL << MAX_LOCKDEP_CHAINS_BITS) 24#define MAX_LOCKDEP_CHAINS (1UL << MAX_LOCKDEP_CHAINS_BITS)
25 25
26#define MAX_LOCKDEP_CHAIN_HLOCKS (MAX_LOCKDEP_CHAINS*5)
27
26/* 28/*
27 * Stack-trace: tightly packed array of stack backtrace 29 * Stack-trace: tightly packed array of stack backtrace
28 * addresses. Protected by the hash_lock. 30 * addresses. Protected by the hash_lock.
@@ -30,15 +32,19 @@
30#define MAX_STACK_TRACE_ENTRIES 262144UL 32#define MAX_STACK_TRACE_ENTRIES 262144UL
31 33
32extern struct list_head all_lock_classes; 34extern struct list_head all_lock_classes;
35extern struct lock_chain lock_chains[];
33 36
34extern void 37extern void
35get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4); 38get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4);
36 39
37extern const char * __get_key_name(struct lockdep_subclass_key *key, char *str); 40extern const char * __get_key_name(struct lockdep_subclass_key *key, char *str);
38 41
42struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i);
43
39extern unsigned long nr_lock_classes; 44extern unsigned long nr_lock_classes;
40extern unsigned long nr_list_entries; 45extern unsigned long nr_list_entries;
41extern unsigned long nr_lock_chains; 46extern unsigned long nr_lock_chains;
47extern int nr_chain_hlocks;
42extern unsigned long nr_stack_trace_entries; 48extern unsigned long nr_stack_trace_entries;
43 49
44extern unsigned int nr_hardirq_chains; 50extern unsigned int nr_hardirq_chains;
diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c
index dc5d29648d85..9b0e940e2545 100644
--- a/kernel/lockdep_proc.c
+++ b/kernel/lockdep_proc.c
@@ -139,7 +139,7 @@ static int l_show(struct seq_file *m, void *v)
139 139
140 list_for_each_entry(entry, &class->locks_after, entry) { 140 list_for_each_entry(entry, &class->locks_after, entry) {
141 if (entry->distance == 1) { 141 if (entry->distance == 1) {
142 seq_printf(m, " -> [%p] ", entry->class); 142 seq_printf(m, " -> [%p] ", entry->class->key);
143 print_name(m, entry->class); 143 print_name(m, entry->class);
144 seq_puts(m, "\n"); 144 seq_puts(m, "\n");
145 } 145 }
@@ -178,6 +178,95 @@ static const struct file_operations proc_lockdep_operations = {
178 .release = seq_release, 178 .release = seq_release,
179}; 179};
180 180
181#ifdef CONFIG_PROVE_LOCKING
182static void *lc_next(struct seq_file *m, void *v, loff_t *pos)
183{
184 struct lock_chain *chain;
185
186 (*pos)++;
187
188 if (v == SEQ_START_TOKEN)
189 chain = m->private;
190 else {
191 chain = v;
192
193 if (*pos < nr_lock_chains)
194 chain = lock_chains + *pos;
195 else
196 chain = NULL;
197 }
198
199 return chain;
200}
201
202static void *lc_start(struct seq_file *m, loff_t *pos)
203{
204 if (*pos == 0)
205 return SEQ_START_TOKEN;
206
207 if (*pos < nr_lock_chains)
208 return lock_chains + *pos;
209
210 return NULL;
211}
212
213static void lc_stop(struct seq_file *m, void *v)
214{
215}
216
217static int lc_show(struct seq_file *m, void *v)
218{
219 struct lock_chain *chain = v;
220 struct lock_class *class;
221 int i;
222
223 if (v == SEQ_START_TOKEN) {
224 seq_printf(m, "all lock chains:\n");
225 return 0;
226 }
227
228 seq_printf(m, "irq_context: %d\n", chain->irq_context);
229
230 for (i = 0; i < chain->depth; i++) {
231 class = lock_chain_get_class(chain, i);
232 seq_printf(m, "[%p] ", class->key);
233 print_name(m, class);
234 seq_puts(m, "\n");
235 }
236 seq_puts(m, "\n");
237
238 return 0;
239}
240
241static const struct seq_operations lockdep_chains_ops = {
242 .start = lc_start,
243 .next = lc_next,
244 .stop = lc_stop,
245 .show = lc_show,
246};
247
248static int lockdep_chains_open(struct inode *inode, struct file *file)
249{
250 int res = seq_open(file, &lockdep_chains_ops);
251 if (!res) {
252 struct seq_file *m = file->private_data;
253
254 if (nr_lock_chains)
255 m->private = lock_chains;
256 else
257 m->private = NULL;
258 }
259 return res;
260}
261
262static const struct file_operations proc_lockdep_chains_operations = {
263 .open = lockdep_chains_open,
264 .read = seq_read,
265 .llseek = seq_lseek,
266 .release = seq_release,
267};
268#endif /* CONFIG_PROVE_LOCKING */
269
181static void lockdep_stats_debug_show(struct seq_file *m) 270static void lockdep_stats_debug_show(struct seq_file *m)
182{ 271{
183#ifdef CONFIG_DEBUG_LOCKDEP 272#ifdef CONFIG_DEBUG_LOCKDEP
@@ -294,6 +383,8 @@ static int lockdep_stats_show(struct seq_file *m, void *v)
294#ifdef CONFIG_PROVE_LOCKING 383#ifdef CONFIG_PROVE_LOCKING
295 seq_printf(m, " dependency chains: %11lu [max: %lu]\n", 384 seq_printf(m, " dependency chains: %11lu [max: %lu]\n",
296 nr_lock_chains, MAX_LOCKDEP_CHAINS); 385 nr_lock_chains, MAX_LOCKDEP_CHAINS);
386 seq_printf(m, " dependency chain hlocks: %11d [max: %lu]\n",
387 nr_chain_hlocks, MAX_LOCKDEP_CHAIN_HLOCKS);
297#endif 388#endif
298 389
299#ifdef CONFIG_TRACE_IRQFLAGS 390#ifdef CONFIG_TRACE_IRQFLAGS
@@ -661,6 +752,10 @@ static const struct file_operations proc_lock_stat_operations = {
661static int __init lockdep_proc_init(void) 752static int __init lockdep_proc_init(void)
662{ 753{
663 proc_create("lockdep", S_IRUSR, NULL, &proc_lockdep_operations); 754 proc_create("lockdep", S_IRUSR, NULL, &proc_lockdep_operations);
755#ifdef CONFIG_PROVE_LOCKING
756 proc_create("lockdep_chains", S_IRUSR, NULL,
757 &proc_lockdep_chains_operations);
758#endif
664 proc_create("lockdep_stats", S_IRUSR, NULL, 759 proc_create("lockdep_stats", S_IRUSR, NULL,
665 &proc_lockdep_stats_operations); 760 &proc_lockdep_stats_operations);
666 761
diff --git a/kernel/mutex-debug.c b/kernel/mutex-debug.c
index 3aaa06c561de..1d94160eb532 100644
--- a/kernel/mutex-debug.c
+++ b/kernel/mutex-debug.c
@@ -79,8 +79,8 @@ void debug_mutex_unlock(struct mutex *lock)
79 if (unlikely(!debug_locks)) 79 if (unlikely(!debug_locks))
80 return; 80 return;
81 81
82 DEBUG_LOCKS_WARN_ON(lock->owner != current_thread_info());
83 DEBUG_LOCKS_WARN_ON(lock->magic != lock); 82 DEBUG_LOCKS_WARN_ON(lock->magic != lock);
83 DEBUG_LOCKS_WARN_ON(lock->owner != current_thread_info());
84 DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next); 84 DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next);
85 DEBUG_LOCKS_WARN_ON(lock->owner != current_thread_info()); 85 DEBUG_LOCKS_WARN_ON(lock->owner != current_thread_info());
86} 86}
diff --git a/kernel/mutex.c b/kernel/mutex.c
index d046a345d365..bcdc9ac8ef60 100644
--- a/kernel/mutex.c
+++ b/kernel/mutex.c
@@ -165,10 +165,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
165 * got a signal? (This code gets eliminated in the 165 * got a signal? (This code gets eliminated in the
166 * TASK_UNINTERRUPTIBLE case.) 166 * TASK_UNINTERRUPTIBLE case.)
167 */ 167 */
168 if (unlikely((state == TASK_INTERRUPTIBLE && 168 if (unlikely(signal_pending_state(state, task))) {
169 signal_pending(task)) ||
170 (state == TASK_KILLABLE &&
171 fatal_signal_pending(task)))) {
172 mutex_remove_waiter(lock, &waiter, 169 mutex_remove_waiter(lock, &waiter,
173 task_thread_info(task)); 170 task_thread_info(task));
174 mutex_release(&lock->dep_map, 1, ip); 171 mutex_release(&lock->dep_map, 1, ip);