home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-s390 / futex.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  3.2 KB  |  123 lines

  1. #ifndef _ASM_S390_FUTEX_H
  2. #define _ASM_S390_FUTEX_H
  3.  
  4. #ifdef __KERNEL__
  5.  
  6. #include <linux/futex.h>
  7. #include <asm/errno.h>
  8. #include <asm/uaccess.h>
  9.  
  10. #ifndef __s390x__
  11. #define __futex_atomic_fixup \
  12.              ".section __ex_table,\"a\"\n"            \
  13.              "   .align 4\n"                    \
  14.              "   .long  0b,4b,2b,4b,3b,4b\n"            \
  15.              ".previous"
  16. #else /* __s390x__ */
  17. #define __futex_atomic_fixup \
  18.              ".section __ex_table,\"a\"\n"            \
  19.              "   .align 8\n"                    \
  20.              "   .quad  0b,4b,2b,4b,3b,4b\n"            \
  21.              ".previous"
  22. #endif /* __s390x__ */
  23.  
  24. #define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg)    \
  25.     asm volatile("   sacf 256\n"                    \
  26.              "0: l   %1,0(%6)\n"                \
  27.              "1: " insn                        \
  28.              "2: cs  %1,%2,0(%6)\n"                \
  29.              "3: jl  1b\n"                    \
  30.              "   lhi %0,0\n"                    \
  31.              "4: sacf 0\n"                    \
  32.              __futex_atomic_fixup                \
  33.              : "=d" (ret), "=&d" (oldval), "=&d" (newval),    \
  34.                "=m" (*uaddr)                    \
  35.              : "0" (-EFAULT), "d" (oparg), "a" (uaddr),        \
  36.                "m" (*uaddr) : "cc" );
  37.  
  38. static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
  39. {
  40.     int op = (encoded_op >> 28) & 7;
  41.     int cmp = (encoded_op >> 24) & 15;
  42.     int oparg = (encoded_op << 8) >> 20;
  43.     int cmparg = (encoded_op << 20) >> 20;
  44.     int oldval = 0, newval, ret;
  45.     if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
  46.         oparg = 1 << oparg;
  47.  
  48.     if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
  49.         return -EFAULT;
  50.  
  51.     inc_preempt_count();
  52.  
  53.     switch (op) {
  54.     case FUTEX_OP_SET:
  55.         __futex_atomic_op("lr %2,%5\n",
  56.                   ret, oldval, newval, uaddr, oparg);
  57.         break;
  58.     case FUTEX_OP_ADD:
  59.         __futex_atomic_op("lr %2,%1\nar %2,%5\n",
  60.                   ret, oldval, newval, uaddr, oparg);
  61.         break;
  62.     case FUTEX_OP_OR:
  63.         __futex_atomic_op("lr %2,%1\nor %2,%5\n",
  64.                   ret, oldval, newval, uaddr, oparg);
  65.         break;
  66.     case FUTEX_OP_ANDN:
  67.         __futex_atomic_op("lr %2,%1\nnr %2,%5\n",
  68.                   ret, oldval, newval, uaddr, oparg);
  69.         break;
  70.     case FUTEX_OP_XOR:
  71.         __futex_atomic_op("lr %2,%1\nxr %2,%5\n",
  72.                   ret, oldval, newval, uaddr, oparg);
  73.         break;
  74.     default:
  75.         ret = -ENOSYS;
  76.     }
  77.  
  78.     dec_preempt_count();
  79.  
  80.     if (!ret) {
  81.         switch (cmp) {
  82.         case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
  83.         case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
  84.         case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
  85.         case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
  86.         case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
  87.         case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
  88.         default: ret = -ENOSYS;
  89.         }
  90.     }
  91.     return ret;
  92. }
  93.  
  94. static inline int
  95. futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
  96. {
  97.     int ret;
  98.  
  99.     if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
  100.         return -EFAULT;
  101.     asm volatile("   cs   %1,%4,0(%5)\n"
  102.              "0: lr   %0,%1\n"
  103.              "1:\n"
  104. #ifndef __s390x__
  105.              ".section __ex_table,\"a\"\n"
  106.              "   .align 4\n"
  107.              "   .long  0b,1b\n"
  108.              ".previous"
  109. #else /* __s390x__ */
  110.              ".section __ex_table,\"a\"\n"
  111.              "   .align 8\n"
  112.              "   .quad  0b,1b\n"
  113.              ".previous"
  114. #endif /* __s390x__ */
  115.              : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
  116.              : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
  117.              : "cc", "memory" );
  118.     return oldval;
  119. }
  120.  
  121. #endif /* __KERNEL__ */
  122. #endif /* _ASM_S390_FUTEX_H */
  123.