linux/arch/microblaze/include/asm/futex.h
<<
>>
Prefs
   1#ifndef _ASM_MICROBLAZE_FUTEX_H
   2#define _ASM_MICROBLAZE_FUTEX_H
   3
   4#ifdef __KERNEL__
   5
   6#include <linux/futex.h>
   7#include <linux/uaccess.h>
   8#include <asm/errno.h>
   9
  10#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
  11({                                                                      \
  12        __asm__ __volatile__ (                                          \
  13                        "1:     lwx     %0, %2, r0; "                   \
  14                                insn                                    \
  15                        "2:     swx     %1, %2, r0;                     \
  16                                addic   %1, r0, 0;                      \
  17                                bnei    %1, 1b;                         \
  18                        3:                                              \
  19                        .section .fixup,\"ax\";                         \
  20                        4:      brid    3b;                             \
  21                                addik   %1, r0, %3;                     \
  22                        .previous;                                      \
  23                        .section __ex_table,\"a\";                      \
  24                        .word   1b,4b,2b,4b;                            \
  25                        .previous;"                                     \
  26        : "=&r" (oldval), "=&r" (ret)                                   \
  27        : "r" (uaddr), "i" (-EFAULT), "r" (oparg)                       \
  28        );                                                              \
  29})
  30
  31static inline int
  32futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
  33{
  34        int op = (encoded_op >> 28) & 7;
  35        int cmp = (encoded_op >> 24) & 15;
  36        int oparg = (encoded_op << 8) >> 20;
  37        int cmparg = (encoded_op << 20) >> 20;
  38        int oldval = 0, ret;
  39        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
  40                oparg = 1 << oparg;
  41
  42        if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
  43                return -EFAULT;
  44
  45        pagefault_disable();
  46
  47        switch (op) {
  48        case FUTEX_OP_SET:
  49                __futex_atomic_op("or %1,%4,%4;", ret, oldval, uaddr, oparg);
  50                break;
  51        case FUTEX_OP_ADD:
  52                __futex_atomic_op("add %1,%0,%4;", ret, oldval, uaddr, oparg);
  53                break;
  54        case FUTEX_OP_OR:
  55                __futex_atomic_op("or %1,%0,%4;", ret, oldval, uaddr, oparg);
  56                break;
  57        case FUTEX_OP_ANDN:
  58                __futex_atomic_op("andn %1,%0,%4;", ret, oldval, uaddr, oparg);
  59                break;
  60        case FUTEX_OP_XOR:
  61                __futex_atomic_op("xor %1,%0,%4;", ret, oldval, uaddr, oparg);
  62                break;
  63        default:
  64                ret = -ENOSYS;
  65        }
  66
  67        pagefault_enable();
  68
  69        if (!ret) {
  70                switch (cmp) {
  71                case FUTEX_OP_CMP_EQ:
  72                        ret = (oldval == cmparg);
  73                        break;
  74                case FUTEX_OP_CMP_NE:
  75                        ret = (oldval != cmparg);
  76                        break;
  77                case FUTEX_OP_CMP_LT:
  78                        ret = (oldval < cmparg);
  79                        break;
  80                case FUTEX_OP_CMP_GE:
  81                        ret = (oldval >= cmparg);
  82                        break;
  83                case FUTEX_OP_CMP_LE:
  84                        ret = (oldval <= cmparg);
  85                        break;
  86                case FUTEX_OP_CMP_GT:
  87                        ret = (oldval > cmparg);
  88                        break;
  89                default:
  90                        ret = -ENOSYS;
  91                }
  92        }
  93        return ret;
  94}
  95
  96static inline int
  97futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
  98                              u32 oldval, u32 newval)
  99{
 100        int ret = 0, cmp;
 101        u32 prev;
 102
 103        if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 104                return -EFAULT;
 105
 106        __asm__ __volatile__ ("1:       lwx     %1, %3, r0;             \
 107                                        cmp     %2, %1, %4;             \
 108                                        bnei    %2, 3f;                 \
 109                                2:      swx     %5, %3, r0;             \
 110                                        addic   %2, r0, 0;              \
 111                                        bnei    %2, 1b;                 \
 112                                3:                                      \
 113                                .section .fixup,\"ax\";                 \
 114                                4:      brid    3b;                     \
 115                                        addik   %0, r0, %6;             \
 116                                .previous;                              \
 117                                .section __ex_table,\"a\";              \
 118                                .word   1b,4b,2b,4b;                    \
 119                                .previous;"                             \
 120                : "+r" (ret), "=&r" (prev), "=&r"(cmp)  \
 121                : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT));
 122
 123        *uval = prev;
 124        return ret;
 125}
 126
 127#endif /* __KERNEL__ */
 128
 129#endif
 130