Blame view

arch/x86/include/asm/atomic64_32.h 6.71 KB
1a3b1d89e   Brian Gerst   x86: Split atomic...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  #ifndef _ASM_X86_ATOMIC64_32_H
  #define _ASM_X86_ATOMIC64_32_H
  
  #include <linux/compiler.h>
  #include <linux/types.h>
  #include <asm/processor.h>
  //#include <asm/cmpxchg.h>
  
  /* An 64bit atomic type */
  
  typedef struct {
  	u64 __aligned(8) counter;
  } atomic64_t;
  
  #define ATOMIC64_INIT(val)	{ (val) }
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  #ifdef CONFIG_X86_CMPXCHG64
  #define ATOMIC64_ALTERNATIVE_(f, g) "call atomic64_" #g "_cx8"
  #else
  #define ATOMIC64_ALTERNATIVE_(f, g) ALTERNATIVE("call atomic64_" #f "_386", "call atomic64_" #g "_cx8", X86_FEATURE_CX8)
  #endif
  
  #define ATOMIC64_ALTERNATIVE(f) ATOMIC64_ALTERNATIVE_(f, f)
  
  /**
   * atomic64_cmpxchg - cmpxchg atomic64 variable
   * @p: pointer to type atomic64_t
   * @o: expected value
   * @n: new value
   *
   * Atomically sets @v to @n if it was equal to @o and returns
   * the old value.
   */
  
  static inline long long atomic64_cmpxchg(atomic64_t *v, long long o, long long n)
  {
  	return cmpxchg64(&v->counter, o, n);
  }
1a3b1d89e   Brian Gerst   x86: Split atomic...
38
39
40
  
  /**
   * atomic64_xchg - xchg atomic64 variable
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
41
42
   * @v: pointer to type atomic64_t
   * @n: value to assign
1a3b1d89e   Brian Gerst   x86: Split atomic...
43
   *
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
44
   * Atomically xchgs the value of @v to @n and returns
1a3b1d89e   Brian Gerst   x86: Split atomic...
45
46
   * the old value.
   */
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
47
48
49
50
51
52
53
54
55
56
57
58
  static inline long long atomic64_xchg(atomic64_t *v, long long n)
  {
  	long long o;
  	unsigned high = (unsigned)(n >> 32);
  	unsigned low = (unsigned)n;
  	asm volatile(ATOMIC64_ALTERNATIVE(xchg)
  		     : "=A" (o), "+b" (low), "+c" (high)
  		     : "S" (v)
  		     : "memory"
  		     );
  	return o;
  }
1a3b1d89e   Brian Gerst   x86: Split atomic...
59
60
61
  
  /**
   * atomic64_set - set atomic64 variable
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
62
63
   * @v: pointer to type atomic64_t
   * @n: value to assign
1a3b1d89e   Brian Gerst   x86: Split atomic...
64
   *
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
65
   * Atomically sets the value of @v to @n.
1a3b1d89e   Brian Gerst   x86: Split atomic...
66
   */
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
67
68
69
70
71
72
73
74
75
76
  static inline void atomic64_set(atomic64_t *v, long long i)
  {
  	unsigned high = (unsigned)(i >> 32);
  	unsigned low = (unsigned)i;
  	asm volatile(ATOMIC64_ALTERNATIVE(set)
  		     : "+b" (low), "+c" (high)
  		     : "S" (v)
  		     : "eax", "edx", "memory"
  		     );
  }
1a3b1d89e   Brian Gerst   x86: Split atomic...
77
78
79
  
  /**
   * atomic64_read - read atomic64 variable
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
80
   * @v: pointer to type atomic64_t
1a3b1d89e   Brian Gerst   x86: Split atomic...
81
   *
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
82
   * Atomically reads the value of @v and returns it.
1a3b1d89e   Brian Gerst   x86: Split atomic...
83
   */
8030c36d1   H. Peter Anvin   x86, atomic: atom...
84
  static inline long long atomic64_read(const atomic64_t *v)
1a3b1d89e   Brian Gerst   x86: Split atomic...
85
  {
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
86
87
88
89
90
91
92
  	long long r;
  	asm volatile(ATOMIC64_ALTERNATIVE(read)
  		     : "=A" (r), "+c" (v)
  		     : : "memory"
  		     );
  	return r;
   }
