From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933320AbbLTNUT (ORCPT ); Sun, 20 Dec 2015 08:20:19 -0500 Received: from terminus.zytor.com ([198.137.202.10]:49651 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932928AbbLTNUQ (ORCPT ); Sun, 20 Dec 2015 08:20:16 -0500 Date: Sun, 20 Dec 2015 05:19:21 -0800 From: tip-bot for Thomas Gleixner Message-ID: Cc: tglx@linutronix.de, dave@stgolabs.net, linux-kernel@vger.kernel.org, darren@dvhart.com, Andy_Lowe@mentor.com, hpa@zytor.com, peterz@infradead.org, mingo@kernel.org Reply-To: linux-kernel@vger.kernel.org, Andy_Lowe@mentor.com, darren@dvhart.com, tglx@linutronix.de, dave@stgolabs.net, mingo@kernel.org, hpa@zytor.com, peterz@infradead.org In-Reply-To: <20151219200607.335938312@linutronix.de> References: <20151219200607.335938312@linutronix.de> To: linux-tip-commits@vger.kernel.org Subject: [tip:locking/core] futex: Document pi_state refcounting in requeue code Git-Commit-ID: ecb38b78f698a51988ec456751b20440e54702fb X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: ecb38b78f698a51988ec456751b20440e54702fb Gitweb: http://git.kernel.org/tip/ecb38b78f698a51988ec456751b20440e54702fb Author: Thomas Gleixner AuthorDate: Sat, 19 Dec 2015 20:07:39 +0000 Committer: Thomas Gleixner CommitDate: Sun, 20 Dec 2015 12:43:24 +0100 futex: Document pi_state refcounting in requeue code Documentation of the pi_state refcounting in the requeue code is non existent. Add it. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Darren Hart Cc: Davidlohr Bueso Cc: Bhuvanesh_Surachari@mentor.com Cc: Andy Lowe Link: http://lkml.kernel.org/r/20151219200607.335938312@linutronix.de Signed-off-by: Thomas Gleixner --- kernel/futex.c | 51 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index f1581ff..20c4683 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1709,27 +1709,31 @@ retry_private: * exist yet, look it up one more time to ensure we have a * reference to it. If the lock was taken, ret contains the * vpid of the top waiter task. + * If the lock was not taken, we have pi_state and an initial + * refcount on it. In case of an error we have nothing. */ if (ret > 0) { WARN_ON(pi_state); drop_count++; task_count++; /* - * If we acquired the lock, then the user - * space value of uaddr2 should be vpid. It - * cannot be changed by the top waiter as it - * is blocked on hb2 lock if it tries to do - * so. If something fiddled with it behind our - * back the pi state lookup might unearth - * it. So we rather use the known value than - * rereading and handing potential crap to - * lookup_pi_state. + * If we acquired the lock, then the user space value + * of uaddr2 should be vpid. It cannot be changed by + * the top waiter as it is blocked on hb2 lock if it + * tries to do so. If something fiddled with it behind + * our back the pi state lookup might unearth it. So + * we rather use the known value than rereading and + * handing potential crap to lookup_pi_state. + * + * If that call succeeds then we have pi_state and an + * initial refcount on it. */ ret = lookup_pi_state(ret, hb2, &key2, &pi_state); } switch (ret) { case 0: + /* We hold a reference on the pi state. */ break; case -EFAULT: put_pi_state(pi_state); @@ -1804,19 +1808,37 @@ retry_private: * of requeue_pi if we couldn't acquire the lock atomically. */ if (requeue_pi) { - /* Prepare the waiter to take the rt_mutex. */ + /* + * Prepare the waiter to take the rt_mutex. Take a + * refcount on the pi_state and store the pointer in + * the futex_q object of the waiter. + */ atomic_inc(&pi_state->refcount); this->pi_state = pi_state; ret = rt_mutex_start_proxy_lock(&pi_state->pi_mutex, this->rt_waiter, this->task); if (ret == 1) { - /* We got the lock. */ + /* + * We got the lock. We do neither drop the + * refcount on pi_state nor clear + * this->pi_state because the waiter needs the + * pi_state for cleaning up the user space + * value. It will drop the refcount after + * doing so. + */ requeue_pi_wake_futex(this, &key2, hb2); drop_count++; continue; } else if (ret) { - /* -EDEADLK */ + /* + * rt_mutex_start_proxy_lock() detected a + * potential deadlock when we tried to queue + * that waiter. Drop the pi_state reference + * which we took above and remove the pointer + * to the state from the waiters futex_q + * object. + */ this->pi_state = NULL; put_pi_state(pi_state); goto out_unlock; @@ -1827,6 +1849,11 @@ retry_private: } out_unlock: + /* + * We took an extra initial reference to the pi_state either + * in futex_proxy_trylock_atomic() or in lookup_pi_state(). We + * need to drop it here again. + */ put_pi_state(pi_state); double_unlock_hb(hb1, hb2); wake_up_q(&wake_q);