Use GCC atomic builtin operations.

Fix for bug #531902.
This commit is contained in:
Hiroyuki Ikezoe 2010-01-07 19:33:39 +09:00
parent 7211f7f8eb
commit 37716bd00a
3 changed files with 213 additions and 96 deletions

View File

@ -2412,103 +2412,119 @@ dnl ********************************
AC_MSG_CHECKING([whether to use assembler code for atomic operations]) 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 if test x"$GCC" = xyes; then
case $host_cpu in AC_MSG_CHECKING([whether GCC supports build-in atomic intrinsics])
i386) AC_TRY_LINK([],
AC_MSG_RESULT([none]) [int i;
glib_memory_barrier_needed=no __sync_synchronize ();
;; __sync_bool_compare_and_swap (&i, 0, 1);
i?86) __sync_fetch_and_add (&i, 1);
AC_MSG_RESULT([i486]) ],
AC_DEFINE_UNQUOTED(G_ATOMIC_I486, 1, [glib_cv_gcc_has_builtin_atomic_operations=yes],
[i486 atomic implementation]) [glib_cv_gcc_has_builtin_atomic_operations=no])
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([[ AC_MSG_RESULT($glib_cv_gcc_has_builtin_atomic_operations)
main () if test $glib_cv_gcc_has_builtin_atomic_operations = yes; then
{ glib_memory_barrier_needed=yes
int tmp1, tmp2, tmp3; else
__asm__ __volatile__("casx [%2], %0, %1" case $host_cpu in
: "=&r" (tmp1), "=&r" (tmp2) : "r" (&tmp3)); i386)
}]], AC_MSG_RESULT([none])
AC_MSG_RESULT([sparcv9]) glib_memory_barrier_needed=no
AC_DEFINE_UNQUOTED(G_ATOMIC_SPARCV9, 1, ;;
[sparcv9 atomic implementation]), i?86)
AC_MSG_RESULT([no]) AC_MSG_RESULT([i486])
AC_MSG_WARN([[$SPARCV9_WARNING]])) AC_DEFINE_UNQUOTED(G_ATOMIC_I486, 1,
glib_memory_barrier_needed=yes [i486 atomic implementation])
;; glib_memory_barrier_needed=no
alpha*) ;;
AC_MSG_RESULT([alpha]) sparc*)
AC_DEFINE_UNQUOTED(G_ATOMIC_ALPHA, 1, SPARCV9_WARNING="Try to rerun configure with CFLAGS='-mcpu=v9',
[alpha atomic implementation]) when you are using a sparc with v9 instruction set (most
glib_memory_barrier_needed=yes sparcs nowadays). This will make the code for atomic
;; operations much faster. The resulting code will not run
x86_64) on very old sparcs though."
AC_MSG_RESULT([x86_64])
AC_DEFINE_UNQUOTED(G_ATOMIC_X86_64, 1, AC_LINK_IFELSE([[
[x86_64 atomic implementation]) main ()
glib_memory_barrier_needed=no {
;; int tmp1, tmp2, tmp3;
powerpc*) __asm__ __volatile__("casx [%2], %0, %1"
AC_MSG_RESULT([powerpc]) : "=&r" (tmp1), "=&r" (tmp2) : "r" (&tmp3));
AC_DEFINE_UNQUOTED(G_ATOMIC_POWERPC, 1, }]],
[powerpc atomic implementation]) AC_MSG_RESULT([sparcv9])
glib_memory_barrier_needed=yes AC_DEFINE_UNQUOTED(G_ATOMIC_SPARCV9, 1,
AC_MSG_CHECKING([whether asm supports numbered local labels]) [sparcv9 atomic implementation]),
AC_TRY_COMPILE( AC_MSG_RESULT([no])
,[ AC_MSG_WARN([[$SPARCV9_WARNING]]))
__asm__ __volatile__ ("1: nop\n" glib_memory_barrier_needed=yes
" bne- 1b") ;;
],[ alpha*)
AC_DEFINE_UNQUOTED(ASM_NUMERIC_LABELS, 1, [define if asm blocks can use numeric local labels]) AC_MSG_RESULT([alpha])
AC_MSG_RESULT([yes]) AC_DEFINE_UNQUOTED(G_ATOMIC_ALPHA, 1,
],[ [alpha atomic implementation])
AC_MSG_RESULT([no]) glib_memory_barrier_needed=yes
]) ;;
;; x86_64)
ia64) AC_MSG_RESULT([x86_64])
AC_MSG_RESULT([ia64]) AC_DEFINE_UNQUOTED(G_ATOMIC_X86_64, 1,
AC_DEFINE_UNQUOTED(G_ATOMIC_IA64, 1, [x86_64 atomic implementation])
[ia64 atomic implementation]) glib_memory_barrier_needed=no
glib_memory_barrier_needed=yes ;;
;; powerpc*)
s390|s390x) AC_MSG_RESULT([powerpc])
AC_MSG_RESULT([s390]) AC_DEFINE_UNQUOTED(G_ATOMIC_POWERPC, 1,
AC_DEFINE_UNQUOTED(G_ATOMIC_S390, 1, [powerpc atomic implementation])
[s390 atomic implementation]) glib_memory_barrier_needed=yes
glib_memory_barrier_needed=no AC_MSG_CHECKING([whether asm supports numbered local labels])
;; AC_TRY_COMPILE(
arm*) ,[
AC_MSG_RESULT([arm]) __asm__ __volatile__ ("1: nop\n"
AC_DEFINE_UNQUOTED(G_ATOMIC_ARM, 1, " bne- 1b")
[arm atomic implementation]) ],[
glib_memory_barrier_needed=no AC_DEFINE_UNQUOTED(ASM_NUMERIC_LABELS, 1, [define if asm blocks can use numeric local labels])
;; AC_MSG_RESULT([yes])
crisv32*|etraxfs*) ],[
AC_MSG_RESULT([crisv32]) AC_MSG_RESULT([no])
AC_DEFINE_UNQUOTED(G_ATOMIC_CRISV32, 1, ])
[crisv32 atomic implementation]) ;;
glib_memory_barrier_needed=no ia64)
;; AC_MSG_RESULT([ia64])
cris*|etrax*) AC_DEFINE_UNQUOTED(G_ATOMIC_IA64, 1,
AC_MSG_RESULT([cris]) [ia64 atomic implementation])
AC_DEFINE_UNQUOTED(G_ATOMIC_CRIS, 1, glib_memory_barrier_needed=yes
[cris atomic implementation]) ;;
glib_memory_barrier_needed=no s390|s390x)
;; AC_MSG_RESULT([s390])
*) AC_DEFINE_UNQUOTED(G_ATOMIC_S390, 1,
AC_MSG_RESULT([none]) [s390 atomic implementation])
glib_memory_barrier_needed=yes glib_memory_barrier_needed=no
;; ;;
esac 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 else
if test $glib_native_win32 = yes; then if test $glib_native_win32 = yes; then
# For Windows but not using gcc. No barriers needed then either. # For Windows but not using gcc. No barriers needed then either.
@ -2516,6 +2532,9 @@ else
fi fi
fi fi
AM_CONDITIONAL(HAVE_GCC_BUILTINS_FOR_ATOMIC_OPERATIONS,
[test $glib_cv_gcc_has_builtin_atomic_operations = yes])
dnl **************************************** dnl ****************************************
dnl *** GLib POLL* compatibility defines *** dnl *** GLib POLL* compatibility defines ***
dnl **************************************** dnl ****************************************

View File

@ -19,6 +19,12 @@ gregex_c =
gregex_h = gregex_h =
endif 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 SUBDIRS = libcharset $(PRINTF_SUBDIR) $(MAYBE_PCRE) update-pcre . tests
DIST_SUBDIRS = libcharset gnulib pcre update-pcre tests DIST_SUBDIRS = libcharset gnulib pcre update-pcre tests
@ -100,7 +106,7 @@ uninstall-ms-lib:
libglib_2_0_la_SOURCES = \ libglib_2_0_la_SOURCES = \
garray.c \ garray.c \
gasyncqueue.c \ gasyncqueue.c \
gatomic.c \ $(gatomic_c) \
gbacktrace.c \ gbacktrace.c \
gbase64.c \ gbase64.c \
gbookmarkfile.c \ gbookmarkfile.c \

92
glib/gatomic-gcc.c Normal file
View File

@ -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"