futex: add double_unlock_hb()
Impact: cleanup The futex code uses double_lock_hb() which locks the hb->lock's in pointer value order. There is no parallel unlock routine, and the code unlocks them in name order, ignoring pointer value. This patch adds double_unlock_hb() to refactor the duplicated code segments. Build and boot tested on a 4 way Intel x86_64 workstation. Passes basic pthread_mutex and PI tests out of ltp/testcases/realtime. Signed-off-by: Darren Hart <dvhltc@us.ibm.com> Acked-by: Peter Zijlstra <peterz@infradead.org> Cc: Rusty Russell <rusty@rustcorp.com.au> LKML-Reference: <20090312075552.9856.48021.stgit@Aeon> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
de87fcc124
commit
5eb3dc62fc
@ -690,6 +690,19 @@ double_lock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
double_unlock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
|
||||||
|
{
|
||||||
|
if (hb1 <= hb2) {
|
||||||
|
spin_unlock(&hb2->lock);
|
||||||
|
if (hb1 < hb2)
|
||||||
|
spin_unlock(&hb1->lock);
|
||||||
|
} else { /* hb1 > hb2 */
|
||||||
|
spin_unlock(&hb1->lock);
|
||||||
|
spin_unlock(&hb2->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wake up waiters matching bitset queued on this futex (uaddr).
|
* Wake up waiters matching bitset queued on this futex (uaddr).
|
||||||
*/
|
*/
|
||||||
@ -767,9 +780,7 @@ retry:
|
|||||||
if (unlikely(op_ret < 0)) {
|
if (unlikely(op_ret < 0)) {
|
||||||
u32 dummy;
|
u32 dummy;
|
||||||
|
|
||||||
spin_unlock(&hb1->lock);
|
double_unlock_hb(hb1, hb2);
|
||||||
if (hb1 != hb2)
|
|
||||||
spin_unlock(&hb2->lock);
|
|
||||||
|
|
||||||
#ifndef CONFIG_MMU
|
#ifndef CONFIG_MMU
|
||||||
/*
|
/*
|
||||||
@ -833,9 +844,7 @@ retry:
|
|||||||
ret += op_ret;
|
ret += op_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock(&hb1->lock);
|
double_unlock_hb(hb1, hb2);
|
||||||
if (hb1 != hb2)
|
|
||||||
spin_unlock(&hb2->lock);
|
|
||||||
out_put_keys:
|
out_put_keys:
|
||||||
put_futex_key(fshared, &key2);
|
put_futex_key(fshared, &key2);
|
||||||
out_put_key1:
|
out_put_key1:
|
||||||
@ -876,9 +885,7 @@ retry:
|
|||||||
ret = get_futex_value_locked(&curval, uaddr1);
|
ret = get_futex_value_locked(&curval, uaddr1);
|
||||||
|
|
||||||
if (unlikely(ret)) {
|
if (unlikely(ret)) {
|
||||||
spin_unlock(&hb1->lock);
|
double_unlock_hb(hb1, hb2);
|
||||||
if (hb1 != hb2)
|
|
||||||
spin_unlock(&hb2->lock);
|
|
||||||
|
|
||||||
put_futex_key(fshared, &key2);
|
put_futex_key(fshared, &key2);
|
||||||
put_futex_key(fshared, &key1);
|
put_futex_key(fshared, &key1);
|
||||||
@ -925,9 +932,7 @@ retry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
spin_unlock(&hb1->lock);
|
double_unlock_hb(hb1, hb2);
|
||||||
if (hb1 != hb2)
|
|
||||||
spin_unlock(&hb2->lock);
|
|
||||||
|
|
||||||
/* drop_futex_key_refs() must be called outside the spinlocks. */
|
/* drop_futex_key_refs() must be called outside the spinlocks. */
|
||||||
while (--drop_count >= 0)
|
while (--drop_count >= 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user