futex.h 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __ASM_SH_FUTEX_H
  3. #define __ASM_SH_FUTEX_H
  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(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. do {
  30. ret = get_user(oldval, uaddr);
  31. if (ret) break;
  32. switch (op) {
  33. case FUTEX_OP_SET:
  34. newval = oparg;
  35. break;
  36. case FUTEX_OP_ADD:
  37. newval = oldval + oparg;
  38. break;
  39. case FUTEX_OP_OR:
  40. newval = oldval | oparg;
  41. break;
  42. case FUTEX_OP_ANDN:
  43. newval = oldval & ~oparg;
  44. break;
  45. case FUTEX_OP_XOR:
  46. newval = oldval ^ oparg;
  47. break;
  48. default:
  49. ret = -ENOSYS;
  50. break;
  51. }
  52. if (ret) break;
  53. ret = futex_atomic_cmpxchg_inatomic(&prev, uaddr, oldval, newval);
  54. } while (!ret && prev != oldval);
  55. if (!ret)
  56. *oval = oldval;
  57. return ret;
  58. }
  59. #endif /* __ASM_SH_FUTEX_H */