linux/arch/s390/include/asm/futex.h
<<
>>
Prefs
   1#ifndef _ASM_S390_FUTEX_H
   2#define _ASM_S390_FUTEX_H
   3
   4#include <linux/uaccess.h>
   5#include <linux/futex.h>
   6#include <asm/mmu_context.h>
   7#include <asm/errno.h>
   8
   9#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg)      \
  10        asm volatile(                                                   \
  11                "   sacf  256\n"                                        \
  12                "0: l     %1,0(%6)\n"                                   \
  13                "1:"insn                                                \
  14                "2: cs    %1,%2,0(%6)\n"                                \
  15                "3: jl    1b\n"                                         \
  16                "   lhi   %0,0\n"                                       \
  17                "4: sacf  768\n"                                        \
  18                EX_TABLE(0b,4b) EX_TABLE(2b,4b) EX_TABLE(3b,4b)         \
  19                : "=d" (ret), "=&d" (oldval), "=&d" (newval),           \
  20                  "=m" (*uaddr)                                         \
  21                : "0" (-EFAULT), "d" (oparg), "a" (uaddr),              \
  22                  "m" (*uaddr) : "cc");
  23
  24static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
  25{
  26        int op = (encoded_op >> 28) & 7;
  27        int cmp = (encoded_op >> 24) & 15;
  28        int oparg = (encoded_op << 8) >> 20;
  29        int cmparg = (encoded_op << 20) >> 20;
  30        int oldval = 0, newval, ret;
  31
  32        update_primary_asce(current);
  33        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
  34                oparg = 1 << oparg;
  35
  36        pagefault_disable();
  37        switch (op) {
  38        case FUTEX_OP_SET:
  39                __futex_atomic_op("lr %2,%5\n",
  40                                  ret, oldval, newval, uaddr, oparg);
  41                break;
  42        case FUTEX_OP_ADD:
  43                __futex_atomic_op("lr %2,%1\nar %2,%5\n",
  44                                  ret, oldval, newval, uaddr, oparg);
  45                break;
  46        case FUTEX_OP_OR:
  47                __futex_atomic_op("lr %2,%1\nor %2,%5\n",
  48                                  ret, oldval, newval, uaddr, oparg);
  49                break;
  50        case FUTEX_OP_ANDN:
  51                __futex_atomic_op("lr %2,%1\nnr %2,%5\n",
  52                                  ret, oldval, newval, uaddr, oparg);
  53                break;
  54        case FUTEX_OP_XOR:
  55                __futex_atomic_op("lr %2,%1\nxr %2,%5\n",
  56                                  ret, oldval, newval, uaddr, oparg);
  57                break;
  58        default:
  59                ret = -ENOSYS;
  60        }
  61        pagefault_enable();
  62
  63        if (!ret) {
  64                switch (cmp) {
  65                case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
  66                case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
  67                case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
  68                case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
  69                case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
  70                case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
  71                default: ret = -ENOSYS;
  72                }
  73        }
  74        return ret;
  75}
  76
  77static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
  78                                                u32 oldval, u32 newval)
  79{
  80        int ret;
  81
  82        update_primary_asce(current);
  83        asm volatile(
  84                "   sacf 256\n"
  85                "0: cs   %1,%4,0(%5)\n"
  86                "1: la   %0,0\n"
  87                "2: sacf 768\n"
  88                EX_TABLE(0b,2b) EX_TABLE(1b,2b)
  89                : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
  90                : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
  91                : "cc", "memory");
  92        *uval = oldval;
  93        return ret;
  94}
  95
  96#endif /* _ASM_S390_FUTEX_H */
  97