1a3b1d89e   Brian Gerst   x86: Split atomic...
93
94
95
  
  /**
   * atomic64_add_return - add and return
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
96
97
   * @i: integer value to add
   * @v: pointer to type atomic64_t
1a3b1d89e   Brian Gerst   x86: Split atomic...
98
   *
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
99
   * Atomically adds @i to @v and returns @i + *@v
1a3b1d89e   Brian Gerst   x86: Split atomic...
100
   */
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
101
102
103
104
105
106
107
108
  static inline long long atomic64_add_return(long long i, atomic64_t *v)
  {
  	asm volatile(ATOMIC64_ALTERNATIVE(add_return)
  		     : "+A" (i), "+c" (v)
  		     : : "memory"
  		     );
  	return i;
  }
1a3b1d89e   Brian Gerst   x86: Split atomic...
109
110
111
112
  
  /*
   * Other variants with different arithmetic operators:
   */
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  static inline long long atomic64_sub_return(long long i, atomic64_t *v)
  {
  	asm volatile(ATOMIC64_ALTERNATIVE(sub_return)
  		     : "+A" (i), "+c" (v)
  		     : : "memory"
  		     );
  	return i;
  }
  
  static inline long long atomic64_inc_return(atomic64_t *v)
  {
  	long long a;
  	asm volatile(ATOMIC64_ALTERNATIVE(inc_return)
  		     : "=A" (a)
  		     : "S" (v)
  		     : "memory", "ecx"
  		     );
  	return a;
  }
  
  static inline long long atomic64_dec_return(atomic64_t *v)
  {
  	long long a;
  	asm volatile(ATOMIC64_ALTERNATIVE(dec_return)
  		     : "=A" (a)
  		     : "S" (v)
  		     : "memory", "ecx"
  		     );
  	return a;
  }
1a3b1d89e   Brian Gerst   x86: Split atomic...
143
144
145
  
  /**
   * atomic64_add - add integer to atomic64 variable
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
146
147
   * @i: integer value to add
   * @v: pointer to type atomic64_t
1a3b1d89e   Brian Gerst   x86: Split atomic...
148
   *
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
149
   * Atomically adds @i to @v.
1a3b1d89e   Brian Gerst   x86: Split atomic...
150
   */
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
151
152
153
154
155
156
157
158
  static inline long long atomic64_add(long long i, atomic64_t *v)
  {
  	asm volatile(ATOMIC64_ALTERNATIVE_(add, add_return)
  		     : "+A" (i), "+c" (v)
  		     : : "memory"
  		     );
  	return i;
  }
1a3b1d89e   Brian Gerst   x86: Split atomic...
159
160
161
  
  /**
   * atomic64_sub - subtract the atomic64 variable
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
162
163
   * @i: integer value to subtract
   * @v: pointer to type atomic64_t
1a3b1d89e   Brian Gerst   x86: Split atomic...
164
   *
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
165
   * Atomically subtracts @i from @v.
1a3b1d89e   Brian Gerst   x86: Split atomic...
166
   */
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
167
168
169
170
171
172
173
174
  static inline long long atomic64_sub(long long i, atomic64_t *v)
  {
  	asm volatile(ATOMIC64_ALTERNATIVE_(sub, sub_return)
  		     : "+A" (i), "+c" (v)
  		     : : "memory"
  		     );
  	return i;
  }
1a3b1d89e   Brian Gerst   x86: Split atomic...
175
176
177
  
  /**
   * atomic64_sub_and_test - subtract value from variable and test result
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
178
179
180
181
   * @i: integer value to subtract
   * @v: pointer to type atomic64_t
    *
   * Atomically subtracts @i from @v and returns
1a3b1d89e   Brian Gerst   x86: Split atomic...
182
183
184
   * true if the result is zero, or false for all
   * other cases.
   */
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
185
186
187
188
  static inline int atomic64_sub_and_test(long long i, atomic64_t *v)
  {
  	return atomic64_sub_return(i, v) == 0;
  }
1a3b1d89e   Brian Gerst   x86: Split atomic...
189
190
191
  
  /**
   * atomic64_inc - increment atomic64 variable
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
192
   * @v: pointer to type atomic64_t
1a3b1d89e   Brian Gerst   x86: Split atomic...
193
   *
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
194
   * Atomically increments @v by 1.
1a3b1d89e   Brian Gerst   x86: Split atomic...
195
   */
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
196
197
198
199
200
201
202
  static inline void atomic64_inc(atomic64_t *v)
  {
  	asm volatile(ATOMIC64_ALTERNATIVE_(inc, inc_return)
  		     : : "S" (v)
  		     : "memory", "eax", "ecx", "edx"
  		     );
  }
