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