Author: attilio
Date: Mon Oct 12 16:05:31 2009
New Revision: 197985
URL: http://svn.freebsd.org/changeset/base/197985

Log:
  MFC r197803, r197824, r197910:
  Per their definition, atomic instructions used in conjuction with
  memory barriers should also ensure that the compiler doesn't reorder paths
  where they are used.  GCC, however, does that aggressively, even in
  presence of volatile operands.  The most reliable way GCC offers for avoid
  instructions reordering is clobbering "memory".
  Not all our memory barriers, right now, clobber memory for GCC-like
  compilers.
  Fix these cases.
  
  Approved by:  re (kib)

Modified:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/atomic.h
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)
  stable/8/sys/i386/include/atomic.h

Modified: stable/8/sys/amd64/include/atomic.h
==============================================================================
--- stable/8/sys/amd64/include/atomic.h Mon Oct 12 15:56:27 2009        
(r197984)
+++ stable/8/sys/amd64/include/atomic.h Mon Oct 12 16:05:31 2009        
(r197985)
@@ -32,9 +32,9 @@
 #error this file needs sys/cdefs.h as a prerequisite
 #endif
 
-#define mb()   __asm__ __volatile__ ("mfence;": : :"memory")
-#define wmb()  __asm__ __volatile__ ("sfence;": : :"memory")
-#define rmb()  __asm__ __volatile__ ("lfence;": : :"memory")
+#define        mb()    __asm __volatile("mfence;" : : : "memory")
+#define        wmb()   __asm __volatile("sfence;" : : : "memory")
+#define        rmb()   __asm __volatile("lfence;" : : : "memory")
 
 /*
  * Various simple operations on memory, each of which is atomic in the
@@ -73,7 +73,8 @@
  */
 #if defined(KLD_MODULE) || !defined(__GNUCLIKE_ASM)
 #define        ATOMIC_ASM(NAME, TYPE, OP, CONS, V)                     \
-void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
+void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v); \
+void atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
 
 int    atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src);
 int    atomic_cmpset_long(volatile u_long *dst, u_long exp, u_long src);
@@ -97,8 +98,9 @@ void          atomic_store_rel_##TYPE(volatile u
 #endif
 
 /*
- * The assembly is volatilized to demark potential before-and-after side
- * effects if an interrupt or SMP collision were to occur.
+ * The assembly is volatilized to avoid code chunk removal by the compiler.
+ * GCC aggressively reorders operations and memory clobbering is necessary
+ * in order to avoid that for memory barriers.
  */
 #define        ATOMIC_ASM(NAME, TYPE, OP, CONS, V)             \
 static __inline void                                   \
@@ -108,6 +110,15 @@ atomic_##NAME##_##TYPE(volatile u_##TYPE
        : "=m" (*p)                                     \
        : CONS (V), "m" (*p));                          \
 }                                                      \
+                                                       \
+static __inline void                                   \
+atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
+{                                                      \
+       __asm __volatile(MPLOCKED OP                    \
+       : "=m" (*p)                                     \
+       : CONS (V), "m" (*p)                            \
+       : "memory");                                    \
+}                                                      \
 struct __hack
 
 /*
@@ -205,18 +216,23 @@ atomic_fetchadd_long(volatile u_long *p,
  * PentiumPro or higher, reads may pass writes, so for that case we have
  * to use a serializing instruction (i.e. with LOCK) to do the load in
  * SMP kernels.  For UP kernels, however, the cache of the single processor
- * is always consistent, so we don't need any memory barriers.
+ * is always consistent, so we only need to take care of compiler.
  */
 #define        ATOMIC_STORE_LOAD(TYPE, LOP, SOP)               \
 static __inline u_##TYPE                               \
 atomic_load_acq_##TYPE(volatile u_##TYPE *p)           \
 {                                                      \
-       return (*p);                                    \
+       u_##TYPE tmp;                                   \
+                                                       \
+       tmp = *p;                                       \
+       __asm __volatile ("" : : : "memory");           \
+       return (tmp);                                   \
 }                                                      \
                                                        \
 static __inline void                                   \
 atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
 {                                                      \
+       __asm __volatile ("" : : : "memory");           \
        *p = v;                                         \
 }                                                      \
 struct __hack
