aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2008-09-26 13:32:21 -0400
committerIngo Molnar <mingo@elte.hu>2008-09-30 06:35:36 -0400
commit61270708ecf1cda148e84fbf6e0703ee5aa81814 (patch)
tree4c5bf27f99e5371da667e8c4105d2839e664409a
parent38d47c1b7075bd7ec3881141bb3629da58f88dab (diff)
futex: reduce mmap_sem usage
now that we rely on get_user_pages() for the shared key handling move all the mmap_sem stuff closely around the slow paths. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: Nick Piggin <nickpiggin@yahoo.com.au> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--kernel/futex.c83
1 files changed, 4 insertions, 79 deletions
diff --git a/kernel/futex.c b/kernel/futex.c
index a4c39fa0a7a3..6a726684217e 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -123,24 +123,6 @@ struct futex_hash_bucket {
123static struct futex_hash_bucket futex_queues[1<<FUTEX_HASHBITS]; 123static struct futex_hash_bucket futex_queues[1<<FUTEX_HASHBITS];
124 124
125/* 125/*
126 * Take mm->mmap_sem, when futex is shared
127 */
128static inline void futex_lock_mm(struct rw_semaphore *fshared)
129{
130 if (fshared)
131 down_read(fshared);
132}
133
134/*
135 * Release mm->mmap_sem, when the futex is shared
136 */
137static inline void futex_unlock_mm(struct rw_semaphore *fshared)
138{
139 if (fshared)
140 up_read(fshared);
141}
142
143/*
144 * We hash on the keys returned from get_futex_key (see below). 126 * We hash on the keys returned from get_futex_key (see below).
145 */ 127 */
146static struct futex_hash_bucket *hash_futex(union futex_key *key) 128static struct futex_hash_bucket *hash_futex(union futex_key *key)
@@ -250,7 +232,9 @@ static int get_futex_key(u32 __user *uaddr, struct rw_semaphore *fshared,
250 } 232 }
251 233
252again: 234again:
235 down_read(&mm->mmap_sem);
253 err = get_user_pages(current, mm, address, 1, 0, 0, &page, NULL); 236 err = get_user_pages(current, mm, address, 1, 0, 0, &page, NULL);
237 up_read(&mm->mmap_sem);
254 if (err < 0) 238 if (err < 0)
255 return err; 239 return err;
256 240
@@ -327,8 +311,7 @@ static int futex_handle_fault(unsigned long address,
327 if (attempt > 2) 311 if (attempt > 2)
328 return ret; 312 return ret;
329 313
330 if (!fshared) 314 down_read(&mm->mmap_sem);
331 down_read(&mm->mmap_sem);
332 vma = find_vma(mm, address); 315 vma = find_vma(mm, address);
333 if (vma && address >= vma->vm_start && 316 if (vma && address >= vma->vm_start &&
334 (vma->vm_flags & VM_WRITE)) { 317 (vma->vm_flags & VM_WRITE)) {
@@ -348,8 +331,7 @@ static int futex_handle_fault(unsigned long address,
348 current->min_flt++; 331 current->min_flt++;
349 } 332 }
350 } 333 }
351 if (!fshared) 334 up_read(&mm->mmap_sem);
352 up_read(&mm->mmap_sem);
353 return ret; 335 return ret;
354} 336}
355 337
@@ -719,8 +701,6 @@ static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared,
719 if (!bitset) 701 if (!bitset)
720 return -EINVAL; 702 return -EINVAL;
721 703
722 futex_lock_mm(fshared);
723
724 ret = get_futex_key(uaddr, fshared, &key); 704 ret = get_futex_key(uaddr, fshared, &key);
725 if (unlikely(ret != 0)) 705 if (unlikely(ret != 0))
726 goto out; 706 goto out;
@@ -749,7 +729,6 @@ static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared,
749 spin_unlock(&hb->lock); 729 spin_unlock(&hb->lock);
750out: 730out:
751 put_futex_key(fshared, &key); 731 put_futex_key(fshared, &key);
752 futex_unlock_mm(fshared);
753 return ret; 732 return ret;
754} 733}
755 734
@@ -769,8 +748,6 @@ futex_wake_op(u32 __user *uaddr1, struct rw_semaphore *fshared,
769 int ret, op_ret, attempt = 0; 748 int ret, op_ret, attempt = 0;
770 749
771retryfull: 750retryfull:
772 futex_lock_mm(fshared);
773
774 ret = get_futex_key(uaddr1, fshared, &key1); 751 ret = get_futex_key(uaddr1, fshared, &key1);
775 if (unlikely(ret != 0)) 752 if (unlikely(ret != 0))
776 goto out; 753 goto out;
@@ -821,12 +798,6 @@ retry:
821 goto retry; 798 goto retry;
822 } 799 }
823 800
824 /*
825 * If we would have faulted, release mmap_sem,
826 * fault it in and start all over again.
827 */
828 futex_unlock_mm(fshared);
829
830 ret = get_user(dummy, uaddr2); 801 ret = get_user(dummy, uaddr2);
831 if (ret) 802 if (ret)
832 return ret; 803 return ret;
@@ -864,7 +835,6 @@ retry:
864out: 835out:
865 put_futex_key(fshared, &key2); 836 put_futex_key(fshared, &key2);
866 put_futex_key(fshared, &key1); 837 put_futex_key(fshared, &key1);
867 futex_unlock_mm(fshared);
868 838
869 return ret; 839 return ret;
870} 840}
@@ -884,8 +854,6 @@ static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared,
884 int ret, drop_count = 0; 854 int ret, drop_count = 0;
885 855
886 retry: 856 retry:
887 futex_lock_mm(fshared);
888
889 ret = get_futex_key(uaddr1, fshared, &key1); 857 ret = get_futex_key(uaddr1, fshared, &key1);
890 if (unlikely(ret != 0)) 858 if (unlikely(ret != 0))
891 goto out; 859 goto out;
@@ -908,12 +876,6 @@ static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared,
908 if (hb1 != hb2) 876 if (hb1 != hb2)
909 spin_unlock(&hb2->lock); 877 spin_unlock(&hb2->lock);
910 878
911 /*
912 * If we would have faulted, release mmap_sem, fault
913 * it in and start all over again.
914 */
915 futex_unlock_mm(fshared);
916
917 ret = get_user(curval, uaddr1); 879 ret = get_user(curval, uaddr1);
918 880
919 if (!ret) 881 if (!ret)
@@ -967,7 +929,6 @@ out_unlock:
967out: 929out:
968 put_futex_key(fshared, &key2); 930 put_futex_key(fshared, &key2);
969 put_futex_key(fshared, &key1); 931 put_futex_key(fshared, &key1);
970 futex_unlock_mm(fshared);
971 return ret; 932 return ret;
972} 933}
973 934
@@ -1211,8 +1172,6 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
1211 q.pi_state = NULL; 1172 q.pi_state = NULL;
1212 q.bitset = bitset; 1173 q.bitset = bitset;
1213 retry: 1174 retry:
1214 futex_lock_mm(fshared);
1215
1216 q.key = FUTEX_KEY_INIT; 1175 q.key = FUTEX_KEY_INIT;
1217 ret = get_futex_key(uaddr, fshared, &q.key); 1176 ret = get_futex_key(uaddr, fshared, &q.key);
1218 if (unlikely(ret != 0)) 1177 if (unlikely(ret != 0))
@@ -1245,12 +1204,6 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
1245 if (unlikely(ret)) { 1204 if (unlikely(ret)) {
1246 queue_unlock(&q, hb); 1205 queue_unlock(&q, hb);
1247 1206
1248 /*
1249 * If we would have faulted, release mmap_sem, fault it in and
1250 * start all over again.
1251 */
1252 futex_unlock_mm(fshared);
1253
1254 ret = get_user(uval, uaddr); 1207 ret = get_user(uval, uaddr);
1255 1208
1256 if (!ret) 1209 if (!ret)
@@ -1265,12 +1218,6 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
1265 queue_me(&q, hb); 1218 queue_me(&q, hb);
1266 1219
1267 /* 1220 /*
1268 * Now the futex is queued and we have checked the data, we
1269 * don't want to hold mmap_sem while we sleep.
1270 */
1271 futex_unlock_mm(fshared);
1272
1273 /*
1274 * There might have been scheduling since the queue_me(), as we 1221 * There might have been scheduling since the queue_me(), as we
1275 * cannot hold a spinlock across the get_user() in case it 1222 * cannot hold a spinlock across the get_user() in case it
1276 * faults, and we cannot just set TASK_INTERRUPTIBLE state when 1223 * faults, and we cannot just set TASK_INTERRUPTIBLE state when
@@ -1355,7 +1302,6 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
1355 1302
1356 out_release_sem: 1303 out_release_sem:
1357 put_futex_key(fshared, &q.key); 1304 put_futex_key(fshared, &q.key);
1358 futex_unlock_mm(fshared);
1359 return ret; 1305 return ret;
1360} 1306}
1361 1307
@@ -1404,8 +1350,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
1404 1350
1405 q.pi_state = NULL; 1351 q.pi_state = NULL;
1406 retry: 1352 retry:
1407 futex_lock_mm(fshared);
1408
1409 q.key = FUTEX_KEY_INIT; 1353 q.key = FUTEX_KEY_INIT;
1410 ret = get_futex_key(uaddr, fshared, &q.key); 1354 ret = get_futex_key(uaddr, fshared, &q.key);
1411 if (unlikely(ret != 0)) 1355 if (unlikely(ret != 0))
@@ -1495,7 +1439,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
1495 * exit to complete. 1439 * exit to complete.
1496 */ 1440 */
1497 queue_unlock(&q, hb); 1441 queue_unlock(&q, hb);
1498 futex_unlock_mm(fshared);
1499 cond_resched(); 1442 cond_resched();
1500 goto retry; 1443 goto retry;
1501 1444
@@ -1527,12 +1470,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
1527 */ 1470 */
1528 queue_me(&q, hb); 1471 queue_me(&q, hb);
1529 1472
1530 /*
1531 * Now the futex is queued and we have checked the data, we
1532 * don't want to hold mmap_sem while we sleep.
1533 */
1534 futex_unlock_mm(fshared);
1535
1536 WARN_ON(!q.pi_state); 1473 WARN_ON(!q.pi_state);
1537 /* 1474 /*
1538 * Block on the PI mutex: 1475 * Block on the PI mutex:
@@ -1545,7 +1482,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
1545 ret = ret ? 0 : -EWOULDBLOCK; 1482 ret = ret ? 0 : -EWOULDBLOCK;
1546 } 1483 }
1547 1484
1548 futex_lock_mm(fshared);
1549 spin_lock(q.lock_ptr); 1485 spin_lock(q.lock_ptr);
1550 1486
1551 if (!ret) { 1487 if (!ret) {
@@ -1611,7 +1547,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
1611 1547
1612 /* Unqueue and drop the lock */ 1548 /* Unqueue and drop the lock */
1613 unqueue_me_pi(&q); 1549 unqueue_me_pi(&q);
1614 futex_unlock_mm(fshared);
1615 1550
1616 if (to) 1551 if (to)
1617 destroy_hrtimer_on_stack(&to->timer); 1552 destroy_hrtimer_on_stack(&to->timer);
@@ -1622,7 +1557,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
1622 1557
1623 out_release_sem: 1558 out_release_sem:
1624 put_futex_key(fshared, &q.key); 1559 put_futex_key(fshared, &q.key);
1625 futex_unlock_mm(fshared);
1626 if (to) 1560 if (to)
1627 destroy_hrtimer_on_stack(&to->timer); 1561 destroy_hrtimer_on_stack(&to->timer);
1628 return ret; 1562 return ret;
@@ -1646,8 +1580,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
1646 goto retry_unlocked; 1580 goto retry_unlocked;
1647 } 1581 }
1648 1582
1649 futex_unlock_mm(fshared);
1650
1651 ret = get_user(uval, uaddr); 1583 ret = get_user(uval, uaddr);
1652 if (!ret && (uval != -EFAULT)) 1584 if (!ret && (uval != -EFAULT))
1653 goto retry; 1585 goto retry;
@@ -1679,10 +1611,6 @@ retry:
1679 */ 1611 */
1680 if ((uval & FUTEX_TID_MASK) != task_pid_vnr(current)) 1612 if ((uval & FUTEX_TID_MASK) != task_pid_vnr(current))
1681 return -EPERM; 1613 return -EPERM;
1682 /*
1683 * First take all the futex related locks:
1684 */
1685 futex_lock_mm(fshared);
1686 1614
1687 ret = get_futex_key(uaddr, fshared, &key); 1615 ret = get_futex_key(uaddr, fshared, &key);
1688 if (unlikely(ret != 0)) 1616 if (unlikely(ret != 0))
@@ -1742,7 +1670,6 @@ out_unlock:
1742 spin_unlock(&hb->lock); 1670 spin_unlock(&hb->lock);
1743out: 1671out:
1744 put_futex_key(fshared, &key); 1672 put_futex_key(fshared, &key);
1745 futex_unlock_mm(fshared);
1746 1673
1747 return ret; 1674 return ret;
1748 1675
@@ -1766,8 +1693,6 @@ pi_faulted:
1766 goto retry_unlocked; 1693 goto retry_unlocked;
1767 } 1694 }
1768 1695
1769 futex_unlock_mm(fshared);
1770
1771 ret = get_user(uval, uaddr); 1696 ret = get_user(uval, uaddr);
1772 if (!ret && (uval != -EFAULT)) 1697 if (!ret && (uval != -EFAULT))
1773 goto retry; 1698 goto retry;