|
@@ -1010,15 +1010,19 @@ void requeue_futex(struct futex_q *q, struct futex_hash_bucket *hb1,
|
|
|
* requeue_pi_wake_futex() - Wake a task that acquired the lock during requeue
|
|
|
* q: the futex_q
|
|
|
* key: the key of the requeue target futex
|
|
|
+ * hb: the hash_bucket of the requeue target futex
|
|
|
*
|
|
|
* During futex_requeue, with requeue_pi=1, it is possible to acquire the
|
|
|
* target futex if it is uncontended or via a lock steal. Set the futex_q key
|
|
|
* to the requeue target futex so the waiter can detect the wakeup on the right
|
|
|
* futex, but remove it from the hb and NULL the rt_waiter so it can detect
|
|
|
- * atomic lock acquisition. Must be called with the q->lock_ptr held.
|
|
|
+ * atomic lock acquisition. Set the q->lock_ptr to the requeue target hb->lock
|
|
|
+ * to protect access to the pi_state to fixup the owner later. Must be called
|
|
|
+ * with both q->lock_ptr and hb->lock held.
|
|
|
*/
|
|
|
static inline
|
|
|
-void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key)
|
|
|
+void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
|
|
|
+ struct futex_hash_bucket *hb)
|
|
|
{
|
|
|
drop_futex_key_refs(&q->key);
|
|
|
get_futex_key_refs(key);
|
|
@@ -1030,6 +1034,11 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key)
|
|
|
WARN_ON(!q->rt_waiter);
|
|
|
q->rt_waiter = NULL;
|
|
|
|
|
|
+ q->lock_ptr = &hb->lock;
|
|
|
+#ifdef CONFIG_DEBUG_PI_LIST
|
|
|
+ q->list.plist.lock = &hb->lock;
|
|
|
+#endif
|
|
|
+
|
|
|
wake_up_state(q->task, TASK_NORMAL);
|
|
|
}
|
|
|
|
|
@@ -1088,7 +1097,7 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
|
|
|
ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task,
|
|
|
set_waiters);
|
|
|
if (ret == 1)
|
|
|
- requeue_pi_wake_futex(top_waiter, key2);
|
|
|
+ requeue_pi_wake_futex(top_waiter, key2, hb2);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
@@ -1273,7 +1282,7 @@ retry_private:
|
|
|
this->task, 1);
|
|
|
if (ret == 1) {
|
|
|
/* We got the lock. */
|
|
|
- requeue_pi_wake_futex(this, &key2);
|
|
|
+ requeue_pi_wake_futex(this, &key2, hb2);
|
|
|
continue;
|
|
|
} else if (ret) {
|
|
|
/* -EDEADLK */
|