X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=include%2Fasm-x86%2Ffutex.h;h=ac0fbf24d722a36f3f0ee20e7060b5aace6bced1;hb=c1fa6c977eb978e1d09867475ec59c9a5799127f;hp=62828d63f1b1d4bc6d79281f3095ca546d8db9ac;hpb=2f18e47c89f1a29cc815cd225b72dd7fd86acffe;p=~andy%2Flinux diff --git a/include/asm-x86/futex.h b/include/asm-x86/futex.h index 62828d63f1b..ac0fbf24d72 100644 --- a/include/asm-x86/futex.h +++ b/include/asm-x86/futex.h @@ -12,40 +12,32 @@ #include #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \ - __asm__ __volatile( \ -"1: " insn "\n" \ -"2: .section .fixup,\"ax\"\n \ -3: mov %3, %1\n \ - jmp 2b\n \ - .previous\n \ - .section __ex_table,\"a\"\n \ - .align 8\n" \ - _ASM_PTR "1b,3b\n \ - .previous" \ - : "=r" (oldval), "=r" (ret), "+m" (*uaddr) \ - : "i" (-EFAULT), "0" (oparg), "1" (0)) + asm volatile("1:\t" insn "\n" \ + "2:\t.section .fixup,\"ax\"\n" \ + "3:\tmov\t%3, %1\n" \ + "\tjmp\t2b\n" \ + "\t.previous\n" \ + _ASM_EXTABLE(1b, 3b) \ + : "=r" (oldval), "=r" (ret), "+m" (*uaddr) \ + : "i" (-EFAULT), "0" (oparg), "1" (0)) #define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg) \ - __asm__ __volatile( \ -"1: movl %2, %0\n \ - movl %0, %3\n" \ - insn "\n" \ -"2: " LOCK_PREFIX "cmpxchgl %3, %2\n \ - jnz 1b\n \ -3: .section .fixup,\"ax\"\n \ -4: mov %5, %1\n \ - jmp 3b\n \ - .previous\n \ - .section __ex_table,\"a\"\n \ - .align 8\n" \ - _ASM_PTR "1b,4b,2b,4b\n \ - .previous" \ - : "=&a" (oldval), "=&r" (ret), "+m" (*uaddr), \ - "=&r" (tem) \ - : "r" (oparg), "i" (-EFAULT), "1" (0)) - -static inline int -futex_atomic_op_inuser(int encoded_op, int __user *uaddr) + asm volatile("1:\tmovl %2, %0\n" \ + "\tmovl\t%0, %3\n" \ + "\t" insn "\n" \ + "2:\tlock; cmpxchgl %3, %2\n" \ + "\tjnz\t1b\n" \ + "3:\t.section .fixup,\"ax\"\n" \ + "4:\tmov\t%5, %1\n" \ + "\tjmp\t3b\n" \ + "\t.previous\n" \ + _ASM_EXTABLE(1b, 4b) \ + _ASM_EXTABLE(2b, 4b) \ + : "=&a" (oldval), "=&r" (ret), \ + "+m" (*uaddr), "=&r" (tem) \ + : "r" (oparg), "i" (-EFAULT), "1" (0)) + +static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) { int op = (encoded_op >> 28) & 7; int cmp = (encoded_op >> 24) & 15; @@ -72,7 +64,7 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr) __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg); break; case FUTEX_OP_ADD: - __futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret, oldval, + __futex_atomic_op1("lock; xaddl %0, %2", ret, oldval, uaddr, oparg); break; case FUTEX_OP_OR: @@ -92,40 +84,53 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr) if (!ret) { switch (cmp) { - case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; - case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; - case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; - case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; - case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; - case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; - default: ret = -ENOSYS; + case FUTEX_OP_CMP_EQ: + ret = (oldval == cmparg); + break; + case FUTEX_OP_CMP_NE: + ret = (oldval != cmparg); + break; + case FUTEX_OP_CMP_LT: + ret = (oldval < cmparg); + break; + case FUTEX_OP_CMP_GE: + ret = (oldval >= cmparg); + break; + case FUTEX_OP_CMP_LE: + ret = (oldval <= cmparg); + break; + case FUTEX_OP_CMP_GT: + ret = (oldval > cmparg); + break; + default: + ret = -ENOSYS; } } return ret; } -static inline int -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) +static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, + int newval) { - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) - return -EFAULT; - __asm__ __volatile__( - "1: " LOCK_PREFIX "cmpxchgl %3, %1 \n" - - "2: .section .fixup, \"ax\" \n" - "3: mov %2, %0 \n" - " jmp 2b \n" - " .previous \n" +#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP) + /* Real i386 machines have no cmpxchg instruction */ + if (boot_cpu_data.x86 == 3) + return -ENOSYS; +#endif - " .section __ex_table, \"a\" \n" - " .align 8 \n" - _ASM_PTR " 1b,3b \n" - " .previous \n" + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; - : "=a" (oldval), "+m" (*uaddr) - : "i" (-EFAULT), "r" (newval), "0" (oldval) - : "memory" + asm volatile("1:\tlock; cmpxchgl %3, %1\n" + "2:\t.section .fixup, \"ax\"\n" + "3:\tmov %2, %0\n" + "\tjmp 2b\n" + "\t.previous\n" + _ASM_EXTABLE(1b, 3b) + : "=a" (oldval), "+m" (*uaddr) + : "i" (-EFAULT), "r" (newval), "0" (oldval) + : "memory" ); return oldval;