The atomic count value right after reader count increment can be useful
to determine the rwsem state at trylock time. So the count value is
passed down to rwsem_down_read_slowpath() to be used when appropriate.

Signed-off-by: Waiman Long <[email protected]>
---
 kernel/locking/rwsem.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c
index f11b9bd3431d..12761e02ab9b 100644
--- a/kernel/locking/rwsem.c
+++ b/kernel/locking/rwsem.c
@@ -270,12 +270,12 @@ static inline void rwsem_set_nonspinnable(struct 
rw_semaphore *sem)
                                          owner | RWSEM_NONSPINNABLE));
 }
 
-static inline bool rwsem_read_trylock(struct rw_semaphore *sem)
+static inline long rwsem_read_trylock(struct rw_semaphore *sem)
 {
        long cnt = atomic_long_add_return_acquire(RWSEM_READER_BIAS, 
&sem->count);
        if (WARN_ON_ONCE(cnt < 0))
                rwsem_set_nonspinnable(sem);
-       return !(cnt & RWSEM_READ_FAILED_MASK);
+       return cnt;
 }
 
 /*
@@ -989,9 +989,9 @@ rwsem_spin_on_owner(struct rw_semaphore *sem, unsigned long 
nonspinnable)
  * Wait for the read lock to be granted
  */
 static struct rw_semaphore __sched *
-rwsem_down_read_slowpath(struct rw_semaphore *sem, int state)
+rwsem_down_read_slowpath(struct rw_semaphore *sem, int state, long count)
 {
-       long count, adjustment = -RWSEM_READER_BIAS;
+       long adjustment = -RWSEM_READER_BIAS;
        struct rwsem_waiter waiter;
        DEFINE_WAKE_Q(wake_q);
        bool wake = false;
@@ -1337,8 +1337,10 @@ static struct rw_semaphore *rwsem_downgrade_wake(struct 
rw_semaphore *sem)
  */
 static inline void __down_read(struct rw_semaphore *sem)
 {
-       if (!rwsem_read_trylock(sem)) {
-               rwsem_down_read_slowpath(sem, TASK_UNINTERRUPTIBLE);
+       long count = rwsem_read_trylock(sem);
+
+       if (count & RWSEM_READ_FAILED_MASK) {
+               rwsem_down_read_slowpath(sem, TASK_UNINTERRUPTIBLE, count);
                DEBUG_RWSEMS_WARN_ON(!is_rwsem_reader_owned(sem), sem);
        } else {
                rwsem_set_reader_owned(sem);
@@ -1347,8 +1349,10 @@ static inline void __down_read(struct rw_semaphore *sem)
 
 static inline int __down_read_killable(struct rw_semaphore *sem)
 {
-       if (!rwsem_read_trylock(sem)) {
-               if (IS_ERR(rwsem_down_read_slowpath(sem, TASK_KILLABLE)))
+       long count = rwsem_read_trylock(sem);
+
+       if (count & RWSEM_READ_FAILED_MASK) {
+               if (IS_ERR(rwsem_down_read_slowpath(sem, TASK_KILLABLE, count)))
                        return -EINTR;
                DEBUG_RWSEMS_WARN_ON(!is_rwsem_reader_owned(sem), sem);
        } else {
-- 
2.18.1

Reply via email to