From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756401AbcJHP4d (ORCPT ); Sat, 8 Oct 2016 11:56:33 -0400 Received: from Galois.linutronix.de ([146.0.238.70]:46477 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750975AbcJHP4Z (ORCPT ); Sat, 8 Oct 2016 11:56:25 -0400 Date: Sat, 8 Oct 2016 17:53:49 +0200 (CEST) From: Thomas Gleixner To: Peter Zijlstra cc: mingo@kernel.org, juri.lelli@arm.com, rostedt@goodmis.org, xlpang@redhat.com, bigeasy@linutronix.de, linux-kernel@vger.kernel.org, mathieu.desnoyers@efficios.com, jdesfossez@efficios.com, bristot@redhat.com Subject: Re: [RFC][PATCH 4/4] futex: Rewrite FUTEX_UNLOCK_PI In-Reply-To: <20161007112143.GJ3117@twins.programming.kicks-ass.net> Message-ID: References: <20161003091234.879763059@infradead.org> <20161003091847.704255067@infradead.org> <20161007112143.GJ3117@twins.programming.kicks-ass.net> User-Agent: Alpine 2.20 (DEB 67 2015-01-07) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, 7 Oct 2016, Peter Zijlstra wrote: > Solve all that by: > > - using futex specific rt_mutex calls that lack the fastpath, futexes > have their own fastpath anyway. This makes that > rt_mutex_futex_unlock() doesn't need to drop rt_mutex::wait_lock > and the unlock is guaranteed if we manage to update user state. > > - make futex_unlock_pi() drop hb->lock early and only use > rt_mutex::wait_lock to serialize against rt_mutex waiters > update the futex value and unlock. > > - in case futex and rt_mutex disagree on waiters, side with rt_mutex > and simply clear the user value. This works because either there > really are no waiters left, or futex_lock_pi() triggers the > lock-steal path and fixes up the WAITERS flag. I stared at this for a few hours and while I'm not yet done analyzing all possible combinations I found at least one thing which is broken: CPU 0 CPU 1 unlock_pi(f) .... unlock(hb->lock) *f = new_owner_tid | WAITERS; lock_pi(f) lock(hb->lock) uval = *f; topwaiter = futex_top_waiter(); attach_to_pi_state(uval, topwaiter->pistate); pid = uval & TID_MASK; if (pid != task_pid_vnr(pistate->owner)) return -EINVAL; .... pistate->owner = newowner; So in this case we tell the caller on CPU 1 that the futex is in inconsistent state, because pistate->owner still points to the unlocking task while the user space value alread shows the new owner. So this sanity check triggers and we simply fail while we should not. It's [10] in the state matrix above attach_to_pi_state(). I suspect that there are more issues like this, especially since I did not look at requeue_pi yet, but by now my brain is completely fried. Thanks, tglx