blob: 8f8cf941a8cd29c716a923002490dc5506ee57a5 [file] [log] [blame]
Kaz Kojimafc1d4c92007-06-18 13:58:32 +09001#ifndef __ASM_SH_FUTEX_H
2#define __ASM_SH_FUTEX_H
Jakub Jelinek4732efb2005-09-06 15:16:25 -07003
Kaz Kojimafc1d4c92007-06-18 13:58:32 +09004#ifdef __KERNEL__
Jakub Jelinek4732efb2005-09-06 15:16:25 -07005
Kaz Kojimafc1d4c92007-06-18 13:58:32 +09006#include <linux/futex.h>
Jeff Dike730f4122008-04-30 00:54:49 -07007#include <linux/uaccess.h>
Kaz Kojimafc1d4c92007-06-18 13:58:32 +09008#include <asm/errno.h>
Kaz Kojimafc1d4c92007-06-18 13:58:32 +09009
Rich Felker00b73d82016-04-25 21:58:03 +000010#if !defined(CONFIG_SMP)
Kaz Kojimafc1d4c92007-06-18 13:58:32 +090011#include <asm/futex-irq.h>
Rich Felker00b73d82016-04-25 21:58:03 +000012#elif defined(CONFIG_CPU_J2)
13#include <asm/futex-cas.h>
14#elif defined(CONFIG_CPU_SH4A)
15#include <asm/futex-llsc.h>
16#else
17#error SMP not supported on this configuration.
18#endif
Kaz Kojimafc1d4c92007-06-18 13:58:32 +090019
20static inline int
Michel Lespinasse8d7718a2011-03-10 18:50:58 -080021futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
22 u32 oldval, u32 newval)
Kaz Kojimafc1d4c92007-06-18 13:58:32 +090023{
Michel Lespinasse8d7718a2011-03-10 18:50:58 -080024 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
Kaz Kojimafc1d4c92007-06-18 13:58:32 +090025 return -EFAULT;
26
Michel Lespinasse37a9d912011-03-10 18:48:51 -080027 return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
Kaz Kojimafc1d4c92007-06-18 13:58:32 +090028}
29
Jiri Slaby30d6e0a2017-08-24 09:31:05 +020030static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,
31 u32 __user *uaddr)
Rich Felker00b73d82016-04-25 21:58:03 +000032{
Rich Felker00b73d82016-04-25 21:58:03 +000033 u32 oldval, newval, prev;
34 int ret;
35
Rich Felker00b73d82016-04-25 21:58:03 +000036 pagefault_disable();
37
38 do {
39 if (op == FUTEX_OP_SET)
40 ret = oldval = 0;
41 else
42 ret = get_user(oldval, uaddr);
43
44 if (ret) break;
45
46 switch (op) {
47 case FUTEX_OP_SET:
48 newval = oparg;
49 break;
50 case FUTEX_OP_ADD:
51 newval = oldval + oparg;
52 break;
53 case FUTEX_OP_OR:
54 newval = oldval | oparg;
55 break;
56 case FUTEX_OP_ANDN:
57 newval = oldval & ~oparg;
58 break;
59 case FUTEX_OP_XOR:
60 newval = oldval ^ oparg;
61 break;
62 default:
63 ret = -ENOSYS;
64 break;
65 }
66
67 if (ret) break;
68
69 ret = futex_atomic_cmpxchg_inatomic(&prev, uaddr, oldval, newval);
70 } while (!ret && prev != oldval);
71
72 pagefault_enable();
73
Jiri Slaby30d6e0a2017-08-24 09:31:05 +020074 if (!ret)
75 *oval = oldval;
Rich Felker00b73d82016-04-25 21:58:03 +000076
77 return ret;
78}
79
Kaz Kojimafc1d4c92007-06-18 13:58:32 +090080#endif /* __KERNEL__ */
81#endif /* __ASM_SH_FUTEX_H */