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 <tglx@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Darren Hart <darren@dvhart.com> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Bhuvanesh_Surachari@mentor.com Cc: Andy Lowe <Andy_Lowe@mentor.com> Link: http://lkml.kernel.org/r/20151219200607.335938312@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
29e9ee5d48
commit
ecb38b78f6
|
@ -1709,27 +1709,31 @@ retry_private:
|
||||||
* exist yet, look it up one more time to ensure we have a
|
* exist yet, look it up one more time to ensure we have a
|
||||||
* reference to it. If the lock was taken, ret contains the
|
* reference to it. If the lock was taken, ret contains the
|
||||||
* vpid of the top waiter task.
|
* 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) {
|
if (ret > 0) {
|
||||||
WARN_ON(pi_state);
|
WARN_ON(pi_state);
|
||||||
drop_count++;
|
drop_count++;
|
||||||
task_count++;
|
task_count++;
|
||||||
/*
|
/*
|
||||||
* If we acquired the lock, then the user
|
* If we acquired the lock, then the user space value
|
||||||
* space value of uaddr2 should be vpid. It
|
* of uaddr2 should be vpid. It cannot be changed by
|
||||||
* cannot be changed by the top waiter as it
|
* the top waiter as it is blocked on hb2 lock if it
|
||||||
* is blocked on hb2 lock if it tries to do
|
* tries to do so. If something fiddled with it behind
|
||||||
* so. If something fiddled with it behind our
|
* our back the pi state lookup might unearth it. So
|
||||||
* back the pi state lookup might unearth
|
* we rather use the known value than rereading and
|
||||||
* it. So we rather use the known value than
|
* handing potential crap to lookup_pi_state.
|
||||||
* 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);
|
ret = lookup_pi_state(ret, hb2, &key2, &pi_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case 0:
|
case 0:
|
||||||
|
/* We hold a reference on the pi state. */
|
||||||
break;
|
break;
|
||||||
case -EFAULT:
|
case -EFAULT:
|
||||||
put_pi_state(pi_state);
|
put_pi_state(pi_state);
|
||||||
|
@ -1804,19 +1808,37 @@ retry_private:
|
||||||
* of requeue_pi if we couldn't acquire the lock atomically.
|
* of requeue_pi if we couldn't acquire the lock atomically.
|
||||||
*/
|
*/
|
||||||
if (requeue_pi) {
|
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);
|
atomic_inc(&pi_state->refcount);
|
||||||
this->pi_state = pi_state;
|
this->pi_state = pi_state;
|
||||||
ret = rt_mutex_start_proxy_lock(&pi_state->pi_mutex,
|
ret = rt_mutex_start_proxy_lock(&pi_state->pi_mutex,
|
||||||
this->rt_waiter,
|
this->rt_waiter,
|
||||||
this->task);
|
this->task);
|
||||||
if (ret == 1) {
|
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);
|
requeue_pi_wake_futex(this, &key2, hb2);
|
||||||
drop_count++;
|
drop_count++;
|
||||||
continue;
|
continue;
|
||||||
} else if (ret) {
|
} 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;
|
this->pi_state = NULL;
|
||||||
put_pi_state(pi_state);
|
put_pi_state(pi_state);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
@ -1827,6 +1849,11 @@ retry_private:
|
||||||
}
|
}
|
||||||
|
|
||||||
out_unlock:
|
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);
|
put_pi_state(pi_state);
|
||||||
double_unlock_hb(hb1, hb2);
|
double_unlock_hb(hb1, hb2);
|
||||||
wake_up_q(&wake_q);
|
wake_up_q(&wake_q);
|
||||||
|
|
Loading…
Reference in New Issue