Commit 8896fab35e62aa748a5ce62ac773508e51f10be1

Authored by Jan Beulich
Committed by Linus Torvalds
1 parent dacb16b1a0

[PATCH] x86: cmpxchg improvements

This adjusts i386's cmpxchg patterns so that

- for word and long cmpxchg-es the compiler can utilize all possible
  registers

- cmpxchg8b gets disabled when the minimum specified hardware architectur
  doesn't support it (like was already happening for the byte, word, and
  long ones).

Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 2 changed files with 35 additions and 3 deletions Side-by-side Diff

... ... @@ -424,6 +424,11 @@
424 424 depends on !M386
425 425 default y
426 426  
  427 +config X86_CMPXCHG64
  428 + bool
  429 + depends on !M386 && !M486
  430 + default y
  431 +
427 432 config X86_ALIGNMENT_16
428 433 bool
429 434 depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
include/asm-i386/system.h
... ... @@ -167,6 +167,8 @@
167 167 #define __xg(x) ((struct __xchg_dummy *)(x))
168 168  
169 169  
  170 +#ifdef CONFIG_X86_CMPXCHG64
  171 +
170 172 /*
171 173 * The semantics of XCHGCMP8B are a bit strange, this is why
172 174 * there is a loop and the loading of %%eax and %%edx has to
... ... @@ -221,6 +223,8 @@
221 223 __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \
222 224 __set_64bit(ptr, ll_low(value), ll_high(value)) )
223 225  
  226 +#endif
  227 +
224 228 /*
225 229 * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
226 230 * Note 2: xchg has side effect, so that attribute volatile is necessary,
... ... @@ -259,7 +263,6 @@
259 263  
260 264 #ifdef CONFIG_X86_CMPXCHG
261 265 #define __HAVE_ARCH_CMPXCHG 1
262   -#endif
263 266  
264 267 static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
265 268 unsigned long new, int size)
266 269  
... ... @@ -275,13 +278,13 @@
275 278 case 2:
276 279 __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
277 280 : "=a"(prev)
278   - : "q"(new), "m"(*__xg(ptr)), "0"(old)
  281 + : "r"(new), "m"(*__xg(ptr)), "0"(old)
279 282 : "memory");
280 283 return prev;
281 284 case 4:
282 285 __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
283 286 : "=a"(prev)
284   - : "q"(new), "m"(*__xg(ptr)), "0"(old)
  287 + : "r"(new), "m"(*__xg(ptr)), "0"(old)
285 288 : "memory");
286 289 return prev;
287 290 }
... ... @@ -291,6 +294,30 @@
291 294 #define cmpxchg(ptr,o,n)\
292 295 ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
293 296 (unsigned long)(n),sizeof(*(ptr))))
  297 +
  298 +#endif
  299 +
  300 +#ifdef CONFIG_X86_CMPXCHG64
  301 +
  302 +static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long long old,
  303 + unsigned long long new)
  304 +{
  305 + unsigned long long prev;
  306 + __asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
  307 + : "=A"(prev)
  308 + : "b"((unsigned long)new),
  309 + "c"((unsigned long)(new >> 32)),
  310 + "m"(*__xg(ptr)),
  311 + "0"(old)
  312 + : "memory");
  313 + return prev;
  314 +}
  315 +
  316 +#define cmpxchg64(ptr,o,n)\
  317 + ((__typeof__(*(ptr)))__cmpxchg64((ptr),(unsigned long long)(o),\
  318 + (unsigned long long)(n)))
  319 +
  320 +#endif
294 321  
295 322 #ifdef __KERNEL__
296 323 struct alt_instr {