diff options
Diffstat (limited to 'kernel/futex.c')
-rw-r--r-- | kernel/futex.c | 45 |
1 files changed, 15 insertions, 30 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index 773815465bac..237f14bfc022 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -381,15 +381,16 @@ static struct futex_q *futex_top_waiter(struct futex_hash_bucket *hb, | |||
381 | return NULL; | 381 | return NULL; |
382 | } | 382 | } |
383 | 383 | ||
384 | static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval) | 384 | static int cmpxchg_futex_value_locked(u32 *curval, u32 __user *uaddr, |
385 | u32 uval, u32 newval) | ||
385 | { | 386 | { |
386 | u32 curval; | 387 | int ret; |
387 | 388 | ||
388 | pagefault_disable(); | 389 | pagefault_disable(); |
389 | curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); | 390 | ret = futex_atomic_cmpxchg_inatomic(curval, uaddr, uval, newval); |
390 | pagefault_enable(); | 391 | pagefault_enable(); |
391 | 392 | ||
392 | return curval; | 393 | return ret; |
393 | } | 394 | } |
394 | 395 | ||
395 | static int get_futex_value_locked(u32 *dest, u32 __user *from) | 396 | static int get_futex_value_locked(u32 *dest, u32 __user *from) |
@@ -688,9 +689,7 @@ retry: | |||
688 | if (set_waiters) | 689 | if (set_waiters) |
689 | newval |= FUTEX_WAITERS; | 690 | newval |= FUTEX_WAITERS; |
690 | 691 | ||
691 | curval = cmpxchg_futex_value_locked(uaddr, 0, newval); | 692 | if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, 0, newval))) |
692 | |||
693 | if (unlikely(curval == -EFAULT)) | ||
694 | return -EFAULT; | 693 | return -EFAULT; |
695 | 694 | ||
696 | /* | 695 | /* |
@@ -728,9 +727,7 @@ retry: | |||
728 | lock_taken = 1; | 727 | lock_taken = 1; |
729 | } | 728 | } |
730 | 729 | ||
731 | curval = cmpxchg_futex_value_locked(uaddr, uval, newval); | 730 | if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))) |
732 | |||
733 | if (unlikely(curval == -EFAULT)) | ||
734 | return -EFAULT; | 731 | return -EFAULT; |
735 | if (unlikely(curval != uval)) | 732 | if (unlikely(curval != uval)) |
736 | goto retry; | 733 | goto retry; |
@@ -843,9 +840,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) | |||
843 | 840 | ||
844 | newval = FUTEX_WAITERS | task_pid_vnr(new_owner); | 841 | newval = FUTEX_WAITERS | task_pid_vnr(new_owner); |
845 | 842 | ||
846 | curval = cmpxchg_futex_value_locked(uaddr, uval, newval); | 843 | if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) |
847 | |||
848 | if (curval == -EFAULT) | ||
849 | ret = -EFAULT; | 844 | ret = -EFAULT; |
850 | else if (curval != uval) | 845 | else if (curval != uval) |
851 | ret = -EINVAL; | 846 | ret = -EINVAL; |
@@ -880,10 +875,8 @@ static int unlock_futex_pi(u32 __user *uaddr, u32 uval) | |||
880 | * There is no waiter, so we unlock the futex. The owner died | 875 | * There is no waiter, so we unlock the futex. The owner died |
881 | * bit has not to be preserved here. We are the owner: | 876 | * bit has not to be preserved here. We are the owner: |
882 | */ | 877 | */ |
883 | oldval = cmpxchg_futex_value_locked(uaddr, uval, 0); | 878 | if (cmpxchg_futex_value_locked(&oldval, uaddr, uval, 0)) |
884 | 879 | return -EFAULT; | |
885 | if (oldval == -EFAULT) | ||
886 | return oldval; | ||
887 | if (oldval != uval) | 880 | if (oldval != uval) |
888 | return -EAGAIN; | 881 | return -EAGAIN; |
889 | 882 | ||
@@ -1578,9 +1571,7 @@ retry: | |||
1578 | while (1) { | 1571 | while (1) { |
1579 | newval = (uval & FUTEX_OWNER_DIED) | newtid; | 1572 | newval = (uval & FUTEX_OWNER_DIED) | newtid; |
1580 | 1573 | ||
1581 | curval = cmpxchg_futex_value_locked(uaddr, uval, newval); | 1574 | if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) |
1582 | |||
1583 | if (curval == -EFAULT) | ||
1584 | goto handle_fault; | 1575 | goto handle_fault; |
1585 | if (curval == uval) | 1576 | if (curval == uval) |
1586 | break; | 1577 | break; |
@@ -2073,11 +2064,8 @@ retry: | |||
2073 | * again. If it succeeds then we can return without waking | 2064 | * again. If it succeeds then we can return without waking |
2074 | * anyone else up: | 2065 | * anyone else up: |
2075 | */ | 2066 | */ |
2076 | if (!(uval & FUTEX_OWNER_DIED)) | 2067 | if (!(uval & FUTEX_OWNER_DIED) && |
2077 | uval = cmpxchg_futex_value_locked(uaddr, vpid, 0); | 2068 | cmpxchg_futex_value_locked(&uval, uaddr, vpid, 0)) |
2078 | |||
2079 | |||
2080 | if (unlikely(uval == -EFAULT)) | ||
2081 | goto pi_faulted; | 2069 | goto pi_faulted; |
2082 | /* | 2070 | /* |
2083 | * Rare case: we managed to release the lock atomically, | 2071 | * Rare case: we managed to release the lock atomically, |
@@ -2464,9 +2452,7 @@ retry: | |||
2464 | * userspace. | 2452 | * userspace. |
2465 | */ | 2453 | */ |
2466 | mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; | 2454 | mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; |
2467 | nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval); | 2455 | if (futex_atomic_cmpxchg_inatomic(&nval, uaddr, uval, mval)) |
2468 | |||
2469 | if (nval == -EFAULT) | ||
2470 | return -1; | 2456 | return -1; |
2471 | 2457 | ||
2472 | if (nval != uval) | 2458 | if (nval != uval) |
@@ -2679,8 +2665,7 @@ static int __init futex_init(void) | |||
2679 | * implementation, the non-functional ones will return | 2665 | * implementation, the non-functional ones will return |
2680 | * -ENOSYS. | 2666 | * -ENOSYS. |
2681 | */ | 2667 | */ |
2682 | curval = cmpxchg_futex_value_locked(NULL, 0, 0); | 2668 | if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT) |
2683 | if (curval == -EFAULT) | ||
2684 | futex_cmpxchg_enabled = 1; | 2669 | futex_cmpxchg_enabled = 1; |
2685 | 2670 | ||
2686 | for (i = 0; i < ARRAY_SIZE(futex_queues); i++) { | 2671 | for (i = 0; i < ARRAY_SIZE(futex_queues); i++) { |