1
2#ifndef _ASM_GENERIC_FUTEX_H
3#define _ASM_GENERIC_FUTEX_H
4
5#include <linux/futex.h>
6#include <linux/uaccess.h>
7#include <asm/errno.h>
8
9#ifndef CONFIG_SMP
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30static inline int
31arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
32{
33 int oldval, ret;
34 u32 tmp;
35
36 preempt_disable();
37
38 ret = -EFAULT;
39 if (unlikely(get_user(oldval, uaddr) != 0))
40 goto out_pagefault_enable;
41
42 ret = 0;
43 tmp = oldval;
44
45 switch (op) {
46 case FUTEX_OP_SET:
47 tmp = oparg;
48 break;
49 case FUTEX_OP_ADD:
50 tmp += oparg;
51 break;
52 case FUTEX_OP_OR:
53 tmp |= oparg;
54 break;
55 case FUTEX_OP_ANDN:
56 tmp &= ~oparg;
57 break;
58 case FUTEX_OP_XOR:
59 tmp ^= oparg;
60 break;
61 default:
62 ret = -ENOSYS;
63 }
64
65 if (ret == 0 && unlikely(put_user(tmp, uaddr) != 0))
66 ret = -EFAULT;
67
68out_pagefault_enable:
69 preempt_enable();
70
71 if (ret == 0)
72 *oval = oldval;
73
74 return ret;
75}
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92static inline int
93futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
94 u32 oldval, u32 newval)
95{
96 u32 val;
97
98 preempt_disable();
99 if (unlikely(get_user(val, uaddr) != 0)) {
100 preempt_enable();
101 return -EFAULT;
102 }
103
104 if (val == oldval && unlikely(put_user(newval, uaddr) != 0)) {
105 preempt_enable();
106 return -EFAULT;
107 }
108
109 *uval = val;
110 preempt_enable();
111
112 return 0;
113}
114
115#else
116static inline int
117arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
118{
119 return -ENOSYS;
120}
121
122static inline int
123futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
124 u32 oldval, u32 newval)
125{
126 return -ENOSYS;
127}
128
129#endif
130#endif
131