Blame view

include/asm-generic/futex.h 3.72 KB
f8aaeacec   Jeff Dike   [PATCH] consolida...
1
2
  #ifndef _ASM_GENERIC_FUTEX_H
  #define _ASM_GENERIC_FUTEX_H
f8aaeacec   Jeff Dike   [PATCH] consolida...
3
  #include <linux/futex.h>
730f412c0   Jeff Dike   asm-*/futex.h sho...
4
  #include <linux/uaccess.h>
f8aaeacec   Jeff Dike   [PATCH] consolida...
5
  #include <asm/errno.h>
f8aaeacec   Jeff Dike   [PATCH] consolida...
6

00f634bc5   Ley Foon Tan   asm-generic: add ...
7
8
9
  #ifndef CONFIG_SMP
  /*
   * The following implementation only for uniprocessor machines.
f3dae07e4   David Hildenbrand   sched/preempt, fu...
10
   * It relies on preempt_disable() ensuring mutual exclusion.
00f634bc5   Ley Foon Tan   asm-generic: add ...
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
   *
   */
  
  /**
   * futex_atomic_op_inuser() - Atomic arithmetic operation with constant
   *			  argument and comparison of the previous
   *			  futex value with another constant.
   *
   * @encoded_op:	encoded operation to execute
   * @uaddr:	pointer to user space address
   *
   * Return:
   * 0 - On success
   * <0 - On error
   */
  static inline int
  futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
  {
  	int op = (encoded_op >> 28) & 7;
  	int cmp = (encoded_op >> 24) & 15;
  	int oparg = (encoded_op << 8) >> 20;
  	int cmparg = (encoded_op << 20) >> 20;
  	int oldval, ret;
  	u32 tmp;
  
  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
  		oparg = 1 << oparg;
f3dae07e4   David Hildenbrand   sched/preempt, fu...
38
  	preempt_disable();
00f634bc5   Ley Foon Tan   asm-generic: add ...
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  	pagefault_disable();
  
  	ret = -EFAULT;
  	if (unlikely(get_user(oldval, uaddr) != 0))
  		goto out_pagefault_enable;
  
  	ret = 0;
  	tmp = oldval;
  
  	switch (op) {
  	case FUTEX_OP_SET:
  		tmp = oparg;
  		break;
  	case FUTEX_OP_ADD:
  		tmp += oparg;
  		break;
  	case FUTEX_OP_OR:
  		tmp |= oparg;
  		break;
  	case FUTEX_OP_ANDN:
  		tmp &= ~oparg;
  		break;
  	case FUTEX_OP_XOR:
  		tmp ^= oparg;
  		break;
  	default:
  		ret = -ENOSYS;
  	}
  
  	if (ret == 0 && unlikely(put_user(tmp, uaddr) != 0))
  		ret = -EFAULT;
  
  out_pagefault_enable:
  	pagefault_enable();
f3dae07e4   David Hildenbrand   sched/preempt, fu...
73
  	preempt_enable();
00f634bc5   Ley Foon Tan   asm-generic: add ...
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  
  	if (ret == 0) {
  		switch (cmp) {
  		case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
  		case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
  		case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
  		case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
  		case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
  		case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
  		default: ret = -ENOSYS;
  		}
  	}
  	return ret;
  }
  
  /**
   * futex_atomic_cmpxchg_inatomic() - Compare and exchange the content of the
   *				uaddr with newval if the current value is
   *				oldval.
   * @uval:	pointer to store content of @uaddr
   * @uaddr:	pointer to user space address
   * @oldval:	old value
   * @newval:	new value to store to @uaddr
   *
   * Return:
   * 0 - On success
   * <0 - On error
   */
  static inline int
  futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
  			      u32 oldval, u32 newval)
  {
  	u32 val;
d9b9ff8c1   David Hildenbrand   sched/preempt, fu...
107
  	preempt_disable();
fba7cd681   Romain Perier   asm-generic/futex...
108
109
  	if (unlikely(get_user(val, uaddr) != 0)) {
  		preempt_enable();
00f634bc5   Ley Foon Tan   asm-generic: add ...
110
  		return -EFAULT;
fba7cd681   Romain Perier   asm-generic/futex...
111
  	}
00f634bc5   Ley Foon Tan   asm-generic: add ...
112

fba7cd681   Romain Perier   asm-generic/futex...
113
114
  	if (val == oldval && unlikely(put_user(newval, uaddr) != 0)) {
  		preempt_enable();
00f634bc5   Ley Foon Tan   asm-generic: add ...
115
  		return -EFAULT;
fba7cd681   Romain Perier   asm-generic/futex...
116
  	}
00f634bc5   Ley Foon Tan   asm-generic: add ...
117
118
  
  	*uval = val;
d9b9ff8c1   David Hildenbrand   sched/preempt, fu...
119
  	preempt_enable();
00f634bc5   Ley Foon Tan   asm-generic: add ...
120
121
122
123
124
  
  	return 0;
  }
  
  #else
f8aaeacec   Jeff Dike   [PATCH] consolida...
125
  static inline int
8d7718aa0   Michel Lespinasse   futex: Sanitize f...
126
  futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
f8aaeacec   Jeff Dike   [PATCH] consolida...
127
128
129
130
131
132
133
134
  {
  	int op = (encoded_op >> 28) & 7;
  	int cmp = (encoded_op >> 24) & 15;
  	int oparg = (encoded_op << 8) >> 20;
  	int cmparg = (encoded_op << 20) >> 20;
  	int oldval = 0, ret;
  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
  		oparg = 1 << oparg;
8d7718aa0   Michel Lespinasse   futex: Sanitize f...
135
  	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
f8aaeacec   Jeff Dike   [PATCH] consolida...
136
  		return -EFAULT;
a866374ae   Peter Zijlstra   [PATCH] mm: pagef...
137
  	pagefault_disable();
f8aaeacec   Jeff Dike   [PATCH] consolida...
138
139
140
141
142
143
144
145
146
147
  
  	switch (op) {
  	case FUTEX_OP_SET:
  	case FUTEX_OP_ADD:
  	case FUTEX_OP_OR:
  	case FUTEX_OP_ANDN:
  	case FUTEX_OP_XOR:
  	default:
  		ret = -ENOSYS;
  	}
a866374ae   Peter Zijlstra   [PATCH] mm: pagef...
148
  	pagefault_enable();
f8aaeacec   Jeff Dike   [PATCH] consolida...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
  
  	if (!ret) {
  		switch (cmp) {
  		case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
  		case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
  		case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
  		case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
  		case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
  		case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
  		default: ret = -ENOSYS;
  		}
  	}
  	return ret;
  }
e9056f13b   Ingo Molnar   [PATCH] lightweig...
163
  static inline int
8d7718aa0   Michel Lespinasse   futex: Sanitize f...
164
165
  futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
  			      u32 oldval, u32 newval)
e9056f13b   Ingo Molnar   [PATCH] lightweig...
166
167
168
  {
  	return -ENOSYS;
  }
00f634bc5   Ley Foon Tan   asm-generic: add ...
169
  #endif /* CONFIG_SMP */
f8aaeacec   Jeff Dike   [PATCH] consolida...
170
  #endif