@@ -247,7 +263,8 @@ atomic_store_rel_##TYPE(volatile u_##TYP
        __asm __volatile(SOP                            \
        : "=m" (*p),                    /* 0 */         \
          "+r" (v)                      /* 1 */         \
-       : "m" (*p));                    /* 2 */         \
+       : "m" (*p)                      /* 2 */         \
+       : "memory");                                    \
 }                                                      \
 struct __hack
 
@@ -327,44 +344,43 @@ u_long    atomic_readandclear_long(volatile
 
 #endif /* __GNUCLIKE_ASM */
 
-/* Acquire and release variants are identical to the normal ones. */
-#define        atomic_set_acq_char             atomic_set_char
-#define        atomic_set_rel_char             atomic_set_char
-#define        atomic_clear_acq_char           atomic_clear_char
-#define        atomic_clear_rel_char           atomic_clear_char
-#define        atomic_add_acq_char             atomic_add_char
-#define        atomic_add_rel_char             atomic_add_char
-#define        atomic_subtract_acq_char        atomic_subtract_char
-#define        atomic_subtract_rel_char        atomic_subtract_char
-
-#define        atomic_set_acq_short            atomic_set_short
-#define        atomic_set_rel_short            atomic_set_short
-#define        atomic_clear_acq_short          atomic_clear_short
-#define        atomic_clear_rel_short          atomic_clear_short
-#define        atomic_add_acq_short            atomic_add_short
-#define        atomic_add_rel_short            atomic_add_short
-#define        atomic_subtract_acq_short       atomic_subtract_short
-#define        atomic_subtract_rel_short       atomic_subtract_short
-
-#define        atomic_set_acq_int              atomic_set_int
-#define        atomic_set_rel_int              atomic_set_int
-#define        atomic_clear_acq_int            atomic_clear_int
-#define        atomic_clear_rel_int            atomic_clear_int
-#define        atomic_add_acq_int              atomic_add_int
-#define        atomic_add_rel_int              atomic_add_int
-#define        atomic_subtract_acq_int         atomic_subtract_int
-#define        atomic_subtract_rel_int         atomic_subtract_int
+#define        atomic_set_acq_char             atomic_set_barr_char
+#define        atomic_set_rel_char             atomic_set_barr_char
+#define        atomic_clear_acq_char           atomic_clear_barr_char
+#define        atomic_clear_rel_char           atomic_clear_barr_char
+#define        atomic_add_acq_char             atomic_add_barr_char
+#define        atomic_add_rel_char             atomic_add_barr_char
+#define        atomic_subtract_acq_char        atomic_subtract_barr_char
+#define        atomic_subtract_rel_char        atomic_subtract_barr_char
+
+#define        atomic_set_acq_short            atomic_set_barr_short
+#define        atomic_set_rel_short            atomic_set_barr_short
+#define        atomic_clear_acq_short          atomic_clear_barr_short
+#define        atomic_clear_rel_short          atomic_clear_barr_short
+#define        atomic_add_acq_short            atomic_add_barr_short
+#define        atomic_add_rel_short            atomic_add_barr_short
+#define        atomic_subtract_acq_short       atomic_subtract_barr_short
+#define        atomic_subtract_rel_short       atomic_subtract_barr_short
+
+#define        atomic_set_acq_int              atomic_set_barr_int
+#define        atomic_set_rel_int              atomic_set_barr_int
+#define        atomic_clear_acq_int            atomic_clear_barr_int
+#define        atomic_clear_rel_int            atomic_clear_barr_int
+#define        atomic_add_acq_int              atomic_add_barr_int
+#define        atomic_add_rel_int              atomic_add_barr_int
+#define        atomic_subtract_acq_int         atomic_subtract_barr_int
+#define        atomic_subtract_rel_int         atomic_subtract_barr_int
 #define        atomic_cmpset_acq_int           atomic_cmpset_int
 #define        atomic_cmpset_rel_int           atomic_cmpset_int
 
-#define        atomic_set_acq_long             atomic_set_long
-#define        atomic_set_rel_long             atomic_set_long
-#define        atomic_clear_acq_long           atomic_clear_long
-#define        atomic_clear_rel_long           atomic_clear_long
-#define        atomic_add_acq_long             atomic_add_long
-#define        atomic_add_rel_long             atomic_add_long
-#define        atomic_subtract_acq_long        atomic_subtract_long
-#define        atomic_subtract_rel_long        atomic_subtract_long
+#define        atomic_set_acq_long             atomic_set_barr_long
+#define        atomic_set_rel_long             atomic_set_barr_long
+#define        atomic_clear_acq_long           atomic_clear_barr_long
+#define        atomic_clear_rel_long           atomic_clear_barr_long
+#define        atomic_add_acq_long             atomic_add_barr_long
+#define        atomic_add_rel_long             atomic_add_barr_long
+#define        atomic_subtract_acq_long        atomic_subtract_barr_long
+#define        atomic_subtract_rel_long        atomic_subtract_barr_long
 #define        atomic_cmpset_acq_long          atomic_cmpset_long
 #define        atomic_cmpset_rel_long          atomic_cmpset_long
 

Modified: stable/8/sys/i386/include/atomic.h
==============================================================================
--- stable/8/sys/i386/include/atomic.h  Mon Oct 12 15:56:27 2009        
(r197984)
+++ stable/8/sys/i386/include/atomic.h  Mon Oct 12 16:05:31 2009        
(r197985)
@@ -73,7 +73,8 @@
  */
 #if defined(KLD_MODULE) || !defined(__GNUCLIKE_ASM)
 #define        ATOMIC_ASM(NAME, TYPE, OP, CONS, V)                     \
-void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
+void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v); \
+void atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
 
 int    atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src);
 u_int  atomic_fetchadd_int(volatile u_int *p, u_int v);
