[glib] Improve atomic ops implementation



commit dec7d41275b025e94beb16f656ce0db70286469f
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun May 22 16:31:43 2011 -0400

    Improve atomic ops implementation
    
    When using gcc builtins for atomic operations, provide them
    as macros, so gcc can see the builtins and do optimizations.
    This change gives considerable speedups in bitlocks, which
    use atomic operations heavily, see bug 650458.
    
    Also, don't define G_ATOMIC_OP_MEMORY_BARRIER_NEEDED unconditionally
    when using gcc builtins.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=617491

 configure.ac       |   12 ++++++------
 glib/gatomic-gcc.c |   40 ++++++++++++++++++++++++++++------------
 glib/gatomic.h     |   32 +++++++++++++++++++++++++++++++-
 3 files changed, 65 insertions(+), 19 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 8fda196..bb0a795 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2468,9 +2468,6 @@ if test x"$GCC" = xyes; then
 	      [glib_cv_gcc_has_builtin_atomic_operations=no])
 
   AC_MSG_RESULT($glib_cv_gcc_has_builtin_atomic_operations)
-  if test $glib_cv_gcc_has_builtin_atomic_operations = yes; then
-    glib_memory_barrier_needed=yes
-  else
     case $host_cpu in
       i386)
         AC_MSG_RESULT([none])
@@ -2567,7 +2564,6 @@ if test x"$GCC" = xyes; then
         glib_memory_barrier_needed=yes
         ;;
     esac
-  fi
 else
   if test $glib_native_win32 = yes; then
     # For Windows but not using gcc. No barriers needed then either.
@@ -2590,7 +2586,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
 int
 main (void)
 {
-  /* not like this actually runs or anything... */
+  /* it is not like this actually runs or anything... */
   syscall (SYS_futex, NULL, FUTEX_WAKE, FUTEX_WAIT);
   return 0;
 }
@@ -3257,7 +3253,10 @@ _______EOF
 	  echo >>$outfile
 	  echo "#define G_ATOMIC_OP_MEMORY_BARRIER_NEEDED 1" >>$outfile
 	fi
-
+	if test x"$g_gcc_atomic_ops" != xno; then
+          echo >>$outfile
+          echo "#define G_ATOMIC_OP_USE_GCC_BUILTINS 1" >>$outfile
+        fi
 	echo >>$outfile
 	g_bit_sizes="16 32 64"
 	for bits in $g_bit_sizes; do
@@ -3634,6 +3633,7 @@ g_system_thread_sizeof="$glib_cv_sizeof_system_thread"
 g_mutex_contents="$glib_cv_byte_contents_gmutex"
 
 g_memory_barrier_needed="$glib_memory_barrier_needed"
+g_gcc_atomic_ops="$glib_cv_gcc_has_builtin_atomic_operations"
 
 g_module_suffix="$glib_gmodule_suffix"
 
diff --git a/glib/gatomic-gcc.c b/glib/gatomic-gcc.c
index 9f28cee..09cd3aa 100644
--- a/glib/gatomic-gcc.c
+++ b/glib/gatomic-gcc.c
@@ -22,32 +22,48 @@
 
 #include "gatomic.h"
 
+/* All atomic operations are available as macros evaluating
+ * to gcc builtins (when using gcc builtins for atomic operations).
+ * For ABI stability, we provide functions for them too.
+ *
+ * To avoid interference, undefine the macros first.
+ */
+
+#undef g_atomic_int_exchange_and_add
+#undef g_atomic_int_compare_and_exchange
+#undef g_atomic_int_add
+#undef g_atomic_int_get
+#undef g_atomic_int_set
+#undef g_atomic_pointer_compare_and_exchange
+#undef g_atomic_pointer_get
+#undef g_atomic_pointer_set
+
 gint
 g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
-			       gint           val)
+                               gint                            val)
 {
   return __sync_fetch_and_add (atomic, val);
 }
 
 void
 g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
-		  gint val)
+                  gint                            val)
 {
   __sync_fetch_and_add (atomic, val);
 }
 
 gboolean
 g_atomic_int_compare_and_exchange (volatile gint G_GNUC_MAY_ALIAS *atomic,
-				   gint           oldval,
-				   gint           newval)
+                                   gint                            oldval,
+                                   gint                            newval)
 {
   return __sync_bool_compare_and_swap (atomic, oldval, newval);
 }
 
 gboolean
 g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-				       gpointer           oldval,
