From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933413AbbLSUJp (ORCPT ); Sat, 19 Dec 2015 15:09:45 -0500 Received: from www.linutronix.de ([62.245.132.108]:43856 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753470AbbLSUI3 (ORCPT ); Sat, 19 Dec 2015 15:08:29 -0500 Message-Id: <20151219200607.335938312@linutronix.de> User-Agent: quilt/0.63-1 Date: Sat, 19 Dec 2015 20:07:39 -0000 From: Thomas Gleixner To: LKML Cc: Ingo Molnar , Peter Zijlstra , Darren Hart , Davidlohr Bueso , Bhuvanesh_Surachari@mentor.com, Andy Lowe Subject: [patch 3/5] futex: Document pi_state refcounting in requeue code References: <20151219200501.563704646@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-15 Content-Disposition: inline; filename=futex--Document-pi_state-refcounting-in-requeue-code X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1,SHORTCIRCUIT=-0.0001,URIBL_BLOCKED=0.001 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Documentation of the pi_state refcounting in the requeue code is non existent. Add it. Signed-off-by: Thomas Gleixner --- kernel/futex.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1709,6 +1709,8 @@ static int futex_requeue(u32 __user *uad * 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); @@ -1724,12 +1726,16 @@ static int futex_requeue(u32 __user *uad * 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 +1810,38 @@ static int futex_requeue(u32 __user *uad * 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 +1852,11 @@ static int futex_requeue(u32 __user *uad } 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);