From 37716bd00a7911de545ebca3dc7a248503eaf46e Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Thu, 7 Jan 2010 19:33:39 +0900 Subject: [PATCH] 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(-) create mode 100644 glib/gatomic-gcc.c 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" -- 2.7.4