-				       gpointer           newval)
+                                       gpointer                            oldval,
+                                       gpointer                            newval)
 {
   return __sync_bool_compare_and_swap (atomic, oldval, newval);
 }
@@ -58,30 +74,30 @@ _g_atomic_thread_init (void)
 }
 
 gint
-(g_atomic_int_get) (volatile gint G_GNUC_MAY_ALIAS *atomic)
+g_atomic_int_get (volatile gint G_GNUC_MAY_ALIAS *atomic)
 {
   __sync_synchronize ();
   return *atomic;
 }
 
 void
-(g_atomic_int_set) (volatile gint G_GNUC_MAY_ALIAS *atomic,
-		    gint           newval)
+g_atomic_int_set (volatile gint G_GNUC_MAY_ALIAS *atomic,
+                  gint                            newval)
 {
   *atomic = newval;
   __sync_synchronize ();
 }
 
 gpointer
-(g_atomic_pointer_get) (volatile gpointer G_GNUC_MAY_ALIAS *atomic)
+g_atomic_pointer_get (volatile gpointer G_GNUC_MAY_ALIAS *atomic)
 {
   __sync_synchronize ();
   return *atomic;
 }
 
 void
-(g_atomic_pointer_set) (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-			gpointer           newval)
+g_atomic_pointer_set (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
+                      gpointer                            newval)
 {
   *atomic = newval;
   __sync_synchronize ();
diff --git a/glib/gatomic.h b/glib/gatomic.h
index ddd39b8..969443a 100644
--- a/glib/gatomic.h
+++ b/glib/gatomic.h
@@ -56,12 +56,41 @@ gpointer g_atomic_pointer_get                  (volatile gpointer G_GNUC_MAY_ALI
 void     g_atomic_pointer_set                  (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
 						gpointer           newval);
 
-#ifndef G_ATOMIC_OP_MEMORY_BARRIER_NEEDED
+#if defined(__GNUC__) && defined(G_ATOMIC_OP_USE_GCC_BUILTINS)
+
+#define g_atomic_int_exchange_and_add(atomic,val) \
+  __sync_fetch_and_add((atomic),(val))
+
+#define g_atomic_int_add(atomic,val) \
+  __sync_fetch_and_add((atomic),(val))
+
+#define g_atomic_int_compare_and_exchange(atomic,oldval,newval) \
+  __sync_bool_compare_and_swap((atomic),(oldval),(newval))
+
+#define g_atomic_int_get(atomic) \
+  __extension__ ({ __sync_synchronize(); *(atomic); })
+
+#define g_atomic_int_set(atomic,newval) \
+  __extension__ ({ *(atomic) = (newval); __sync_synchronize(); })
+
+#define g_atomic_pointer_compare_and_exchange(atomic,oldval,newval) \
+  __sync_bool_compare_and_swap((atomic),(oldval),(newval))
+
+#define g_atomic_pointer_get(atomic) \
+  __extension__ ({ __sync_synchronize(); *(atomic); })
+
+#define g_atomic_pointer_set(atomic,newval) \
+  __extension__ ({ *(atomic) = (newval); __sync_synchronize(); })
+
+#elif !defined(G_ATOMIC_OP_MEMORY_BARRIER_NEEDED)
+
 # define g_atomic_int_get(atomic) 		((gint)*(atomic))
 # define g_atomic_int_set(atomic, newval) 	((void) (*(atomic) = (newval)))
 # define g_atomic_pointer_get(atomic) 		((gpointer)*(atomic))
 # define g_atomic_pointer_set(atomic, newval)	((void) (*(atomic) = (newval)))
+
 #else
+
 # define g_atomic_int_get(atomic) \
  ((void) sizeof (gchar [sizeof (*(atomic)) == sizeof (gint) ? 1 : -1]), \
   (g_atomic_int_get) ((volatile gint G_GNUC_MAY_ALIAS *) (volatile void *) (atomic)))
@@ -74,6 +103,7 @@ void     g_atomic_pointer_set                  (volatile gpointer G_GNUC_MAY_ALI
 # define g_atomic_pointer_set(atomic, newval) \
  ((void) sizeof (gchar [sizeof (*(atomic)) == sizeof (gpointer) ? 1 : -1]), \
   (g_atomic_pointer_set) ((volatile gpointer G_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (newval)))
+
 #endif /* G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */
 
 /**



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]