@@ -95,8 +96,9 @@ void          atomic_store_rel_##TYPE(volatile u
 #endif
 
 /*
- * The assembly is volatilized to demark potential before-and-after side
- * effects if an interrupt or SMP collision were to occur.
+ * The assembly is volatilized to avoid code chunk removal by the compiler.
+ * GCC aggressively reorders operations and memory clobbering is necessary
+ * in order to avoid that for memory barriers.
  */
 #define        ATOMIC_ASM(NAME, TYPE, OP, CONS, V)             \
 static __inline void                                   \
@@ -106,6 +108,15 @@ atomic_##NAME##_##TYPE(volatile u_##TYPE
        : "=m" (*p)                                     \
        : CONS (V), "m" (*p));                          \
 }                                                      \
+                                                       \
+static __inline void                                   \
+atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
+{                                                      \
+       __asm __volatile(MPLOCKED OP                    \
+       : "=m" (*p)                                     \
+       : CONS (V), "m" (*p)                            \
+       : "memory");                                    \
+}                                                      \
 struct __hack
 
 /*
@@ -194,18 +205,23 @@ atomic_fetchadd_int(volatile u_int *p, u
  * PentiumPro or higher, reads may pass writes, so for that case we have
  * to use a serializing instruction (i.e. with LOCK) to do the load in
  * SMP kernels.  For UP kernels, however, the cache of the single processor
- * is always consistent, so we don't need any memory barriers.
+ * is always consistent, so we only need to take care of compiler.
  */
 #define        ATOMIC_STORE_LOAD(TYPE, LOP, SOP)               \
 static __inline u_##TYPE                               \
 atomic_load_acq_##TYPE(volatile u_##TYPE *p)           \
 {                                                      \
-       return (*p);                                    \
+       u_##TYPE tmp;                                   \
+                                                       \
+       tmp = *p;                                       \
+       __asm __volatile("" : : : "memory");            \
+       return (tmp);                                   \
 }                                                      \
                                                        \
 static __inline void                                   \
 atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
 {                                                      \
+       __asm __volatile("" : : : "memory");            \
        *p = v;                                         \
 }                                                      \
 struct __hack
@@ -236,7 +252,8 @@ atomic_store_rel_##TYPE(volatile u_##TYP
        __asm __volatile(SOP                            \
        : "=m" (*p),                    /* 0 */         \
          "+r" (v)                      /* 1 */         \
-       : "m" (*p));                    /* 2 */         \
+       : "m" (*p)                      /* 2 */         \
+       : "memory");                                    \
 }                                                      \
 struct __hack
 
