[tip:core/futexes] futex: add double_unlock_hb()

From: Darren Hart
Date: Thu Mar 12 2009 - 06:26:28 EST


Commit-ID: 5eb3dc62fc5986e85715041c23dcf3832812be4b
Gitweb: http://git.kernel.org/tip/5eb3dc62fc5986e85715041c23dcf3832812be4b
Author: "Darren Hart" <dvhltc@xxxxxxxxxx>
AuthorDate: Thu, 12 Mar 2009 00:55:52 -0700
Commit: Ingo Molnar <mingo@xxxxxxx>
CommitDate: Thu, 12 Mar 2009 11:20:56 +0100

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@xxxxxxxxxx>
Acked-by: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: Rusty Russell <rusty@xxxxxxxxxxxxxxx>
LKML-Reference: <20090312075552.9856.48021.stgit@Aeon>
Signed-off-by: Ingo Molnar <mingo@xxxxxxx>


---
kernel/futex.c | 29 +++++++++++++++++------------
1 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/kernel/futex.c b/kernel/futex.c
index 4000454..e149545 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -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).
*/
@@ -767,9 +780,7 @@ retry:
if (unlikely(op_ret < 0)) {
u32 dummy;

- spin_unlock(&hb1->lock);
- if (hb1 != hb2)
- spin_unlock(&hb2->lock);
+ double_unlock_hb(hb1, hb2);

#ifndef CONFIG_MMU
/*
@@ -833,9 +844,7 @@ retry:
ret += op_ret;
}

- spin_unlock(&hb1->lock);
- if (hb1 != hb2)
- spin_unlock(&hb2->lock);
+ double_unlock_hb(hb1, hb2);
out_put_keys:
put_futex_key(fshared, &key2);
out_put_key1:
@@ -876,9 +885,7 @@ retry:
ret = get_futex_value_locked(&curval, uaddr1);

if (unlikely(ret)) {
- spin_unlock(&hb1->lock);
- if (hb1 != hb2)
- spin_unlock(&hb2->lock);
+ double_unlock_hb(hb1, hb2);

put_futex_key(fshared, &key2);
put_futex_key(fshared, &key1);
@@ -925,9 +932,7 @@ retry:
}

out_unlock:
- spin_unlock(&hb1->lock);
- if (hb1 != hb2)
- spin_unlock(&hb2->lock);
+ double_unlock_hb(hb1, hb2);

/* drop_futex_key_refs() must be called outside the spinlocks. */
while (--drop_count >= 0)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/