[glib] Use GCC atomic builtin operations.



commit 37716bd00a7911de545ebca3dc7a248503eaf46e
Author: Hiroyuki Ikezoe <poincare ikezoe net>
Date:   Thu Jan 7 19:33:39 2010 +0900

    Use GCC atomic builtin operations.
    
    Fix for bug #531902.

 configure.in       |  211 ++++++++++++++++++++++++++++------------------------
 glib/Makefile.am   |    8 ++-
 glib/gatomic-gcc.c |   92 +++++++++++++++++++++++
 3 files changed, 214 insertions(+), 97 deletions(-)
---
diff --git a/configure.in b/configure.in
index edc4142..8221911 100644
--- a/configure.in
+++ b/configure.in
@@ -2412,103 +2412,119 @@ dnl ********************************
 
 AC_MSG_CHECKING([whether to use assembler code for atomic operations])
 
+glib_cv_gcc_has_builtin_atomic_operations=no
 if test x"$GCC" = xyes; then
-  case $host_cpu in
-    i386)
-      AC_MSG_RESULT([none])
-      glib_memory_barrier_needed=no
-      ;;
-    i?86)
-      AC_MSG_RESULT([i486])
-      AC_DEFINE_UNQUOTED(G_ATOMIC_I486, 1,
-		   	 [i486 atomic implementation])
-      glib_memory_barrier_needed=no
-      ;;
-    sparc*)
-      SPARCV9_WARNING="Try to rerun configure with CFLAGS='-mcpu=v9',
-		when you are using a sparc with v9 instruction set (most
-		sparcs nowadays). This will make the code for atomic
-		operations much faster.	The resulting code will not run
-		on very old sparcs though."
-
-      AC_LINK_IFELSE([[
-        main () 
-        {
-	  int tmp1, tmp2, tmp3;
-          __asm__ __volatile__("casx [%2], %0, %1" 
-	                       : "=&r" (tmp1), "=&r" (tmp2) : "r" (&tmp3));
-        }]],
-	AC_MSG_RESULT([sparcv9])
-        AC_DEFINE_UNQUOTED(G_ATOMIC_SPARCV9, 1,
-		   	   [sparcv9 atomic implementation]),
-	AC_MSG_RESULT([no])
-        AC_MSG_WARN([[$SPARCV9_WARNING]]))
-      glib_memory_barrier_needed=yes
-      ;;
-    alpha*)
-      AC_MSG_RESULT([alpha])
-      AC_DEFINE_UNQUOTED(G_ATOMIC_ALPHA, 1,
-		   	 [alpha atomic implementation])
-      glib_memory_barrier_needed=yes
-      ;;
-    x86_64)
-      AC_MSG_RESULT([x86_64])
-      AC_DEFINE_UNQUOTED(G_ATOMIC_X86_64, 1,
-		   	 [x86_64 atomic implementation])
-      glib_memory_barrier_needed=no
-     ;;
-    powerpc*)
-      AC_MSG_RESULT([powerpc])
-      AC_DEFINE_UNQUOTED(G_ATOMIC_POWERPC, 1,
-		   	 [powerpc atomic implementation])
-      glib_memory_barrier_needed=yes
-      AC_MSG_CHECKING([whether asm supports numbered local labels])
-      AC_TRY_COMPILE(
-		,[ 
-			__asm__ __volatile__ ("1:       nop\n"
-					      "         bne-    1b")
-		],[
-			AC_DEFINE_UNQUOTED(ASM_NUMERIC_LABELS, 1, [define if asm blocks can use numeric local labels])
-			AC_MSG_RESULT([yes])
-		],[
-			AC_MSG_RESULT([no])
-		])
-      ;;	
-    ia64)
-      AC_MSG_RESULT([ia64])
-      AC_DEFINE_UNQUOTED(G_ATOMIC_IA64, 1,
-		   	 [ia64 atomic implementation])
-      glib_memory_barrier_needed=yes
-      ;;	
-    s390|s390x)
-      AC_MSG_RESULT([s390])
-      AC_DEFINE_UNQUOTED(G_ATOMIC_S390, 1,
-		   	 [s390 atomic implementation])
-      glib_memory_barrier_needed=no
-      ;;	
-    arm*)
-      AC_MSG_RESULT([arm])
-      AC_DEFINE_UNQUOTED(G_ATOMIC_ARM, 1,
-                         [arm atomic implementation])
-      glib_memory_barrier_needed=no
-      ;;
-    crisv32*|etraxfs*)
-      AC_MSG_RESULT([crisv32])
-      AC_DEFINE_UNQUOTED(G_ATOMIC_CRISV32, 1,
-		   	 [crisv32 atomic implementation])
-      glib_memory_barrier_needed=no
-      ;;
-    cris*|etrax*)
-      AC_MSG_RESULT([cris])
-      AC_DEFINE_UNQUOTED(G_ATOMIC_CRIS, 1,
-			 [cris atomic implementation])
-      glib_memory_barrier_needed=no
-      ;;
-    *)
-      AC_MSG_RESULT([none])
-      glib_memory_barrier_needed=yes
-      ;;
-  esac
+  AC_MSG_CHECKING([whether GCC supports build-in atomic intrinsics])
+  AC_TRY_LINK([],
+	      [int i;
+	       __sync_synchronize ();
+	       __sync_bool_compare_and_swap (&i, 0, 1);
+	       __sync_fetch_and_add (&i, 1);
+	      ],
+	      [glib_cv_gcc_has_builtin_atomic_operations=yes],
+	      [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])
+        glib_memory_barrier_needed=no
+        ;;
+      i?86)
+        AC_MSG_RESULT([i486])
+        AC_DEFINE_UNQUOTED(G_ATOMIC_I486, 1,
+			   [i486 atomic implementation])
+        glib_memory_barrier_needed=no
+        ;;
+      sparc*)
+        SPARCV9_WARNING="Try to rerun configure with CFLAGS='-mcpu=v9',
+			 when you are using a sparc with v9 instruction set (most
+			 sparcs nowadays). This will make the code for atomic
+			 operations much faster. The resulting code will not run
+			 on very old sparcs though."
+
+        AC_LINK_IFELSE([[
+          main ()
+          {
+            int tmp1, tmp2, tmp3;
+            __asm__ __volatile__("casx [%2], %0, %1"
+                                 : "=&r" (tmp1), "=&r" (tmp2) : "r" (&tmp3));
+          }]],
+          AC_MSG_RESULT([sparcv9])
+          AC_DEFINE_UNQUOTED(G_ATOMIC_SPARCV9, 1,
+			     [sparcv9 atomic implementation]),
+          AC_MSG_RESULT([no])
+          AC_MSG_WARN([[$SPARCV9_WARNING]]))
+        glib_memory_barrier_needed=yes
+        ;;
+      alpha*)
+        AC_MSG_RESULT([alpha])
+        AC_DEFINE_UNQUOTED(G_ATOMIC_ALPHA, 1,
+			   [alpha atomic implementation])
+        glib_memory_barrier_needed=yes
+        ;;
+      x86_64)
+        AC_MSG_RESULT([x86_64])
+        AC_DEFINE_UNQUOTED(G_ATOMIC_X86_64, 1,
+			   [x86_64 atomic implementation])
+        glib_memory_barrier_needed=no
+       ;;
+      powerpc*)
+        AC_MSG_RESULT([powerpc])
+        AC_DEFINE_UNQUOTED(G_ATOMIC_POWERPC, 1,
+			   [powerpc atomic implementation])
+        glib_memory_barrier_needed=yes
+        AC_MSG_CHECKING([whether asm supports numbered local labels])
+        AC_TRY_COMPILE(
+		       ,[
+		       __asm__ __volatile__ ("1:       nop\n"
+			       "         bne-    1b")
+		       ],[
+		       AC_DEFINE_UNQUOTED(ASM_NUMERIC_LABELS, 1, [define if asm blocks can use numeric local labels])
+		       AC_MSG_RESULT([yes])
+		       ],[
+		       AC_MSG_RESULT([no])
+		       ])
+        ;;
+      ia64)
+        AC_MSG_RESULT([ia64])
+        AC_DEFINE_UNQUOTED(G_ATOMIC_IA64, 1,
+			   [ia64 atomic implementation])
+        glib_memory_barrier_needed=yes
+        ;;
+      s390|s390x)
+        AC_MSG_RESULT([s390])
+        AC_DEFINE_UNQUOTED(G_ATOMIC_S390, 1,
+			   [s390 atomic implementation])
+        glib_memory_barrier_needed=no
+        ;;
+      arm*)
+        AC_MSG_RESULT([arm])
+        AC_DEFINE_UNQUOTED(G_ATOMIC_ARM, 1,
+			   [arm atomic implementation])
+        glib_memory_barrier_needed=no
+        ;;
+      crisv32*|etraxfs*)
+        AC_MSG_RESULT([crisv32])
+        AC_DEFINE_UNQUOTED(G_ATOMIC_CRISV32, 1,
+			   [crisv32 atomic implementation])
+        glib_memory_barrier_needed=no
+        ;;
+      cris*|etrax*)
+        AC_MSG_RESULT([cris])
+        AC_DEFINE_UNQUOTED(G_ATOMIC_CRIS, 1,
+			   [cris atomic implementation])
+        glib_memory_barrier_needed=no
+        ;;
+      *)
+        AC_MSG_RESULT([none])
+        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.
@@ -2516,6 +2532,9 @@ else
   fi
 fi
 
