locking/lockdep: Mark local_lock_t
authorPeter Zijlstra <peterz@infradead.org>
Wed, 9 Dec 2020 15:06:21 +0000 (16:06 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 15 Sep 2021 07:50:41 +0000 (09:50 +0200)
[ Upstream commit dfd5e3f5fe27bda91d5cc028c86ffbb7a0614489 ]

The local_lock_t's are special, because they cannot form IRQ
inversions, make sure we can tell them apart from the rest of the
locks.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/linux/local_lock_internal.h
include/linux/lockdep.h
include/linux/lockdep_types.h
kernel/locking/lockdep.c

index 4a8795b..ded90b0 100644 (file)
@@ -18,6 +18,7 @@ typedef struct {
        .dep_map = {                                    \
                .name = #lockname,                      \
                .wait_type_inner = LD_WAIT_CONFIG,      \
+               .lock_type = LD_LOCK_PERCPU,                    \
        }
 #else
 # define LL_DEP_MAP_INIT(lockname)
@@ -30,7 +31,9 @@ do {                                                          \
        static struct lock_class_key __key;                     \
                                                                \
        debug_check_no_locks_freed((void *)lock, sizeof(*lock));\
-       lockdep_init_map_wait(&(lock)->dep_map, #lock, &__key, 0, LD_WAIT_CONFIG);\
+       lockdep_init_map_type(&(lock)->dep_map, #lock, &__key, 0, \
+                             LD_WAIT_CONFIG, LD_WAIT_INV,      \
+                             LD_LOCK_PERCPU);                  \
 } while (0)
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
index f559487..20b6797 100644 (file)
@@ -185,12 +185,19 @@ extern void lockdep_unregister_key(struct lock_class_key *key);
  * to lockdep:
  */
 
-extern void lockdep_init_map_waits(struct lockdep_map *lock, const char *name,
-       struct lock_class_key *key, int subclass, short inner, short outer);
+extern void lockdep_init_map_type(struct lockdep_map *lock, const char *name,
+       struct lock_class_key *key, int subclass, u8 inner, u8 outer, u8 lock_type);
+
+static inline void
+lockdep_init_map_waits(struct lockdep_map *lock, const char *name,
+                      struct lock_class_key *key, int subclass, u8 inner, u8 outer)
+{
+       lockdep_init_map_type(lock, name, key, subclass, inner, LD_WAIT_INV, LD_LOCK_NORMAL);
+}
 
 static inline void
 lockdep_init_map_wait(struct lockdep_map *lock, const char *name,
-                     struct lock_class_key *key, int subclass, short inner)
+                     struct lock_class_key *key, int subclass, u8 inner)
 {
        lockdep_init_map_waits(lock, name, key, subclass, inner, LD_WAIT_INV);
 }
@@ -340,6 +347,8 @@ static inline void lockdep_set_selftest_task(struct task_struct *task)
 # define lock_set_class(l, n, k, s, i)         do { } while (0)
 # define lock_set_subclass(l, s, i)            do { } while (0)
 # define lockdep_init()                                do { } while (0)
+# define lockdep_init_map_type(lock, name, key, sub, inner, outer, type) \
+               do { (void)(name); (void)(key); } while (0)
 # define lockdep_init_map_waits(lock, name, key, sub, inner, outer) \
                do { (void)(name); (void)(key); } while (0)
 # define lockdep_init_map_wait(lock, name, key, sub, inner) \
index 9a1fd49..2ec9ff5 100644 (file)
@@ -30,6 +30,12 @@ enum lockdep_wait_type {
        LD_WAIT_MAX,            /* must be last */
 };
 
+enum lockdep_lock_type {
+       LD_LOCK_NORMAL = 0,     /* normal, catch all */
+       LD_LOCK_PERCPU,         /* percpu */
+       LD_LOCK_MAX,
+};
+
 #ifdef CONFIG_LOCKDEP
 
 /*
@@ -119,8 +125,10 @@ struct lock_class {
        int                             name_version;
        const char                      *name;
 
-       short                           wait_type_inner;
-       short                           wait_type_outer;
+       u8                              wait_type_inner;
+       u8                              wait_type_outer;
+       u8                              lock_type;
+       /* u8                           hole; */
 
 #ifdef CONFIG_LOCK_STAT
        unsigned long                   contention_point[LOCKSTAT_POINTS];
@@ -169,8 +177,10 @@ struct lockdep_map {
        struct lock_class_key           *key;
        struct lock_class               *class_cache[NR_LOCKDEP_CACHING_CLASSES];
        const char                      *name;
-       short                           wait_type_outer; /* can be taken in this context */
-       short                           wait_type_inner; /* presents this context */
+       u8                              wait_type_outer; /* can be taken in this context */
+       u8                              wait_type_inner; /* presents this context */
+       u8                              lock_type;
+       /* u8                           hole; */
 #ifdef CONFIG_LOCK_STAT
        int                             cpu;
        unsigned long                   ip;
index 8ae9d7a..5184f68 100644 (file)
@@ -1293,6 +1293,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
        class->name_version = count_matching_names(class);
        class->wait_type_inner = lock->wait_type_inner;
        class->wait_type_outer = lock->wait_type_outer;
+       class->lock_type = lock->lock_type;
        /*
         * We use RCU's safe list-add method to make
         * parallel walking of the hash-list safe:
@@ -4621,9 +4622,9 @@ print_lock_invalid_wait_context(struct task_struct *curr,
  */
 static int check_wait_context(struct task_struct *curr, struct held_lock *next)
 {
-       short next_inner = hlock_class(next)->wait_type_inner;
-       short next_outer = hlock_class(next)->wait_type_outer;
-       short curr_inner;
+       u8 next_inner = hlock_class(next)->wait_type_inner;
+       u8 next_outer = hlock_class(next)->wait_type_outer;
+       u8 curr_inner;
        int depth;
 
        if (!next_inner || next->trylock)
@@ -4646,7 +4647,7 @@ static int check_wait_context(struct task_struct *curr, struct held_lock *next)
 
        for (; depth < curr->lockdep_depth; depth++) {
                struct held_lock *prev = curr->held_locks + depth;
-               short prev_inner = hlock_class(prev)->wait_type_inner;
+               u8 prev_inner = hlock_class(prev)->wait_type_inner;
 
                if (prev_inner) {
                        /*
@@ -4695,9 +4696,9 @@ static inline int check_wait_context(struct task_struct *curr,
 /*
  * Initialize a lock instance's lock-class mapping info:
  */
-void lockdep_init_map_waits(struct lockdep_map *lock, const char *name,
+void lockdep_init_map_type(struct lockdep_map *lock, const char *name,
                            struct lock_class_key *key, int subclass,
-                           short inner, short outer)
+                           u8 inner, u8 outer, u8 lock_type)
 {
        int i;
 
@@ -4720,6 +4721,7 @@ void lockdep_init_map_waits(struct lockdep_map *lock, const char *name,
 
        lock->wait_type_outer = outer;
        lock->wait_type_inner = inner;
+       lock->lock_type = lock_type;
 
        /*
         * No key, no joy, we need to hash something.
@@ -4754,7 +4756,7 @@ void lockdep_init_map_waits(struct lockdep_map *lock, const char *name,
                raw_local_irq_restore(flags);
        }
 }
-EXPORT_SYMBOL_GPL(lockdep_init_map_waits);
+EXPORT_SYMBOL_GPL(lockdep_init_map_type);
 
 struct lock_class_key __lockdep_no_validate__;
 EXPORT_SYMBOL_GPL(__lockdep_no_validate__);