diff options
| author | Ingo Molnar <mingo@elte.hu> | 2009-08-24 12:25:44 +0200 | 
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-08-24 12:25:54 +0200 | 
| commit | 5f9ece02401116b29eb04396b99ea092acb75dd8 (patch) | |
| tree | e10386e2dc63c275646b4eb0bed857da7bf86c6a /kernel/futex.c | |
| parent | 9f51e24ee8b5a1595b6a5ac0c2be278a16488e75 (diff) | |
| parent | 422bef879e84104fee6dc68ded0e371dbeb5f88e (diff) | |
| download | olio-linux-3.10-5f9ece02401116b29eb04396b99ea092acb75dd8.tar.xz olio-linux-3.10-5f9ece02401116b29eb04396b99ea092acb75dd8.zip  | |
Merge commit 'v2.6.31-rc7' into x86/cleanups
Merge reason: we were on -rc1 before - go up to -rc7
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/futex.c')
| -rw-r--r-- | kernel/futex.c | 29 | 
1 files changed, 23 insertions, 6 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index 794c862125f..e18cfbdc719 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -247,6 +247,7 @@ again:  	if (err < 0)  		return err; +	page = compound_head(page);  	lock_page(page);  	if (!page->mapping) {  		unlock_page(page); @@ -1009,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); @@ -1029,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);  } @@ -1087,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;  } @@ -1246,8 +1256,15 @@ retry_private:  		if (!match_futex(&this->key, &key1))  			continue; -		WARN_ON(!requeue_pi && this->rt_waiter); -		WARN_ON(requeue_pi && !this->rt_waiter); +		/* +		 * FUTEX_WAIT_REQEUE_PI and FUTEX_CMP_REQUEUE_PI should always +		 * be paired with each other and no other futex ops. +		 */ +		if ((requeue_pi && !this->rt_waiter) || +		    (!requeue_pi && this->rt_waiter)) { +			ret = -EINVAL; +			break; +		}  		/*  		 * Wake nr_wake waiters.  For requeue_pi, if we acquired the @@ -1272,7 +1289,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 */  |