From e2fb73f0fc1f80dc422d81657f3e8549aac446b1 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 27 Aug 2022 16:22:51 -0400 Subject: six locks: six_lock_waiter() This allows passing in the wait list entry - to be used for a deadlock cycle detector. Signed-off-by: Kent Overstreet --- include/linux/six.h | 9 +++++++++ kernel/locking/six.c | 36 +++++++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/include/linux/six.h b/include/linux/six.h index 313154a7927a..59ced467ee86 100644 --- a/include/linux/six.h +++ b/include/linux/six.h @@ -151,6 +151,8 @@ do { \ bool six_trylock_##type(struct six_lock *); \ bool six_relock_##type(struct six_lock *, u32); \ int six_lock_##type(struct six_lock *, six_lock_should_sleep_fn, void *);\ +int six_lock_waiter_##type(struct six_lock *, struct six_lock_waiter *, \ + six_lock_should_sleep_fn, void *); \ void six_unlock_##type(struct six_lock *); __SIX_LOCK(read) @@ -187,6 +189,13 @@ static inline int six_lock_type(struct six_lock *lock, enum six_lock_type type, SIX_LOCK_DISPATCH(type, six_lock, lock, should_sleep_fn, p); } +static inline int six_lock_type_waiter(struct six_lock *lock, enum six_lock_type type, + struct six_lock_waiter *wait, + six_lock_should_sleep_fn should_sleep_fn, void *p) +{ + SIX_LOCK_DISPATCH(type, six_lock_waiter, lock, wait, should_sleep_fn, p); +} + static inline void six_unlock_type(struct six_lock *lock, enum six_lock_type type) { SIX_LOCK_DISPATCH(type, six_unlock, lock); diff --git a/kernel/locking/six.c b/kernel/locking/six.c index d0cf2a904538..4aebc064066c 100644 --- a/kernel/locking/six.c +++ b/kernel/locking/six.c @@ -438,10 +438,10 @@ static inline bool six_optimistic_spin(struct six_lock *lock, enum six_lock_type noinline static int __six_lock_type_slowpath(struct six_lock *lock, enum six_lock_type type, + struct six_lock_waiter *wait, six_lock_should_sleep_fn should_sleep_fn, void *p) { union six_lock_state old; - struct six_lock_waiter wait; int ret = 0; if (type == SIX_LOCK_write) { @@ -459,13 +459,13 @@ static int __six_lock_type_slowpath(struct six_lock *lock, enum six_lock_type ty lock_contended(&lock->dep_map, _RET_IP_); - wait.task = current; - wait.lock_want = type; + wait->task = current; + wait->lock_want = type; raw_spin_lock(&lock->wait_lock); if (!(lock->state.waiters & (1 << type))) set_bit(waitlist_bitnr(type), (unsigned long *) &lock->state.v); - list_add_tail(&wait.list, &lock->wait_list); + list_add_tail(&wait->list, &lock->wait_list); raw_spin_unlock(&lock->wait_lock); while (1) { @@ -483,7 +483,7 @@ static int __six_lock_type_slowpath(struct six_lock *lock, enum six_lock_type ty __set_current_state(TASK_RUNNING); raw_spin_lock(&lock->wait_lock); - list_del(&wait.list); + list_del(&wait->list); raw_spin_unlock(&lock->wait_lock); out_before_sleep: if (ret && type == SIX_LOCK_write) { @@ -495,9 +495,10 @@ out_before_sleep: return ret; } -__always_inline -static int __six_lock_type(struct six_lock *lock, enum six_lock_type type, - six_lock_should_sleep_fn should_sleep_fn, void *p) +__always_inline __flatten +static int __six_lock_type_waiter(struct six_lock *lock, enum six_lock_type type, + struct six_lock_waiter *wait, + six_lock_should_sleep_fn should_sleep_fn, void *p) { int ret; @@ -505,7 +506,7 @@ static int __six_lock_type(struct six_lock *lock, enum six_lock_type type, six_acquire(&lock->dep_map, 0); ret = do_six_trylock_type(lock, type, true) ? 0 - : __six_lock_type_slowpath(lock, type, should_sleep_fn, p); + : __six_lock_type_slowpath(lock, type, wait, should_sleep_fn, p); if (ret && type != SIX_LOCK_write) six_release(&lock->dep_map); @@ -515,6 +516,15 @@ static int __six_lock_type(struct six_lock *lock, enum six_lock_type type, return ret; } +__always_inline +static int __six_lock_type(struct six_lock *lock, enum six_lock_type type, + six_lock_should_sleep_fn should_sleep_fn, void *p) +{ + struct six_lock_waiter wait; + + return __six_lock_type_waiter(lock, type, &wait, should_sleep_fn, p); +} + __always_inline __flatten static void __six_unlock_type(struct six_lock *lock, enum six_lock_type type) { @@ -573,6 +583,14 @@ int six_lock_##type(struct six_lock *lock, \ } \ EXPORT_SYMBOL_GPL(six_lock_##type); \ \ +int six_lock_waiter_##type(struct six_lock *lock, \ + struct six_lock_waiter *wait, \ + six_lock_should_sleep_fn should_sleep_fn, void *p)\ +{ \ + return __six_lock_type_waiter(lock, SIX_LOCK_##type, wait, should_sleep_fn, p);\ +} \ +EXPORT_SYMBOL_GPL(six_lock_waiter_##type); \ + \ void six_unlock_##type(struct six_lock *lock) \ { \ __six_unlock_type(lock, SIX_LOCK_##type); \ -- cgit v1.2.3