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