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
This commit is contained in:
Matthias Clasen 2011-05-22 16:31:43 -04:00
parent 9255350a70
commit dec7d41275
3 changed files with 65 additions and 19 deletions

View File

@ -2468,9 +2468,6 @@ if test x"$GCC" = xyes; then
[glib_cv_gcc_has_builtin_atomic_operations=no]) [glib_cv_gcc_has_builtin_atomic_operations=no])
AC_MSG_RESULT($glib_cv_gcc_has_builtin_atomic_operations) 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 case $host_cpu in
i386) i386)
AC_MSG_RESULT([none]) AC_MSG_RESULT([none])
@ -2567,7 +2564,6 @@ if test x"$GCC" = xyes; then
glib_memory_barrier_needed=yes glib_memory_barrier_needed=yes
;; ;;
esac 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.
@ -2590,7 +2586,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
int int
main (void) 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); syscall (SYS_futex, NULL, FUTEX_WAKE, FUTEX_WAIT);
return 0; return 0;
} }
@ -3257,7 +3253,10 @@ _______EOF
echo >>$outfile echo >>$outfile
echo "#define G_ATOMIC_OP_MEMORY_BARRIER_NEEDED 1" >>$outfile echo "#define G_ATOMIC_OP_MEMORY_BARRIER_NEEDED 1" >>$outfile
fi 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 echo >>$outfile
g_bit_sizes="16 32 64" g_bit_sizes="16 32 64"
for bits in $g_bit_sizes; do 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_mutex_contents="$glib_cv_byte_contents_gmutex"
g_memory_barrier_needed="$glib_memory_barrier_needed" 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" g_module_suffix="$glib_gmodule_suffix"

View File

@ -22,6 +22,22 @@
#include "gatomic.h" #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 gint
g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic, g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
gint val) gint val)
@ -58,14 +74,14 @@ _g_atomic_thread_init (void)
} }
gint 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 (); __sync_synchronize ();
return *atomic; return *atomic;
} }
void void
(g_atomic_int_set) (volatile gint G_GNUC_MAY_ALIAS *atomic, g_atomic_int_set (volatile gint G_GNUC_MAY_ALIAS *atomic,
gint newval) gint newval)
{ {
*atomic = newval; *atomic = newval;
@ -73,14 +89,14 @@ void
} }
gpointer 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 (); __sync_synchronize ();
return *atomic; return *atomic;
} }
void void
(g_atomic_pointer_set) (volatile gpointer G_GNUC_MAY_ALIAS *atomic, g_atomic_pointer_set (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
gpointer newval) gpointer newval)
{ {
*atomic = newval; *atomic = newval;

View File

@ -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, void g_atomic_pointer_set (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
gpointer newval); 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_get(atomic) ((gint)*(atomic))
# define g_atomic_int_set(atomic, newval) ((void) (*(atomic) = (newval))) # define g_atomic_int_set(atomic, newval) ((void) (*(atomic) = (newval)))
# define g_atomic_pointer_get(atomic) ((gpointer)*(atomic)) # define g_atomic_pointer_get(atomic) ((gpointer)*(atomic))
# define g_atomic_pointer_set(atomic, newval) ((void) (*(atomic) = (newval))) # define g_atomic_pointer_set(atomic, newval) ((void) (*(atomic) = (newval)))
#else #else
# define g_atomic_int_get(atomic) \ # define g_atomic_int_get(atomic) \
((void) sizeof (gchar [sizeof (*(atomic)) == sizeof (gint) ? 1 : -1]), \ ((void) sizeof (gchar [sizeof (*(atomic)) == sizeof (gint) ? 1 : -1]), \
(g_atomic_int_get) ((volatile gint G_GNUC_MAY_ALIAS *) (volatile void *) (atomic))) (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) \ # define g_atomic_pointer_set(atomic, newval) \
((void) sizeof (gchar [sizeof (*(atomic)) == sizeof (gpointer) ? 1 : -1]), \ ((void) sizeof (gchar [sizeof (*(atomic)) == sizeof (gpointer) ? 1 : -1]), \
(g_atomic_pointer_set) ((volatile gpointer G_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (newval))) (g_atomic_pointer_set) ((volatile gpointer G_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (newval)))
#endif /* G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */ #endif /* G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */
/** /**