+AM_CONDITIONAL(HAVE_GCC_BUILTINS_FOR_ATOMIC_OPERATIONS,
+	       [test $glib_cv_gcc_has_builtin_atomic_operations = yes])
+
 dnl ****************************************
 dnl *** GLib POLL* compatibility defines ***
 dnl ****************************************
diff --git a/glib/Makefile.am b/glib/Makefile.am
index e2080fb..5701922 100644
--- a/glib/Makefile.am
+++ b/glib/Makefile.am
@@ -19,6 +19,12 @@ gregex_c =
 gregex_h =
 endif
 
+if HAVE_GCC_BUILTINS_FOR_ATOMIC_OPERATIONS
+gatomic_c = gatomic-gcc.c
+else
+gatomic_c = gatomic.c
+endif
+
 SUBDIRS = libcharset $(PRINTF_SUBDIR) $(MAYBE_PCRE) update-pcre . tests
 
 DIST_SUBDIRS = libcharset gnulib pcre update-pcre tests
@@ -100,7 +106,7 @@ uninstall-ms-lib:
 libglib_2_0_la_SOURCES = 	\
 	garray.c		\
 	gasyncqueue.c		\
-	gatomic.c		\
+	$(gatomic_c)		\
 	gbacktrace.c		\
 	gbase64.c		\
 	gbookmarkfile.c 	\
diff --git a/glib/gatomic-gcc.c b/glib/gatomic-gcc.c
new file mode 100644
index 0000000..7b33b19
--- /dev/null
+++ b/glib/gatomic-gcc.c
@@ -0,0 +1,92 @@
+/* GLIB - Library of useful routines for C programming
+ * gatomic-gcc.c: atomic operations using GCC builtins.
+ * Copyright (C) 2009 Hiroyuki Ikezoe
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "glib.h"
+#include "galias.h"
+
+gint
+g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
+			       gint           val)
+{
+  return __sync_fetch_and_add (atomic, val);
+}
+
+void
+g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
+		  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)
+{
+  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)
+{
+  return __sync_bool_compare_and_swap (atomic, oldval, newval);
+}
+
+void
+_g_atomic_thread_init (void)
+{
+}
+
+gint
+(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)
+{
+  *atomic = newval;
+  __sync_synchronize ();
+}
+
+gpointer
+(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)
+{
+  *atomic = newval;
+  __sync_synchronize ();
+}
+
+#define __G_ATOMIC_C__
+#include "galiasdef.c"



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