diff --git a/configure.ac b/configure.ac index 8fda196f4..bb0a795f1 100644 --- a/configure.ac +++ b/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" diff --git a/glib/gatomic-gcc.c b/glib/gatomic-gcc.c index 9f28ceeca..09cd3aafa 100644 --- a/glib/gatomic-gcc.c +++ b/glib/gatomic-gcc.c @@ -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 (); diff --git a/glib/gatomic.h b/glib/gatomic.h index ddd39b8a3..969443a0f 100644 --- a/glib/gatomic.h +++ b/glib/gatomic.h @@ -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 */ /**