[PATCH] Rework write_/mem_barrier() macro definitions
Matt Turner
mattst88 at gmail.com
Tue Aug 4 14:13:06 PDT 2009
Also (1) Use {s,m}fence on AMD64
(2) Clean ups
Signed-off-by: Matt Turner <mattst88 at gmail.com>
---
hw/xfree86/common/compiler.h | 134 ++++++++++++++++++++++++------------------
1 files changed, 77 insertions(+), 57 deletions(-)
diff --git a/hw/xfree86/common/compiler.h b/hw/xfree86/common/compiler.h
index 2ef95d8..72e1fe6 100644
--- a/hw/xfree86/common/compiler.h
+++ b/hw/xfree86/common/compiler.h
@@ -84,7 +84,79 @@
# define __FUNCTION__ __func__ /* C99 */
#endif
-# if defined(NO_INLINE) || defined(DO_PROTOTYPES)
+# ifndef NO_INLINE /* XXX: why can't NO_INLINE be defined? */
+# ifdef __GNUC__
+ /* DEC Alpha and (Linux or BSD) */
+# if defined(__alpha__) && (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))
+# define mem_barrier() __asm__ __volatile__("mb" :::"memory")
+# define write_mem_barrier() __asm__ __volatile__("wmb":::"memory")
+
+ /* IA64 and Linux */ /* XXX: no BSD? */
+# elif defined(__ia64__) && defined(linux)
+# ifndef __INTEL_COMPILER
+# define mem_barrier() __asm__ __volatile__("mf":::"memory")
+# else
+# include "ia64intrin.h"
+# define mem_barrier() __mf()
+# endif
+
+ /* AMD64 and (Linux or FreeBSD) */ /* XXX: no Open or Net BSD? */
+# elif defined(__amd64__) && (defined(linux) || defined(__FreeBSD__))
+# define mem_barrier() __asm__ __volatile__("mfence":::"memory")
+# define write_ mem_barrier() __asm__ __volatile__("sfence":::"memory")
+
+ /* x86 and (Linux or FreeBSD */ /* XXX: check on Open/Net BSDs */
+# elif defined(__i386__) && (defined(linux) || defined(__FreeBSD__))
+ /* XXX: mfence is better for mem_barrier() on CPUs with SSE2 support */
+# define mem_barrier() \
+ __asm__ __volatile__("lock; addl $0,0(%%esp)":::"memory")
+ /* XXX: write_mem_barrier() can either be the lock; addl sequence,
+ * or preferably (on CPUs with SSE) sfence */
+
+ /* SPARC and (Linux or Sun or OpenBSD or FreeBSD) */ /* XXX: no NetBSD? */ /* XXX: what is sun? */
+# elif defined(__sparc__) && (defined(linux) || defined(sun) || defined(__OpenBSD__) || defined(__FreeBSD__))
+# define barrier() __asm__ __volatile__(".word 0x8143e00a":::"memory") /* XXX: WTF is this? */
+
+ /* MIPS and Linux */ /* XXX: what about BSDs? */
+# elif defined(__mips__) && defined(__linux__)
+ /* XXX: this seems like a hilariously bad idea... */
+ /* XXX: what about the MIPS III 'sync' instruction? */
+# define mem_barrier() \
+ __asm__ __volatile__( \
+ "# prevent instructions being moved around\n\t" \
+ ".set\tnoreorder\n\t" \
+ "# 8 nops to fool the R4400 pipeline\n\t" \
+ "nop;nop;nop;nop;nop;nop;nop;nop\n\t" \
+ ".set\treorder" \
+ : /* no output */ \
+ : /* no input */ \
+ : "memory")
+
+ /* PowerPC and (Linux or BSD) */
+# elif defined(__powerpc__) && (defined(linux) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__))
+ /* XXX: eieio never mentioned before this, following comment is bogus, so
+ * what are we missing? */
+# ifndef eieio /* We deal with arch-specific eieio() routines above... */
+# define eieio() __asm__ __volatile__("eieio":::"memory")
+# endif /* eieio */
+ /* XXX: any reason we can't rename eieio() mem_barrier() to match others? */
+# define mem_barrier() eieio()
+# endif
+# endif /* __GNUC__ */
+# endif /* NO_INLINE */
+
+/* If we haven't defined an architecture-specific mem_barrier() yet,
+ * then define it as a no-op */
+# ifndef mem_barrier()
+# define mem_barrier() /* NOP */
+# endif
+
+/* If we haven't defined an architecture-specific write_mem_barrier() yet,
+ * assume it is the same as mem_barrier(), which has the side effect that
+ * if neither are defined, then both will be no-ops */
+# ifndef write_mem_barrier()
+# define write_mem_barrier() mem_barrier()
+# endif
# if !defined(__arm__)
# if !defined(__sparc__) && !defined(__sparc) && !defined(__arm32__) \
@@ -357,9 +429,6 @@ static __inline__ void stw_u(unsigned long r5, unsigned short * r11)
# endif
}
-# define mem_barrier() __asm__ __volatile__("mb" : : : "memory")
-# define write_mem_barrier() __asm__ __volatile__("wmb" : : : "memory")
-
# elif defined(linux) && defined(__ia64__)
# include <inttypes.h>
@@ -419,15 +488,6 @@ __ustw (unsigned long r5, unsigned short * r11)
# define stl_u(v,p) __ustl(v,p)
# define stw_u(v,p) __ustw(v,p)
-# ifndef __INTEL_COMPILER
-# define mem_barrier() __asm__ __volatile__ ("mf" ::: "memory")
-# define write_mem_barrier() __asm__ __volatile__ ("mf" ::: "memory")
-# else
-# include "ia64intrin.h"
-# define mem_barrier() __mf()
-# define write_mem_barrier() __mf()
-# endif
-
/*
* This is overkill, but for different reasons depending on where it is used.
* This is thus general enough to be used everywhere cache flushes are needed.
@@ -473,12 +533,6 @@ extern _X_EXPORT unsigned int inl(unsigned long port);
# define stl_u(v,p) (*(unsigned int *)(p)) = (v)
# define stw_u(v,p) (*(unsigned short *)(p)) = (v)
-# define mem_barrier() \
- __asm__ __volatile__ ("lock; addl $0,0(%%rsp)": : :"memory")
-# define write_mem_barrier() \
- __asm__ __volatile__ ("": : :"memory")
-
-
static __inline__ void
outb(unsigned short port, unsigned char val)
{
@@ -530,11 +584,9 @@ inl(unsigned short port)
# elif (defined(linux) || defined(sun) || defined(__OpenBSD__) || defined(__FreeBSD__)) && defined(__sparc__)
-# ifndef ASI_PL
-# define ASI_PL 0x88
-# endif
-
-# define barrier() __asm__ __volatile__(".word 0x8143e00a": : :"memory")
+# ifndef ASI_PL
+# define ASI_PL 0x88
+# endif
static __inline__ void
outb(unsigned long port, unsigned char val)
@@ -857,9 +909,6 @@ static __inline__ void stw_u(unsigned long val, unsigned short *p)
# endif
}
-# define mem_barrier() /* XXX: nop for now */
-# define write_mem_barrier() /* XXX: nop for now */
-
# elif defined(__mips__) || (defined(__arm32__) && !defined(__linux__))
# ifdef __arm32__
# define PORT_SIZE long
@@ -905,7 +954,6 @@ inl(unsigned PORT_SIZE port)
return *(volatile unsigned int*)(((unsigned PORT_SIZE)(port))+IOPortBase);
}
-
# if defined(__mips__)
static __inline__ unsigned long ldq_u(unsigned long * r11)
{
@@ -991,18 +1039,6 @@ xf86WriteMmio32Be(__volatile__ void *base, const unsigned long offset,
}
# endif
-# define mem_barrier() \
- __asm__ __volatile__( \
- "# prevent instructions being moved around\n\t" \
- ".set\tnoreorder\n\t" \
- "# 8 nops to fool the R4400 pipeline\n\t" \
- "nop;nop;nop;nop;nop;nop;nop;nop\n\t" \
- ".set\treorder" \
- : /* no output */ \
- : /* no input */ \
- : "memory")
-# define write_mem_barrier() mem_barrier()
-
# else /* !linux */
# define stq_u(v,p) stl_u(v,p)
@@ -1013,8 +1049,6 @@ xf86WriteMmio32Be(__volatile__ void *base, const unsigned long offset,
# define stw_u(v,p) (*(unsigned char *)(p)) = (v); \
(*(unsigned char *)(p)+1) = ((v) >> 8)
-
-# define mem_barrier() /* NOP */
# endif /* !linux */
# endif /* __mips__ */
@@ -1025,8 +1059,6 @@ xf86WriteMmio32Be(__volatile__ void *base, const unsigned long offset,
# define stq_u(v,p) (*(unsigned long *)(p)) = (v)
# define stl_u(v,p) (*(unsigned int *)(p)) = (v)
# define stw_u(v,p) (*(unsigned short *)(p)) = (v)
-# define mem_barrier() /* NOP */
-# define write_mem_barrier() /* NOP */
# endif /* __arm32__ */
# elif (defined(linux) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)) && defined(__powerpc__)
@@ -1043,9 +1075,6 @@ extern _X_EXPORT volatile unsigned char *ioBase;
# include <asm/memory.h>
# endif
#endif /* defined(linux) && defined(__powerpc64__) */
-#ifndef eieio /* We deal with arch-specific eieio() routines above... */
-# define eieio() __asm__ __volatile__ ("eieio" ::: "memory")
-#endif /* eieio */
static __inline__ unsigned char
xf86ReadMmio8(__volatile__ void *base, const unsigned long offset)
@@ -1261,9 +1290,6 @@ inl(unsigned short port)
# define stw_u(v,p) (*(unsigned char *)(p)) = (v); \
(*((unsigned char *)(p)+1)) = ((v) >> 8)
-# define mem_barrier() eieio()
-# define write_mem_barrier() eieio()
-
#elif defined(__arm__) && defined(__linux__)
#define ldq_u(p) (*((unsigned long *)(p)))
@@ -1272,8 +1298,6 @@ inl(unsigned short port)
#define stq_u(v,p) (*(unsigned long *)(p)) = (v)
#define stl_u(v,p) (*(unsigned int *)(p)) = (v)
#define stw_u(v,p) (*(unsigned short *)(p)) = (v)
-#define mem_barrier() /* NOP */
-#define write_mem_barrier() /* NOP */
/* for Linux on ARM, we use the LIBC inx/outx routines */
/* note that the appropriate setup via "ioperm" needs to be done */
@@ -1321,8 +1345,6 @@ do { \
# define stq_u(v,p) (*(unsigned long *)(p)) = (v)
# define stl_u(v,p) (*(unsigned int *)(p)) = (v)
# define stw_u(v,p) (*(unsigned short *)(p)) = (v)
-# define mem_barrier() /* NOP */
-# define write_mem_barrier() /* NOP */
# if !defined(__SUNPRO_C)
# if !defined(FAKEIT) && !defined(__mc68000__) && !defined(__arm__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__m32r__)
@@ -1511,8 +1533,6 @@ inl(unsigned short port)
# define stq_u(v,p) (*(unsigned long *)(p)) = (v)
# define stl_u(v,p) (*(unsigned int *)(p)) = (v)
# define stw_u(v,p) (*(unsigned short *)(p)) = (v)
-# define mem_barrier() /* NOP */
-# define write_mem_barrier() /* NOP */
# endif /* __GNUC__ */
# endif /* NO_INLINE */
@@ -1528,7 +1548,7 @@ extern _X_EXPORT int (*xf86ReadMmio32)(void *, unsigned long);
static __inline__ int
xf86ReadMmio32(void *Base, unsigned long Offset)
{
- __asm__ __volatile__("mb" : : : "memory");
+ mem_barrier();
return *(volatile unsigned int*)((unsigned long)Base+(Offset));
}
# endif
--
1.6.0.6
More information about the xorg-devel
mailing list