aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/futex.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/futex.c')
-rw-r--r--kernel/futex.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/kernel/futex.c b/kernel/futex.c
index b911adceb2c4..d73ef1f3e55d 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}
@@ -303,8 +304,14 @@ void put_futex_key(int fshared, union futex_key *key)
303 */ 304 */
304static int fault_in_user_writeable(u32 __user *uaddr) 305static int fault_in_user_writeable(u32 __user *uaddr)
305{ 306{
306 int ret = get_user_pages(current, current->mm, (unsigned long)uaddr, 307 struct mm_struct *mm = current->mm;
307 1, 1, 0, NULL, NULL); 308 int ret;
309
310 down_read(&mm->mmap_sem);
311 ret = get_user_pages(current, mm, (unsigned long)uaddr,
312 1, 1, 0, NULL, NULL);
313 up_read(&mm->mmap_sem);
314
308 return ret < 0 ? ret : 0; 315 return ret < 0 ? ret : 0;
309} 316}
310 317
@@ -916,8 +923,8 @@ retry:
916 hb1 = hash_futex(&key1); 923 hb1 = hash_futex(&key1);
917 hb2 = hash_futex(&key2); 924 hb2 = hash_futex(&key2);
918 925
919 double_lock_hb(hb1, hb2);
920retry_private: 926retry_private:
927 double_lock_hb(hb1, hb2);
921 op_ret = futex_atomic_op_inuser(op, uaddr2); 928 op_ret = futex_atomic_op_inuser(op, uaddr2);
922 if (unlikely(op_ret < 0)) { 929 if (unlikely(op_ret < 0)) {
923 930
@@ -1028,7 +1035,6 @@ static inline
1028void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key, 1035void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
1029 struct futex_hash_bucket *hb) 1036 struct futex_hash_bucket *hb)
1030{ 1037{
1031 drop_futex_key_refs(&q->key);
1032 get_futex_key_refs(key); 1038 get_futex_key_refs(key);
1033 q->key = *key; 1039 q->key = *key;
1034 1040
@@ -1226,6 +1232,7 @@ retry_private:
1226 */ 1232 */
1227 if (ret == 1) { 1233 if (ret == 1) {
1228 WARN_ON(pi_state); 1234 WARN_ON(pi_state);
1235 drop_count++;
1229 task_count++; 1236 task_count++;
1230 ret = get_futex_value_locked(&curval2, uaddr2); 1237 ret = get_futex_value_locked(&curval2, uaddr2);
1231 if (!ret) 1238 if (!ret)
@@ -1304,6 +1311,7 @@ retry_private:
1304 if (ret == 1) { 1311 if (ret == 1) {
1305 /* We got the lock. */ 1312 /* We got the lock. */
1306 requeue_pi_wake_futex(this, &key2, hb2); 1313 requeue_pi_wake_futex(this, &key2, hb2);
1314 drop_count++;
1307 continue; 1315 continue;
1308 } else if (ret) { 1316 } else if (ret) {
1309 /* -EDEADLK */ 1317 /* -EDEADLK */
@@ -1791,6 +1799,7 @@ static int futex_wait(u32 __user *uaddr, int fshared,
1791 current->timer_slack_ns); 1799 current->timer_slack_ns);
1792 } 1800 }
1793 1801
1802retry:
1794 /* Prepare to wait on uaddr. */ 1803 /* Prepare to wait on uaddr. */
1795 ret = futex_wait_setup(uaddr, val, fshared, &q, &hb); 1804 ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
1796 if (ret) 1805 if (ret)
@@ -1808,9 +1817,14 @@ static int futex_wait(u32 __user *uaddr, int fshared,
1808 goto out_put_key; 1817 goto out_put_key;
1809 1818
1810 /* 1819 /*
1811 * We expect signal_pending(current), but another thread may 1820 * We expect signal_pending(current), but we might be the
1812 * have handled it for us already. 1821 * victim of a spurious wakeup as well.
1813 */ 1822 */
1823 if (!signal_pending(current)) {
1824 put_futex_key(fshared, &q.key);
1825 goto retry;
1826 }
1827
1814 ret = -ERESTARTSYS; 1828 ret = -ERESTARTSYS;
1815 if (!abs_time) 1829 if (!abs_time)
1816 goto out_put_key; 1830 goto out_put_key;
@@ -2117,11 +2131,12 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
2117 * Unqueue the futex_q and determine which it was. 2131 * Unqueue the futex_q and determine which it was.
2118 */ 2132 */
2119 plist_del(&q->list, &q->list.plist); 2133 plist_del(&q->list, &q->list.plist);
2120 drop_futex_key_refs(&q->key);
2121 2134
2135 /* Handle spurious wakeups gracefully */
2136 ret = -EWOULDBLOCK;
2122 if (timeout && !timeout->task) 2137 if (timeout && !timeout->task)
2123 ret = -ETIMEDOUT; 2138 ret = -ETIMEDOUT;
2124 else 2139 else if (signal_pending(current))
2125 ret = -ERESTARTNOINTR; 2140 ret = -ERESTARTNOINTR;
2126 } 2141 }
2127 return ret; 2142 return ret;