|
@@ -1363,7 +1363,6 @@ static inline struct futex_hash_bucket *queue_lock(struct futex_q *q)
|
|
{
|
|
{
|
|
struct futex_hash_bucket *hb;
|
|
struct futex_hash_bucket *hb;
|
|
|
|
|
|
- get_futex_key_refs(&q->key);
|
|
|
|
hb = hash_futex(&q->key);
|
|
hb = hash_futex(&q->key);
|
|
q->lock_ptr = &hb->lock;
|
|
q->lock_ptr = &hb->lock;
|
|
|
|
|
|
@@ -1375,7 +1374,6 @@ static inline void
|
|
queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb)
|
|
queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb)
|
|
{
|
|
{
|
|
spin_unlock(&hb->lock);
|
|
spin_unlock(&hb->lock);
|
|
- drop_futex_key_refs(&q->key);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -1480,8 +1478,6 @@ static void unqueue_me_pi(struct futex_q *q)
|
|
q->pi_state = NULL;
|
|
q->pi_state = NULL;
|
|
|
|
|
|
spin_unlock(q->lock_ptr);
|
|
spin_unlock(q->lock_ptr);
|
|
-
|
|
|
|
- drop_futex_key_refs(&q->key);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1812,7 +1808,10 @@ static int futex_wait(u32 __user *uaddr, int fshared,
|
|
}
|
|
}
|
|
|
|
|
|
retry:
|
|
retry:
|
|
- /* Prepare to wait on uaddr. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Prepare to wait on uaddr. On success, holds hb lock and increments
|
|
|
|
+ * q.key refs.
|
|
|
|
+ */
|
|
ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
|
|
ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
|
|
if (ret)
|
|
if (ret)
|
|
goto out;
|
|
goto out;
|
|
@@ -1822,24 +1821,23 @@ retry:
|
|
|
|
|
|
/* If we were woken (and unqueued), we succeeded, whatever. */
|
|
/* If we were woken (and unqueued), we succeeded, whatever. */
|
|
ret = 0;
|
|
ret = 0;
|
|
|
|
+ /* unqueue_me() drops q.key ref */
|
|
if (!unqueue_me(&q))
|
|
if (!unqueue_me(&q))
|
|
- goto out_put_key;
|
|
|
|
|
|
+ goto out;
|
|
ret = -ETIMEDOUT;
|
|
ret = -ETIMEDOUT;
|
|
if (to && !to->task)
|
|
if (to && !to->task)
|
|
- goto out_put_key;
|
|
|
|
|
|
+ goto out;
|
|
|
|
|
|
/*
|
|
/*
|
|
* We expect signal_pending(current), but we might be the
|
|
* We expect signal_pending(current), but we might be the
|
|
* victim of a spurious wakeup as well.
|
|
* victim of a spurious wakeup as well.
|
|
*/
|
|
*/
|
|
- if (!signal_pending(current)) {
|
|
|
|
- put_futex_key(fshared, &q.key);
|
|
|
|
|
|
+ if (!signal_pending(current))
|
|
goto retry;
|
|
goto retry;
|
|
- }
|
|
|
|
|
|
|
|
ret = -ERESTARTSYS;
|
|
ret = -ERESTARTSYS;
|
|
if (!abs_time)
|
|
if (!abs_time)
|
|
- goto out_put_key;
|
|
|
|
|
|
+ goto out;
|
|
|
|
|
|
restart = ¤t_thread_info()->restart_block;
|
|
restart = ¤t_thread_info()->restart_block;
|
|
restart->fn = futex_wait_restart;
|
|
restart->fn = futex_wait_restart;
|
|
@@ -1856,8 +1854,6 @@ retry:
|
|
|
|
|
|
ret = -ERESTART_RESTARTBLOCK;
|
|
ret = -ERESTART_RESTARTBLOCK;
|
|
|
|
|
|
-out_put_key:
|
|
|
|
- put_futex_key(fshared, &q.key);
|
|
|
|
out:
|
|
out:
|
|
if (to) {
|
|
if (to) {
|
|
hrtimer_cancel(&to->timer);
|
|
hrtimer_cancel(&to->timer);
|
|
@@ -2236,7 +2232,10 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared,
|
|
q.rt_waiter = &rt_waiter;
|
|
q.rt_waiter = &rt_waiter;
|
|
q.requeue_pi_key = &key2;
|
|
q.requeue_pi_key = &key2;
|
|
|
|
|
|
- /* Prepare to wait on uaddr. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Prepare to wait on uaddr. On success, increments q.key (key1) ref
|
|
|
|
+ * count.
|
|
|
|
+ */
|
|
ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
|
|
ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
|
|
if (ret)
|
|
if (ret)
|
|
goto out_key2;
|
|
goto out_key2;
|
|
@@ -2254,7 +2253,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared,
|
|
* In order for us to be here, we know our q.key == key2, and since
|
|
* In order for us to be here, we know our q.key == key2, and since
|
|
* we took the hb->lock above, we also know that futex_requeue() has
|
|
* we took the hb->lock above, we also know that futex_requeue() has
|
|
* completed and we no longer have to concern ourselves with a wakeup
|
|
* completed and we no longer have to concern ourselves with a wakeup
|
|
- * race with the atomic proxy lock acquition by the requeue code.
|
|
|
|
|
|
+ * race with the atomic proxy lock acquisition by the requeue code. The
|
|
|
|
+ * futex_requeue dropped our key1 reference and incremented our key2
|
|
|
|
+ * reference count.
|
|
*/
|
|
*/
|
|
|
|
|
|
/* Check if the requeue code acquired the second futex for us. */
|
|
/* Check if the requeue code acquired the second futex for us. */
|