Code using ww_mutexes typically by design have a number of such mutexes sharing the same ww_class, and within a ww transaction they are all lockdep annotated using a nest_lock which means that multiple ww_mutexes of the same lockdep class may be locked at the same time. That means that lock_is_held() returns true and lockdep_assert_held() doesn't fire as long as there is a *single* ww_mutex held of the same class. IOW within a WW transaction.
Code using these mutexes typically want to assert that individual ww_mutexes are held. Not that any ww_mutex of the same class is held.
Introduce functions that can be used for that.
RFC: Placement of the functions? lockdep.c? Are the #ifdefs testing for the correct config?
Signed-off-by: Thomas Hellström thomas.hellstrom@linux.intel.com --- include/linux/ww_mutex.h | 18 ++++++++++++++++++ kernel/locking/mutex.c | 10 ++++++++++ 2 files changed, 28 insertions(+)
diff --git a/include/linux/ww_mutex.h b/include/linux/ww_mutex.h index 45ff6f7a872b..7bc0f533dea6 100644 --- a/include/linux/ww_mutex.h +++ b/include/linux/ww_mutex.h @@ -380,4 +380,22 @@ static inline bool ww_mutex_is_locked(struct ww_mutex *lock) return ww_mutex_base_is_locked(&lock->base); }
+#ifdef CONFIG_PROVE_LOCKING + +bool ww_mutex_held(struct ww_mutex *lock); + +#else /* CONFIG_PROVE_LOCKING */ + +static inline bool ww_mutex_held(struct ww_mutex *lock) +{ + return true; +} + +#endif /* CONFIG_PROVE_LOCKING */ + +static inline void ww_mutex_assert_held(struct ww_mutex *lock) +{ + lockdep_assert(ww_mutex_held(lock)); +} + #endif diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c index de7d6702cd96..37868b739efd 100644 --- a/kernel/locking/mutex.c +++ b/kernel/locking/mutex.c @@ -1174,3 +1174,13 @@ int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock) return 1; } EXPORT_SYMBOL(atomic_dec_and_mutex_lock); + +#ifdef CONFIG_PROVE_LOCKING + +bool ww_mutex_held(struct ww_mutex *lock) +{ + return __ww_mutex_owner(&lock->base) == current; +} +EXPORT_SYMBOL(ww_mutex_held); + +#endif /* CONFIG_PROVE_LOCKING */