Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'core-futexes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'core-futexes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
arm: Remove bogus comment in futex_atomic_cmpxchg_inatomic()
futex: Deobfuscate handle_futex_death()
plist: Add priority list test
plist: Shrink struct plist_head
futex,plist: Remove debug lock assignment from plist_node
futex,plist: Pass the real head of the priority list to plist_del()
futex: Sanitize futex ops argument types
futex: Sanitize cmpxchg_futex_value_locked API
futex: Remove redundant pagefault_disable in futex_atomic_cmpxchg_inatomic()
futex: Avoid redudant evaluation of task_pid_vnr()
futex: Update futex_wait_setup comments about locking

+404 -276
+16 -13
arch/alpha/include/asm/futex.h
··· 29 29 : "r" (uaddr), "r"(oparg) \ 30 30 : "memory") 31 31 32 - static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) 32 + static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) 33 33 { 34 34 int op = (encoded_op >> 28) & 7; 35 35 int cmp = (encoded_op >> 24) & 15; ··· 39 39 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 40 40 oparg = 1 << oparg; 41 41 42 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 42 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 43 43 return -EFAULT; 44 44 45 45 pagefault_disable(); ··· 81 81 } 82 82 83 83 static inline int 84 - futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 84 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 85 + u32 oldval, u32 newval) 85 86 { 86 - int prev, cmp; 87 + int ret = 0, cmp; 88 + u32 prev; 87 89 88 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 90 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 89 91 return -EFAULT; 90 92 91 93 __asm__ __volatile__ ( 92 94 __ASM_SMP_MB 93 - "1: ldl_l %0,0(%2)\n" 94 - " cmpeq %0,%3,%1\n" 95 - " beq %1,3f\n" 96 - " mov %4,%1\n" 97 - "2: stl_c %1,0(%2)\n" 98 - " beq %1,4f\n" 95 + "1: ldl_l %1,0(%3)\n" 96 + " cmpeq %1,%4,%2\n" 97 + " beq %2,3f\n" 98 + " mov %5,%2\n" 99 + "2: stl_c %2,0(%3)\n" 100 + " beq %2,4f\n" 99 101 "3: .subsection 2\n" 100 102 "4: br 1b\n" 101 103 " .previous\n" ··· 107 105 " .long 2b-.\n" 108 106 " lda $31,3b-2b(%0)\n" 109 107 " .previous\n" 110 - : "=&r"(prev), "=&r"(cmp) 108 + : "+r"(ret), "=&r"(prev), "=&r"(cmp) 111 109 : "r"(uaddr), "r"((long)oldval), "r"(newval) 112 110 : "memory"); 113 111 114 - return prev; 112 + *uval = prev; 113 + return ret; 115 114 } 116 115 117 116 #endif /* __KERNEL__ */
+14 -15
arch/arm/include/asm/futex.h
··· 35 35 : "cc", "memory") 36 36 37 37 static inline int 38 - futex_atomic_op_inuser (int encoded_op, int __user *uaddr) 38 + futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) 39 39 { 40 40 int op = (encoded_op >> 28) & 7; 41 41 int cmp = (encoded_op >> 24) & 15; ··· 46 46 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 47 47 oparg = 1 << oparg; 48 48 49 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 49 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 50 50 return -EFAULT; 51 51 52 52 pagefault_disable(); /* implies preempt_disable() */ ··· 88 88 } 89 89 90 90 static inline int 91 - futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 91 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 92 + u32 oldval, u32 newval) 92 93 { 93 - int val; 94 + int ret = 0; 95 + u32 val; 94 96 95 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 97 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 96 98 return -EFAULT; 97 99 98 - pagefault_disable(); /* implies preempt_disable() */ 99 - 100 100 __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" 101 - "1: " T(ldr) " %0, [%3]\n" 102 - " teq %0, %1\n" 101 + "1: " T(ldr) " %1, [%4]\n" 102 + " teq %1, %2\n" 103 103 " it eq @ explicit IT needed for the 2b label\n" 104 - "2: " T(streq) " %2, [%3]\n" 104 + "2: " T(streq) " %3, [%4]\n" 105 105 "3:\n" 106 106 " .pushsection __ex_table,\"a\"\n" 107 107 " .align 3\n" 108 108 " .long 1b, 4f, 2b, 4f\n" 109 109 " .popsection\n" 110 110 " .pushsection .fixup,\"ax\"\n" 111 - "4: mov %0, %4\n" 111 + "4: mov %0, %5\n" 112 112 " b 3b\n" 113 113 " .popsection" 114 - : "=&r" (val) 114 + : "+r" (ret), "=&r" (val) 115 115 : "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT) 116 116 : "cc", "memory"); 117 117 118 - pagefault_enable(); /* subsumes preempt_enable() */ 119 - 120 - return val; 118 + *uval = val; 119 + return ret; 121 120 } 122 121 123 122 #endif /* !SMP */
+3 -2
arch/frv/include/asm/futex.h
··· 7 7 #include <asm/errno.h> 8 8 #include <asm/uaccess.h> 9 9 10 - extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr); 10 + extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr); 11 11 12 12 static inline int 13 - futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 13 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 14 + u32 oldval, u32 newval) 14 15 { 15 16 return -ENOSYS; 16 17 }
+7 -7
arch/frv/kernel/futex.c
··· 18 18 * the various futex operations; MMU fault checking is ignored under no-MMU 19 19 * conditions 20 20 */ 21 - static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval) 21 + static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr, int *_oldval) 22 22 { 23 23 int oldval, ret; 24 24 ··· 50 50 return ret; 51 51 } 52 52 53 - static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval) 53 + static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr, int *_oldval) 54 54 { 55 55 int oldval, ret; 56 56 ··· 83 83 return ret; 84 84 } 85 85 86 - static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval) 86 + static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr, int *_oldval) 87 87 { 88 88 int oldval, ret; 89 89 ··· 116 116 return ret; 117 117 } 118 118 119 - static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval) 119 + static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr, int *_oldval) 120 120 { 121 121 int oldval, ret; 122 122 ··· 149 149 return ret; 150 150 } 151 151 152 - static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval) 152 + static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_oldval) 153 153 { 154 154 int oldval, ret; 155 155 ··· 186 186 /* 187 187 * do the futex operations 188 188 */ 189 - int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) 189 + int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) 190 190 { 191 191 int op = (encoded_op >> 28) & 7; 192 192 int cmp = (encoded_op >> 24) & 15; ··· 197 197 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 198 198 oparg = 1 << oparg; 199 199 200 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 200 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 201 201 return -EFAULT; 202 202 203 203 pagefault_disable();
+9 -6
arch/ia64/include/asm/futex.h
··· 46 46 } while (0) 47 47 48 48 static inline int 49 - futex_atomic_op_inuser (int encoded_op, int __user *uaddr) 49 + futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) 50 50 { 51 51 int op = (encoded_op >> 28) & 7; 52 52 int cmp = (encoded_op >> 24) & 15; ··· 56 56 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 57 57 oparg = 1 << oparg; 58 58 59 - if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) 59 + if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) 60 60 return -EFAULT; 61 61 62 62 pagefault_disable(); ··· 100 100 } 101 101 102 102 static inline int 103 - futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 103 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 104 + u32 oldval, u32 newval) 104 105 { 105 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 106 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 106 107 return -EFAULT; 107 108 108 109 { 109 - register unsigned long r8 __asm ("r8"); 110 + register unsigned long r8 __asm ("r8") = 0; 111 + unsigned long prev; 110 112 __asm__ __volatile__( 111 113 " mf;; \n" 112 114 " mov ar.ccv=%3;; \n" 113 115 "[1:] cmpxchg4.acq %0=[%1],%2,ar.ccv \n" 114 116 " .xdata4 \"__ex_table\", 1b-., 2f-. \n" 115 117 "[2:]" 116 - : "=r" (r8) 118 + : "=r" (prev) 117 119 : "r" (uaddr), "r" (newval), 118 120 "rO" ((long) (unsigned) oldval) 119 121 : "memory"); 122 + *uval = prev; 120 123 return r8; 121 124 } 122 125 }
+17 -14
arch/microblaze/include/asm/futex.h
··· 29 29 }) 30 30 31 31 static inline int 32 - futex_atomic_op_inuser(int encoded_op, int __user *uaddr) 32 + futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) 33 33 { 34 34 int op = (encoded_op >> 28) & 7; 35 35 int cmp = (encoded_op >> 24) & 15; ··· 39 39 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 40 40 oparg = 1 << oparg; 41 41 42 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 42 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 43 43 return -EFAULT; 44 44 45 45 pagefault_disable(); ··· 94 94 } 95 95 96 96 static inline int 97 - futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 97 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 98 + u32 oldval, u32 newval) 98 99 { 99 - int prev, cmp; 100 + int ret = 0, cmp; 101 + u32 prev; 100 102 101 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 103 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 102 104 return -EFAULT; 103 105 104 - __asm__ __volatile__ ("1: lwx %0, %2, r0; \ 105 - cmp %1, %0, %3; \ 106 - beqi %1, 3f; \ 107 - 2: swx %4, %2, r0; \ 108 - addic %1, r0, 0; \ 109 - bnei %1, 1b; \ 106 + __asm__ __volatile__ ("1: lwx %1, %3, r0; \ 107 + cmp %2, %1, %4; \ 108 + beqi %2, 3f; \ 109 + 2: swx %5, %3, r0; \ 110 + addic %2, r0, 0; \ 111 + bnei %2, 1b; \ 110 112 3: \ 111 113 .section .fixup,\"ax\"; \ 112 114 4: brid 3b; \ 113 - addik %0, r0, %5; \ 115 + addik %0, r0, %6; \ 114 116 .previous; \ 115 117 .section __ex_table,\"a\"; \ 116 118 .word 1b,4b,2b,4b; \ 117 119 .previous;" \ 118 - : "=&r" (prev), "=&r"(cmp) \ 120 + : "+r" (ret), "=&r" (prev), "=&r"(cmp) \ 119 121 : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)); 120 122 121 - return prev; 123 + *uval = prev; 124 + return ret; 122 125 } 123 126 124 127 #endif /* __KERNEL__ */
+21 -18
arch/mips/include/asm/futex.h
··· 75 75 } 76 76 77 77 static inline int 78 - futex_atomic_op_inuser(int encoded_op, int __user *uaddr) 78 + futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) 79 79 { 80 80 int op = (encoded_op >> 28) & 7; 81 81 int cmp = (encoded_op >> 24) & 15; ··· 85 85 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 86 86 oparg = 1 << oparg; 87 87 88 - if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) 88 + if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) 89 89 return -EFAULT; 90 90 91 91 pagefault_disable(); ··· 132 132 } 133 133 134 134 static inline int 135 - futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 135 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 136 + u32 oldval, u32 newval) 136 137 { 137 - int retval; 138 + int ret = 0; 139 + u32 val; 138 140 139 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 141 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 140 142 return -EFAULT; 141 143 142 144 if (cpu_has_llsc && R10000_LLSC_WAR) { ··· 147 145 " .set push \n" 148 146 " .set noat \n" 149 147 " .set mips3 \n" 150 - "1: ll %0, %2 \n" 151 - " bne %0, %z3, 3f \n" 148 + "1: ll %1, %3 \n" 149 + " bne %1, %z4, 3f \n" 152 150 " .set mips0 \n" 153 - " move $1, %z4 \n" 151 + " move $1, %z5 \n" 154 152 " .set mips3 \n" 155 - "2: sc $1, %1 \n" 153 + "2: sc $1, %2 \n" 156 154 " beqzl $1, 1b \n" 157 155 __WEAK_LLSC_MB 158 156 "3: \n" 159 157 " .set pop \n" 160 158 " .section .fixup,\"ax\" \n" 161 - "4: li %0, %5 \n" 159 + "4: li %0, %6 \n" 162 160 " j 3b \n" 163 161 " .previous \n" 164 162 " .section __ex_table,\"a\" \n" 165 163 " "__UA_ADDR "\t1b, 4b \n" 166 164 " "__UA_ADDR "\t2b, 4b \n" 167 165 " .previous \n" 168 - : "=&r" (retval), "=R" (*uaddr) 166 + : "+r" (ret), "=&r" (val), "=R" (*uaddr) 169 167 : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT) 170 168 : "memory"); 171 169 } else if (cpu_has_llsc) { ··· 174 172 " .set push \n" 175 173 " .set noat \n" 176 174 " .set mips3 \n" 177 - "1: ll %0, %2 \n" 178 - " bne %0, %z3, 3f \n" 175 + "1: ll %1, %3 \n" 176 + " bne %1, %z4, 3f \n" 179 177 " .set mips0 \n" 180 - " move $1, %z4 \n" 178 + " move $1, %z5 \n" 181 179 " .set mips3 \n" 182 - "2: sc $1, %1 \n" 180 + "2: sc $1, %2 \n" 183 181 " beqz $1, 1b \n" 184 182 __WEAK_LLSC_MB 185 183 "3: \n" 186 184 " .set pop \n" 187 185 " .section .fixup,\"ax\" \n" 188 - "4: li %0, %5 \n" 186 + "4: li %0, %6 \n" 189 187 " j 3b \n" 190 188 " .previous \n" 191 189 " .section __ex_table,\"a\" \n" 192 190 " "__UA_ADDR "\t1b, 4b \n" 193 191 " "__UA_ADDR "\t2b, 4b \n" 194 192 " .previous \n" 195 - : "=&r" (retval), "=R" (*uaddr) 193 + : "+r" (ret), "=&r" (val), "=R" (*uaddr) 196 194 : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT) 197 195 : "memory"); 198 196 } else 199 197 return -ENOSYS; 200 198 201 - return retval; 199 + *uval = val; 200 + return ret; 202 201 } 203 202 204 203 #endif
+12 -12
arch/parisc/include/asm/futex.h
··· 8 8 #include <asm/errno.h> 9 9 10 10 static inline int 11 - futex_atomic_op_inuser (int encoded_op, int __user *uaddr) 11 + futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) 12 12 { 13 13 int op = (encoded_op >> 28) & 7; 14 14 int cmp = (encoded_op >> 24) & 15; ··· 18 18 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 19 19 oparg = 1 << oparg; 20 20 21 - if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) 21 + if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) 22 22 return -EFAULT; 23 23 24 24 pagefault_disable(); ··· 51 51 52 52 /* Non-atomic version */ 53 53 static inline int 54 - futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 54 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 55 + u32 oldval, u32 newval) 55 56 { 56 - int err = 0; 57 - int uval; 57 + u32 val; 58 58 59 59 /* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is 60 60 * our gateway page, and causes no end of trouble... ··· 62 62 if (segment_eq(KERNEL_DS, get_fs()) && !uaddr) 63 63 return -EFAULT; 64 64 65 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 65 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 66 66 return -EFAULT; 67 67 68 - err = get_user(uval, uaddr); 69 - if (err) return -EFAULT; 70 - if (uval == oldval) 71 - err = put_user(newval, uaddr); 72 - if (err) return -EFAULT; 73 - return uval; 68 + if (get_user(val, uaddr)) 69 + return -EFAULT; 70 + if (val == oldval && put_user(newval, uaddr)) 71 + return -EFAULT; 72 + *uval = val; 73 + return 0; 74 74 } 75 75 76 76 #endif /*__KERNEL__*/
+15 -12
arch/powerpc/include/asm/futex.h
··· 30 30 : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \ 31 31 : "cr0", "memory") 32 32 33 - static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) 33 + static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) 34 34 { 35 35 int op = (encoded_op >> 28) & 7; 36 36 int cmp = (encoded_op >> 24) & 15; ··· 40 40 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 41 41 oparg = 1 << oparg; 42 42 43 - if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) 43 + if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) 44 44 return -EFAULT; 45 45 46 46 pagefault_disable(); ··· 82 82 } 83 83 84 84 static inline int 85 - futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 85 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 86 + u32 oldval, u32 newval) 86 87 { 87 - int prev; 88 + int ret = 0; 89 + u32 prev; 88 90 89 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 91 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 90 92 return -EFAULT; 91 93 92 94 __asm__ __volatile__ ( 93 95 PPC_RELEASE_BARRIER 94 - "1: lwarx %0,0,%2 # futex_atomic_cmpxchg_inatomic\n\ 95 - cmpw 0,%0,%3\n\ 96 + "1: lwarx %1,0,%3 # futex_atomic_cmpxchg_inatomic\n\ 97 + cmpw 0,%1,%4\n\ 96 98 bne- 3f\n" 97 - PPC405_ERR77(0,%2) 98 - "2: stwcx. %4,0,%2\n\ 99 + PPC405_ERR77(0,%3) 100 + "2: stwcx. %5,0,%3\n\ 99 101 bne- 1b\n" 100 102 PPC_ACQUIRE_BARRIER 101 103 "3: .section .fixup,\"ax\"\n\ 102 - 4: li %0,%5\n\ 104 + 4: li %0,%6\n\ 103 105 b 3b\n\ 104 106 .previous\n\ 105 107 .section __ex_table,\"a\"\n\ 106 108 .align 3\n\ 107 109 " PPC_LONG "1b,4b,2b,4b\n\ 108 110 .previous" \ 109 - : "=&r" (prev), "+m" (*uaddr) 111 + : "+r" (ret), "=&r" (prev), "+m" (*uaddr) 110 112 : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT) 111 113 : "cc", "memory"); 112 114 113 - return prev; 115 + *uval = prev; 116 + return ret; 114 117 } 115 118 116 119 #endif /* __KERNEL__ */
+6 -6
arch/s390/include/asm/futex.h
··· 7 7 #include <linux/uaccess.h> 8 8 #include <asm/errno.h> 9 9 10 - static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) 10 + static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) 11 11 { 12 12 int op = (encoded_op >> 28) & 7; 13 13 int cmp = (encoded_op >> 24) & 15; ··· 18 18 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 19 19 oparg = 1 << oparg; 20 20 21 - if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) 21 + if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) 22 22 return -EFAULT; 23 23 24 24 pagefault_disable(); ··· 39 39 return ret; 40 40 } 41 41 42 - static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, 43 - int oldval, int newval) 42 + static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 43 + u32 oldval, u32 newval) 44 44 { 45 - if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) 45 + if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) 46 46 return -EFAULT; 47 47 48 - return uaccess.futex_atomic_cmpxchg(uaddr, oldval, newval); 48 + return uaccess.futex_atomic_cmpxchg(uval, uaddr, oldval, newval); 49 49 } 50 50 51 51 #endif /* __KERNEL__ */
+2 -2
arch/s390/include/asm/uaccess.h
··· 83 83 size_t (*clear_user)(size_t, void __user *); 84 84 size_t (*strnlen_user)(size_t, const char __user *); 85 85 size_t (*strncpy_from_user)(size_t, const char __user *, char *); 86 - int (*futex_atomic_op)(int op, int __user *, int oparg, int *old); 87 - int (*futex_atomic_cmpxchg)(int __user *, int old, int new); 86 + int (*futex_atomic_op)(int op, u32 __user *, int oparg, int *old); 87 + int (*futex_atomic_cmpxchg)(u32 *, u32 __user *, u32 old, u32 new); 88 88 }; 89 89 90 90 extern struct uaccess_ops uaccess;
+4 -4
arch/s390/lib/uaccess.h
··· 12 12 extern size_t copy_to_user_std(size_t, void __user *, const void *); 13 13 extern size_t strnlen_user_std(size_t, const char __user *); 14 14 extern size_t strncpy_from_user_std(size_t, const char __user *, char *); 15 - extern int futex_atomic_cmpxchg_std(int __user *, int, int); 16 - extern int futex_atomic_op_std(int, int __user *, int, int *); 15 + extern int futex_atomic_cmpxchg_std(u32 *, u32 __user *, u32, u32); 16 + extern int futex_atomic_op_std(int, u32 __user *, int, int *); 17 17 18 18 extern size_t copy_from_user_pt(size_t, const void __user *, void *); 19 19 extern size_t copy_to_user_pt(size_t, void __user *, const void *); 20 - extern int futex_atomic_op_pt(int, int __user *, int, int *); 21 - extern int futex_atomic_cmpxchg_pt(int __user *, int, int); 20 + extern int futex_atomic_op_pt(int, u32 __user *, int, int *); 21 + extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32); 22 22 23 23 #endif /* __ARCH_S390_LIB_UACCESS_H */
+10 -7
arch/s390/lib/uaccess_pt.c
··· 302 302 : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ 303 303 "m" (*uaddr) : "cc" ); 304 304 305 - static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old) 305 + static int __futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old) 306 306 { 307 307 int oldval = 0, newval, ret; 308 308 ··· 335 335 return ret; 336 336 } 337 337 338 - int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old) 338 + int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old) 339 339 { 340 340 int ret; 341 341 ··· 354 354 return ret; 355 355 } 356 356 357 - static int __futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval) 357 + static int __futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr, 358 + u32 oldval, u32 newval) 358 359 { 359 360 int ret; 360 361 361 362 asm volatile("0: cs %1,%4,0(%5)\n" 362 - "1: lr %0,%1\n" 363 + "1: la %0,0\n" 363 364 "2:\n" 364 365 EX_TABLE(0b,2b) EX_TABLE(1b,2b) 365 366 : "=d" (ret), "+d" (oldval), "=m" (*uaddr) 366 367 : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr) 367 368 : "cc", "memory" ); 369 + *uval = oldval; 368 370 return ret; 369 371 } 370 372 371 - int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval) 373 + int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr, 374 + u32 oldval, u32 newval) 372 375 { 373 376 int ret; 374 377 375 378 if (segment_eq(get_fs(), KERNEL_DS)) 376 - return __futex_atomic_cmpxchg_pt(uaddr, oldval, newval); 379 + return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval); 377 380 spin_lock(&current->mm->page_table_lock); 378 381 uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr); 379 382 if (!uaddr) { ··· 385 382 } 386 383 get_page(virt_to_page(uaddr)); 387 384 spin_unlock(&current->mm->page_table_lock); 388 - ret = __futex_atomic_cmpxchg_pt(uaddr, oldval, newval); 385 + ret = __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval); 389 386 put_page(virt_to_page(uaddr)); 390 387 return ret; 391 388 }
+5 -3
arch/s390/lib/uaccess_std.c
··· 255 255 : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ 256 256 "m" (*uaddr) : "cc"); 257 257 258 - int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old) 258 + int futex_atomic_op_std(int op, u32 __user *uaddr, int oparg, int *old) 259 259 { 260 260 int oldval = 0, newval, ret; 261 261 ··· 287 287 return ret; 288 288 } 289 289 290 - int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval) 290 + int futex_atomic_cmpxchg_std(u32 *uval, u32 __user *uaddr, 291 + u32 oldval, u32 newval) 291 292 { 292 293 int ret; 293 294 294 295 asm volatile( 295 296 " sacf 256\n" 296 297 "0: cs %1,%4,0(%5)\n" 297 - "1: lr %0,%1\n" 298 + "1: la %0,0\n" 298 299 "2: sacf 0\n" 299 300 EX_TABLE(0b,2b) EX_TABLE(1b,2b) 300 301 : "=d" (ret), "+d" (oldval), "=m" (*uaddr) 301 302 : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr) 302 303 : "cc", "memory" ); 304 + *uval = oldval; 303 305 return ret; 304 306 } 305 307
+12 -12
arch/sh/include/asm/futex-irq.h
··· 3 3 4 4 #include <asm/system.h> 5 5 6 - static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, 6 + static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr, 7 7 int *oldval) 8 8 { 9 9 unsigned long flags; ··· 20 20 return ret; 21 21 } 22 22 23 - static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, 23 + static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr, 24 24 int *oldval) 25 25 { 26 26 unsigned long flags; ··· 37 37 return ret; 38 38 } 39 39 40 - static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, 40 + static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr, 41 41 int *oldval) 42 42 { 43 43 unsigned long flags; ··· 54 54 return ret; 55 55 } 56 56 57 - static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, 57 + static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr, 58 58 int *oldval) 59 59 { 60 60 unsigned long flags; ··· 71 71 return ret; 72 72 } 73 73 74 - static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, 74 + static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, 75 75 int *oldval) 76 76 { 77 77 unsigned long flags; ··· 88 88 return ret; 89 89 } 90 90 91 - static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr, 92 - int oldval, int newval) 91 + static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval, 92 + u32 __user *uaddr, 93 + u32 oldval, u32 newval) 93 94 { 94 95 unsigned long flags; 95 - int ret, prev = 0; 96 + int ret; 97 + u32 prev = 0; 96 98 97 99 local_irq_save(flags); 98 100 ··· 104 102 105 103 local_irq_restore(flags); 106 104 107 - if (ret) 108 - return ret; 109 - 110 - return prev; 105 + *uval = prev; 106 + return ret; 111 107 } 112 108 113 109 #endif /* __ASM_SH_FUTEX_IRQ_H */
+6 -5
arch/sh/include/asm/futex.h
··· 10 10 /* XXX: UP variants, fix for SH-4A and SMP.. */ 11 11 #include <asm/futex-irq.h> 12 12 13 - static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) 13 + static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) 14 14 { 15 15 int op = (encoded_op >> 28) & 7; 16 16 int cmp = (encoded_op >> 24) & 15; ··· 21 21 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 22 22 oparg = 1 << oparg; 23 23 24 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 24 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 25 25 return -EFAULT; 26 26 27 27 pagefault_disable(); ··· 65 65 } 66 66 67 67 static inline int 68 - futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 68 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 69 + u32 oldval, u32 newval) 69 70 { 70 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 71 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 71 72 return -EFAULT; 72 73 73 - return atomic_futex_op_cmpxchg_inatomic(uaddr, oldval, newval); 74 + return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval); 74 75 } 75 76 76 77 #endif /* __KERNEL__ */
+12 -8
arch/sparc/include/asm/futex_64.h
··· 30 30 : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \ 31 31 : "memory") 32 32 33 - static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) 33 + static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) 34 34 { 35 35 int op = (encoded_op >> 28) & 7; 36 36 int cmp = (encoded_op >> 24) & 15; ··· 38 38 int cmparg = (encoded_op << 20) >> 20; 39 39 int oldval = 0, ret, tem; 40 40 41 - if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))) 41 + if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))) 42 42 return -EFAULT; 43 43 if (unlikely((((unsigned long) uaddr) & 0x3UL))) 44 44 return -EINVAL; ··· 85 85 } 86 86 87 87 static inline int 88 - futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 88 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 89 + u32 oldval, u32 newval) 89 90 { 91 + int ret = 0; 92 + 90 93 __asm__ __volatile__( 91 - "\n1: casa [%3] %%asi, %2, %0\n" 94 + "\n1: casa [%4] %%asi, %3, %1\n" 92 95 "2:\n" 93 96 " .section .fixup,#alloc,#execinstr\n" 94 97 " .align 4\n" 95 98 "3: sethi %%hi(2b), %0\n" 96 99 " jmpl %0 + %%lo(2b), %%g0\n" 97 - " mov %4, %0\n" 100 + " mov %5, %0\n" 98 101 " .previous\n" 99 102 " .section __ex_table,\"a\"\n" 100 103 " .align 4\n" 101 104 " .word 1b, 3b\n" 102 105 " .previous\n" 103 - : "=r" (newval) 104 - : "0" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT) 106 + : "+r" (ret), "=r" (newval) 107 + : "1" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT) 105 108 : "memory"); 106 109 107 - return newval; 110 + *uval = newval; 111 + return ret; 108 112 } 109 113 110 114 #endif /* !(_SPARC64_FUTEX_H) */
+14 -13
arch/tile/include/asm/futex.h
··· 29 29 #include <linux/uaccess.h> 30 30 #include <linux/errno.h> 31 31 32 - extern struct __get_user futex_set(int __user *v, int i); 33 - extern struct __get_user futex_add(int __user *v, int n); 34 - extern struct __get_user futex_or(int __user *v, int n); 35 - extern struct __get_user futex_andn(int __user *v, int n); 36 - extern struct __get_user futex_cmpxchg(int __user *v, int o, int n); 32 + extern struct __get_user futex_set(u32 __user *v, int i); 33 + extern struct __get_user futex_add(u32 __user *v, int n); 34 + extern struct __get_user futex_or(u32 __user *v, int n); 35 + extern struct __get_user futex_andn(u32 __user *v, int n); 36 + extern struct __get_user futex_cmpxchg(u32 __user *v, int o, int n); 37 37 38 38 #ifndef __tilegx__ 39 - extern struct __get_user futex_xor(int __user *v, int n); 39 + extern struct __get_user futex_xor(u32 __user *v, int n); 40 40 #else 41 - static inline struct __get_user futex_xor(int __user *uaddr, int n) 41 + static inline struct __get_user futex_xor(u32 __user *uaddr, int n) 42 42 { 43 43 struct __get_user asm_ret = __get_user_4(uaddr); 44 44 if (!asm_ret.err) { ··· 53 53 } 54 54 #endif 55 55 56 - static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) 56 + static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) 57 57 { 58 58 int op = (encoded_op >> 28) & 7; 59 59 int cmp = (encoded_op >> 24) & 15; ··· 65 65 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 66 66 oparg = 1 << oparg; 67 67 68 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 68 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 69 69 return -EFAULT; 70 70 71 71 pagefault_disable(); ··· 119 119 return ret; 120 120 } 121 121 122 - static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, 123 - int newval) 122 + static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 123 + u32 oldval, u32 newval) 124 124 { 125 125 struct __get_user asm_ret; 126 126 127 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 127 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 128 128 return -EFAULT; 129 129 130 130 asm_ret = futex_cmpxchg(uaddr, oldval, newval); 131 - return asm_ret.err ? asm_ret.err : asm_ret.val; 131 + *uval = asm_ret.val; 132 + return asm_ret.err; 132 133 } 133 134 134 135 #ifndef __tilegx__
+12 -10
arch/x86/include/asm/futex.h
··· 37 37 "+m" (*uaddr), "=&r" (tem) \ 38 38 : "r" (oparg), "i" (-EFAULT), "1" (0)) 39 39 40 - static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) 40 + static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) 41 41 { 42 42 int op = (encoded_op >> 28) & 7; 43 43 int cmp = (encoded_op >> 24) & 15; ··· 48 48 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 49 49 oparg = 1 << oparg; 50 50 51 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 51 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 52 52 return -EFAULT; 53 53 54 54 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP) ··· 109 109 return ret; 110 110 } 111 111 112 - static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, 113 - int newval) 112 + static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 113 + u32 oldval, u32 newval) 114 114 { 115 + int ret = 0; 115 116 116 117 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP) 117 118 /* Real i386 machines have no cmpxchg instruction */ ··· 120 119 return -ENOSYS; 121 120 #endif 122 121 123 - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 122 + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 124 123 return -EFAULT; 125 124 126 - asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n" 125 + asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n" 127 126 "2:\t.section .fixup, \"ax\"\n" 128 - "3:\tmov %2, %0\n" 127 + "3:\tmov %3, %0\n" 129 128 "\tjmp 2b\n" 130 129 "\t.previous\n" 131 130 _ASM_EXTABLE(1b, 3b) 132 - : "=a" (oldval), "+m" (*uaddr) 133 - : "i" (-EFAULT), "r" (newval), "0" (oldval) 131 + : "+r" (ret), "=a" (oldval), "+m" (*uaddr) 132 + : "i" (-EFAULT), "r" (newval), "1" (oldval) 134 133 : "memory" 135 134 ); 136 135 137 - return oldval; 136 + *uval = oldval; 137 + return ret; 138 138 } 139 139 140 140 #endif
+4 -3
include/asm-generic/futex.h
··· 6 6 #include <asm/errno.h> 7 7 8 8 static inline int 9 - futex_atomic_op_inuser (int encoded_op, int __user *uaddr) 9 + futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) 10 10 { 11 11 int op = (encoded_op >> 28) & 7; 12 12 int cmp = (encoded_op >> 24) & 15; ··· 16 16 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 17 17 oparg = 1 << oparg; 18 18 19 - if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) 19 + if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) 20 20 return -EFAULT; 21 21 22 22 pagefault_disable(); ··· 48 48 } 49 49 50 50 static inline int 51 - futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 51 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 52 + u32 oldval, u32 newval) 52 53 { 53 54 return -ENOSYS; 54 55 }
+24 -23
include/linux/plist.h
··· 31 31 * 32 32 * Simple ASCII art explanation: 33 33 * 34 - * |HEAD | 35 - * | | 36 - * |prio_list.prev|<------------------------------------| 37 - * |prio_list.next|<->|pl|<->|pl|<--------------->|pl|<-| 38 - * |10 | |10| |21| |21| |21| |40| (prio) 39 - * | | | | | | | | | | | | 40 - * | | | | | | | | | | | | 41 - * |node_list.next|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-| 42 - * |node_list.prev|<------------------------------------| 34 + * pl:prio_list (only for plist_node) 35 + * nl:node_list 36 + * HEAD| NODE(S) 37 + * | 38 + * ||------------------------------------| 39 + * ||->|pl|<->|pl|<--------------->|pl|<-| 40 + * | |10| |21| |21| |21| |40| (prio) 41 + * | | | | | | | | | | | 42 + * | | | | | | | | | | | 43 + * |->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-| 44 + * |-------------------------------------------| 43 45 * 44 46 * The nodes on the prio_list list are sorted by priority to simplify 45 47 * the insertion of new nodes. There are no nodes with duplicate ··· 80 78 #include <linux/spinlock_types.h> 81 79 82 80 struct plist_head { 83 - struct list_head prio_list; 84 81 struct list_head node_list; 85 82 #ifdef CONFIG_DEBUG_PI_LIST 86 83 raw_spinlock_t *rawlock; ··· 89 88 90 89 struct plist_node { 91 90 int prio; 92 - struct plist_head plist; 91 + struct list_head prio_list; 92 + struct list_head node_list; 93 93 }; 94 94 95 95 #ifdef CONFIG_DEBUG_PI_LIST ··· 102 100 #endif 103 101 104 102 #define _PLIST_HEAD_INIT(head) \ 105 - .prio_list = LIST_HEAD_INIT((head).prio_list), \ 106 103 .node_list = LIST_HEAD_INIT((head).node_list) 107 104 108 105 /** ··· 134 133 #define PLIST_NODE_INIT(node, __prio) \ 135 134 { \ 136 135 .prio = (__prio), \ 137 - .plist = { _PLIST_HEAD_INIT((node).plist) }, \ 136 + .prio_list = LIST_HEAD_INIT((node).prio_list), \ 137 + .node_list = LIST_HEAD_INIT((node).node_list), \ 138 138 } 139 139 140 140 /** ··· 146 144 static inline void 147 145 plist_head_init(struct plist_head *head, spinlock_t *lock) 148 146 { 149 - INIT_LIST_HEAD(&head->prio_list); 150 147 INIT_LIST_HEAD(&head->node_list); 151 148 #ifdef CONFIG_DEBUG_PI_LIST 152 149 head->spinlock = lock; ··· 161 160 static inline void 162 161 plist_head_init_raw(struct plist_head *head, raw_spinlock_t *lock) 163 162 { 164 - INIT_LIST_HEAD(&head->prio_list); 165 163 INIT_LIST_HEAD(&head->node_list); 166 164 #ifdef CONFIG_DEBUG_PI_LIST 167 165 head->rawlock = lock; ··· 176 176 static inline void plist_node_init(struct plist_node *node, int prio) 177 177 { 178 178 node->prio = prio; 179 - plist_head_init(&node->plist, NULL); 179 + INIT_LIST_HEAD(&node->prio_list); 180 + INIT_LIST_HEAD(&node->node_list); 180 181 } 181 182 182 183 extern void plist_add(struct plist_node *node, struct plist_head *head); ··· 189 188 * @head: the head for your list 190 189 */ 191 190 #define plist_for_each(pos, head) \ 192 - list_for_each_entry(pos, &(head)->node_list, plist.node_list) 191 + list_for_each_entry(pos, &(head)->node_list, node_list) 193 192 194 193 /** 195 194 * plist_for_each_safe - iterate safely over a plist of given type ··· 200 199 * Iterate over a plist of given type, safe against removal of list entry. 201 200 */ 202 201 #define plist_for_each_safe(pos, n, head) \ 203 - list_for_each_entry_safe(pos, n, &(head)->node_list, plist.node_list) 202 + list_for_each_entry_safe(pos, n, &(head)->node_list, node_list) 204 203 205 204 /** 206 205 * plist_for_each_entry - iterate over list of given type ··· 209 208 * @mem: the name of the list_struct within the struct 210 209 */ 211 210 #define plist_for_each_entry(pos, head, mem) \ 212 - list_for_each_entry(pos, &(head)->node_list, mem.plist.node_list) 211 + list_for_each_entry(pos, &(head)->node_list, mem.node_list) 213 212 214 213 /** 215 214 * plist_for_each_entry_safe - iterate safely over list of given type ··· 221 220 * Iterate over list of given type, safe against removal of list entry. 222 221 */ 223 222 #define plist_for_each_entry_safe(pos, n, head, m) \ 224 - list_for_each_entry_safe(pos, n, &(head)->node_list, m.plist.node_list) 223 + list_for_each_entry_safe(pos, n, &(head)->node_list, m.node_list) 225 224 226 225 /** 227 226 * plist_head_empty - return !0 if a plist_head is empty ··· 238 237 */ 239 238 static inline int plist_node_empty(const struct plist_node *node) 240 239 { 241 - return plist_head_empty(&node->plist); 240 + return list_empty(&node->node_list); 242 241 } 243 242 244 243 /* All functions below assume the plist_head is not empty. */ ··· 286 285 static inline struct plist_node *plist_first(const struct plist_head *head) 287 286 { 288 287 return list_entry(head->node_list.next, 289 - struct plist_node, plist.node_list); 288 + struct plist_node, node_list); 290 289 } 291 290 292 291 /** ··· 298 297 static inline struct plist_node *plist_last(const struct plist_head *head) 299 298 { 300 299 return list_entry(head->node_list.prev, 301 - struct plist_node, plist.node_list); 300 + struct plist_node, node_list); 302 301 } 303 302 304 303 #endif
+64 -61
kernel/futex.c
··· 381 381 return NULL; 382 382 } 383 383 384 - static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval) 384 + static int cmpxchg_futex_value_locked(u32 *curval, u32 __user *uaddr, 385 + u32 uval, u32 newval) 385 386 { 386 - u32 curval; 387 + int ret; 387 388 388 389 pagefault_disable(); 389 - curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); 390 + ret = futex_atomic_cmpxchg_inatomic(curval, uaddr, uval, newval); 390 391 pagefault_enable(); 391 392 392 - return curval; 393 + return ret; 393 394 } 394 395 395 396 static int get_futex_value_locked(u32 *dest, u32 __user *from) ··· 675 674 struct task_struct *task, int set_waiters) 676 675 { 677 676 int lock_taken, ret, ownerdied = 0; 678 - u32 uval, newval, curval; 677 + u32 uval, newval, curval, vpid = task_pid_vnr(task); 679 678 680 679 retry: 681 680 ret = lock_taken = 0; ··· 685 684 * (by doing a 0 -> TID atomic cmpxchg), while holding all 686 685 * the locks. It will most likely not succeed. 687 686 */ 688 - newval = task_pid_vnr(task); 687 + newval = vpid; 689 688 if (set_waiters) 690 689 newval |= FUTEX_WAITERS; 691 690 692 - curval = cmpxchg_futex_value_locked(uaddr, 0, newval); 693 - 694 - if (unlikely(curval == -EFAULT)) 691 + if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, 0, newval))) 695 692 return -EFAULT; 696 693 697 694 /* 698 695 * Detect deadlocks. 699 696 */ 700 - if ((unlikely((curval & FUTEX_TID_MASK) == task_pid_vnr(task)))) 697 + if ((unlikely((curval & FUTEX_TID_MASK) == vpid))) 701 698 return -EDEADLK; 702 699 703 700 /* ··· 722 723 */ 723 724 if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { 724 725 /* Keep the OWNER_DIED bit */ 725 - newval = (curval & ~FUTEX_TID_MASK) | task_pid_vnr(task); 726 + newval = (curval & ~FUTEX_TID_MASK) | vpid; 726 727 ownerdied = 0; 727 728 lock_taken = 1; 728 729 } 729 730 730 - curval = cmpxchg_futex_value_locked(uaddr, uval, newval); 731 - 732 - if (unlikely(curval == -EFAULT)) 731 + if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))) 733 732 return -EFAULT; 734 733 if (unlikely(curval != uval)) 735 734 goto retry; ··· 772 775 return ret; 773 776 } 774 777 778 + /** 779 + * __unqueue_futex() - Remove the futex_q from its futex_hash_bucket 780 + * @q: The futex_q to unqueue 781 + * 782 + * The q->lock_ptr must not be NULL and must be held by the caller. 783 + */ 784 + static void __unqueue_futex(struct futex_q *q) 785 + { 786 + struct futex_hash_bucket *hb; 787 + 788 + if (WARN_ON(!q->lock_ptr || !spin_is_locked(q->lock_ptr) 789 + || plist_node_empty(&q->list))) 790 + return; 791 + 792 + hb = container_of(q->lock_ptr, struct futex_hash_bucket, lock); 793 + plist_del(&q->list, &hb->chain); 794 + } 795 + 775 796 /* 776 797 * The hash bucket lock must be held when this is called. 777 798 * Afterwards, the futex_q must not be accessed. ··· 807 792 */ 808 793 get_task_struct(p); 809 794 810 - plist_del(&q->list, &q->list.plist); 795 + __unqueue_futex(q); 811 796 /* 812 797 * The waiting task can free the futex_q as soon as 813 798 * q->lock_ptr = NULL is written, without taking any locks. A ··· 858 843 859 844 newval = FUTEX_WAITERS | task_pid_vnr(new_owner); 860 845 861 - curval = cmpxchg_futex_value_locked(uaddr, uval, newval); 862 - 863 - if (curval == -EFAULT) 846 + if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) 864 847 ret = -EFAULT; 865 848 else if (curval != uval) 866 849 ret = -EINVAL; ··· 893 880 * There is no waiter, so we unlock the futex. The owner died 894 881 * bit has not to be preserved here. We are the owner: 895 882 */ 896 - oldval = cmpxchg_futex_value_locked(uaddr, uval, 0); 897 - 898 - if (oldval == -EFAULT) 899 - return oldval; 883 + if (cmpxchg_futex_value_locked(&oldval, uaddr, uval, 0)) 884 + return -EFAULT; 900 885 if (oldval != uval) 901 886 return -EAGAIN; 902 887 ··· 1082 1071 plist_del(&q->list, &hb1->chain); 1083 1072 plist_add(&q->list, &hb2->chain); 1084 1073 q->lock_ptr = &hb2->lock; 1085 - #ifdef CONFIG_DEBUG_PI_LIST 1086 - q->list.plist.spinlock = &hb2->lock; 1087 - #endif 1088 1074 } 1089 1075 get_futex_key_refs(key2); 1090 1076 q->key = *key2; ··· 1108 1100 get_futex_key_refs(key); 1109 1101 q->key = *key; 1110 1102 1111 - WARN_ON(plist_node_empty(&q->list)); 1112 - plist_del(&q->list, &q->list.plist); 1103 + __unqueue_futex(q); 1113 1104 1114 1105 WARN_ON(!q->rt_waiter); 1115 1106 q->rt_waiter = NULL; 1116 1107 1117 1108 q->lock_ptr = &hb->lock; 1118 - #ifdef CONFIG_DEBUG_PI_LIST 1119 - q->list.plist.spinlock = &hb->lock; 1120 - #endif 1121 1109 1122 1110 wake_up_state(q->task, TASK_NORMAL); 1123 1111 } ··· 1461 1457 prio = min(current->normal_prio, MAX_RT_PRIO); 1462 1458 1463 1459 plist_node_init(&q->list, prio); 1464 - #ifdef CONFIG_DEBUG_PI_LIST 1465 - q->list.plist.spinlock = &hb->lock; 1466 - #endif 1467 1460 plist_add(&q->list, &hb->chain); 1468 1461 q->task = current; 1469 1462 spin_unlock(&hb->lock); ··· 1505 1504 spin_unlock(lock_ptr); 1506 1505 goto retry; 1507 1506 } 1508 - WARN_ON(plist_node_empty(&q->list)); 1509 - plist_del(&q->list, &q->list.plist); 1507 + __unqueue_futex(q); 1510 1508 1511 1509 BUG_ON(q->pi_state); 1512 1510 ··· 1525 1525 static void unqueue_me_pi(struct futex_q *q) 1526 1526 __releases(q->lock_ptr) 1527 1527 { 1528 - WARN_ON(plist_node_empty(&q->list)); 1529 - plist_del(&q->list, &q->list.plist); 1528 + __unqueue_futex(q); 1530 1529 1531 1530 BUG_ON(!q->pi_state); 1532 1531 free_pi_state(q->pi_state); ··· 1577 1578 while (1) { 1578 1579 newval = (uval & FUTEX_OWNER_DIED) | newtid; 1579 1580 1580 - curval = cmpxchg_futex_value_locked(uaddr, uval, newval); 1581 - 1582 - if (curval == -EFAULT) 1581 + if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) 1583 1582 goto handle_fault; 1584 1583 if (curval == uval) 1585 1584 break; ··· 1778 1781 * 1779 1782 * The basic logical guarantee of a futex is that it blocks ONLY 1780 1783 * if cond(var) is known to be true at the time of blocking, for 1781 - * any cond. If we queued after testing *uaddr, that would open 1782 - * a race condition where we could block indefinitely with 1784 + * any cond. If we locked the hash-bucket after testing *uaddr, that 1785 + * would open a race condition where we could block indefinitely with 1783 1786 * cond(var) false, which would violate the guarantee. 1784 1787 * 1785 - * A consequence is that futex_wait() can return zero and absorb 1786 - * a wakeup when *uaddr != val on entry to the syscall. This is 1787 - * rare, but normal. 1788 + * On the other hand, we insert q and release the hash-bucket only 1789 + * after testing *uaddr. This guarantees that futex_wait() will NOT 1790 + * absorb a wakeup if *uaddr does not match the desired values 1791 + * while the syscall executes. 1788 1792 */ 1789 1793 retry: 1790 1794 ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q->key); ··· 2044 2046 { 2045 2047 struct futex_hash_bucket *hb; 2046 2048 struct futex_q *this, *next; 2047 - u32 uval; 2048 2049 struct plist_head *head; 2049 2050 union futex_key key = FUTEX_KEY_INIT; 2051 + u32 uval, vpid = task_pid_vnr(current); 2050 2052 int ret; 2051 2053 2052 2054 retry: ··· 2055 2057 /* 2056 2058 * We release only a lock we actually own: 2057 2059 */ 2058 - if ((uval & FUTEX_TID_MASK) != task_pid_vnr(current)) 2060 + if ((uval & FUTEX_TID_MASK) != vpid) 2059 2061 return -EPERM; 2060 2062 2061 2063 ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key); ··· 2070 2072 * again. If it succeeds then we can return without waking 2071 2073 * anyone else up: 2072 2074 */ 2073 - if (!(uval & FUTEX_OWNER_DIED)) 2074 - uval = cmpxchg_futex_value_locked(uaddr, task_pid_vnr(current), 0); 2075 - 2076 - 2077 - if (unlikely(uval == -EFAULT)) 2075 + if (!(uval & FUTEX_OWNER_DIED) && 2076 + cmpxchg_futex_value_locked(&uval, uaddr, vpid, 0)) 2078 2077 goto pi_faulted; 2079 2078 /* 2080 2079 * Rare case: we managed to release the lock atomically, 2081 2080 * no need to wake anyone else up: 2082 2081 */ 2083 - if (unlikely(uval == task_pid_vnr(current))) 2082 + if (unlikely(uval == vpid)) 2084 2083 goto out_unlock; 2085 2084 2086 2085 /* ··· 2162 2167 * We were woken prior to requeue by a timeout or a signal. 2163 2168 * Unqueue the futex_q and determine which it was. 2164 2169 */ 2165 - plist_del(&q->list, &q->list.plist); 2170 + plist_del(&q->list, &hb->chain); 2166 2171 2167 2172 /* Handle spurious wakeups gracefully */ 2168 2173 ret = -EWOULDBLOCK; ··· 2458 2463 * userspace. 2459 2464 */ 2460 2465 mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; 2461 - nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval); 2462 - 2463 - if (nval == -EFAULT) 2464 - return -1; 2465 - 2466 + /* 2467 + * We are not holding a lock here, but we want to have 2468 + * the pagefault_disable/enable() protection because 2469 + * we want to handle the fault gracefully. If the 2470 + * access fails we try to fault in the futex with R/W 2471 + * verification via get_user_pages. get_user() above 2472 + * does not guarantee R/W access. If that fails we 2473 + * give up and leave the futex locked. 2474 + */ 2475 + if (cmpxchg_futex_value_locked(&nval, uaddr, uval, mval)) { 2476 + if (fault_in_user_writeable(uaddr)) 2477 + return -1; 2478 + goto retry; 2479 + } 2466 2480 if (nval != uval) 2467 2481 goto retry; 2468 2482 ··· 2682 2678 * implementation, the non-functional ones will return 2683 2679 * -ENOSYS. 2684 2680 */ 2685 - curval = cmpxchg_futex_value_locked(NULL, 0, 0); 2686 - if (curval == -EFAULT) 2681 + if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT) 2687 2682 futex_cmpxchg_enabled = 1; 2688 2683 2689 2684 for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
+115 -20
lib/plist.c
··· 28 28 29 29 #ifdef CONFIG_DEBUG_PI_LIST 30 30 31 + static struct plist_head test_head; 32 + 31 33 static void plist_check_prev_next(struct list_head *t, struct list_head *p, 32 34 struct list_head *n) 33 35 { ··· 56 54 57 55 static void plist_check_head(struct plist_head *head) 58 56 { 59 - WARN_ON(!head->rawlock && !head->spinlock); 57 + WARN_ON(head != &test_head && !head->rawlock && !head->spinlock); 60 58 if (head->rawlock) 61 59 WARN_ON_SMP(!raw_spin_is_locked(head->rawlock)); 62 60 if (head->spinlock) 63 61 WARN_ON_SMP(!spin_is_locked(head->spinlock)); 64 - plist_check_list(&head->prio_list); 62 + if (!plist_head_empty(head)) 63 + plist_check_list(&plist_first(head)->prio_list); 65 64 plist_check_list(&head->node_list); 66 65 } 67 66 ··· 78 75 */ 79 76 void plist_add(struct plist_node *node, struct plist_head *head) 80 77 { 81 - struct plist_node *iter; 78 + struct plist_node *first, *iter, *prev = NULL; 79 + struct list_head *node_next = &head->node_list; 82 80 83 81 plist_check_head(head); 84 82 WARN_ON(!plist_node_empty(node)); 83 + WARN_ON(!list_empty(&node->prio_list)); 85 84 86 - list_for_each_entry(iter, &head->prio_list, plist.prio_list) { 87 - if (node->prio < iter->prio) 88 - goto lt_prio; 89 - else if (node->prio == iter->prio) { 90 - iter = list_entry(iter->plist.prio_list.next, 91 - struct plist_node, plist.prio_list); 92 - goto eq_prio; 85 + if (plist_head_empty(head)) 86 + goto ins_node; 87 + 88 + first = iter = plist_first(head); 89 + 90 + do { 91 + if (node->prio < iter->prio) { 92 + node_next = &iter->node_list; 93 + break; 93 94 } 94 - } 95 95 96 - lt_prio: 97 - list_add_tail(&node->plist.prio_list, &iter->plist.prio_list); 98 - eq_prio: 99 - list_add_tail(&node->plist.node_list, &iter->plist.node_list); 96 + prev = iter; 97 + iter = list_entry(iter->prio_list.next, 98 + struct plist_node, prio_list); 99 + } while (iter != first); 100 + 101 + if (!prev || prev->prio != node->prio) 102 + list_add_tail(&node->prio_list, &iter->prio_list); 103 + ins_node: 104 + list_add_tail(&node->node_list, node_next); 100 105 101 106 plist_check_head(head); 102 107 } ··· 119 108 { 120 109 plist_check_head(head); 121 110 122 - if (!list_empty(&node->plist.prio_list)) { 123 - struct plist_node *next = plist_first(&node->plist); 111 + if (!list_empty(&node->prio_list)) { 112 + if (node->node_list.next != &head->node_list) { 113 + struct plist_node *next; 124 114 125 - list_move_tail(&next->plist.prio_list, &node->plist.prio_list); 126 - list_del_init(&node->plist.prio_list); 115 + next = list_entry(node->node_list.next, 116 + struct plist_node, node_list); 117 + 118 + /* add the next plist_node into prio_list */ 119 + if (list_empty(&next->prio_list)) 120 + list_add(&next->prio_list, &node->prio_list); 121 + } 122 + list_del_init(&node->prio_list); 127 123 } 128 124 129 - list_del_init(&node->plist.node_list); 125 + list_del_init(&node->node_list); 130 126 131 127 plist_check_head(head); 132 128 } 129 + 130 + #ifdef CONFIG_DEBUG_PI_LIST 131 + #include <linux/sched.h> 132 + #include <linux/module.h> 133 + #include <linux/init.h> 134 + 135 + static struct plist_node __initdata test_node[241]; 136 + 137 + static void __init plist_test_check(int nr_expect) 138 + { 139 + struct plist_node *first, *prio_pos, *node_pos; 140 + 141 + if (plist_head_empty(&test_head)) { 142 + BUG_ON(nr_expect != 0); 143 + return; 144 + } 145 + 146 + prio_pos = first = plist_first(&test_head); 147 + plist_for_each(node_pos, &test_head) { 148 + if (nr_expect-- < 0) 149 + break; 150 + if (node_pos == first) 151 + continue; 152 + if (node_pos->prio == prio_pos->prio) { 153 + BUG_ON(!list_empty(&node_pos->prio_list)); 154 + continue; 155 + } 156 + 157 + BUG_ON(prio_pos->prio > node_pos->prio); 158 + BUG_ON(prio_pos->prio_list.next != &node_pos->prio_list); 159 + prio_pos = node_pos; 160 + } 161 + 162 + BUG_ON(nr_expect != 0); 163 + BUG_ON(prio_pos->prio_list.next != &first->prio_list); 164 + } 165 + 166 + static int __init plist_test(void) 167 + { 168 + int nr_expect = 0, i, loop; 169 + unsigned int r = local_clock(); 170 + 171 + printk(KERN_INFO "start plist test\n"); 172 + plist_head_init(&test_head, NULL); 173 + for (i = 0; i < ARRAY_SIZE(test_node); i++) 174 + plist_node_init(test_node + i, 0); 175 + 176 + for (loop = 0; loop < 1000; loop++) { 177 + r = r * 193939 % 47629; 178 + i = r % ARRAY_SIZE(test_node); 179 + if (plist_node_empty(test_node + i)) { 180 + r = r * 193939 % 47629; 181 + test_node[i].prio = r % 99; 182 + plist_add(test_node + i, &test_head); 183 + nr_expect++; 184 + } else { 185 + plist_del(test_node + i, &test_head); 186 + nr_expect--; 187 + } 188 + plist_test_check(nr_expect); 189 + } 190 + 191 + for (i = 0; i < ARRAY_SIZE(test_node); i++) { 192 + if (plist_node_empty(test_node + i)) 193 + continue; 194 + plist_del(test_node + i, &test_head); 195 + nr_expect--; 196 + plist_test_check(nr_expect); 197 + } 198 + 199 + printk(KERN_INFO "end plist test\n"); 200 + return 0; 201 + } 202 + 203 + module_init(plist_test); 204 + 205 + #endif