aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Gerst <brgerst@gmail.com>2010-01-07 11:53:34 -0500
committerH. Peter Anvin <hpa@zytor.com>2010-01-07 14:47:55 -0500
commit3ce59bb8352e1c53446bef1ead1c63956dfef64a (patch)
tree5a2f965e26443c5a293802920e0b81859abbdf63
parent1a3b1d89eded68d64e5ea409ad37827310059441 (diff)
x86: Sync asm/atomic_32.h and asm/atomic_64.h
Prepare for merging into asm/atomic.h. Signed-off-by: Brian Gerst <brgerst@gmail.com> LKML-Reference: <1262883215-4034-3-git-send-email-brgerst@gmail.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--arch/x86/include/asm/atomic_32.h42
-rw-r--r--arch/x86/include/asm/atomic_64.h81
2 files changed, 89 insertions, 34 deletions
diff --git a/arch/x86/include/asm/atomic_32.h b/arch/x86/include/asm/atomic_32.h
index e128ae988cc9..036962ef8203 100644
--- a/arch/x86/include/asm/atomic_32.h
+++ b/arch/x86/include/asm/atomic_32.h
@@ -4,6 +4,7 @@
4#include <linux/compiler.h> 4#include <linux/compiler.h>
5#include <linux/types.h> 5#include <linux/types.h>
6#include <asm/processor.h> 6#include <asm/processor.h>
7#include <asm/alternative.h>
7#include <asm/cmpxchg.h> 8#include <asm/cmpxchg.h>
8 9
9/* 10/*
@@ -145,8 +146,8 @@ static inline int atomic_inc_and_test(atomic_t *v)
145 146
146/** 147/**
147 * atomic_add_negative - add and test if negative 148 * atomic_add_negative - add and test if negative
148 * @v: pointer of type atomic_t
149 * @i: integer value to add 149 * @i: integer value to add
150 * @v: pointer of type atomic_t
150 * 151 *
151 * Atomically adds @i to @v and returns true 152 * Atomically adds @i to @v and returns true
152 * if the result is negative, or false when 153 * if the result is negative, or false when
@@ -164,8 +165,8 @@ static inline int atomic_add_negative(int i, atomic_t *v)
164 165
165/** 166/**
166 * atomic_add_return - add integer and return 167 * atomic_add_return - add integer and return
167 * @v: pointer of type atomic_t
168 * @i: integer value to add 168 * @i: integer value to add
169 * @v: pointer of type atomic_t
169 * 170 *
170 * Atomically adds @i to @v and returns @i + @v 171 * Atomically adds @i to @v and returns @i + @v
171 */ 172 */
@@ -206,6 +207,9 @@ static inline int atomic_sub_return(int i, atomic_t *v)
206 return atomic_add_return(-i, v); 207 return atomic_add_return(-i, v);
207} 208}
208 209
210#define atomic_inc_return(v) (atomic_add_return(1, v))
211#define atomic_dec_return(v) (atomic_sub_return(1, v))
212
209static inline int atomic_cmpxchg(atomic_t *v, int old, int new) 213static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
210{ 214{
211 return cmpxchg(&v->counter, old, new); 215 return cmpxchg(&v->counter, old, new);
@@ -242,8 +246,33 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
242 246
243#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) 247#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
244 248
245#define atomic_inc_return(v) (atomic_add_return(1, v)) 249/**
246#define atomic_dec_return(v) (atomic_sub_return(1, v)) 250 * atomic_inc_short - increment of a short integer
251 * @v: pointer to type int
252 *
253 * Atomically adds 1 to @v
254 * Returns the new value of @u
255 */
256static inline short int atomic_inc_short(short int *v)
257{
258 asm(LOCK_PREFIX "addw $1, %0" : "+m" (*v));
259 return *v;
260}
261
262#ifdef CONFIG_X86_64
263/**
264 * atomic_or_long - OR of two long integers
265 * @v1: pointer to type unsigned long
266 * @v2: pointer to type unsigned long
267 *
268 * Atomically ORs @v1 and @v2
269 * Returns the result of the OR
270 */
271static inline void atomic_or_long(unsigned long *v1, unsigned long v2)
272{
273 asm(LOCK_PREFIX "orq %1, %0" : "+m" (*v1) : "r" (v2));
274}
275#endif
247 276
248/* These are x86-specific, used by some header files */ 277/* These are x86-specific, used by some header files */
249#define atomic_clear_mask(mask, addr) \ 278#define atomic_clear_mask(mask, addr) \
@@ -251,8 +280,9 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
251 : : "r" (~(mask)), "m" (*(addr)) : "memory") 280 : : "r" (~(mask)), "m" (*(addr)) : "memory")
252 281
253#define atomic_set_mask(mask, addr) \ 282#define atomic_set_mask(mask, addr) \
254 asm volatile(LOCK_PREFIX "orl %0,%1" \ 283 asm volatile(LOCK_PREFIX "orl %0,%1" \
255 : : "r" (mask), "m" (*(addr)) : "memory") 284 : : "r" ((unsigned)(mask)), "m" (*(addr)) \
285 : "memory")
256 286
257/* Atomic operations are already serializing on x86 */ 287/* Atomic operations are already serializing on x86 */
258#define smp_mb__before_atomic_dec() barrier() 288#define smp_mb__before_atomic_dec() barrier()
diff --git a/arch/x86/include/asm/atomic_64.h b/arch/x86/include/asm/atomic_64.h
index 042c33100c69..77407887cfcd 100644
--- a/arch/x86/include/asm/atomic_64.h
+++ b/arch/x86/include/asm/atomic_64.h
@@ -1,7 +1,9 @@
1#ifndef _ASM_X86_ATOMIC_64_H 1#ifndef _ASM_X86_ATOMIC_64_H
2#define _ASM_X86_ATOMIC_64_H 2#define _ASM_X86_ATOMIC_64_H
3 3
4#include <linux/compiler.h>
4#include <linux/types.h> 5#include <linux/types.h>
6#include <asm/processor.h>
5#include <asm/alternative.h> 7#include <asm/alternative.h>
6#include <asm/cmpxchg.h> 8#include <asm/cmpxchg.h>
7 9
@@ -45,12 +47,12 @@ static inline void atomic_set(atomic_t *v, int i)
45static inline void atomic_add(int i, atomic_t *v) 47static inline void atomic_add(int i, atomic_t *v)
46{ 48{
47 asm volatile(LOCK_PREFIX "addl %1,%0" 49 asm volatile(LOCK_PREFIX "addl %1,%0"
48 : "=m" (v->counter) 50 : "+m" (v->counter)
49 : "ir" (i), "m" (v->counter)); 51 : "ir" (i));
50} 52}
51 53
52/** 54/**
53 * atomic_sub - subtract the atomic variable 55 * atomic_sub - subtract integer from atomic variable
54 * @i: integer value to subtract 56 * @i: integer value to subtract
55 * @v: pointer of type atomic_t 57 * @v: pointer of type atomic_t
56 * 58 *
@@ -59,8 +61,8 @@ static inline void atomic_add(int i, atomic_t *v)
59static inline void atomic_sub(int i, atomic_t *v) 61static inline void atomic_sub(int i, atomic_t *v)
60{ 62{
61 asm volatile(LOCK_PREFIX "subl %1,%0" 63 asm volatile(LOCK_PREFIX "subl %1,%0"
62 : "=m" (v->counter) 64 : "+m" (v->counter)
63 : "ir" (i), "m" (v->counter)); 65 : "ir" (i));
64} 66}
65 67
66/** 68/**
@@ -77,8 +79,8 @@ static inline int atomic_sub_and_test(int i, atomic_t *v)
77 unsigned char c; 79 unsigned char c;
78 80
79 asm volatile(LOCK_PREFIX "subl %2,%0; sete %1" 81 asm volatile(LOCK_PREFIX "subl %2,%0; sete %1"
80 : "=m" (v->counter), "=qm" (c) 82 : "+m" (v->counter), "=qm" (c)
81 : "ir" (i), "m" (v->counter) : "memory"); 83 : "ir" (i) : "memory");
82 return c; 84 return c;
83} 85}
84 86
@@ -91,8 +93,7 @@ static inline int atomic_sub_and_test(int i, atomic_t *v)
91static inline void atomic_inc(atomic_t *v) 93static inline void atomic_inc(atomic_t *v)
92{ 94{
93 asm volatile(LOCK_PREFIX "incl %0" 95 asm volatile(LOCK_PREFIX "incl %0"
94 : "=m" (v->counter) 96 : "+m" (v->counter));
95 : "m" (v->counter));
96} 97}
97 98
98/** 99/**
@@ -104,8 +105,7 @@ static inline void atomic_inc(atomic_t *v)
104static inline void atomic_dec(atomic_t *v) 105static inline void atomic_dec(atomic_t *v)
105{ 106{
106 asm volatile(LOCK_PREFIX "decl %0" 107 asm volatile(LOCK_PREFIX "decl %0"
107 : "=m" (v->counter) 108 : "+m" (v->counter));
108 : "m" (v->counter));
109} 109}
110 110
111/** 111/**
@@ -121,8 +121,8 @@ static inline int atomic_dec_and_test(atomic_t *v)
121 unsigned char c; 121 unsigned char c;
122 122
123 asm volatile(LOCK_PREFIX "decl %0; sete %1" 123 asm volatile(LOCK_PREFIX "decl %0; sete %1"
124 : "=m" (v->counter), "=qm" (c) 124 : "+m" (v->counter), "=qm" (c)
125 : "m" (v->counter) : "memory"); 125 : : "memory");
126 return c != 0; 126 return c != 0;
127} 127}
128 128
@@ -139,8 +139,8 @@ static inline int atomic_inc_and_test(atomic_t *v)
139 unsigned char c; 139 unsigned char c;
140 140
141 asm volatile(LOCK_PREFIX "incl %0; sete %1" 141 asm volatile(LOCK_PREFIX "incl %0; sete %1"
142 : "=m" (v->counter), "=qm" (c) 142 : "+m" (v->counter), "=qm" (c)
143 : "m" (v->counter) : "memory"); 143 : : "memory");
144 return c != 0; 144 return c != 0;
145} 145}
146 146
@@ -158,13 +158,13 @@ static inline int atomic_add_negative(int i, atomic_t *v)
158 unsigned char c; 158 unsigned char c;
159 159
160 asm volatile(LOCK_PREFIX "addl %2,%0; sets %1" 160 asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"
161 : "=m" (v->counter), "=qm" (c) 161 : "+m" (v->counter), "=qm" (c)
162 : "ir" (i), "m" (v->counter) : "memory"); 162 : "ir" (i) : "memory");
163 return c; 163 return c;
164} 164}
165 165
166/** 166/**
167 * atomic_add_return - add and return 167 * atomic_add_return - add integer and return
168 * @i: integer value to add 168 * @i: integer value to add
169 * @v: pointer of type atomic_t 169 * @v: pointer of type atomic_t
170 * 170 *
@@ -172,13 +172,36 @@ static inline int atomic_add_negative(int i, atomic_t *v)
172 */ 172 */
173static inline int atomic_add_return(int i, atomic_t *v) 173static inline int atomic_add_return(int i, atomic_t *v)
174{ 174{
175 int __i = i; 175 int __i;
176#ifdef CONFIG_M386
177 unsigned long flags;
178 if (unlikely(boot_cpu_data.x86 <= 3))
179 goto no_xadd;
180#endif
181 /* Modern 486+ processor */
182 __i = i;
176 asm volatile(LOCK_PREFIX "xaddl %0, %1" 183 asm volatile(LOCK_PREFIX "xaddl %0, %1"
177 : "+r" (i), "+m" (v->counter) 184 : "+r" (i), "+m" (v->counter)
178 : : "memory"); 185 : : "memory");
179 return i + __i; 186 return i + __i;
187
188#ifdef CONFIG_M386
189no_xadd: /* Legacy 386 processor */
190 local_irq_save(flags);
191 __i = atomic_read(v);
192 atomic_set(v, i + __i);
193 local_irq_restore(flags);
194 return i + __i;
195#endif
180} 196}
181 197
198/**
199 * atomic_sub_return - subtract integer and return
200 * @v: pointer of type atomic_t
201 * @i: integer value to subtract
202 *
203 * Atomically subtracts @i from @v and returns @v - @i
204 */
182static inline int atomic_sub_return(int i, atomic_t *v) 205static inline int atomic_sub_return(int i, atomic_t *v)
183{ 206{
184 return atomic_add_return(-i, v); 207 return atomic_add_return(-i, v);
@@ -187,23 +210,23 @@ static inline int atomic_sub_return(int i, atomic_t *v)
187#define atomic_inc_return(v) (atomic_add_return(1, v)) 210#define atomic_inc_return(v) (atomic_add_return(1, v))
188#define atomic_dec_return(v) (atomic_sub_return(1, v)) 211#define atomic_dec_return(v) (atomic_sub_return(1, v))
189 212
190static inline long atomic_cmpxchg(atomic_t *v, int old, int new) 213static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
191{ 214{
192 return cmpxchg(&v->counter, old, new); 215 return cmpxchg(&v->counter, old, new);
193} 216}
194 217
195static inline long atomic_xchg(atomic_t *v, int new) 218static inline int atomic_xchg(atomic_t *v, int new)
196{ 219{
197 return xchg(&v->counter, new); 220 return xchg(&v->counter, new);
198} 221}
199 222
200/** 223/**
201 * atomic_add_unless - add unless the number is a given value 224 * atomic_add_unless - add unless the number is already a given value
202 * @v: pointer of type atomic_t 225 * @v: pointer of type atomic_t
203 * @a: the amount to add to v... 226 * @a: the amount to add to v...
204 * @u: ...unless v is equal to u. 227 * @u: ...unless v is equal to u.
205 * 228 *
206 * Atomically adds @a to @v, so long as it was not @u. 229 * Atomically adds @a to @v, so long as @v was not already @u.
207 * Returns non-zero if @v was not @u, and zero otherwise. 230 * Returns non-zero if @v was not @u, and zero otherwise.
208 */ 231 */
209static inline int atomic_add_unless(atomic_t *v, int a, int u) 232static inline int atomic_add_unless(atomic_t *v, int a, int u)
@@ -236,6 +259,7 @@ static inline short int atomic_inc_short(short int *v)
236 return *v; 259 return *v;
237} 260}
238 261
262#ifdef CONFIG_X86_64
239/** 263/**
240 * atomic_or_long - OR of two long integers 264 * atomic_or_long - OR of two long integers
241 * @v1: pointer to type unsigned long 265 * @v1: pointer to type unsigned long
@@ -248,15 +272,16 @@ static inline void atomic_or_long(unsigned long *v1, unsigned long v2)
248{ 272{
249 asm(LOCK_PREFIX "orq %1, %0" : "+m" (*v1) : "r" (v2)); 273 asm(LOCK_PREFIX "orq %1, %0" : "+m" (*v1) : "r" (v2));
250} 274}
275#endif
251 276
252/* These are x86-specific, used by some header files */ 277/* These are x86-specific, used by some header files */
253#define atomic_clear_mask(mask, addr) \ 278#define atomic_clear_mask(mask, addr) \
254 asm volatile(LOCK_PREFIX "andl %0,%1" \ 279 asm volatile(LOCK_PREFIX "andl %0,%1" \
255 : : "r" (~(mask)), "m" (*(addr)) : "memory") 280 : : "r" (~(mask)), "m" (*(addr)) : "memory")
256 281
257#define atomic_set_mask(mask, addr) \ 282#define atomic_set_mask(mask, addr) \
258 asm volatile(LOCK_PREFIX "orl %0,%1" \ 283 asm volatile(LOCK_PREFIX "orl %0,%1" \
259 : : "r" ((unsigned)(mask)), "m" (*(addr)) \ 284 : : "r" ((unsigned)(mask)), "m" (*(addr)) \
260 : "memory") 285 : "memory")
261 286
262/* Atomic operations are already serializing on x86 */ 287/* Atomic operations are already serializing on x86 */