locking/lockdep: Mark local_lock_t

[ Upstream commit dfd5e3f5fe ]

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>
This commit is contained in:
Peter Zijlstra 2020-12-09 16:06:21 +01:00 committed by Greg Kroah-Hartman
parent 22b106df73
commit d5462a630f
4 changed files with 39 additions and 15 deletions

View file

@ -18,6 +18,7 @@ typedef struct {
.dep_map = { \ .dep_map = { \
.name = #lockname, \ .name = #lockname, \
.wait_type_inner = LD_WAIT_CONFIG, \ .wait_type_inner = LD_WAIT_CONFIG, \
.lock_type = LD_LOCK_PERCPU, \
} }
#else #else
# define LL_DEP_MAP_INIT(lockname) # define LL_DEP_MAP_INIT(lockname)
@ -30,7 +31,9 @@ do { \
static struct lock_class_key __key; \ static struct lock_class_key __key; \
\ \
debug_check_no_locks_freed((void *)lock, sizeof(*lock));\ 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) } while (0)
#ifdef CONFIG_DEBUG_LOCK_ALLOC #ifdef CONFIG_DEBUG_LOCK_ALLOC

View file

@ -185,12 +185,19 @@ extern void lockdep_unregister_key(struct lock_class_key *key);
* to lockdep: * to lockdep:
*/ */
extern void lockdep_init_map_waits(struct lockdep_map *lock, const char *name, extern void lockdep_init_map_type(struct lockdep_map *lock, const char *name,
struct lock_class_key *key, int subclass, short inner, short outer); 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 static inline void
lockdep_init_map_wait(struct lockdep_map *lock, const char *name, 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); 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_class(l, n, k, s, i) do { } while (0)
# define lock_set_subclass(l, s, i) do { } while (0) # define lock_set_subclass(l, s, i) do { } while (0)
# define lockdep_init() 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) \ # define lockdep_init_map_waits(lock, name, key, sub, inner, outer) \
do { (void)(name); (void)(key); } while (0) do { (void)(name); (void)(key); } while (0)
# define lockdep_init_map_wait(lock, name, key, sub, inner) \ # define lockdep_init_map_wait(lock, name, key, sub, inner) \

View file

@ -30,6 +30,12 @@ enum lockdep_wait_type {
LD_WAIT_MAX, /* must be last */ 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 #ifdef CONFIG_LOCKDEP
/* /*
@ -119,8 +125,10 @@ struct lock_class {
int name_version; int name_version;
const char *name; const char *name;
short wait_type_inner; u8 wait_type_inner;
short wait_type_outer; u8 wait_type_outer;
u8 lock_type;
/* u8 hole; */
#ifdef CONFIG_LOCK_STAT #ifdef CONFIG_LOCK_STAT
unsigned long contention_point[LOCKSTAT_POINTS]; unsigned long contention_point[LOCKSTAT_POINTS];
@ -169,8 +177,10 @@ struct lockdep_map {
struct lock_class_key *key; struct lock_class_key *key;
struct lock_class *class_cache[NR_LOCKDEP_CACHING_CLASSES]; struct lock_class *class_cache[NR_LOCKDEP_CACHING_CLASSES];
const char *name; const char *name;
short wait_type_outer; /* can be taken in this context */ u8 wait_type_outer; /* can be taken in this context */
short wait_type_inner; /* presents this context */ u8 wait_type_inner; /* presents this context */
u8 lock_type;
/* u8 hole; */
#ifdef CONFIG_LOCK_STAT #ifdef CONFIG_LOCK_STAT
int cpu; int cpu;
unsigned long ip; unsigned long ip;

View 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->name_version = count_matching_names(class);
class->wait_type_inner = lock->wait_type_inner; class->wait_type_inner = lock->wait_type_inner;
class->wait_type_outer = lock->wait_type_outer; class->wait_type_outer = lock->wait_type_outer;
class->lock_type = lock->lock_type;
/* /*
* We use RCU's safe list-add method to make * We use RCU's safe list-add method to make
* parallel walking of the hash-list safe: * 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) static int check_wait_context(struct task_struct *curr, struct held_lock *next)
{ {
short next_inner = hlock_class(next)->wait_type_inner; u8 next_inner = hlock_class(next)->wait_type_inner;
short next_outer = hlock_class(next)->wait_type_outer; u8 next_outer = hlock_class(next)->wait_type_outer;
short curr_inner; u8 curr_inner;
int depth; int depth;
if (!next_inner || next->trylock) 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++) { for (; depth < curr->lockdep_depth; depth++) {
struct held_lock *prev = curr->held_locks + 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) { 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: * 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, struct lock_class_key *key, int subclass,
short inner, short outer) u8 inner, u8 outer, u8 lock_type)
{ {
int i; 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_outer = outer;
lock->wait_type_inner = inner; lock->wait_type_inner = inner;
lock->lock_type = lock_type;
/* /*
* No key, no joy, we need to hash something. * 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); 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__; struct lock_class_key __lockdep_no_validate__;
EXPORT_SYMBOL_GPL(__lockdep_no_validate__); EXPORT_SYMBOL_GPL(__lockdep_no_validate__);