aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/futex.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/futex.c')
-rw-r--r--kernel/futex.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/kernel/futex.c b/kernel/futex.c
index 6c91f938005d..1dc98e4dd287 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -607,6 +607,22 @@ static int unlock_futex_pi(u32 __user *uaddr, u32 uval)
607} 607}
608 608
609/* 609/*
610 * Express the locking dependencies for lockdep:
611 */
612static inline void
613double_lock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
614{
615 if (hb1 <= hb2) {
616 spin_lock(&hb1->lock);
617 if (hb1 < hb2)
618 spin_lock_nested(&hb2->lock, SINGLE_DEPTH_NESTING);
619 } else { /* hb1 > hb2 */
620 spin_lock(&hb2->lock);
621 spin_lock_nested(&hb1->lock, SINGLE_DEPTH_NESTING);
622 }
623}
624
625/*
610 * Wake up all waiters hashed on the physical page that is mapped 626 * Wake up all waiters hashed on the physical page that is mapped
611 * to this virtual address: 627 * to this virtual address:
612 */ 628 */
@@ -630,8 +646,10 @@ static int futex_wake(u32 __user *uaddr, int nr_wake)
630 646
631 list_for_each_entry_safe(this, next, head, list) { 647 list_for_each_entry_safe(this, next, head, list) {
632 if (match_futex (&this->key, &key)) { 648 if (match_futex (&this->key, &key)) {
633 if (this->pi_state) 649 if (this->pi_state) {
634 return -EINVAL; 650 ret = -EINVAL;
651 break;
652 }
635 wake_futex(this); 653 wake_futex(this);
636 if (++ret >= nr_wake) 654 if (++ret >= nr_wake)
637 break; 655 break;
@@ -672,11 +690,7 @@ retryfull:
672 hb2 = hash_futex(&key2); 690 hb2 = hash_futex(&key2);
673 691
674retry: 692retry:
675 if (hb1 < hb2) 693 double_lock_hb(hb1, hb2);
676 spin_lock(&hb1->lock);
677 spin_lock(&hb2->lock);
678 if (hb1 > hb2)
679 spin_lock(&hb1->lock);
680 694
681 op_ret = futex_atomic_op_inuser(op, uaddr2); 695 op_ret = futex_atomic_op_inuser(op, uaddr2);
682 if (unlikely(op_ret < 0)) { 696 if (unlikely(op_ret < 0)) {
@@ -785,11 +799,7 @@ static int futex_requeue(u32 __user *uaddr1, u32 __user *uaddr2,
785 hb1 = hash_futex(&key1); 799 hb1 = hash_futex(&key1);
786 hb2 = hash_futex(&key2); 800 hb2 = hash_futex(&key2);
787 801
788 if (hb1 < hb2) 802 double_lock_hb(hb1, hb2);
789 spin_lock(&hb1->lock);
790 spin_lock(&hb2->lock);
791 if (hb1 > hb2)
792 spin_lock(&hb1->lock);
793 803
794 if (likely(cmpval != NULL)) { 804 if (likely(cmpval != NULL)) {
795 u32 curval; 805 u32 curval;
@@ -1208,7 +1218,7 @@ static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock,
1208 } 1218 }
1209 1219
1210 down_read(&curr->mm->mmap_sem); 1220 down_read(&curr->mm->mmap_sem);
1211 hb = queue_lock(&q, -1, NULL); 1221 spin_lock(q.lock_ptr);
1212 1222
1213 /* 1223 /*
1214 * Got the lock. We might not be the anticipated owner if we 1224 * Got the lock. We might not be the anticipated owner if we