lockdep: add lock_class information to lock_chain and output it
PATCH 1/1 lockdep: add lock_class information to lock_chain and output it
This patch records array of lock_class into lock_chain, and export lock_chain information via /proc/lockdep_chains.
It is based on x86/master branch of git-x86 tree, and has been tested on x86_64 platform.
ChangeLog:
v2:
- Enclosing proc file system related code into CONFIG_PROVE_LOCKING.
- Fix nr_chain_hlocks update code.
Signed-off-by Huang Ying <[email protected]>
--- include/linux/lockdep.h | 3 + kernel/lockdep.c | 44 +++++++++++++++++++- kernel/lockdep_internals.h | 6 ++ kernel/lockdep_proc.c | 95 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 3 deletions(-)
kernel/lockdep.c +41 -3
@@ -1463,7 +1463,14 @@ out_bug: }unsigned long nr_lock_chains; -static struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS ]; +struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS ]; +int nr_chain_hlocks; +static u16 chain_hlocks[MAX_LOCKDEP_CHAIN_HLOCKS ]; + +struct lock_class *lock_chain_get_class (struct lock_chain *chain,int i) +{ +return lock_classes + chain_hlocks[chain->base + i]; +}/* * Look up a dependency chain. If the key is not present yet then
@@ -1471,10 +1478,15 @@ static struct lock_chain lock_chains[MAX* validated. If the key is already hashed, return 0. * (On return with 1 graph_lock is held.) */ -static inline int lookup_chain_cache (u64 chain_key,struct lock_class *class) +static inline int lookup_chain_cache (struct task_struct *curr, +struct held_lock *hlock, +u64 chain_key) { +struct lock_class *class = hlock->class;struct list_head *hash_head =chainhashentry (chain_key);struct lock_chain *chain; +struct held_lock *hlock_curr, *hlock_next; +int i, j, n, cn;if (DEBUG_LOCKS_WARN_ON (!irqs_disabled ()))return 0 ;
@@ -1522,6 +1534,32 @@ cache_hit: } chain = lock_chains + nr_lock_chains++; chain->chain_key = chain_key; + chain->irq_context = hlock->irq_context; +/* Find the first held_lock of current chain */ + hlock_next = hlock; +for (i = curr->lockdep_depth -1 ; i >=0 ; i--) { + hlock_curr = curr->held_locks + i; +if (hlock_curr->irq_context != hlock_next->irq_context) +break ; + hlock_next = hlock; + } + i++; + chain->depth = curr->lockdep_depth +1 - i; + cn = nr_chain_hlocks; +while (cn + chain->depth <=MAX_LOCKDEP_CHAIN_HLOCKS ) { + n =cmpxchg (&nr_chain_hlocks, cn, cn + chain->depth); +if (n == cn) +break ; + cn = n; + } +if (likely (cn + chain->depth <=MAX_LOCKDEP_CHAIN_HLOCKS )) { + chain->base = cn; +for (j =0 ; j < chain->depth -1 ; j++, i++) { +int lock_id = curr->held_locks[i].class - lock_classes; + chain_hlocks[chain->base + j] = lock_id; + } + chain_hlocks[chain->base + j] = class - lock_classes; + }list_add_tail_rcu (&chain->entry, hash_head);debug_atomic_inc (&chain_lookup_misses);inc_chains ();
@@ -1543,7 +1581,7 @@ static int validate_chain(struct task_st* graph_lock for us) */ if (!hlock->trylock && (hlock->check ==2 ) && -lookup_chain_cache (chain_key, hlock->class)) { +lookup_chain_cache (curr, hlock, chain_key)) {/* * Check whether last held lock: *
include/linux/lockdep.h +3 -0
@@ -182,6 +182,9 @@ struct lock_list {* We record lock dependency chains, so that we can cache them: */ struct lock_chain { +u8 irq_context; +u8 depth; +u16 base;struct list_head entry;u64 chain_key; };
kernel/lockdep_proc.c +95 -0
113 lines not on this page · raw message
kernel/lockdep_internals.h +6 -0
@@ -23,6 +23,8 @@#define MAX_LOCKDEP_CHAINS_BITS 14#define MAX_LOCKDEP_CHAINS (1UL << MAX_LOCKDEP_CHAINS_BITS) +#define MAX_LOCKDEP_CHAIN_HLOCKS (MAX_LOCKDEP_CHAINS*5) +/* * Stack-trace: tightly packed array of stack backtrace * addresses. Protected by the hash_lock.
@@ -30,15 +32,19 @@#define MAX_STACK_TRACE_ENTRIES 262144ULextern struct list_head all_lock_classes; +extern struct lock_chain lock_chains[];extern void get_usage_chars (struct lock_class *class,char *c1,char *c2,char *c3,char *c4);extern const char *__get_key_name (struct lockdep_subclass_key *key,char *str); +struct lock_class *lock_chain_get_class (struct lock_chain *chain,int i); +extern unsigned long nr_lock_classes;extern unsigned long nr_list_entries;extern unsigned long nr_lock_chains; +extern int nr_chain_hlocks;extern unsigned long nr_stack_trace_entries;extern unsigned int nr_hardirq_chains;