[PATCH] locking/rwsem: Introduce __rwsem_spin_on_owner()

From: Yanfei Xu
Date: Fri Oct 15 2021 - 14:33:29 EST


'enum owner_state' is only declared when CONFIG_RWSEM_SPIN_ON_OWNER
is selected. To avoid the build failure, we introduce
__rwsem_spin_on_owner function.

Reported-by: kernel test robot <lkp@xxxxxxxxx>
Signed-off-by: Yanfei Xu <yanfei.xu@xxxxxxxxxxxxx>
---
kernel/locking/rwsem.c | 29 ++++++++++++++++++-----------
1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c
index 2bd914187399..7d85c85ad8a5 100644
--- a/kernel/locking/rwsem.c
+++ b/kernel/locking/rwsem.c
@@ -634,7 +634,7 @@ static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem)
}

/*
- * The rwsem_spin_on_owner() function returns the following 4 values
+ * The __rwsem_spin_on_owner() function returns the following 4 values
* depending on the lock owner state.
* OWNER_NULL : owner is currently NULL
* OWNER_WRITER: when owner changes and is a writer
@@ -665,7 +665,7 @@ rwsem_owner_state(struct task_struct *owner, unsigned long flags)
}

static noinline enum owner_state
-rwsem_spin_on_owner(struct rw_semaphore *sem)
+__rwsem_spin_on_owner(struct rw_semaphore *sem)
{
struct task_struct *new, *owner;
unsigned long flags, new_flags;
@@ -712,6 +712,17 @@ rwsem_spin_on_owner(struct rw_semaphore *sem)
return state;
}

+static inline enum owner_state
+rwsem_spin_on_owner(struct rw_semaphore *sem)
+{
+ enum owner_state state;
+
+ preempt_disable();
+ state = __rwsem_spin_on_owner(sem);
+ preempt_enable();
+ return state;
+}
+
/*
* Calculate reader-owned rwsem spinning threshold for writer
*
@@ -759,7 +770,7 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
for (;;) {
enum owner_state owner_state;

- owner_state = rwsem_spin_on_owner(sem);
+ owner_state = __rwsem_spin_on_owner(sem);
if (!(owner_state & OWNER_SPINNABLE))
break;

@@ -831,7 +842,7 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
* quit spinning.
*
* If the owner is a writer, the need_resched() check is
- * done inside rwsem_spin_on_owner(). If the owner is not
+ * done inside __rwsem_spin_on_owner(). If the owner is not
* a writer, need_resched() check needs to be done here.
*/
if (owner_state != OWNER_WRITER) {
@@ -1023,7 +1034,6 @@ rwsem_down_write_slowpath(struct rw_semaphore *sem, int state)
enum writer_wait_state wstate;
struct rwsem_waiter waiter;
struct rw_semaphore *ret = sem;
- enum owner_state owner_state;
DEFINE_WAKE_Q(wake_q);

/* do optimistic spinning and steal lock if possible */
@@ -1099,12 +1109,9 @@ rwsem_down_write_slowpath(struct rw_semaphore *sem, int state)
* In this case, we attempt to acquire the lock again
* without sleeping.
*/
- if (wstate == WRITER_HANDOFF) {
- preempt_disable();
- owner_state = rwsem_spin_on_owner(sem);
- preempt_enable();
- if (owner_state == OWNER_NULL)
- goto trylock_again;
+ if (wstate == WRITER_HANDOFF &&
+ rwsem_spin_on_owner(sem) == OWNER_NULL) {
+ goto trylock_again;
}

/* Block until there are no active lockers. */
--
2.27.0