diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/futex.c | 41 |
1 files changed, 22 insertions, 19 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index 3717e7b306e0..20ef219bbe9b 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
| @@ -716,7 +716,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, | |||
| 716 | struct futex_pi_state **ps, | 716 | struct futex_pi_state **ps, |
| 717 | struct task_struct *task, int set_waiters) | 717 | struct task_struct *task, int set_waiters) |
| 718 | { | 718 | { |
| 719 | int lock_taken, ret, ownerdied = 0; | 719 | int lock_taken, ret, force_take = 0; |
| 720 | u32 uval, newval, curval, vpid = task_pid_vnr(task); | 720 | u32 uval, newval, curval, vpid = task_pid_vnr(task); |
| 721 | 721 | ||
| 722 | retry: | 722 | retry: |
| @@ -755,17 +755,15 @@ retry: | |||
| 755 | newval = curval | FUTEX_WAITERS; | 755 | newval = curval | FUTEX_WAITERS; |
| 756 | 756 | ||
| 757 | /* | 757 | /* |
| 758 | * There are two cases, where a futex might have no owner (the | 758 | * Should we force take the futex? See below. |
| 759 | * owner TID is 0): OWNER_DIED. We take over the futex in this | ||
| 760 | * case. We also do an unconditional take over, when the owner | ||
| 761 | * of the futex died. | ||
| 762 | * | ||
| 763 | * This is safe as we are protected by the hash bucket lock ! | ||
| 764 | */ | 759 | */ |
| 765 | if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { | 760 | if (unlikely(force_take)) { |
| 766 | /* Keep the OWNER_DIED bit */ | 761 | /* |
| 762 | * Keep the OWNER_DIED and the WAITERS bit and set the | ||
| 763 | * new TID value. | ||
| 764 | */ | ||
| 767 | newval = (curval & ~FUTEX_TID_MASK) | vpid; | 765 | newval = (curval & ~FUTEX_TID_MASK) | vpid; |
| 768 | ownerdied = 0; | 766 | force_take = 0; |
| 769 | lock_taken = 1; | 767 | lock_taken = 1; |
| 770 | } | 768 | } |
| 771 | 769 | ||
| @@ -775,7 +773,7 @@ retry: | |||
| 775 | goto retry; | 773 | goto retry; |
| 776 | 774 | ||
| 777 | /* | 775 | /* |
| 778 | * We took the lock due to owner died take over. | 776 | * We took the lock due to forced take over. |
| 779 | */ | 777 | */ |
| 780 | if (unlikely(lock_taken)) | 778 | if (unlikely(lock_taken)) |
| 781 | return 1; | 779 | return 1; |
| @@ -790,20 +788,25 @@ retry: | |||
| 790 | switch (ret) { | 788 | switch (ret) { |
| 791 | case -ESRCH: | 789 | case -ESRCH: |
| 792 | /* | 790 | /* |
| 793 | * No owner found for this futex. Check if the | 791 | * We failed to find an owner for this |
| 794 | * OWNER_DIED bit is set to figure out whether | 792 | * futex. So we have no pi_state to block |
| 795 | * this is a robust futex or not. | 793 | * on. This can happen in two cases: |
| 794 | * | ||
| 795 | * 1) The owner died | ||
| 796 | * 2) A stale FUTEX_WAITERS bit | ||
| 797 | * | ||
| 798 | * Re-read the futex value. | ||
| 796 | */ | 799 | */ |
| 797 | if (get_futex_value_locked(&curval, uaddr)) | 800 | if (get_futex_value_locked(&curval, uaddr)) |
| 798 | return -EFAULT; | 801 | return -EFAULT; |
| 799 | 802 | ||
| 800 | /* | 803 | /* |
| 801 | * We simply start over in case of a robust | 804 | * If the owner died or we have a stale |
| 802 | * futex. The code above will take the futex | 805 | * WAITERS bit the owner TID in the user space |
| 803 | * and return happy. | 806 | * futex is 0. |
| 804 | */ | 807 | */ |
| 805 | if (curval & FUTEX_OWNER_DIED) { | 808 | if (!(curval & FUTEX_TID_MASK)) { |
| 806 | ownerdied = 1; | 809 | force_take = 1; |
| 807 | goto retry; | 810 | goto retry; |
| 808 | } | 811 | } |
| 809 | default: | 812 | default: |
