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-mips / futex.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  4.8 KB  |  200 lines

  1. #ifndef _ASM_FUTEX_H
  2. #define _ASM_FUTEX_H
  3.  
  4. #ifdef __KERNEL__
  5.  
  6. #include <linux/futex.h>
  7. #include <asm/errno.h>
  8. #include <asm/uaccess.h>
  9. #include <asm/war.h>
  10.  
  11. #ifdef CONFIG_SMP
  12. #define __FUTEX_SMP_SYNC "    sync                    \n"
  13. #else
  14. #define __FUTEX_SMP_SYNC
  15. #endif
  16.  
  17. #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)        \
  18. {                                    \
  19.     if (cpu_has_llsc && R10000_LLSC_WAR) {                \
  20.         __asm__ __volatile__(                    \
  21.         "    .set    push                \n"    \
  22.         "    .set    noat                \n"    \
  23.         "    .set    mips3                \n"    \
  24.         "1:    ll    %1, (%3)    # __futex_atomic_op    \n" \
  25.         "    .set    mips0                \n"    \
  26.         "    " insn    "                \n"    \
  27.         "    .set    mips3                \n"    \
  28.         "2:    sc    $1, (%3)            \n"    \
  29.         "    beqzl    $1, 1b                \n"    \
  30.         __FUTEX_SMP_SYNC                    \
  31.         "3:                        \n"    \
  32.         "    .set    pop                \n"    \
  33.         "    .set    mips0                \n"    \
  34.         "    .section .fixup,\"ax\"            \n"    \
  35.         "4:    li    %0, %5                \n"    \
  36.         "    j    2b                \n"    \
  37.         "    .previous                \n"    \
  38.         "    .section __ex_table,\"a\"        \n"    \
  39.         "    "__UA_ADDR "\t1b, 4b            \n"    \
  40.         "    "__UA_ADDR "\t2b, 4b            \n"    \
  41.         "    .previous                \n"    \
  42.         : "=r" (ret), "=r" (oldval)                \
  43.         : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT));    \
  44.     } else if (cpu_has_llsc) {                    \
  45.         __asm__ __volatile__(                    \
  46.         "    .set    push                \n"    \
  47.         "    .set    noat                \n"    \
  48.         "    .set    mips3                \n"    \
  49.         "1:    ll    %1, (%3)    # __futex_atomic_op    \n" \
  50.         "    .set    mips0                \n"    \
  51.         "    " insn    "                \n"    \
  52.         "    .set    mips3                \n"    \
  53.         "2:    sc    $1, (%3)            \n"    \
  54.         "    beqz    $1, 1b                \n"    \
  55.         __FUTEX_SMP_SYNC                    \
  56.         "3:                        \n"    \
  57.         "    .set    pop                \n"    \
  58.         "    .set    mips0                \n"    \
  59.         "    .section .fixup,\"ax\"            \n"    \
  60.         "4:    li    %0, %5                \n"    \
  61.         "    j    2b                \n"    \
  62.         "    .previous                \n"    \
  63.         "    .section __ex_table,\"a\"        \n"    \
  64.         "    "__UA_ADDR "\t1b, 4b            \n"    \
  65.         "    "__UA_ADDR "\t2b, 4b            \n"    \
  66.         "    .previous                \n"    \
  67.         : "=r" (ret), "=r" (oldval)                \
  68.         : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT));    \
  69.     } else                                \
  70.         ret = -ENOSYS;                        \
  71. }
  72.  
  73. static inline int
  74. futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
  75. {
  76.     int op = (encoded_op >> 28) & 7;
  77.     int cmp = (encoded_op >> 24) & 15;
  78.     int oparg = (encoded_op << 8) >> 20;
  79.     int cmparg = (encoded_op << 20) >> 20;
  80.     int oldval = 0, ret;
  81.     if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
  82.         oparg = 1 << oparg;
  83.  
  84.     if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
  85.         return -EFAULT;
  86.  
  87.     inc_preempt_count();
  88.  
  89.     switch (op) {
  90.     case FUTEX_OP_SET:
  91.         __futex_atomic_op("move    $1, %z4", ret, oldval, uaddr, oparg);
  92.         break;
  93.  
  94.     case FUTEX_OP_ADD:
  95.         __futex_atomic_op("addu    $1, %1, %z4",
  96.                           ret, oldval, uaddr, oparg);
  97.         break;
  98.     case FUTEX_OP_OR:
  99.         __futex_atomic_op("or    $1, %1, %z4",
  100.                           ret, oldval, uaddr, oparg);
  101.         break;
  102.     case FUTEX_OP_ANDN:
  103.         __futex_atomic_op("and    $1, %1, %z4",
  104.                           ret, oldval, uaddr, ~oparg);
  105.         break;
  106.     case FUTEX_OP_XOR:
  107.         __futex_atomic_op("xor    $1, %1, %z4",
  108.                           ret, oldval, uaddr, oparg);
  109.         break;
  110.     default:
  111.         ret = -ENOSYS;
  112.     }
  113.  
  114.     dec_preempt_count();
  115.  
  116.     if (!ret) {
  117.         switch (cmp) {
  118.         case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
  119.         case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
  120.         case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
  121.         case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
  122.         case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
  123.         case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
  124.         default: ret = -ENOSYS;
  125.         }
  126.     }
  127.     return ret;
  128. }
  129.  
  130. static inline int
  131. futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
  132. {
  133.     int retval;
  134.  
  135.     if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
  136.         return -EFAULT;
  137.  
  138.     if (cpu_has_llsc && R10000_LLSC_WAR) {
  139.         __asm__ __volatile__(
  140.         "# futex_atomic_cmpxchg_inatomic            \n"
  141.         "    .set    push                    \n"
  142.         "    .set    noat                    \n"
  143.         "    .set    mips3                    \n"
  144.         "1:    ll    %0, %2                    \n"
  145.         "    bne    %0, %z3, 3f                \n"
  146.         "    .set    mips0                    \n"
  147.         "    move    $1, %z4                    \n"
  148.         "    .set    mips3                    \n"
  149.         "2:    sc    $1, %1                    \n"
  150.         "    beqzl    $1, 1b                    \n"
  151.         __FUTEX_SMP_SYNC
  152.         "3:                            \n"
  153.         "    .set    pop                    \n"
  154.         "    .section .fixup,\"ax\"                \n"
  155.         "4:    li    %0, %5                    \n"
  156.         "    j    3b                    \n"
  157.         "    .previous                    \n"
  158.         "    .section __ex_table,\"a\"            \n"
  159.         "    "__UA_ADDR "\t1b, 4b                \n"
  160.         "    "__UA_ADDR "\t2b, 4b                \n"
  161.         "    .previous                    \n"
  162.         : "=&r" (retval), "=R" (*uaddr)
  163.         : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
  164.         : "memory");
  165.     } else if (cpu_has_llsc) {
  166.         __asm__ __volatile__(
  167.         "# futex_atomic_cmpxchg_inatomic            \n"
  168.         "    .set    push                    \n"
  169.         "    .set    noat                    \n"
  170.         "    .set    mips3                    \n"
  171.         "1:    ll    %0, %2                    \n"
  172.         "    bne    %0, %z3, 3f                \n"
  173.         "    .set    mips0                    \n"
  174.         "    move    $1, %z4                    \n"
  175.         "    .set    mips3                    \n"
  176.         "2:    sc    $1, %1                    \n"
  177.         "    beqz    $1, 1b                    \n"
  178.         __FUTEX_SMP_SYNC
  179.         "3:                            \n"
  180.         "    .set    pop                    \n"
  181.         "    .section .fixup,\"ax\"                \n"
  182.         "4:    li    %0, %5                    \n"
  183.         "    j    3b                    \n"
  184.         "    .previous                    \n"
  185.         "    .section __ex_table,\"a\"            \n"
  186.         "    "__UA_ADDR "\t1b, 4b                \n"
  187.         "    "__UA_ADDR "\t2b, 4b                \n"
  188.         "    .previous                    \n"
  189.         : "=&r" (retval), "=R" (*uaddr)
  190.         : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
  191.         : "memory");
  192.     } else
  193.         return -ENOSYS;
  194.  
  195.     return retval;
  196. }
  197.  
  198. #endif
  199. #endif
  200.