aboutsummaryrefslogtreecommitdiffstats
path: root/xen/include/asm-x86/system.h
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-05-25 13:07:42 +0000
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-05-25 13:07:42 +0000
commite69550b83aef6e4cb61602239cde612355d3d27c (patch)
tree16246d73f19b302545bbcc9e45fe69e88c8a8936 /xen/include/asm-x86/system.h
parent28d92ab92e4f70afd59b0a90ccb6564313d9b802 (diff)
downloadxen-e69550b83aef6e4cb61602239cde612355d3d27c.tar.gz
xen-e69550b83aef6e4cb61602239cde612355d3d27c.tar.bz2
xen-e69550b83aef6e4cb61602239cde612355d3d27c.zip
bitkeeper revision 1.1551 (4294789ea5Ghsn6s5aIMFHK5LY4uSw)
Add 64-bit (cmpxchg8b) support to the cmpxchg() macro for x86_32. Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'xen/include/asm-x86/system.h')
-rw-r--r--xen/include/asm-x86/system.h51
1 files changed, 46 insertions, 5 deletions
diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h
index cd0619008d..a614d11b4a 100644
--- a/xen/include/asm-x86/system.h
+++ b/xen/include/asm-x86/system.h
@@ -2,6 +2,7 @@
#define __ASM_SYSTEM_H
#include <xen/config.h>
+#include <xen/types.h>
#include <asm/bitops.h>
/* Clear and set 'TS' bit respectively */
@@ -70,8 +71,8 @@ static always_inline unsigned long __xchg(unsigned long x, volatile void * ptr,
* indicated by comparing RETURN with OLD.
*/
-static always_inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
- unsigned long new, int size)
+static always_inline unsigned long __cmpxchg(
+ volatile void *ptr, unsigned long old, unsigned long new, int size)
{
unsigned long prev;
switch (size) {
@@ -113,9 +114,49 @@ static always_inline unsigned long __cmpxchg(volatile void *ptr, unsigned long o
}
#define __HAVE_ARCH_CMPXCHG
-#define cmpxchg(ptr,o,n)\
- ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
- (unsigned long)(n),sizeof(*(ptr))))
+
+#if BITS_PER_LONG == 64
+
+#define cmpxchg(ptr,o,n) \
+ ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o), \
+ (unsigned long)(n),sizeof(*(ptr))))
+#else
+
+static always_inline unsigned long long __cmpxchg8b(
+ volatile void *ptr, unsigned long long old, unsigned long long new)
+{
+ unsigned long long prev;
+ __asm__ __volatile__ (
+ LOCK_PREFIX "cmpxchg8b %3"
+ : "=A" (prev)
+ : "c" ((u32)(new>>32)), "b" ((u32)new),
+ "m" (*__xg((volatile void *)ptr)), "0" (old)
+ : "memory" );
+ return prev;
+}
+
+#define cmpxchg(ptr,o,n) \
+({ \
+ __typeof__(*(ptr)) __prev; \
+ switch ( sizeof(*(ptr)) ) { \
+ case 8: \
+ __prev = ((__typeof__(*(ptr)))__cmpxchg8b( \
+ (ptr), \
+ (unsigned long long)(o), \
+ (unsigned long long)(n))); \
+ break; \
+ default: \
+ __prev = ((__typeof__(*(ptr)))__cmpxchg( \
+ (ptr), \
+ (unsigned long)(o), \
+ (unsigned long)(n), \
+ sizeof(*(ptr)))); \
+ break; \
+ } \
+ __prev; \
+})
+
+#endif
/*