aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/lockdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/lockdep.c')
-rw-r--r--kernel/lockdep.c38
1 files changed, 35 insertions, 3 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 81a4e4a3f087..a796f1f38ac5 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -1458,7 +1458,14 @@ out_bug:
1458} 1458}
1459 1459
1460unsigned long nr_lock_chains; 1460unsigned long nr_lock_chains;
1461static struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS]; 1461struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS];
1462atomic_t nr_chain_hlocks;
1463static u16 chain_hlocks[MAX_LOCKDEP_CHAIN_HLOCKS];
1464
1465struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i)
1466{
1467 return lock_classes + chain_hlocks[chain->base + i];
1468}
1462 1469
1463/* 1470/*
1464 * Look up a dependency chain. If the key is not present yet then 1471 * Look up a dependency chain. If the key is not present yet then
@@ -1466,10 +1473,15 @@ static struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS];
1466 * validated. If the key is already hashed, return 0. 1473 * validated. If the key is already hashed, return 0.
1467 * (On return with 1 graph_lock is held.) 1474 * (On return with 1 graph_lock is held.)
1468 */ 1475 */
1469static inline int lookup_chain_cache(u64 chain_key, struct lock_class *class) 1476static inline int lookup_chain_cache(struct task_struct *curr,
1477 struct held_lock *hlock,
1478 u64 chain_key)
1470{ 1479{
1480 struct lock_class *class = hlock->class;
1471 struct list_head *hash_head = chainhashentry(chain_key); 1481 struct list_head *hash_head = chainhashentry(chain_key);
1472 struct lock_chain *chain; 1482 struct lock_chain *chain;
1483 struct held_lock *hlock_curr, *hlock_next;
1484 int i, j, n;
1473 1485
1474 if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) 1486 if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
1475 return 0; 1487 return 0;
@@ -1517,6 +1529,26 @@ cache_hit:
1517 } 1529 }
1518 chain = lock_chains + nr_lock_chains++; 1530 chain = lock_chains + nr_lock_chains++;
1519 chain->chain_key = chain_key; 1531 chain->chain_key = chain_key;
1532 chain->irq_context = hlock->irq_context;
1533 /* Find the first held_lock of current chain */
1534 hlock_next = hlock;
1535 for (i = curr->lockdep_depth - 1; i >= 0; i--) {
1536 hlock_curr = curr->held_locks + i;
1537 if (hlock_curr->irq_context != hlock_next->irq_context)
1538 break;
1539 hlock_next = hlock;
1540 }
1541 i++;
1542 chain->depth = curr->lockdep_depth + 1 - i;
1543 n = atomic_add_return(chain->depth, &nr_chain_hlocks);
1544 if (unlikely(n < MAX_LOCKDEP_CHAIN_HLOCKS)) {
1545 chain->base = n - chain->depth;
1546 for (j = 0; j < chain->depth - 1; j++, i++) {
1547 int lock_id = curr->held_locks[i].class - lock_classes;
1548 chain_hlocks[chain->base + j] = lock_id;
1549 }
1550 chain_hlocks[chain->base + j] = class - lock_classes;
1551 }
1520 list_add_tail_rcu(&chain->entry, hash_head); 1552 list_add_tail_rcu(&chain->entry, hash_head);
1521 debug_atomic_inc(&chain_lookup_misses); 1553 debug_atomic_inc(&chain_lookup_misses);
1522 inc_chains(); 1554 inc_chains();
@@ -1538,7 +1570,7 @@ static int validate_chain(struct task_struct *curr, struct lockdep_map *lock,
1538 * graph_lock for us) 1570 * graph_lock for us)
1539 */ 1571 */
1540 if (!hlock->trylock && (hlock->check == 2) && 1572 if (!hlock->trylock && (hlock->check == 2) &&
1541 lookup_chain_cache(chain_key, hlock->class)) { 1573 lookup_chain_cache(curr, hlock, chain_key)) {
1542 /* 1574 /*
1543 * Check whether last held lock: 1575 * Check whether last held lock:
1544 * 1576 *