aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/futex.c40
1 files changed, 18 insertions, 22 deletions
diff --git a/kernel/futex.c b/kernel/futex.c
index 520e7b23bf3c..e1cb1baa23fb 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -1052,6 +1052,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
1052 struct task_struct *new_owner; 1052 struct task_struct *new_owner;
1053 struct futex_pi_state *pi_state = this->pi_state; 1053 struct futex_pi_state *pi_state = this->pi_state;
1054 u32 uninitialized_var(curval), newval; 1054 u32 uninitialized_var(curval), newval;
1055 int ret = 0;
1055 1056
1056 if (!pi_state) 1057 if (!pi_state)
1057 return -EINVAL; 1058 return -EINVAL;
@@ -1075,23 +1076,19 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
1075 new_owner = this->task; 1076 new_owner = this->task;
1076 1077
1077 /* 1078 /*
1078 * We pass it to the next owner. (The WAITERS bit is always 1079 * We pass it to the next owner. The WAITERS bit is always
1079 * kept enabled while there is PI state around. We must also 1080 * kept enabled while there is PI state around. We cleanup the
1080 * preserve the owner died bit.) 1081 * owner died bit, because we are the owner.
1081 */ 1082 */
1082 if (!(uval & FUTEX_OWNER_DIED)) { 1083 newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
1083 int ret = 0;
1084
1085 newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
1086 1084
1087 if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) 1085 if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
1088 ret = -EFAULT; 1086 ret = -EFAULT;
1089 else if (curval != uval) 1087 else if (curval != uval)
1090 ret = -EINVAL; 1088 ret = -EINVAL;
1091 if (ret) { 1089 if (ret) {
1092 raw_spin_unlock(&pi_state->pi_mutex.wait_lock); 1090 raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
1093 return ret; 1091 return ret;
1094 }
1095 } 1092 }
1096 1093
1097 raw_spin_lock_irq(&pi_state->owner->pi_lock); 1094 raw_spin_lock_irq(&pi_state->owner->pi_lock);
@@ -2351,9 +2348,10 @@ retry:
2351 /* 2348 /*
2352 * To avoid races, try to do the TID -> 0 atomic transition 2349 * To avoid races, try to do the TID -> 0 atomic transition
2353 * again. If it succeeds then we can return without waking 2350 * again. If it succeeds then we can return without waking
2354 * anyone else up: 2351 * anyone else up. We only try this if neither the waiters nor
2352 * the owner died bit are set.
2355 */ 2353 */
2356 if (!(uval & FUTEX_OWNER_DIED) && 2354 if (!(uval & ~FUTEX_TID_MASK) &&
2357 cmpxchg_futex_value_locked(&uval, uaddr, vpid, 0)) 2355 cmpxchg_futex_value_locked(&uval, uaddr, vpid, 0))
2358 goto pi_faulted; 2356 goto pi_faulted;
2359 /* 2357 /*
@@ -2383,11 +2381,9 @@ retry:
2383 /* 2381 /*
2384 * No waiters - kernel unlocks the futex: 2382 * No waiters - kernel unlocks the futex:
2385 */ 2383 */
2386 if (!(uval & FUTEX_OWNER_DIED)) { 2384 ret = unlock_futex_pi(uaddr, uval);
2387 ret = unlock_futex_pi(uaddr, uval); 2385 if (ret == -EFAULT)
2388 if (ret == -EFAULT) 2386 goto pi_faulted;
2389 goto pi_faulted;
2390 }
2391 2387
2392out_unlock: 2388out_unlock:
2393 spin_unlock(&hb->lock); 2389 spin_unlock(&hb->lock);