On Wed 11-05-16 11:41:28, Peter Zijlstra wrote:
> On Wed, May 11, 2016 at 11:31:27AM +0200, Michal Hocko wrote:
> 
> > Care to cook up a full patch?
> 
> compile tested only, if someone could please test it?

I have tried to run the test case from Tetsuo[1] with a small printk to
show the interrupted writer case:
[ 2753.596678] XXX: Writer interrupted. Woken waiters:0
[ 2998.266978] XXX: Writer interrupted. Woken waiters:0

which means rwsem_atomic_update(-RWSEM_WAITING_BIAS, sem) path which is
the problematic case. oom_reaper was always able to succeed so I guess
the patch works as expected. I will leave the test run for longer to be
sure.

[1] 
http://lkml.kernel.org/r/201605061958.hhg48967.jvftslfqofo...@i-love.sakura.ne.jp
> 
> I'll go write a Changelog if it turns out to actually work ;-)
> 
> ---
>  kernel/locking/rwsem-xadd.c | 21 +++++++++++++++------
>  1 file changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c
> index df4dcb883b50..09e30c6225e5 100644
> --- a/kernel/locking/rwsem-xadd.c
> +++ b/kernel/locking/rwsem-xadd.c
> @@ -487,23 +487,32 @@ __rwsem_down_write_failed_common(struct rw_semaphore 
> *sem, int state)
>  
>               /* Block until there are no active lockers. */
>               do {
> -                     if (signal_pending_state(state, current)) {
> -                             raw_spin_lock_irq(&sem->wait_lock);
> -                             ret = ERR_PTR(-EINTR);
> -                             goto out;
> -                     }
> +                     if (signal_pending_state(state, current))
> +                             goto out_nolock;
> +
>                       schedule();
>                       set_current_state(state);
>               } while ((count = sem->count) & RWSEM_ACTIVE_MASK);
>  
>               raw_spin_lock_irq(&sem->wait_lock);
>       }
> -out:
>       __set_current_state(TASK_RUNNING);
>       list_del(&waiter.list);
>       raw_spin_unlock_irq(&sem->wait_lock);
>  
>       return ret;
> +
> +out_nolock:
> +     __set_current_state(TASK_RUNNING);
> +     raw_spin_lock_irq(&sem->wait_lock);
> +     list_del(&waiter.list);
> +     if (list_empty(&sem->wait_list))
> +             rwsem_atomic_update(-RWSEM_WAITING_BIAS, sem);
> +     else
> +             __rwsem_do_wake(sem, RWSEM_WAKE_ANY);
> +     raw_spin_unlock_irq(&sem->wait_lock);
> +
> +     return ERR_PTR(-EINTR);
>  }
>  
>  __visible struct rw_semaphore * __sched

-- 
Michal Hocko
SUSE Labs

Reply via email to