diff options
Diffstat (limited to 'kernel/futex.c')
| -rw-r--r-- | kernel/futex.c | 36 |
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 | */ | ||
| 612 | static inline void | ||
| 613 | double_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 | ||
| 674 | retry: | 692 | retry: |
| 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 |
