Commit 36cf3b5c3b7228bcf5124c530d50080b61a59f69
Committed by
Linus Torvalds
1 parent
0746aec3c7
Exists in
master
and in
39 other branches
FUTEX: Tidy up the code
The recent PRIVATE and REQUEUE_PI changes to the futex code made it hard to read. Tidy it up. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 4 changed files with 74 additions and 85 deletions Side-by-side Diff
kernel/futex.c
... | ... | @@ -121,6 +121,24 @@ |
121 | 121 | static struct vfsmount *futex_mnt; |
122 | 122 | |
123 | 123 | /* |
124 | + * Take mm->mmap_sem, when futex is shared | |
125 | + */ | |
126 | +static inline void futex_lock_mm(struct rw_semaphore *fshared) | |
127 | +{ | |
128 | + if (fshared) | |
129 | + down_read(fshared); | |
130 | +} | |
131 | + | |
132 | +/* | |
133 | + * Release mm->mmap_sem, when the futex is shared | |
134 | + */ | |
135 | +static inline void futex_unlock_mm(struct rw_semaphore *fshared) | |
136 | +{ | |
137 | + if (fshared) | |
138 | + up_read(fshared); | |
139 | +} | |
140 | + | |
141 | +/* | |
124 | 142 | * We hash on the keys returned from get_futex_key (see below). |
125 | 143 | */ |
126 | 144 | static struct futex_hash_bucket *hash_futex(union futex_key *key) |
127 | 145 | |
... | ... | @@ -287,8 +305,19 @@ |
287 | 305 | } |
288 | 306 | EXPORT_SYMBOL_GPL(drop_futex_key_refs); |
289 | 307 | |
290 | -static inline int get_futex_value_locked(u32 *dest, u32 __user *from) | |
308 | +static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval) | |
291 | 309 | { |
310 | + u32 curval; | |
311 | + | |
312 | + pagefault_disable(); | |
313 | + curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); | |
314 | + pagefault_enable(); | |
315 | + | |
316 | + return curval; | |
317 | +} | |
318 | + | |
319 | +static int get_futex_value_locked(u32 *dest, u32 __user *from) | |
320 | +{ | |
292 | 321 | int ret; |
293 | 322 | |
294 | 323 | pagefault_disable(); |
... | ... | @@ -620,9 +649,7 @@ |
620 | 649 | |
621 | 650 | newval = FUTEX_WAITERS | new_owner->pid; |
622 | 651 | |
623 | - pagefault_disable(); | |
624 | - curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); | |
625 | - pagefault_enable(); | |
652 | + curval = cmpxchg_futex_value_locked(uaddr, uval, newval); | |
626 | 653 | |
627 | 654 | if (curval == -EFAULT) |
628 | 655 | ret = -EFAULT; |
... | ... | @@ -659,9 +686,7 @@ |
659 | 686 | * There is no waiter, so we unlock the futex. The owner died |
660 | 687 | * bit has not to be preserved here. We are the owner: |
661 | 688 | */ |
662 | - pagefault_disable(); | |
663 | - oldval = futex_atomic_cmpxchg_inatomic(uaddr, uval, 0); | |
664 | - pagefault_enable(); | |
689 | + oldval = cmpxchg_futex_value_locked(uaddr, uval, 0); | |
665 | 690 | |
666 | 691 | if (oldval == -EFAULT) |
667 | 692 | return oldval; |
... | ... | @@ -700,8 +725,7 @@ |
700 | 725 | union futex_key key; |
701 | 726 | int ret; |
702 | 727 | |
703 | - if (fshared) | |
704 | - down_read(fshared); | |
728 | + futex_lock_mm(fshared); | |
705 | 729 | |
706 | 730 | ret = get_futex_key(uaddr, fshared, &key); |
707 | 731 | if (unlikely(ret != 0)) |
... | ... | @@ -725,8 +749,7 @@ |
725 | 749 | |
726 | 750 | spin_unlock(&hb->lock); |
727 | 751 | out: |
728 | - if (fshared) | |
729 | - up_read(fshared); | |
752 | + futex_unlock_mm(fshared); | |
730 | 753 | return ret; |
731 | 754 | } |
732 | 755 | |
... | ... | @@ -746,8 +769,7 @@ |
746 | 769 | int ret, op_ret, attempt = 0; |
747 | 770 | |
748 | 771 | retryfull: |
749 | - if (fshared) | |
750 | - down_read(fshared); | |
772 | + futex_lock_mm(fshared); | |
751 | 773 | |
752 | 774 | ret = get_futex_key(uaddr1, fshared, &key1); |
753 | 775 | if (unlikely(ret != 0)) |
... | ... | @@ -793,7 +815,7 @@ |
793 | 815 | */ |
794 | 816 | if (attempt++) { |
795 | 817 | ret = futex_handle_fault((unsigned long)uaddr2, |
796 | - fshared, attempt); | |
818 | + fshared, attempt); | |
797 | 819 | if (ret) |
798 | 820 | goto out; |
799 | 821 | goto retry; |
... | ... | @@ -803,8 +825,7 @@ |
803 | 825 | * If we would have faulted, release mmap_sem, |
804 | 826 | * fault it in and start all over again. |
805 | 827 | */ |
806 | - if (fshared) | |
807 | - up_read(fshared); | |
828 | + futex_unlock_mm(fshared); | |
808 | 829 | |
809 | 830 | ret = get_user(dummy, uaddr2); |
810 | 831 | if (ret) |
... | ... | @@ -841,8 +862,8 @@ |
841 | 862 | if (hb1 != hb2) |
842 | 863 | spin_unlock(&hb2->lock); |
843 | 864 | out: |
844 | - if (fshared) | |
845 | - up_read(fshared); | |
865 | + futex_unlock_mm(fshared); | |
866 | + | |
846 | 867 | return ret; |
847 | 868 | } |
848 | 869 | |
... | ... | @@ -861,8 +882,7 @@ |
861 | 882 | int ret, drop_count = 0; |
862 | 883 | |
863 | 884 | retry: |
864 | - if (fshared) | |
865 | - down_read(fshared); | |
885 | + futex_lock_mm(fshared); | |
866 | 886 | |
867 | 887 | ret = get_futex_key(uaddr1, fshared, &key1); |
868 | 888 | if (unlikely(ret != 0)) |
... | ... | @@ -890,8 +910,7 @@ |
890 | 910 | * If we would have faulted, release mmap_sem, fault |
891 | 911 | * it in and start all over again. |
892 | 912 | */ |
893 | - if (fshared) | |
894 | - up_read(fshared); | |
913 | + futex_unlock_mm(fshared); | |
895 | 914 | |
896 | 915 | ret = get_user(curval, uaddr1); |
897 | 916 | |
... | ... | @@ -944,8 +963,7 @@ |
944 | 963 | drop_futex_key_refs(&key1); |
945 | 964 | |
946 | 965 | out: |
947 | - if (fshared) | |
948 | - up_read(fshared); | |
966 | + futex_unlock_mm(fshared); | |
949 | 967 | return ret; |
950 | 968 | } |
951 | 969 | |
... | ... | @@ -1113,10 +1131,7 @@ |
1113 | 1131 | while (!ret) { |
1114 | 1132 | newval = (uval & FUTEX_OWNER_DIED) | newtid; |
1115 | 1133 | |
1116 | - pagefault_disable(); | |
1117 | - curval = futex_atomic_cmpxchg_inatomic(uaddr, | |
1118 | - uval, newval); | |
1119 | - pagefault_enable(); | |
1134 | + curval = cmpxchg_futex_value_locked(uaddr, uval, newval); | |
1120 | 1135 | |
1121 | 1136 | if (curval == -EFAULT) |
1122 | 1137 | ret = -EFAULT; |
... | ... | @@ -1134,6 +1149,7 @@ |
1134 | 1149 | #define ARG3_SHARED 1 |
1135 | 1150 | |
1136 | 1151 | static long futex_wait_restart(struct restart_block *restart); |
1152 | + | |
1137 | 1153 | static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, |
1138 | 1154 | u32 val, ktime_t *abs_time) |
1139 | 1155 | { |
... | ... | @@ -1148,8 +1164,7 @@ |
1148 | 1164 | |
1149 | 1165 | q.pi_state = NULL; |
1150 | 1166 | retry: |
1151 | - if (fshared) | |
1152 | - down_read(fshared); | |
1167 | + futex_lock_mm(fshared); | |
1153 | 1168 | |
1154 | 1169 | ret = get_futex_key(uaddr, fshared, &q.key); |
1155 | 1170 | if (unlikely(ret != 0)) |
... | ... | @@ -1186,8 +1201,7 @@ |
1186 | 1201 | * If we would have faulted, release mmap_sem, fault it in and |
1187 | 1202 | * start all over again. |
1188 | 1203 | */ |
1189 | - if (fshared) | |
1190 | - up_read(fshared); | |
1204 | + futex_unlock_mm(fshared); | |
1191 | 1205 | |
1192 | 1206 | ret = get_user(uval, uaddr); |
1193 | 1207 | |
... | ... | @@ -1206,8 +1220,7 @@ |
1206 | 1220 | * Now the futex is queued and we have checked the data, we |
1207 | 1221 | * don't want to hold mmap_sem while we sleep. |
1208 | 1222 | */ |
1209 | - if (fshared) | |
1210 | - up_read(fshared); | |
1223 | + futex_unlock_mm(fshared); | |
1211 | 1224 | |
1212 | 1225 | /* |
1213 | 1226 | * There might have been scheduling since the queue_me(), as we |
... | ... | @@ -1285,8 +1298,7 @@ |
1285 | 1298 | queue_unlock(&q, hb); |
1286 | 1299 | |
1287 | 1300 | out_release_sem: |
1288 | - if (fshared) | |
1289 | - up_read(fshared); | |
1301 | + futex_unlock_mm(fshared); | |
1290 | 1302 | return ret; |
1291 | 1303 | } |
1292 | 1304 | |
... | ... | @@ -1333,8 +1345,7 @@ |
1333 | 1345 | |
1334 | 1346 | q.pi_state = NULL; |
1335 | 1347 | retry: |
1336 | - if (fshared) | |
1337 | - down_read(fshared); | |
1348 | + futex_lock_mm(fshared); | |
1338 | 1349 | |
1339 | 1350 | ret = get_futex_key(uaddr, fshared, &q.key); |
1340 | 1351 | if (unlikely(ret != 0)) |
... | ... | @@ -1353,9 +1364,7 @@ |
1353 | 1364 | */ |
1354 | 1365 | newval = current->pid; |
1355 | 1366 | |
1356 | - pagefault_disable(); | |
1357 | - curval = futex_atomic_cmpxchg_inatomic(uaddr, 0, newval); | |
1358 | - pagefault_enable(); | |
1367 | + curval = cmpxchg_futex_value_locked(uaddr, 0, newval); | |
1359 | 1368 | |
1360 | 1369 | if (unlikely(curval == -EFAULT)) |
1361 | 1370 | goto uaddr_faulted; |
... | ... | @@ -1398,9 +1407,7 @@ |
1398 | 1407 | lock_taken = 1; |
1399 | 1408 | } |
1400 | 1409 | |
1401 | - pagefault_disable(); | |
1402 | - curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); | |
1403 | - pagefault_enable(); | |
1410 | + curval = cmpxchg_futex_value_locked(uaddr, uval, newval); | |
1404 | 1411 | |
1405 | 1412 | if (unlikely(curval == -EFAULT)) |
1406 | 1413 | goto uaddr_faulted; |
... | ... | @@ -1428,8 +1435,7 @@ |
1428 | 1435 | * exit to complete. |
1429 | 1436 | */ |
1430 | 1437 | queue_unlock(&q, hb); |
1431 | - if (fshared) | |
1432 | - up_read(fshared); | |
1438 | + futex_unlock_mm(fshared); | |
1433 | 1439 | cond_resched(); |
1434 | 1440 | goto retry; |
1435 | 1441 | |
... | ... | @@ -1465,8 +1471,7 @@ |
1465 | 1471 | * Now the futex is queued and we have checked the data, we |
1466 | 1472 | * don't want to hold mmap_sem while we sleep. |
1467 | 1473 | */ |
1468 | - if (fshared) | |
1469 | - up_read(fshared); | |
1474 | + futex_unlock_mm(fshared); | |
1470 | 1475 | |
1471 | 1476 | WARN_ON(!q.pi_state); |
1472 | 1477 | /* |
... | ... | @@ -1480,8 +1485,7 @@ |
1480 | 1485 | ret = ret ? 0 : -EWOULDBLOCK; |
1481 | 1486 | } |
1482 | 1487 | |
1483 | - if (fshared) | |
1484 | - down_read(fshared); | |
1488 | + futex_lock_mm(fshared); | |
1485 | 1489 | spin_lock(q.lock_ptr); |
1486 | 1490 | |
1487 | 1491 | if (!ret) { |
... | ... | @@ -1518,8 +1522,7 @@ |
1518 | 1522 | |
1519 | 1523 | /* Unqueue and drop the lock */ |
1520 | 1524 | unqueue_me_pi(&q); |
1521 | - if (fshared) | |
1522 | - up_read(fshared); | |
1525 | + futex_unlock_mm(fshared); | |
1523 | 1526 | |
1524 | 1527 | return ret != -EINTR ? ret : -ERESTARTNOINTR; |
1525 | 1528 | |
... | ... | @@ -1527,8 +1530,7 @@ |
1527 | 1530 | queue_unlock(&q, hb); |
1528 | 1531 | |
1529 | 1532 | out_release_sem: |
1530 | - if (fshared) | |
1531 | - up_read(fshared); | |
1533 | + futex_unlock_mm(fshared); | |
1532 | 1534 | return ret; |
1533 | 1535 | |
1534 | 1536 | uaddr_faulted: |
... | ... | @@ -1550,8 +1552,7 @@ |
1550 | 1552 | goto retry_unlocked; |
1551 | 1553 | } |
1552 | 1554 | |
1553 | - if (fshared) | |
1554 | - up_read(fshared); | |
1555 | + futex_unlock_mm(fshared); | |
1555 | 1556 | |
1556 | 1557 | ret = get_user(uval, uaddr); |
1557 | 1558 | if (!ret && (uval != -EFAULT)) |
... | ... | @@ -1585,8 +1586,7 @@ |
1585 | 1586 | /* |
1586 | 1587 | * First take all the futex related locks: |
1587 | 1588 | */ |
1588 | - if (fshared) | |
1589 | - down_read(fshared); | |
1589 | + futex_lock_mm(fshared); | |
1590 | 1590 | |
1591 | 1591 | ret = get_futex_key(uaddr, fshared, &key); |
1592 | 1592 | if (unlikely(ret != 0)) |
1593 | 1593 | |
... | ... | @@ -1601,12 +1601,10 @@ |
1601 | 1601 | * again. If it succeeds then we can return without waking |
1602 | 1602 | * anyone else up: |
1603 | 1603 | */ |
1604 | - if (!(uval & FUTEX_OWNER_DIED)) { | |
1605 | - pagefault_disable(); | |
1606 | - uval = futex_atomic_cmpxchg_inatomic(uaddr, current->pid, 0); | |
1607 | - pagefault_enable(); | |
1608 | - } | |
1604 | + if (!(uval & FUTEX_OWNER_DIED)) | |
1605 | + uval = cmpxchg_futex_value_locked(uaddr, current->pid, 0); | |
1609 | 1606 | |
1607 | + | |
1610 | 1608 | if (unlikely(uval == -EFAULT)) |
1611 | 1609 | goto pi_faulted; |
1612 | 1610 | /* |
... | ... | @@ -1647,8 +1645,7 @@ |
1647 | 1645 | out_unlock: |
1648 | 1646 | spin_unlock(&hb->lock); |
1649 | 1647 | out: |
1650 | - if (fshared) | |
1651 | - up_read(fshared); | |
1648 | + futex_unlock_mm(fshared); | |
1652 | 1649 | |
1653 | 1650 | return ret; |
1654 | 1651 | |
... | ... | @@ -1671,8 +1668,7 @@ |
1671 | 1668 | goto retry_unlocked; |
1672 | 1669 | } |
1673 | 1670 | |
1674 | - if (fshared) | |
1675 | - up_read(fshared); | |
1671 | + futex_unlock_mm(fshared); | |
1676 | 1672 | |
1677 | 1673 | ret = get_user(uval, uaddr); |
1678 | 1674 | if (!ret && (uval != -EFAULT)) |
... | ... | @@ -1729,8 +1725,8 @@ |
1729 | 1725 | |
1730 | 1726 | if (printk_timed_ratelimit(&printk_interval, 60 * 60 * 1000)) { |
1731 | 1727 | printk(KERN_WARNING "Process `%s' used FUTEX_FD, which " |
1732 | - "will be removed from the kernel in June 2007\n", | |
1733 | - current->comm); | |
1728 | + "will be removed from the kernel in June 2007\n", | |
1729 | + current->comm); | |
1734 | 1730 | } |
1735 | 1731 | |
1736 | 1732 | ret = -EINVAL; |
1737 | 1733 | |
... | ... | @@ -1908,10 +1904,8 @@ |
1908 | 1904 | * Wake robust non-PI futexes here. The wakeup of |
1909 | 1905 | * PI futexes happens in exit_pi_state(): |
1910 | 1906 | */ |
1911 | - if (!pi) { | |
1912 | - if (uval & FUTEX_WAITERS) | |
1907 | + if (!pi && (uval & FUTEX_WAITERS)) | |
1913 | 1908 | futex_wake(uaddr, &curr->mm->mmap_sem, 1); |
1914 | - } | |
1915 | 1909 | } |
1916 | 1910 | return 0; |
1917 | 1911 | } |
kernel/rtmutex-debug.c
kernel/rtmutex.c
kernel/rtmutex_common.h
... | ... | @@ -103,7 +103,7 @@ |
103 | 103 | |
104 | 104 | static inline struct task_struct *rt_mutex_real_owner(struct rt_mutex *lock) |
105 | 105 | { |
106 | - return (struct task_struct *) | |
106 | + return (struct task_struct *) | |
107 | 107 | ((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS); |
108 | 108 | } |
109 | 109 | |
... | ... | @@ -120,5 +120,12 @@ |
120 | 120 | struct task_struct *proxy_owner); |
121 | 121 | extern void rt_mutex_proxy_unlock(struct rt_mutex *lock, |
122 | 122 | struct task_struct *proxy_owner); |
123 | + | |
124 | +#ifdef CONFIG_DEBUG_RT_MUTEXES | |
125 | +# include "rtmutex-debug.h" | |
126 | +#else | |
127 | +# include "rtmutex.h" | |
128 | +#endif | |
129 | + | |
123 | 130 | #endif |