git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
powerpc/ps3: Fix system hang with GCC 5 builds
[pandora-kernel.git]
/
kernel
/
futex.c
diff --git
a/kernel/futex.c
b/kernel/futex.c
index
1bb37d0
..
9dc2c71
100644
(file)
--- a/
kernel/futex.c
+++ b/
kernel/futex.c
@@
-484,8
+484,14
@@
static struct futex_pi_state * alloc_pi_state(void)
return pi_state;
}
return pi_state;
}
+/*
+ * Must be called with the hb lock held.
+ */
static void free_pi_state(struct futex_pi_state *pi_state)
{
static void free_pi_state(struct futex_pi_state *pi_state)
{
+ if (!pi_state)
+ return;
+
if (!atomic_dec_and_test(&pi_state->refcount))
return;
if (!atomic_dec_and_test(&pi_state->refcount))
return;
@@
-1399,15
+1405,6
@@
static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
}
retry:
}
retry:
- if (pi_state != NULL) {
- /*
- * We will have to lookup the pi_state again, so free this one
- * to keep the accounting correct.
- */
- free_pi_state(pi_state);
- pi_state = NULL;
- }
-
ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, VERIFY_READ);
if (unlikely(ret != 0))
goto out;
ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, VERIFY_READ);
if (unlikely(ret != 0))
goto out;
@@
-1495,6
+1492,8
@@
retry_private:
case 0:
break;
case -EFAULT:
case 0:
break;
case -EFAULT:
+ free_pi_state(pi_state);
+ pi_state = NULL;
double_unlock_hb(hb1, hb2);
put_futex_key(&key2);
put_futex_key(&key1);
double_unlock_hb(hb1, hb2);
put_futex_key(&key2);
put_futex_key(&key1);
@@
-1504,6
+1503,8
@@
retry_private:
goto out;
case -EAGAIN:
/* The owner was exiting, try again. */
goto out;
case -EAGAIN:
/* The owner was exiting, try again. */
+ free_pi_state(pi_state);
+ pi_state = NULL;
double_unlock_hb(hb1, hb2);
put_futex_key(&key2);
put_futex_key(&key1);
double_unlock_hb(hb1, hb2);
put_futex_key(&key2);
put_futex_key(&key1);
@@
-1580,6
+1581,7
@@
retry_private:
}
out_unlock:
}
out_unlock:
+ free_pi_state(pi_state);
double_unlock_hb(hb1, hb2);
/*
double_unlock_hb(hb1, hb2);
/*
@@
-1596,8
+1598,6
@@
out_put_keys:
out_put_key1:
put_futex_key(&key1);
out:
out_put_key1:
put_futex_key(&key1);
out:
- if (pi_state != NULL)
- free_pi_state(pi_state);
return ret ? ret : task_count;
}
return ret ? ret : task_count;
}
@@
-2460,6
+2460,7
@@
static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
* shared futexes. We need to compare the keys:
*/
if (match_futex(&q.key, &key2)) {
* shared futexes. We need to compare the keys:
*/
if (match_futex(&q.key, &key2)) {
+ queue_unlock(&q, hb);
ret = -EINVAL;
goto out_put_keys;
}
ret = -EINVAL;
goto out_put_keys;
}
@@
-2491,6
+2492,11
@@
static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
if (q.pi_state && (q.pi_state->owner != current)) {
spin_lock(q.lock_ptr);
ret = fixup_pi_state_owner(uaddr2, &q, current);
if (q.pi_state && (q.pi_state->owner != current)) {
spin_lock(q.lock_ptr);
ret = fixup_pi_state_owner(uaddr2, &q, current);
+ /*
+ * Drop the reference to the pi state which
+ * the requeue_pi() code acquired for us.
+ */
+ free_pi_state(q.pi_state);
spin_unlock(q.lock_ptr);
}
} else {
spin_unlock(q.lock_ptr);
}
} else {