summaryrefslogtreecommitdiffstats
path: root/include/linux/lockdep.h
diff options
context:
space:
mode:
authorBart Van Assche <bvanassche@acm.org>2019-02-14 18:00:53 -0500
committerIngo Molnar <mingo@kernel.org>2019-02-28 01:55:47 -0500
commit108c14858b9ea224686e476c8f5ec345a0df9e27 (patch)
treeada6db8dd14a4bb2ee10d5664ac9ae4dd55cc32f /include/linux/lockdep.h
parent4bf508621855613ca2ac782f70c3171e0e8bb011 (diff)
locking/lockdep: Add support for dynamic keys
A shortcoming of the current lockdep implementation is that it requires lock keys to be allocated statically. That forces all instances of lock objects that occur in a given data structure to share a lock key. Since lock dependency analysis groups lock objects per key sharing lock keys can cause false positive lockdep reports. Make it possible to avoid such false positive reports by allowing lock keys to be allocated dynamically. Require that dynamically allocated lock keys are registered before use by calling lockdep_register_key(). Complain about attempts to register the same lock key pointer twice without calling lockdep_unregister_key() between successive registration calls. The purpose of the new lock_keys_hash[] data structure that keeps track of all dynamic keys is twofold: - Verify whether the lockdep_register_key() and lockdep_unregister_key() functions are used correctly. - Avoid that lockdep_init_map() complains when encountering a dynamically allocated key. Signed-off-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Johannes Berg <johannes@sipsolutions.net> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Waiman Long <longman@redhat.com> Cc: Will Deacon <will.deacon@arm.com> Cc: johannes.berg@intel.com Cc: tj@kernel.org Link: https://lkml.kernel.org/r/20190214230058.196511-19-bvanassche@acm.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'include/linux/lockdep.h')
-rw-r--r--include/linux/lockdep.h21
1 files changed, 18 insertions, 3 deletions
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 619ec3f26cdc..43fb35bd7baf 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -46,15 +46,19 @@ extern int lock_stat;
46#define NR_LOCKDEP_CACHING_CLASSES 2 46#define NR_LOCKDEP_CACHING_CLASSES 2
47 47
48/* 48/*
49 * Lock-classes are keyed via unique addresses, by embedding the 49 * A lockdep key is associated with each lock object. For static locks we use
50 * lockclass-key into the kernel (or module) .data section. (For 50 * the lock address itself as the key. Dynamically allocated lock objects can
51 * static locks we use the lock address itself as the key.) 51 * have a statically or dynamically allocated key. Dynamically allocated lock
52 * keys must be registered before being used and must be unregistered before
53 * the key memory is freed.
52 */ 54 */
53struct lockdep_subclass_key { 55struct lockdep_subclass_key {
54 char __one_byte; 56 char __one_byte;
55} __attribute__ ((__packed__)); 57} __attribute__ ((__packed__));
56 58
59/* hash_entry is used to keep track of dynamically allocated keys. */
57struct lock_class_key { 60struct lock_class_key {
61 struct hlist_node hash_entry;
58 struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES]; 62 struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES];
59}; 63};
60 64
@@ -273,6 +277,9 @@ extern void lockdep_set_selftest_task(struct task_struct *task);
273extern void lockdep_off(void); 277extern void lockdep_off(void);
274extern void lockdep_on(void); 278extern void lockdep_on(void);
275 279
280extern void lockdep_register_key(struct lock_class_key *key);
281extern void lockdep_unregister_key(struct lock_class_key *key);
282
276/* 283/*
277 * These methods are used by specific locking variants (spinlocks, 284 * These methods are used by specific locking variants (spinlocks,
278 * rwlocks, mutexes and rwsems) to pass init/acquire/release events 285 * rwlocks, mutexes and rwsems) to pass init/acquire/release events
@@ -434,6 +441,14 @@ static inline void lockdep_set_selftest_task(struct task_struct *task)
434 */ 441 */
435struct lock_class_key { }; 442struct lock_class_key { };
436 443
444static inline void lockdep_register_key(struct lock_class_key *key)
445{
446}
447
448static inline void lockdep_unregister_key(struct lock_class_key *key)
449{
450}
451
437/* 452/*
438 * The lockdep_map takes no space if lockdep is disabled: 453 * The lockdep_map takes no space if lockdep is disabled:
439 */ 454 */