@@ -331,44 +348,43 @@ u_long    atomic_readandclear_long(volatile
 
 #endif /* __GNUCLIKE_ASM */
 
-/* Acquire and release variants are identical to the normal ones. */
-#define        atomic_set_acq_char             atomic_set_char
-#define        atomic_set_rel_char             atomic_set_char
-#define        atomic_clear_acq_char           atomic_clear_char
-#define        atomic_clear_rel_char           atomic_clear_char
-#define        atomic_add_acq_char             atomic_add_char
-#define        atomic_add_rel_char             atomic_add_char
-#define        atomic_subtract_acq_char        atomic_subtract_char
-#define        atomic_subtract_rel_char        atomic_subtract_char
-
-#define        atomic_set_acq_short            atomic_set_short
-#define        atomic_set_rel_short            atomic_set_short
-#define        atomic_clear_acq_short          atomic_clear_short
-#define        atomic_clear_rel_short          atomic_clear_short
-#define        atomic_add_acq_short            atomic_add_short
-#define        atomic_add_rel_short            atomic_add_short
-#define        atomic_subtract_acq_short       atomic_subtract_short
-#define        atomic_subtract_rel_short       atomic_subtract_short
-
-#define        atomic_set_acq_int              atomic_set_int
-#define        atomic_set_rel_int              atomic_set_int
-#define        atomic_clear_acq_int            atomic_clear_int
-#define        atomic_clear_rel_int            atomic_clear_int
-#define        atomic_add_acq_int              atomic_add_int
-#define        atomic_add_rel_int              atomic_add_int
-#define        atomic_subtract_acq_int         atomic_subtract_int
-#define        atomic_subtract_rel_int         atomic_subtract_int
+#define        atomic_set_acq_char             atomic_set_barr_char
+#define        atomic_set_rel_char             atomic_set_barr_char
+#define        atomic_clear_acq_char           atomic_clear_barr_char
+#define        atomic_clear_rel_char           atomic_clear_barr_char
+#define        atomic_add_acq_char             atomic_add_barr_char
+#define        atomic_add_rel_char             atomic_add_barr_char
+#define        atomic_subtract_acq_char        atomic_subtract_barr_char
+#define        atomic_subtract_rel_char        atomic_subtract_barr_char
+
+#define        atomic_set_acq_short            atomic_set_barr_short
+#define        atomic_set_rel_short            atomic_set_barr_short
+#define        atomic_clear_acq_short          atomic_clear_barr_short
+#define        atomic_clear_rel_short          atomic_clear_barr_short
+#define        atomic_add_acq_short            atomic_add_barr_short
+#define        atomic_add_rel_short            atomic_add_barr_short
+#define        atomic_subtract_acq_short       atomic_subtract_barr_short
+#define        atomic_subtract_rel_short       atomic_subtract_barr_short
+
+#define        atomic_set_acq_int              atomic_set_barr_int
+#define        atomic_set_rel_int              atomic_set_barr_int
+#define        atomic_clear_acq_int            atomic_clear_barr_int
+#define        atomic_clear_rel_int            atomic_clear_barr_int
+#define        atomic_add_acq_int              atomic_add_barr_int
+#define        atomic_add_rel_int              atomic_add_barr_int
+#define        atomic_subtract_acq_int         atomic_subtract_barr_int
+#define        atomic_subtract_rel_int         atomic_subtract_barr_int
 #define        atomic_cmpset_acq_int           atomic_cmpset_int
 #define        atomic_cmpset_rel_int           atomic_cmpset_int
 
-#define        atomic_set_acq_long             atomic_set_long
-#define        atomic_set_rel_long             atomic_set_long
-#define        atomic_clear_acq_long           atomic_clear_long
-#define        atomic_clear_rel_long           atomic_clear_long
-#define        atomic_add_acq_long             atomic_add_long
-#define        atomic_add_rel_long             atomic_add_long
-#define        atomic_subtract_acq_long        atomic_subtract_long
-#define        atomic_subtract_rel_long        atomic_subtract_long
+#define        atomic_set_acq_long             atomic_set_barr_long
+#define        atomic_set_rel_long             atomic_set_barr_long
+#define        atomic_clear_acq_long           atomic_clear_barr_long
+#define        atomic_clear_rel_long           atomic_clear_barr_long
+#define        atomic_add_acq_long             atomic_add_barr_long
+#define        atomic_add_rel_long             atomic_add_barr_long
+#define        atomic_subtract_acq_long        atomic_subtract_barr_long
+#define        atomic_subtract_rel_long        atomic_subtract_barr_long
 #define        atomic_cmpset_acq_long          atomic_cmpset_long
 #define        atomic_cmpset_rel_long          atomic_cmpset_long
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to