aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/futex.c18
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
1794retry:
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
2209retry:
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:
2292out_key2: 2301out_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;
2295out: 2307out:
2296 if (to) { 2308 if (to) {
2297 hrtimer_cancel(&to->timer); 2309 hrtimer_cancel(&to->timer);