0001
0002 #ifndef _ASM_ALPHA_FUTEX_H
0003 #define _ASM_ALPHA_FUTEX_H
0004
0005 #ifdef __KERNEL__
0006
0007 #include <linux/futex.h>
0008 #include <linux/uaccess.h>
0009 #include <asm/errno.h>
0010 #include <asm/barrier.h>
0011
0012 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
0013 __asm__ __volatile__( \
0014 __ASM_SMP_MB \
0015 "1: ldl_l %0,0(%2)\n" \
0016 insn \
0017 "2: stl_c %1,0(%2)\n" \
0018 " beq %1,4f\n" \
0019 " mov $31,%1\n" \
0020 "3: .subsection 2\n" \
0021 "4: br 1b\n" \
0022 " .previous\n" \
0023 EXC(1b,3b,$31,%1) \
0024 EXC(2b,3b,$31,%1) \
0025 : "=&r" (oldval), "=&r"(ret) \
0026 : "r" (uaddr), "r"(oparg) \
0027 : "memory")
0028
0029 static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
0030 u32 __user *uaddr)
0031 {
0032 int oldval = 0, ret;
0033
0034 if (!access_ok(uaddr, sizeof(u32)))
0035 return -EFAULT;
0036
0037 switch (op) {
0038 case FUTEX_OP_SET:
0039 __futex_atomic_op("mov %3,%1\n", ret, oldval, uaddr, oparg);
0040 break;
0041 case FUTEX_OP_ADD:
0042 __futex_atomic_op("addl %0,%3,%1\n", ret, oldval, uaddr, oparg);
0043 break;
0044 case FUTEX_OP_OR:
0045 __futex_atomic_op("or %0,%3,%1\n", ret, oldval, uaddr, oparg);
0046 break;
0047 case FUTEX_OP_ANDN:
0048 __futex_atomic_op("andnot %0,%3,%1\n", ret, oldval, uaddr, oparg);
0049 break;
0050 case FUTEX_OP_XOR:
0051 __futex_atomic_op("xor %0,%3,%1\n", ret, oldval, uaddr, oparg);
0052 break;
0053 default:
0054 ret = -ENOSYS;
0055 }
0056
0057 if (!ret)
0058 *oval = oldval;
0059
0060 return ret;
0061 }
0062
0063 static inline int
0064 futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
0065 u32 oldval, u32 newval)
0066 {
0067 int ret = 0, cmp;
0068 u32 prev;
0069
0070 if (!access_ok(uaddr, sizeof(u32)))
0071 return -EFAULT;
0072
0073 __asm__ __volatile__ (
0074 __ASM_SMP_MB
0075 "1: ldl_l %1,0(%3)\n"
0076 " cmpeq %1,%4,%2\n"
0077 " beq %2,3f\n"
0078 " mov %5,%2\n"
0079 "2: stl_c %2,0(%3)\n"
0080 " beq %2,4f\n"
0081 "3: .subsection 2\n"
0082 "4: br 1b\n"
0083 " .previous\n"
0084 EXC(1b,3b,$31,%0)
0085 EXC(2b,3b,$31,%0)
0086 : "+r"(ret), "=&r"(prev), "=&r"(cmp)
0087 : "r"(uaddr), "r"((long)(int)oldval), "r"(newval)
0088 : "memory");
0089
0090 *uval = prev;
0091 return ret;
0092 }
0093
0094 #endif
0095 #endif