futex.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * linux/arch/unicore32/include/asm/futex.h
  3. *
  4. * Code specific to PKUnity SoC and UniCore ISA
  5. *
  6. * Copyright (C) 2001-2010 GUAN Xue-tao
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. #ifndef __UNICORE_FUTEX_H__
  13. #define __UNICORE_FUTEX_H__
  14. #ifdef __KERNEL__
  15. #include <linux/futex.h>
  16. #include <linux/preempt.h>
  17. #include <linux/uaccess.h>
  18. #include <linux/errno.h>
  19. #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
  20. __asm__ __volatile__( \
  21. "1: ldw.u %1, [%2]\n" \
  22. " " insn "\n" \
  23. "2: stw.u %0, [%2]\n" \
  24. " mov %0, #0\n" \
  25. "3:\n" \
  26. " .pushsection __ex_table,\"a\"\n" \
  27. " .align 3\n" \
  28. " .long 1b, 4f, 2b, 4f\n" \
  29. " .popsection\n" \
  30. " .pushsection .fixup,\"ax\"\n" \
  31. "4: mov %0, %4\n" \
  32. " b 3b\n" \
  33. " .popsection" \
  34. : "=&r" (ret), "=&r" (oldval) \
  35. : "r" (uaddr), "r" (oparg), "Ir" (-EFAULT) \
  36. : "cc", "memory")
  37. static inline int
  38. 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, ret;
  45. if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
  46. oparg = 1 << oparg;
  47. if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
  48. return -EFAULT;
  49. pagefault_disable(); /* implies preempt_disable() */
  50. switch (op) {
  51. case FUTEX_OP_SET:
  52. __futex_atomic_op("mov %0, %3", ret, oldval, uaddr, oparg);
  53. break;
  54. case FUTEX_OP_ADD:
  55. __futex_atomic_op("add %0, %1, %3", ret, oldval, uaddr, oparg);
  56. break;
  57. case FUTEX_OP_OR:
  58. __futex_atomic_op("or %0, %1, %3", ret, oldval, uaddr, oparg);
  59. break;
  60. case FUTEX_OP_ANDN:
  61. __futex_atomic_op("and %0, %1, %3",
  62. ret, oldval, uaddr, ~oparg);
  63. break;
  64. case FUTEX_OP_XOR:
  65. __futex_atomic_op("xor %0, %1, %3", ret, oldval, uaddr, oparg);
  66. break;
  67. default:
  68. ret = -ENOSYS;
  69. }
  70. pagefault_enable(); /* subsumes preempt_enable() */
  71. if (!ret) {
  72. switch (cmp) {
  73. case FUTEX_OP_CMP_EQ:
  74. ret = (oldval == cmparg);
  75. break;
  76. case FUTEX_OP_CMP_NE:
  77. ret = (oldval != cmparg);
  78. break;
  79. case FUTEX_OP_CMP_LT:
  80. ret = (oldval < cmparg);
  81. break;
  82. case FUTEX_OP_CMP_GE:
  83. ret = (oldval >= cmparg);
  84. break;
  85. case FUTEX_OP_CMP_LE:
  86. ret = (oldval <= cmparg);
  87. break;
  88. case FUTEX_OP_CMP_GT:
  89. ret = (oldval > cmparg);
  90. break;
  91. default:
  92. ret = -ENOSYS;
  93. }
  94. }
  95. return ret;
  96. }
  97. static inline int
  98. futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
  99. {
  100. int val;
  101. if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
  102. return -EFAULT;
  103. pagefault_disable(); /* implies preempt_disable() */
  104. __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
  105. "1: ldw.u %0, [%3]\n"
  106. " cmpxor.a %0, %1\n"
  107. " bne 3f\n"
  108. "2: stw.u %2, [%3]\n"
  109. "3:\n"
  110. " .pushsection __ex_table,\"a\"\n"
  111. " .align 3\n"
  112. " .long 1b, 4f, 2b, 4f\n"
  113. " .popsection\n"
  114. " .pushsection .fixup,\"ax\"\n"
  115. "4: mov %0, %4\n"
  116. " b 3b\n"
  117. " .popsection"
  118. : "=&r" (val)
  119. : "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
  120. : "cc", "memory");
  121. pagefault_enable(); /* subsumes preempt_enable() */
  122. return val;
  123. }
  124. #endif /* __KERNEL__ */
  125. #endif /* __UNICORE_FUTEX_H__ */