1a3b1d89e   Brian Gerst   x86: Split atomic...
203
204
205
206
207
208
209
  
  /**
   * atomic64_dec - decrement atomic64 variable
   * @ptr: pointer to type atomic64_t
   *
   * Atomically decrements @ptr by 1.
   */
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
210
211
212
213
214
215
216
  static inline void atomic64_dec(atomic64_t *v)
  {
  	asm volatile(ATOMIC64_ALTERNATIVE_(dec, dec_return)
  		     : : "S" (v)
  		     : "memory", "eax", "ecx", "edx"
  		     );
  }
1a3b1d89e   Brian Gerst   x86: Split atomic...
217
218
219
  
  /**
   * atomic64_dec_and_test - decrement and test
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
220
   * @v: pointer to type atomic64_t
1a3b1d89e   Brian Gerst   x86: Split atomic...
221
   *
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
222
   * Atomically decrements @v by 1 and
1a3b1d89e   Brian Gerst   x86: Split atomic...
223
224
225
   * returns true if the result is 0, or false for all other
   * cases.
   */
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
226
227
228
229
  static inline int atomic64_dec_and_test(atomic64_t *v)
  {
  	return atomic64_dec_return(v) == 0;
  }
1a3b1d89e   Brian Gerst   x86: Split atomic...
230
231
232
  
  /**
   * atomic64_inc_and_test - increment and test
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
233
   * @v: pointer to type atomic64_t
1a3b1d89e   Brian Gerst   x86: Split atomic...
234
   *
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
235
   * Atomically increments @v by 1
1a3b1d89e   Brian Gerst   x86: Split atomic...
236
237
238
   * and returns true if the result is zero, or false for all
   * other cases.
   */
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
239
240
241
242
  static inline int atomic64_inc_and_test(atomic64_t *v)
  {
  	return atomic64_inc_return(v) == 0;
  }
1a3b1d89e   Brian Gerst   x86: Split atomic...
243
244
245
  
  /**
   * atomic64_add_negative - add and test if negative
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
246
247
   * @i: integer value to add
   * @v: pointer to type atomic64_t
1a3b1d89e   Brian Gerst   x86: Split atomic...
248
   *
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
249
   * Atomically adds @i to @v and returns true
1a3b1d89e   Brian Gerst   x86: Split atomic...
250
251
252
   * if the result is negative, or false when
   * result is greater than or equal to zero.
   */
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
253
254
255
256
257
258
259
260
261
262
263
264
  static inline int atomic64_add_negative(long long i, atomic64_t *v)
  {
  	return atomic64_add_return(i, v) < 0;
  }
  
  /**
   * atomic64_add_unless - add unless the number is a given value
   * @v: pointer of type atomic64_t
   * @a: the amount to add to v...
   * @u: ...unless v is equal to u.
   *
   * Atomically adds @a to @v, so long as it was not @u.
f24219b4e   Arun Sharma   atomic: move atom...
265
   * Returns the old value of @v.
a7e926abc   Luca Barbieri   x86-32: Rewrite 3...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
   */
  static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u)
  {
  	unsigned low = (unsigned)u;
  	unsigned high = (unsigned)(u >> 32);
  	asm volatile(ATOMIC64_ALTERNATIVE(add_unless) "
  \t"
  		     : "+A" (a), "+c" (v), "+S" (low), "+D" (high)
  		     : : "memory");
  	return (int)a;
  }
  
  
  static inline int atomic64_inc_not_zero(atomic64_t *v)
  {
  	int r;
  	asm volatile(ATOMIC64_ALTERNATIVE(inc_not_zero)
  		     : "=a" (r)
  		     : "S" (v)
  		     : "ecx", "edx", "memory"
  		     );
  	return r;
  }
  
  static inline long long atomic64_dec_if_positive(atomic64_t *v)
  {
  	long long r;
  	asm volatile(ATOMIC64_ALTERNATIVE(dec_if_positive)
  		     : "=A" (r)
  		     : "S" (v)
  		     : "ecx", "memory"
  		     );
  	return r;
  }
  
  #undef ATOMIC64_ALTERNATIVE
  #undef ATOMIC64_ALTERNATIVE_
1a3b1d89e   Brian Gerst   x86: Split atomic...
303
304
  
  #endif /* _ASM_X86_ATOMIC64_32_H */