aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/futex.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/futex.c')
-rw-r--r--kernel/futex.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/kernel/futex.c b/kernel/futex.c
index b911adceb2c4..642f3bbaacc7 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -150,7 +150,8 @@ static struct futex_hash_bucket *hash_futex(union futex_key *key)
150 */ 150 */
151static inline int match_futex(union futex_key *key1, union futex_key *key2) 151static inline int match_futex(union futex_key *key1, union futex_key *key2)
152{ 152{
153 return (key1->both.word == key2->both.word 153 return (key1 && key2
154 && key1->both.word == key2->both.word
154 && key1->both.ptr == key2->both.ptr 155 && key1->both.ptr == key2->both.ptr
155 && key1->both.offset == key2->both.offset); 156 && key1->both.offset == key2->both.offset);
156} 157}
@@ -916,8 +917,8 @@ retry:
916 hb1 = hash_futex(&key1); 917 hb1 = hash_futex(&key1);
917 hb2 = hash_futex(&key2); 918 hb2 = hash_futex(&key2);
918 919
919 double_lock_hb(hb1, hb2);
920retry_private: 920retry_private:
921 double_lock_hb(hb1, hb2);
921 op_ret = futex_atomic_op_inuser(op, uaddr2); 922 op_ret = futex_atomic_op_inuser(op, uaddr2);
922 if (unlikely(op_ret < 0)) { 923 if (unlikely(op_ret < 0)) {
923 924
@@ -1028,7 +1029,6 @@ static inline
1028void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key, 1029void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
1029 struct futex_hash_bucket *hb) 1030 struct futex_hash_bucket *hb)
1030{ 1031{
1031 drop_futex_key_refs(&q->key);
1032 get_futex_key_refs(key); 1032 get_futex_key_refs(key);
1033 q->key = *key; 1033 q->key = *key;
1034 1034
@@ -1226,6 +1226,7 @@ retry_private:
1226 */ 1226 */
1227 if (ret == 1) { 1227 if (ret == 1) {
1228 WARN_ON(pi_state); 1228 WARN_ON(pi_state);
1229 drop_count++;
1229 task_count++; 1230 task_count++;
1230 ret = get_futex_value_locked(&curval2, uaddr2); 1231 ret = get_futex_value_locked(&curval2, uaddr2);
1231 if (!ret) 1232 if (!ret)
@@ -1304,6 +1305,7 @@ retry_private:
1304 if (ret == 1) { 1305 if (ret == 1) {
1305 /* We got the lock. */ 1306 /* We got the lock. */
1306 requeue_pi_wake_futex(this, &key2, hb2); 1307 requeue_pi_wake_futex(this, &key2, hb2);
1308 drop_count++;
1307 continue; 1309 continue;
1308 } else if (ret) { 1310 } else if (ret) {
1309 /* -EDEADLK */ 1311 /* -EDEADLK */
@@ -1791,6 +1793,7 @@ static int futex_wait(u32 __user *uaddr, int fshared,
1791 current->timer_slack_ns); 1793 current->timer_slack_ns);
1792 } 1794 }
1793 1795
1796retry:
1794 /* Prepare to wait on uaddr. */ 1797 /* Prepare to wait on uaddr. */
1795 ret = futex_wait_setup(uaddr, val, fshared, &q, &hb); 1798 ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
1796 if (ret) 1799 if (ret)
@@ -1808,9 +1811,14 @@ static int futex_wait(u32 __user *uaddr, int fshared,
1808 goto out_put_key; 1811 goto out_put_key;
1809 1812
1810 /* 1813 /*
1811 * We expect signal_pending(current), but another thread may 1814 * We expect signal_pending(current), but we might be the
1812 * have handled it for us already. 1815 * victim of a spurious wakeup as well.
1813 */ 1816 */
1817 if (!signal_pending(current)) {
1818 put_futex_key(fshared, &q.key);
1819 goto retry;
1820 }
1821
1814 ret = -ERESTARTSYS; 1822 ret = -ERESTARTSYS;
1815 if (!abs_time) 1823 if (!abs_time)
1816 goto out_put_key; 1824 goto out_put_key;
@@ -2117,11 +2125,12 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
2117 * Unqueue the futex_q and determine which it was. 2125 * Unqueue the futex_q and determine which it was.
2118 */ 2126 */
2119 plist_del(&q->list, &q->list.plist); 2127 plist_del(&q->list, &q->list.plist);
2120 drop_futex_key_refs(&q->key);
2121 2128
2129 /* Handle spurious wakeups gracefully */
2130 ret = -EAGAIN;
2122 if (timeout && !timeout->task) 2131 if (timeout && !timeout->task)
2123 ret = -ETIMEDOUT; 2132 ret = -ETIMEDOUT;
2124 else 2133 else if (signal_pending(current))
2125 ret = -ERESTARTNOINTR; 2134 ret = -ERESTARTNOINTR;
2126 } 2135 }
2127 return ret; 2136 return ret;
@@ -2199,6 +2208,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared,
2199 debug_rt_mutex_init_waiter(&rt_waiter); 2208 debug_rt_mutex_init_waiter(&rt_waiter);
2200 rt_waiter.task = NULL; 2209 rt_waiter.task = NULL;
2201 2210
2211retry:
2202 key2 = FUTEX_KEY_INIT; 2212 key2 = FUTEX_KEY_INIT;
2203 ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE); 2213 ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE);
2204 if (unlikely(ret != 0)) 2214 if (unlikely(ret != 0))
@@ -2293,6 +2303,9 @@ out_put_keys:
2293out_key2: 2303out_key2:
2294 put_futex_key(fshared, &key2); 2304 put_futex_key(fshared, &key2);
2295 2305
2306 /* Spurious wakeup ? */
2307 if (ret == -EAGAIN)
2308 goto retry;
2296out: 2309out:
2297 if (to) { 2310 if (to) {
2298 hrtimer_cancel(&to->timer); 2311 hrtimer_cancel(&to->timer);