futex.h 1.4 KB

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