futex.h 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #ifndef __ASM_SH_FUTEX_H
  2. #define __ASM_SH_FUTEX_H
  3. #ifdef __KERNEL__
  4. #include <linux/futex.h>
  5. #include <linux/uaccess.h>
  6. #include <asm/errno.h>
  7. #if !defined(CONFIG_SMP)
  8. #include <asm/futex-irq.h>
  9. #elif defined(CONFIG_CPU_J2)
  10. #include <asm/futex-cas.h>
  11. #elif defined(CONFIG_CPU_SH4A)
  12. #include <asm/futex-llsc.h>
  13. #else
  14. #error SMP not supported on this configuration.
  15. #endif
  16. static inline int
  17. futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
  18. u32 oldval, u32 newval)
  19. {
  20. if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
  21. return -EFAULT;
  22. return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
  23. }
  24. static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,
  25. u32 __user *uaddr)
  26. {
  27. u32 oldval, newval, prev;
  28. int ret;
  29. pagefault_disable();
  30. do {
  31. if (op == FUTEX_OP_SET)
  32. ret = oldval = 0;
  33. else
  34. ret = get_user(oldval, uaddr);
  35. if (ret) break;
  36. switch (op) {
  37. case FUTEX_OP_SET:
  38. newval = oparg;
  39. break;
  40. case FUTEX_OP_ADD:
  41. newval = oldval + oparg;
  42. break;
  43. case FUTEX_OP_OR:
  44. newval = oldval | oparg;
  45. break;
  46. case FUTEX_OP_ANDN:
  47. newval = oldval & ~oparg;
  48. break;
  49. case FUTEX_OP_XOR:
  50. newval = oldval ^ oparg;
  51. break;
  52. default:
  53. ret = -ENOSYS;
  54. break;
  55. }
  56. if (ret) break;
  57. ret = futex_atomic_cmpxchg_inatomic(&prev, uaddr, oldval, newval);
  58. } while (!ret && prev != oldval);
  59. pagefault_enable();
  60. if (!ret)
  61. *oval = oldval;
  62. return ret;
  63. }
  64. #endif /* __KERNEL__ */
  65. #endif /* __ASM_SH_FUTEX_H */