|
@@ -1052,6 +1052,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
|
|
|
struct task_struct *new_owner;
|
|
|
struct futex_pi_state *pi_state = this->pi_state;
|
|
|
u32 uninitialized_var(curval), newval;
|
|
|
+ int ret = 0;
|
|
|
|
|
|
if (!pi_state)
|
|
|
return -EINVAL;
|
|
@@ -1075,23 +1076,19 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
|
|
|
new_owner = this->task;
|
|
|
|
|
|
/*
|
|
|
- * We pass it to the next owner. (The WAITERS bit is always
|
|
|
- * kept enabled while there is PI state around. We must also
|
|
|
- * preserve the owner died bit.)
|
|
|
+ * We pass it to the next owner. The WAITERS bit is always
|
|
|
+ * kept enabled while there is PI state around. We cleanup the
|
|
|
+ * owner died bit, because we are the owner.
|
|
|
*/
|
|
|
- if (!(uval & FUTEX_OWNER_DIED)) {
|
|
|
- int ret = 0;
|
|
|
-
|
|
|
- newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
|
|
|
+ newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
|
|
|
|
|
|
- if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
|
|
|
- ret = -EFAULT;
|
|
|
- else if (curval != uval)
|
|
|
- ret = -EINVAL;
|
|
|
- if (ret) {
|
|
|
- raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
|
|
|
- return ret;
|
|
|
- }
|
|
|
+ if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
|
|
|
+ ret = -EFAULT;
|
|
|
+ else if (curval != uval)
|
|
|
+ ret = -EINVAL;
|
|
|
+ if (ret) {
|
|
|
+ raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
raw_spin_lock_irq(&pi_state->owner->pi_lock);
|
|
@@ -2351,9 +2348,10 @@ retry:
|
|
|
/*
|
|
|
* To avoid races, try to do the TID -> 0 atomic transition
|
|
|
* again. If it succeeds then we can return without waking
|
|
|
- * anyone else up:
|
|
|
+ * anyone else up. We only try this if neither the waiters nor
|
|
|
+ * the owner died bit are set.
|
|
|
*/
|
|
|
- if (!(uval & FUTEX_OWNER_DIED) &&
|
|
|
+ if (!(uval & ~FUTEX_TID_MASK) &&
|
|
|
cmpxchg_futex_value_locked(&uval, uaddr, vpid, 0))
|
|
|
goto pi_faulted;
|
|
|
/*
|
|
@@ -2383,11 +2381,9 @@ retry:
|
|
|
/*
|
|
|
* No waiters - kernel unlocks the futex:
|
|
|
*/
|
|
|
- if (!(uval & FUTEX_OWNER_DIED)) {
|
|
|
- ret = unlock_futex_pi(uaddr, uval);
|
|
|
- if (ret == -EFAULT)
|
|
|
- goto pi_faulted;
|
|
|
- }
|
|
|
+ ret = unlock_futex_pi(uaddr, uval);
|
|
|
+ if (ret == -EFAULT)
|
|
|
+ goto pi_faulted;
|
|
|
|
|
|
out_unlock:
|
|
|
spin_unlock(&hb->lock);
|