History

futex: Always cleanup owner tid in unlock_pi

If the owner died bit is set at futex_unlock_pi, we currently do not cleanup the user space futex. So the owner TID of the current owner (the unlocker) persists. That's observable inconsistant state, especially when the ownership of the pi state got transferred. Clean it up unconditionally.

Thomas Gleixner committed 12 years ago

Commit 13fbca41 parent b3eaa9f1 file · +18 −22Browse files

Unified · Split

kernel/futex.c+18−22
@@ -1052,6 +1052,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) · 1051 unmodified lines
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) · 17 unmodified lines
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 always1079 * We pass it to the next owner. The WAITERS bit is always
1079 * kept enabled while there is PI state around. We must also1080 * 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: · 1253 unmodified lines
2351 /*2348 /*
2352 * To avoid races, try to do the TID -> 0 atomic transition2349 * To avoid races, try to do the TID -> 0 atomic transition
2353 * again. If it succeeds then we can return without waking2350 * 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: · 23 unmodified lines
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);