Commit 8486d12f authored by Peter Zijlstra's avatar Peter Zijlstra
Browse files

futex: Create hb scopes

parent 2fb29209
Loading
Loading
Loading
Loading
+43 −40
Original line number Diff line number Diff line
@@ -944,7 +944,6 @@ static void exit_pi_state_list(struct task_struct *curr)
{
	struct list_head *next, *head = &curr->pi_state_list;
	struct futex_pi_state *pi_state;
	struct futex_hash_bucket *hb;
	union futex_key key = FUTEX_KEY_INIT;

	/*
@@ -957,6 +956,9 @@ static void exit_pi_state_list(struct task_struct *curr)
		next = head->next;
		pi_state = list_entry(next, struct futex_pi_state, list);
		key = pi_state->key;
		if (1) {
			struct futex_hash_bucket *hb;

			hb = futex_hash(&key);

			/*
@@ -1000,6 +1002,7 @@ static void exit_pi_state_list(struct task_struct *curr)
			raw_spin_unlock(&curr->pi_lock);
			raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
			spin_unlock(&hb->lock);
		}

		rt_mutex_futex_unlock(&pi_state->pi_mutex);
		put_pi_state(pi_state);
+143 −139
Original line number Diff line number Diff line
@@ -920,7 +920,6 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl
	struct hrtimer_sleeper timeout, *to;
	struct task_struct *exiting = NULL;
	struct rt_mutex_waiter rt_waiter;
	struct futex_hash_bucket *hb;
	struct futex_q q = futex_q_init;
	DEFINE_WAKE_Q(wake_q);
	int res, ret;
@@ -939,6 +938,9 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl
		goto out;

retry_private:
	if (1) {
		struct futex_hash_bucket *hb;

		hb = futex_hash(&q.key);
		futex_q_lock(&q, hb);

@@ -1037,7 +1039,7 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl
cleanup:
		/*
		 * If we failed to acquire the lock (deadlock/signal/timeout), we must
	 * must unwind the above, however we canont lock hb->lock because
		 * unwind the above, however we canont lock hb->lock because
		 * rt_mutex already has a waiter enqueued and hb->lock can itself try
		 * and enqueue an rt_waiter through rtlock.
		 *
@@ -1085,13 +1087,7 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl

out_unlock_put_key:
		futex_q_unlock(hb);

out:
	if (to) {
		hrtimer_cancel(&to->timer);
		destroy_hrtimer_on_stack(&to->timer);
	}
	return ret != -EINTR ? ret : -ERESTARTNOINTR;
		goto out;

uaddr_faulted:
		futex_q_unlock(hb);
@@ -1106,6 +1102,14 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl
		goto retry;
	}

out:
	if (to) {
		hrtimer_cancel(&to->timer);
		destroy_hrtimer_on_stack(&to->timer);
	}
	return ret != -EINTR ? ret : -ERESTARTNOINTR;
}

/*
 * Userspace attempted a TID -> 0 atomic transition, and failed.
 * This is the in-kernel slowpath: we look up the PI state (if any),
+208 −205
Original line number Diff line number Diff line
@@ -371,7 +371,6 @@ int futex_requeue(u32 __user *uaddr1, unsigned int flags1,
	union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
	int task_count = 0, ret;
	struct futex_pi_state *pi_state = NULL;
	struct futex_hash_bucket *hb1, *hb2;
	struct futex_q *this, *next;
	DEFINE_WAKE_Q(wake_q);

@@ -443,10 +442,13 @@ int futex_requeue(u32 __user *uaddr1, unsigned int flags1,
	if (requeue_pi && futex_match(&key1, &key2))
		return -EINVAL;

retry_private:
	if (1) {
		struct futex_hash_bucket *hb1, *hb2;

		hb1 = futex_hash(&key1);
		hb2 = futex_hash(&key2);

retry_private:
		futex_hb_waiters_inc(hb2);
		double_lock_hb(hb1, hb2);

@@ -675,8 +677,9 @@ int futex_requeue(u32 __user *uaddr1, unsigned int flags1,

out_unlock:
		double_unlock_hb(hb1, hb2);
	wake_up_q(&wake_q);
		futex_hb_waiters_dec(hb2);
	}
	wake_up_q(&wake_q);
	return ret ? ret : task_count;
}

+99 −90
Original line number Diff line number Diff line
@@ -253,7 +253,6 @@ int futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
		  int nr_wake, int nr_wake2, int op)
{
	union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
	struct futex_hash_bucket *hb1, *hb2;
	struct futex_q *this, *next;
	int ret, op_ret;
	DEFINE_WAKE_Q(wake_q);
@@ -266,10 +265,13 @@ int futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
	if (unlikely(ret != 0))
		return ret;

retry_private:
	if (1) {
		struct futex_hash_bucket *hb1, *hb2;

		hb1 = futex_hash(&key1);
		hb2 = futex_hash(&key2);

retry_private:
		double_lock_hb(hb1, hb2);
		op_ret = futex_atomic_op_inuser(op, uaddr2);
		if (unlikely(op_ret < 0)) {
@@ -327,6 +329,7 @@ int futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,

out_unlock:
		double_unlock_hb(hb1, hb2);
	}
	wake_up_q(&wake_q);
	return ret;
}
@@ -402,7 +405,6 @@ int futex_unqueue_multiple(struct futex_vector *v, int count)
 */
int futex_wait_multiple_setup(struct futex_vector *vs, int count, int *woken)
{
	struct futex_hash_bucket *hb;
	bool retry = false;
	int ret, i;
	u32 uval;
@@ -441,6 +443,9 @@ int futex_wait_multiple_setup(struct futex_vector *vs, int count, int *woken)
		struct futex_q *q = &vs[i].q;
		u32 val = vs[i].w.val;

		if (1) {
			struct futex_hash_bucket *hb;

			hb = futex_hash(&q->key);
			futex_q_lock(q, hb);
			ret = futex_get_value_locked(&uval, uaddr);
@@ -456,6 +461,7 @@ int futex_wait_multiple_setup(struct futex_vector *vs, int count, int *woken)
			}

			futex_q_unlock(hb);
		}
		__set_current_state(TASK_RUNNING);

		/*
@@ -584,7 +590,6 @@ int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
		     struct futex_q *q, union futex_key *key2,
		     struct task_struct *task)
{
	struct futex_hash_bucket *hb;
	u32 uval;
	int ret;

@@ -612,6 +617,9 @@ int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
		return ret;

retry_private:
	if (1) {
		struct futex_hash_bucket *hb;

		hb = futex_hash(&q->key);
		futex_q_lock(q, hb);

@@ -649,6 +657,7 @@ int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
		if (task == current)
			set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE);
		futex_queue(q, hb, task);
	}

	return ret;
}