lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20170408005543.GA16143@fury>
Date:   Fri, 7 Apr 2017 17:55:43 -0700
From:   Darren Hart <dvhart@...radead.org>
To:     Peter Zijlstra <peterz@...radead.org>
Cc:     tglx@...utronix.de, mingo@...nel.org, juri.lelli@....com,
        rostedt@...dmis.org, xlpang@...hat.com, bigeasy@...utronix.de,
        linux-kernel@...r.kernel.org, mathieu.desnoyers@...icios.com,
        jdesfossez@...icios.com, bristot@...hat.com
Subject: Re: [PATCH -v6 11/13] futex: Rework futex_lock_pi() to use
 rt_mutex_*_proxy_lock()

On Wed, Mar 22, 2017 at 11:35:58AM +0100, Peter Zijlstra wrote:
> By changing futex_lock_pi() to use rt_mutex_*_proxy_lock() we arrive
> at a point where all wait_list modifications are done under both
> hb->lock and wait_lock.
> 
> This closes the obvious interleave pattern between futex_lock_pi() and
> futex_unlock_pi(), but not entirely so. See below:
> 
> Before:
> 
> futex_lock_pi()			futex_unlock_pi()
>   unlock hb->lock
> 
> 				  lock hb->lock
> 				  unlock hb->lock
> 
> 				  lock rt_mutex->wait_lock
> 				  unlock rt_mutex_wait_lock
> 				    -EAGAIN
> 
>   lock rt_mutex->wait_lock
>   list_add
>   unlock rt_mutex->wait_lock
> 
>   schedule()
> 
>   lock rt_mutex->wait_lock
>   list_del
>   unlock rt_mutex->wait_lock
> 
> 				  <idem>
> 				    -EAGAIN
> 
>   lock hb->lock
> 
> 
> After:
> 
> futex_lock_pi()			futex_unlock_pi()
> 
>   lock hb->lock
>   lock rt_mutex->wait_lock
>   list_add
>   unlock rt_mutex->wait_lock
>   unlock hb->lock
> 
>   schedule()
> 				  lock hb->lock
> 				  unlock hb->lock
>   lock hb->lock
>   lock rt_mutex->wait_lock
>   list_del
>   unlock rt_mutex->wait_lock
> 
> 				  lock rt_mutex->wait_lock
> 				  unlock rt_mutex_wait_lock

Underscore to dereference:	  rt_mutex->wait_lock

> 				    -EAGAIN
> 
>   unlock hb->lock
> 
> 
> It does however solve the earlier starvation/live-lock scenario which
> got introduced with the -EAGAIN since unlike the before scenario;
> where the -EAGAIN happens while futex_unlock_pi() doesn't hold any
> locks; in the after scenario it happens while futex_unlock_pi()

I think you mean futex_lock_pi() here ----------^
And possibly in the previous reference, although both are true.

> actually holds a lock, and then we can serialize on that lock.
> 
> Signed-off-by: Peter Zijlstra (Intel) <peterz@...radead.org>
> ---
>  kernel/futex.c                  |   70 +++++++++++++++++++++++++++-------------
>  kernel/locking/rtmutex.c        |   13 -------
>  kernel/locking/rtmutex_common.h |    1 
>  3 files changed, 48 insertions(+), 36 deletions(-)
> 
> Index: linux-2.6/kernel/futex.c

...

> @@ -2587,6 +2592,7 @@ static int futex_lock_pi(u32 __user *uad

...

> +no_block:
> +	/*
>  	 * Fixup the pi_state owner and possibly acquire the lock if we
>  	 * haven't already.
>  	 */

Deleted a bunch of commentary about the following comment and the code to follow
(which shows up just below this point). Turns out it isn't wrong... it's just
really complex. This snippet used to be self contained within the first if
block, and now the connection to the comment is less direct. I didn't come up
with a better way to say it though.... so just noting this here in case you or
someone else has a better idea.


        /*
         * If fixup_owner() faulted and was unable to handle the fault, unlock
         * it and return the fault to userspace.
         */
        if (ret && (rt_mutex_owner(&q.pi_state->pi_mutex) == current)) {
                pi_state = q.pi_state;
                get_pi_state(pi_state);
        }

        /* Unqueue and drop the lock */
        unqueue_me_pi(&q);

        if (pi_state) {
                rt_mutex_futex_unlock(&pi_state->pi_mutex);
                put_pi_state(pi_state);
        }

-- 
Darren Hart
VMware Open Source Technology Center

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