|
@@ -716,7 +716,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
|
|
|
struct futex_pi_state **ps,
|
|
|
struct task_struct *task, int set_waiters)
|
|
|
{
|
|
|
- int lock_taken, ret, ownerdied = 0;
|
|
|
+ int lock_taken, ret, force_take = 0;
|
|
|
u32 uval, newval, curval, vpid = task_pid_vnr(task);
|
|
|
|
|
|
retry:
|
|
@@ -755,17 +755,15 @@ retry:
|
|
|
newval = curval | FUTEX_WAITERS;
|
|
|
|
|
|
/*
|
|
|
- * There are two cases, where a futex might have no owner (the
|
|
|
- * owner TID is 0): OWNER_DIED. We take over the futex in this
|
|
|
- * case. We also do an unconditional take over, when the owner
|
|
|
- * of the futex died.
|
|
|
- *
|
|
|
- * This is safe as we are protected by the hash bucket lock !
|
|
|
+ * Should we force take the futex? See below.
|
|
|
*/
|
|
|
- if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) {
|
|
|
- /* Keep the OWNER_DIED bit */
|
|
|
+ if (unlikely(force_take)) {
|
|
|
+ /*
|
|
|
+ * Keep the OWNER_DIED and the WAITERS bit and set the
|
|
|
+ * new TID value.
|
|
|
+ */
|
|
|
newval = (curval & ~FUTEX_TID_MASK) | vpid;
|
|
|
- ownerdied = 0;
|
|
|
+ force_take = 0;
|
|
|
lock_taken = 1;
|
|
|
}
|
|
|
|
|
@@ -775,7 +773,7 @@ retry:
|
|
|
goto retry;
|
|
|
|
|
|
/*
|
|
|
- * We took the lock due to owner died take over.
|
|
|
+ * We took the lock due to forced take over.
|
|
|
*/
|
|
|
if (unlikely(lock_taken))
|
|
|
return 1;
|
|
@@ -790,20 +788,25 @@ retry:
|
|
|
switch (ret) {
|
|
|
case -ESRCH:
|
|
|
/*
|
|
|
- * No owner found for this futex. Check if the
|
|
|
- * OWNER_DIED bit is set to figure out whether
|
|
|
- * this is a robust futex or not.
|
|
|
+ * We failed to find an owner for this
|
|
|
+ * futex. So we have no pi_state to block
|
|
|
+ * on. This can happen in two cases:
|
|
|
+ *
|
|
|
+ * 1) The owner died
|
|
|
+ * 2) A stale FUTEX_WAITERS bit
|
|
|
+ *
|
|
|
+ * Re-read the futex value.
|
|
|
*/
|
|
|
if (get_futex_value_locked(&curval, uaddr))
|
|
|
return -EFAULT;
|
|
|
|
|
|
/*
|
|
|
- * We simply start over in case of a robust
|
|
|
- * futex. The code above will take the futex
|
|
|
- * and return happy.
|
|
|
+ * If the owner died or we have a stale
|
|
|
+ * WAITERS bit the owner TID in the user space
|
|
|
+ * futex is 0.
|
|
|
*/
|
|
|
- if (curval & FUTEX_OWNER_DIED) {
|
|
|
- ownerdied = 1;
|
|
|
+ if (!(curval & FUTEX_TID_MASK)) {
|
|
|
+ force_take = 1;
|
|
|
goto retry;
|
|
|
}
|
|
|
default:
|