|
@@ -843,6 +843,9 @@ static void wake_futex(struct futex_q *q)
|
|
|
{
|
|
|
struct task_struct *p = q->task;
|
|
|
|
|
|
+ if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n"))
|
|
|
+ return;
|
|
|
+
|
|
|
/*
|
|
|
* We set q->lock_ptr = NULL _before_ we wake up the task. If
|
|
|
* a non-futex wake up happens on another CPU then the task
|
|
@@ -1078,6 +1081,10 @@ retry_private:
|
|
|
|
|
|
plist_for_each_entry_safe(this, next, head, list) {
|
|
|
if (match_futex (&this->key, &key1)) {
|
|
|
+ if (this->pi_state || this->rt_waiter) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto out_unlock;
|
|
|
+ }
|
|
|
wake_futex(this);
|
|
|
if (++ret >= nr_wake)
|
|
|
break;
|
|
@@ -1090,6 +1097,10 @@ retry_private:
|
|
|
op_ret = 0;
|
|
|
plist_for_each_entry_safe(this, next, head, list) {
|
|
|
if (match_futex (&this->key, &key2)) {
|
|
|
+ if (this->pi_state || this->rt_waiter) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto out_unlock;
|
|
|
+ }
|
|
|
wake_futex(this);
|
|
|
if (++op_ret >= nr_wake2)
|
|
|
break;
|
|
@@ -1098,6 +1109,7 @@ retry_private:
|
|
|
ret += op_ret;
|
|
|
}
|
|
|
|
|
|
+out_unlock:
|
|
|
double_unlock_hb(hb1, hb2);
|
|
|
out_put_keys:
|
|
|
put_futex_key(&key2);
|
|
@@ -1387,9 +1399,13 @@ retry_private:
|
|
|
/*
|
|
|
* FUTEX_WAIT_REQEUE_PI and FUTEX_CMP_REQUEUE_PI should always
|
|
|
* be paired with each other and no other futex ops.
|
|
|
+ *
|
|
|
+ * We should never be requeueing a futex_q with a pi_state,
|
|
|
+ * which is awaiting a futex_unlock_pi().
|
|
|
*/
|
|
|
if ((requeue_pi && !this->rt_waiter) ||
|
|
|
- (!requeue_pi && this->rt_waiter)) {
|
|
|
+ (!requeue_pi && this->rt_waiter) ||
|
|
|
+ this->pi_state) {
|
|
|
ret = -EINVAL;
|
|
|
break;
|
|
|
}
|