mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 15:36:17 +01:00
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:
parent
9255350a70
commit
dec7d41275
12
configure.ac
12
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"
|
||||
|
||||
|
@ -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 ();
|
||||
|
@ -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 */
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user