aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2019-05-01 10:34:17 -0400
committerWill Deacon <will.deacon@arm.com>2019-05-01 10:34:17 -0400
commit9431ac2bf6b742d87cdac051adc1976308070110 (patch)
tree653c740b32bd411c2b79f81ecd6841f46814c87b
parent61cf61d81e326163ce1557ceccfca76e11d0e57c (diff)
parent427503519739e779c0db8afe876c1b33f3ac60ae (diff)
Merge branch 'for-next/futex' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux into for-next/core
-rw-r--r--Documentation/robust-futexes.txt3
-rw-r--r--arch/arm64/include/asm/futex.h63
-rw-r--r--include/asm-generic/futex.h8
-rw-r--r--kernel/futex.c188
4 files changed, 163 insertions, 99 deletions
diff --git a/Documentation/robust-futexes.txt b/Documentation/robust-futexes.txt
index 6c42c75103eb..6361fb01c9c1 100644
--- a/Documentation/robust-futexes.txt
+++ b/Documentation/robust-futexes.txt
@@ -218,5 +218,4 @@ All other architectures should build just fine too - but they won't have
218the new syscalls yet. 218the new syscalls yet.
219 219
220Architectures need to implement the new futex_atomic_cmpxchg_inatomic() 220Architectures need to implement the new futex_atomic_cmpxchg_inatomic()
221inline function before writing up the syscalls (that function returns 221inline function before writing up the syscalls.
222-ENOSYS right now).
diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h
index cccb83ad7fa8..bdb3c05070a2 100644
--- a/arch/arm64/include/asm/futex.h
+++ b/arch/arm64/include/asm/futex.h
@@ -23,26 +23,34 @@
23 23
24#include <asm/errno.h> 24#include <asm/errno.h>
25 25
26#define FUTEX_MAX_LOOPS 128 /* What's the largest number you can think of? */
27
26#define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg) \ 28#define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg) \
27do { \ 29do { \
30 unsigned int loops = FUTEX_MAX_LOOPS; \
31 \
28 uaccess_enable(); \ 32 uaccess_enable(); \
29 asm volatile( \ 33 asm volatile( \
30" prfm pstl1strm, %2\n" \ 34" prfm pstl1strm, %2\n" \
31"1: ldxr %w1, %2\n" \ 35"1: ldxr %w1, %2\n" \
32 insn "\n" \ 36 insn "\n" \
33"2: stlxr %w3, %w0, %2\n" \ 37"2: stlxr %w0, %w3, %2\n" \
34" cbnz %w3, 1b\n" \ 38" cbz %w0, 3f\n" \
35" dmb ish\n" \ 39" sub %w4, %w4, %w0\n" \
40" cbnz %w4, 1b\n" \
41" mov %w0, %w7\n" \
36"3:\n" \ 42"3:\n" \
43" dmb ish\n" \
37" .pushsection .fixup,\"ax\"\n" \ 44" .pushsection .fixup,\"ax\"\n" \
38" .align 2\n" \ 45" .align 2\n" \
39"4: mov %w0, %w5\n" \ 46"4: mov %w0, %w6\n" \
40" b 3b\n" \ 47" b 3b\n" \
41" .popsection\n" \ 48" .popsection\n" \
42 _ASM_EXTABLE(1b, 4b) \ 49 _ASM_EXTABLE(1b, 4b) \
43 _ASM_EXTABLE(2b, 4b) \ 50 _ASM_EXTABLE(2b, 4b) \
44 : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp) \ 51 : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp), \
45 : "r" (oparg), "Ir" (-EFAULT) \ 52 "+r" (loops) \
53 : "r" (oparg), "Ir" (-EFAULT), "Ir" (-EAGAIN) \
46 : "memory"); \ 54 : "memory"); \
47 uaccess_disable(); \ 55 uaccess_disable(); \
48} while (0) 56} while (0)
@@ -50,30 +58,30 @@ do { \
50static inline int 58static inline int
51arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *_uaddr) 59arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *_uaddr)
52{ 60{
53 int oldval = 0, ret, tmp; 61 int oldval, ret, tmp;
54 u32 __user *uaddr = __uaccess_mask_ptr(_uaddr); 62 u32 __user *uaddr = __uaccess_mask_ptr(_uaddr);
55 63
56 pagefault_disable(); 64 pagefault_disable();
57 65
58 switch (op) { 66 switch (op) {
59 case FUTEX_OP_SET: 67 case FUTEX_OP_SET:
60 __futex_atomic_op("mov %w0, %w4", 68 __futex_atomic_op("mov %w3, %w5",
61 ret, oldval, uaddr, tmp, oparg); 69 ret, oldval, uaddr, tmp, oparg);
62 break; 70 break;
63 case FUTEX_OP_ADD: 71 case FUTEX_OP_ADD:
64 __futex_atomic_op("add %w0, %w1, %w4", 72 __futex_atomic_op("add %w3, %w1, %w5",
65 ret, oldval, uaddr, tmp, oparg); 73 ret, oldval, uaddr, tmp, oparg);
66 break; 74 break;
67 case FUTEX_OP_OR: 75 case FUTEX_OP_OR:
68 __futex_atomic_op("orr %w0, %w1, %w4", 76 __futex_atomic_op("orr %w3, %w1, %w5",
69 ret, oldval, uaddr, tmp, oparg); 77 ret, oldval, uaddr, tmp, oparg);
70 break; 78 break;
71 case FUTEX_OP_ANDN: 79 case FUTEX_OP_ANDN:
72 __futex_atomic_op("and %w0, %w1, %w4", 80 __futex_atomic_op("and %w3, %w1, %w5",
73 ret, oldval, uaddr, tmp, ~oparg); 81 ret, oldval, uaddr, tmp, ~oparg);
74 break; 82 break;
75 case FUTEX_OP_XOR: 83 case FUTEX_OP_XOR:
76 __futex_atomic_op("eor %w0, %w1, %w4", 84 __futex_atomic_op("eor %w3, %w1, %w5",
77 ret, oldval, uaddr, tmp, oparg); 85 ret, oldval, uaddr, tmp, oparg);
78 break; 86 break;
79 default: 87 default:
@@ -93,6 +101,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *_uaddr,
93 u32 oldval, u32 newval) 101 u32 oldval, u32 newval)
94{ 102{
95 int ret = 0; 103 int ret = 0;
104 unsigned int loops = FUTEX_MAX_LOOPS;
96 u32 val, tmp; 105 u32 val, tmp;
97 u32 __user *uaddr; 106 u32 __user *uaddr;
98 107
@@ -104,24 +113,30 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *_uaddr,
104 asm volatile("// futex_atomic_cmpxchg_inatomic\n" 113 asm volatile("// futex_atomic_cmpxchg_inatomic\n"
105" prfm pstl1strm, %2\n" 114" prfm pstl1strm, %2\n"
106"1: ldxr %w1, %2\n" 115"1: ldxr %w1, %2\n"
107" sub %w3, %w1, %w4\n" 116" sub %w3, %w1, %w5\n"
108" cbnz %w3, 3f\n" 117" cbnz %w3, 4f\n"
109"2: stlxr %w3, %w5, %2\n" 118"2: stlxr %w3, %w6, %2\n"
110" cbnz %w3, 1b\n" 119" cbz %w3, 3f\n"
111" dmb ish\n" 120" sub %w4, %w4, %w3\n"
121" cbnz %w4, 1b\n"
122" mov %w0, %w8\n"
112"3:\n" 123"3:\n"
124" dmb ish\n"
125"4:\n"
113" .pushsection .fixup,\"ax\"\n" 126" .pushsection .fixup,\"ax\"\n"
114"4: mov %w0, %w6\n" 127"5: mov %w0, %w7\n"
115" b 3b\n" 128" b 4b\n"
116" .popsection\n" 129" .popsection\n"
117 _ASM_EXTABLE(1b, 4b) 130 _ASM_EXTABLE(1b, 5b)
118 _ASM_EXTABLE(2b, 4b) 131 _ASM_EXTABLE(2b, 5b)
119 : "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp) 132 : "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp), "+r" (loops)
120 : "r" (oldval), "r" (newval), "Ir" (-EFAULT) 133 : "r" (oldval), "r" (newval), "Ir" (-EFAULT), "Ir" (-EAGAIN)
121 : "memory"); 134 : "memory");
122 uaccess_disable(); 135 uaccess_disable();
123 136
124 *uval = val; 137 if (!ret)
138 *uval = val;
139
125 return ret; 140 return ret;
126} 141}
127 142
diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
index fcb61b4659b3..8666fe7f35d7 100644
--- a/include/asm-generic/futex.h
+++ b/include/asm-generic/futex.h
@@ -23,7 +23,9 @@
23 * 23 *
24 * Return: 24 * Return:
25 * 0 - On success 25 * 0 - On success
26 * <0 - On error 26 * -EFAULT - User access resulted in a page fault
27 * -EAGAIN - Atomic operation was unable to complete due to contention
28 * -ENOSYS - Operation not supported
27 */ 29 */
28static inline int 30static inline int
29arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr) 31arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
@@ -85,7 +87,9 @@ out_pagefault_enable:
85 * 87 *
86 * Return: 88 * Return:
87 * 0 - On success 89 * 0 - On success
88 * <0 - On error 90 * -EFAULT - User access resulted in a page fault
91 * -EAGAIN - Atomic operation was unable to complete due to contention
92 * -ENOSYS - Function not implemented (only if !HAVE_FUTEX_CMPXCHG)
89 */ 93 */
90static inline int 94static inline int
91futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 95futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
diff --git a/kernel/futex.c b/kernel/futex.c
index 9e40cf7be606..6262f1534ac9 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -1311,13 +1311,15 @@ static int lookup_pi_state(u32 __user *uaddr, u32 uval,
1311 1311
1312static int lock_pi_update_atomic(u32 __user *uaddr, u32 uval, u32 newval) 1312static int lock_pi_update_atomic(u32 __user *uaddr, u32 uval, u32 newval)
1313{ 1313{
1314 int err;
1314 u32 uninitialized_var(curval); 1315 u32 uninitialized_var(curval);
1315 1316
1316 if (unlikely(should_fail_futex(true))) 1317 if (unlikely(should_fail_futex(true)))
1317 return -EFAULT; 1318 return -EFAULT;
1318 1319
1319 if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))) 1320 err = cmpxchg_futex_value_locked(&curval, uaddr, uval, newval);
1320 return -EFAULT; 1321 if (unlikely(err))
1322 return err;
1321 1323
1322 /* If user space value changed, let the caller retry */ 1324 /* If user space value changed, let the caller retry */
1323 return curval != uval ? -EAGAIN : 0; 1325 return curval != uval ? -EAGAIN : 0;
@@ -1502,10 +1504,8 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_
1502 if (unlikely(should_fail_futex(true))) 1504 if (unlikely(should_fail_futex(true)))
1503 ret = -EFAULT; 1505 ret = -EFAULT;
1504 1506
1505 if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) { 1507 ret = cmpxchg_futex_value_locked(&curval, uaddr, uval, newval);
1506 ret = -EFAULT; 1508 if (!ret && (curval != uval)) {
1507
1508 } else if (curval != uval) {
1509 /* 1509 /*
1510 * If a unconditional UNLOCK_PI operation (user space did not 1510 * If a unconditional UNLOCK_PI operation (user space did not
1511 * try the TID->0 transition) raced with a waiter setting the 1511 * try the TID->0 transition) raced with a waiter setting the
@@ -1700,32 +1700,32 @@ retry_private:
1700 double_lock_hb(hb1, hb2); 1700 double_lock_hb(hb1, hb2);
1701 op_ret = futex_atomic_op_inuser(op, uaddr2); 1701 op_ret = futex_atomic_op_inuser(op, uaddr2);
1702 if (unlikely(op_ret < 0)) { 1702 if (unlikely(op_ret < 0)) {
1703
1704 double_unlock_hb(hb1, hb2); 1703 double_unlock_hb(hb1, hb2);
1705 1704
1706#ifndef CONFIG_MMU 1705 if (!IS_ENABLED(CONFIG_MMU) ||
1707 /* 1706 unlikely(op_ret != -EFAULT && op_ret != -EAGAIN)) {
1708 * we don't get EFAULT from MMU faults if we don't have an MMU, 1707 /*
1709 * but we might get them from range checking 1708 * we don't get EFAULT from MMU faults if we don't have
1710 */ 1709 * an MMU, but we might get them from range checking
1711 ret = op_ret; 1710 */
1712 goto out_put_keys;
1713#endif
1714
1715 if (unlikely(op_ret != -EFAULT)) {
1716 ret = op_ret; 1711 ret = op_ret;
1717 goto out_put_keys; 1712 goto out_put_keys;
1718 } 1713 }
1719 1714
1720 ret = fault_in_user_writeable(uaddr2); 1715 if (op_ret == -EFAULT) {
1721 if (ret) 1716 ret = fault_in_user_writeable(uaddr2);
1722 goto out_put_keys; 1717 if (ret)
1718 goto out_put_keys;
1719 }
1723 1720
1724 if (!(flags & FLAGS_SHARED)) 1721 if (!(flags & FLAGS_SHARED)) {
1722 cond_resched();
1725 goto retry_private; 1723 goto retry_private;
1724 }
1726 1725
1727 put_futex_key(&key2); 1726 put_futex_key(&key2);
1728 put_futex_key(&key1); 1727 put_futex_key(&key1);
1728 cond_resched();
1729 goto retry; 1729 goto retry;
1730 } 1730 }
1731 1731
@@ -2350,7 +2350,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
2350 u32 uval, uninitialized_var(curval), newval; 2350 u32 uval, uninitialized_var(curval), newval;
2351 struct task_struct *oldowner, *newowner; 2351 struct task_struct *oldowner, *newowner;
2352 u32 newtid; 2352 u32 newtid;
2353 int ret; 2353 int ret, err = 0;
2354 2354
2355 lockdep_assert_held(q->lock_ptr); 2355 lockdep_assert_held(q->lock_ptr);
2356 2356
@@ -2421,14 +2421,17 @@ retry:
2421 if (!pi_state->owner) 2421 if (!pi_state->owner)
2422 newtid |= FUTEX_OWNER_DIED; 2422 newtid |= FUTEX_OWNER_DIED;
2423 2423
2424 if (get_futex_value_locked(&uval, uaddr)) 2424 err = get_futex_value_locked(&uval, uaddr);
2425 goto handle_fault; 2425 if (err)
2426 goto handle_err;
2426 2427
2427 for (;;) { 2428 for (;;) {
2428 newval = (uval & FUTEX_OWNER_DIED) | newtid; 2429 newval = (uval & FUTEX_OWNER_DIED) | newtid;
2429 2430
2430 if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) 2431 err = cmpxchg_futex_value_locked(&curval, uaddr, uval, newval);
2431 goto handle_fault; 2432 if (err)
2433 goto handle_err;
2434
2432 if (curval == uval) 2435 if (curval == uval)
2433 break; 2436 break;
2434 uval = curval; 2437 uval = curval;
@@ -2456,23 +2459,37 @@ retry:
2456 return 0; 2459 return 0;
2457 2460
2458 /* 2461 /*
2459 * To handle the page fault we need to drop the locks here. That gives 2462 * In order to reschedule or handle a page fault, we need to drop the
2460 * the other task (either the highest priority waiter itself or the 2463 * locks here. In the case of a fault, this gives the other task
2461 * task which stole the rtmutex) the chance to try the fixup of the 2464 * (either the highest priority waiter itself or the task which stole
2462 * pi_state. So once we are back from handling the fault we need to 2465 * the rtmutex) the chance to try the fixup of the pi_state. So once we
2463 * check the pi_state after reacquiring the locks and before trying to 2466 * are back from handling the fault we need to check the pi_state after
2464 * do another fixup. When the fixup has been done already we simply 2467 * reacquiring the locks and before trying to do another fixup. When
2465 * return. 2468 * the fixup has been done already we simply return.
2466 * 2469 *
2467 * Note: we hold both hb->lock and pi_mutex->wait_lock. We can safely 2470 * Note: we hold both hb->lock and pi_mutex->wait_lock. We can safely
2468 * drop hb->lock since the caller owns the hb -> futex_q relation. 2471 * drop hb->lock since the caller owns the hb -> futex_q relation.
2469 * Dropping the pi_mutex->wait_lock requires the state revalidate. 2472 * Dropping the pi_mutex->wait_lock requires the state revalidate.
2470 */ 2473 */
2471handle_fault: 2474handle_err:
2472 raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); 2475 raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
2473 spin_unlock(q->lock_ptr); 2476 spin_unlock(q->lock_ptr);
2474 2477
2475 ret = fault_in_user_writeable(uaddr); 2478 switch (err) {
2479 case -EFAULT:
2480 ret = fault_in_user_writeable(uaddr);
2481 break;
2482
2483 case -EAGAIN:
2484 cond_resched();
2485 ret = 0;
2486 break;
2487
2488 default:
2489 WARN_ON_ONCE(1);
2490 ret = err;
2491 break;
2492 }
2476 2493
2477 spin_lock(q->lock_ptr); 2494 spin_lock(q->lock_ptr);
2478 raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); 2495 raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
@@ -3041,10 +3058,8 @@ retry:
3041 * A unconditional UNLOCK_PI op raced against a waiter 3058 * A unconditional UNLOCK_PI op raced against a waiter
3042 * setting the FUTEX_WAITERS bit. Try again. 3059 * setting the FUTEX_WAITERS bit. Try again.
3043 */ 3060 */
3044 if (ret == -EAGAIN) { 3061 if (ret == -EAGAIN)
3045 put_futex_key(&key); 3062 goto pi_retry;
3046 goto retry;
3047 }
3048 /* 3063 /*
3049 * wake_futex_pi has detected invalid state. Tell user 3064 * wake_futex_pi has detected invalid state. Tell user
3050 * space. 3065 * space.
@@ -3059,9 +3074,19 @@ retry:
3059 * preserve the WAITERS bit not the OWNER_DIED one. We are the 3074 * preserve the WAITERS bit not the OWNER_DIED one. We are the
3060 * owner. 3075 * owner.
3061 */ 3076 */
3062 if (cmpxchg_futex_value_locked(&curval, uaddr, uval, 0)) { 3077 if ((ret = cmpxchg_futex_value_locked(&curval, uaddr, uval, 0))) {
3063 spin_unlock(&hb->lock); 3078 spin_unlock(&hb->lock);
3064 goto pi_faulted; 3079 switch (ret) {
3080 case -EFAULT:
3081 goto pi_faulted;
3082
3083 case -EAGAIN:
3084 goto pi_retry;
3085
3086 default:
3087 WARN_ON_ONCE(1);
3088 goto out_putkey;
3089 }
3065 } 3090 }
3066 3091
3067 /* 3092 /*
@@ -3075,6 +3100,11 @@ out_putkey:
3075 put_futex_key(&key); 3100 put_futex_key(&key);
3076 return ret; 3101 return ret;
3077 3102
3103pi_retry:
3104 put_futex_key(&key);
3105 cond_resched();
3106 goto retry;
3107
3078pi_faulted: 3108pi_faulted:
3079 put_futex_key(&key); 3109 put_futex_key(&key);
3080 3110
@@ -3435,6 +3465,7 @@ err_unlock:
3435static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi) 3465static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi)
3436{ 3466{
3437 u32 uval, uninitialized_var(nval), mval; 3467 u32 uval, uninitialized_var(nval), mval;
3468 int err;
3438 3469
3439 /* Futex address must be 32bit aligned */ 3470 /* Futex address must be 32bit aligned */
3440 if ((((unsigned long)uaddr) % sizeof(*uaddr)) != 0) 3471 if ((((unsigned long)uaddr) % sizeof(*uaddr)) != 0)
@@ -3444,42 +3475,57 @@ retry:
3444 if (get_user(uval, uaddr)) 3475 if (get_user(uval, uaddr))
3445 return -1; 3476 return -1;
3446 3477
3447 if ((uval & FUTEX_TID_MASK) == task_pid_vnr(curr)) { 3478 if ((uval & FUTEX_TID_MASK) != task_pid_vnr(curr))
3448 /* 3479 return 0;
3449 * Ok, this dying thread is truly holding a futex 3480
3450 * of interest. Set the OWNER_DIED bit atomically 3481 /*
3451 * via cmpxchg, and if the value had FUTEX_WAITERS 3482 * Ok, this dying thread is truly holding a futex
3452 * set, wake up a waiter (if any). (We have to do a 3483 * of interest. Set the OWNER_DIED bit atomically
3453 * futex_wake() even if OWNER_DIED is already set - 3484 * via cmpxchg, and if the value had FUTEX_WAITERS
3454 * to handle the rare but possible case of recursive 3485 * set, wake up a waiter (if any). (We have to do a
3455 * thread-death.) The rest of the cleanup is done in 3486 * futex_wake() even if OWNER_DIED is already set -
3456 * userspace. 3487 * to handle the rare but possible case of recursive
3457 */ 3488 * thread-death.) The rest of the cleanup is done in
3458 mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; 3489 * userspace.
3459 /* 3490 */
3460 * We are not holding a lock here, but we want to have 3491 mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
3461 * the pagefault_disable/enable() protection because 3492
3462 * we want to handle the fault gracefully. If the 3493 /*
3463 * access fails we try to fault in the futex with R/W 3494 * We are not holding a lock here, but we want to have
3464 * verification via get_user_pages. get_user() above 3495 * the pagefault_disable/enable() protection because
3465 * does not guarantee R/W access. If that fails we 3496 * we want to handle the fault gracefully. If the
3466 * give up and leave the futex locked. 3497 * access fails we try to fault in the futex with R/W
3467 */ 3498 * verification via get_user_pages. get_user() above
3468 if (cmpxchg_futex_value_locked(&nval, uaddr, uval, mval)) { 3499 * does not guarantee R/W access. If that fails we
3500 * give up and leave the futex locked.
3501 */
3502 if ((err = cmpxchg_futex_value_locked(&nval, uaddr, uval, mval))) {
3503 switch (err) {
3504 case -EFAULT:
3469 if (fault_in_user_writeable(uaddr)) 3505 if (fault_in_user_writeable(uaddr))
3470 return -1; 3506 return -1;
3471 goto retry; 3507 goto retry;
3472 } 3508
3473 if (nval != uval) 3509 case -EAGAIN:
3510 cond_resched();
3474 goto retry; 3511 goto retry;
3475 3512
3476 /* 3513 default:
3477 * Wake robust non-PI futexes here. The wakeup of 3514 WARN_ON_ONCE(1);
3478 * PI futexes happens in exit_pi_state(): 3515 return err;
3479 */ 3516 }
3480 if (!pi && (uval & FUTEX_WAITERS))
3481 futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
3482 } 3517 }
3518
3519 if (nval != uval)
3520 goto retry;
3521
3522 /*
3523 * Wake robust non-PI futexes here. The wakeup of
3524 * PI futexes happens in exit_pi_state():
3525 */
3526 if (!pi && (uval & FUTEX_WAITERS))
3527 futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
3528
3483 return 0; 3529 return 0;
3484} 3530}
3485 3531