diff options
-rw-r--r-- | kernel/futex.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index 4949d336d88d..5c88839bd993 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -1791,6 +1791,7 @@ static int futex_wait(u32 __user *uaddr, int fshared, | |||
1791 | current->timer_slack_ns); | 1791 | current->timer_slack_ns); |
1792 | } | 1792 | } |
1793 | 1793 | ||
1794 | retry: | ||
1794 | /* Prepare to wait on uaddr. */ | 1795 | /* Prepare to wait on uaddr. */ |
1795 | ret = futex_wait_setup(uaddr, val, fshared, &q, &hb); | 1796 | ret = futex_wait_setup(uaddr, val, fshared, &q, &hb); |
1796 | if (ret) | 1797 | if (ret) |
@@ -1808,9 +1809,14 @@ static int futex_wait(u32 __user *uaddr, int fshared, | |||
1808 | goto out_put_key; | 1809 | goto out_put_key; |
1809 | 1810 | ||
1810 | /* | 1811 | /* |
1811 | * We expect signal_pending(current), but another thread may | 1812 | * We expect signal_pending(current), but we might be the |
1812 | * have handled it for us already. | 1813 | * victim of a spurious wakeup as well. |
1813 | */ | 1814 | */ |
1815 | if (!signal_pending(current)) { | ||
1816 | put_futex_key(fshared, &q.key); | ||
1817 | goto retry; | ||
1818 | } | ||
1819 | |||
1814 | ret = -ERESTARTSYS; | 1820 | ret = -ERESTARTSYS; |
1815 | if (!abs_time) | 1821 | if (!abs_time) |
1816 | goto out_put_key; | 1822 | goto out_put_key; |
@@ -2118,9 +2124,11 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb, | |||
2118 | */ | 2124 | */ |
2119 | plist_del(&q->list, &q->list.plist); | 2125 | plist_del(&q->list, &q->list.plist); |
2120 | 2126 | ||
2127 | /* Handle spurious wakeups gracefully */ | ||
2128 | ret = -EAGAIN; | ||
2121 | if (timeout && !timeout->task) | 2129 | if (timeout && !timeout->task) |
2122 | ret = -ETIMEDOUT; | 2130 | ret = -ETIMEDOUT; |
2123 | else | 2131 | else if (signal_pending(current)) |
2124 | ret = -ERESTARTNOINTR; | 2132 | ret = -ERESTARTNOINTR; |
2125 | } | 2133 | } |
2126 | return ret; | 2134 | return ret; |
@@ -2198,6 +2206,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared, | |||
2198 | debug_rt_mutex_init_waiter(&rt_waiter); | 2206 | debug_rt_mutex_init_waiter(&rt_waiter); |
2199 | rt_waiter.task = NULL; | 2207 | rt_waiter.task = NULL; |
2200 | 2208 | ||
2209 | retry: | ||
2201 | key2 = FUTEX_KEY_INIT; | 2210 | key2 = FUTEX_KEY_INIT; |
2202 | ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE); | 2211 | ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE); |
2203 | if (unlikely(ret != 0)) | 2212 | if (unlikely(ret != 0)) |
@@ -2292,6 +2301,9 @@ out_put_keys: | |||
2292 | out_key2: | 2301 | out_key2: |
2293 | put_futex_key(fshared, &key2); | 2302 | put_futex_key(fshared, &key2); |
2294 | 2303 | ||
2304 | /* Spurious wakeup ? */ | ||
2305 | if (ret == -EAGAIN) | ||
2306 | goto retry; | ||
2295 | out: | 2307 | out: |
2296 | if (to) { | 2308 | if (to) { |
2297 | hrtimer_cancel(&to->timer); | 2309 | hrtimer_cancel(&to->timer); |