atomic: implement atomic operations based on gcc's __sync extension
authorLennart Poettering <lennart@poettering.net>
Tue, 19 May 2009 20:30:14 +0000 (22:30 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 20 May 2009 00:09:32 +0000 (02:09 +0200)
Newer gccs and intel ccs support a __sync extension for making use of
atomic operations. This patch replaces the handcrafted x86 atomic
operation support with usage of __sync.

__sync is supported by more processors and by more compilers than the
old assembler code. Also, this extension has been available on gcc for
quite a while now for x86, so replacing the old assembler code should
only be a loss when very old compiilers are used.

configure.in
dbus/dbus-internals.h
dbus/dbus-sysdeps-unix.c
dbus/dbus-threads.c

index b087b00..c2c6a8c 100644 (file)
@@ -590,41 +590,23 @@ if test "x$dbus_cv_va_val_copy" = "xno"; then
 fi
 
 
-#### Atomic integers (checks by Sebastian Wilhelmi for GLib)
-AC_MSG_CHECKING([whether to use inline assembler routines for atomic integers])
-have_atomic_inc_cond=0
-if test x"$GCC" = xyes; then
-  if test "x$enable_ansi" = "xyes"; then
-    AC_MSG_RESULT([no])
-  else
-    case $host_cpu in
-      i386)
-        AC_MSG_RESULT([no])
-        ;;
-      i?86)
-        case $host_os in
-          darwin*)
-            AC_MSG_RESULT([darwin])
-            # check at compile-time, so that it is possible to build universal
-            # (with multiple architectures at once on the compile line)
-            have_atomic_inc_cond="(defined(__i386__) || defined(__x86_64__))"
-            ;;
-          *)
-            AC_MSG_RESULT([i486])
-            have_atomic_inc_cond=1
-            ;;
-        esac
-        ;;
-      *)
-        AC_MSG_RESULT([no])
-        ;;
-    esac
-  fi
+#### Atomic integers
+
+AC_CACHE_CHECK([whether $CC knows __sync_sub_and_fetch()],
+  dbus_cv_sync_sub_and_fetch,
+  [AC_LINK_IFELSE(
+     AC_LANG_PROGRAM([], [[int a = 4; __sync_sub_and_fetch(&a, 4);]]),
+     [dbus_cv_sync_sub_and_fetch=yes],
+     [dbus_cv_sync_sub_and_fetch=no])
+  ])
+
+if test "x$dbus_cv_sync_sub_and_fetch" = "xyes" ; then
+   have_sync=1
+else
+   have_sync=0
 fi
-AC_DEFINE_UNQUOTED([DBUS_USE_ATOMIC_INT_486_COND], [$have_atomic_inc_cond],
-                   [Always defined; expands to 1 if we should use atomic integer implementation for 486, else 0])
-AC_DEFINE_UNQUOTED(DBUS_HAVE_ATOMIC_INT_COND, [$have_atomic_inc_cond],
-                   [Always defined; expands to 1 if we have an atomic integer implementation, else 0])
+
+AC_DEFINE_UNQUOTED([DBUS_USE_SYNC], [$have_sync], [Use the gcc __sync extension])
 
 #### Various functions
 AC_CHECK_LIB(socket,socket)
index 3e5f989..835fe46 100644 (file)
@@ -294,18 +294,23 @@ _DBUS_DECLARE_GLOBAL_LOCK (pending_call_slots);
 _DBUS_DECLARE_GLOBAL_LOCK (server_slots);
 _DBUS_DECLARE_GLOBAL_LOCK (message_slots);
 /* 5-10 */
-_DBUS_DECLARE_GLOBAL_LOCK (atomic);
 _DBUS_DECLARE_GLOBAL_LOCK (bus);
 _DBUS_DECLARE_GLOBAL_LOCK (bus_datas);
 _DBUS_DECLARE_GLOBAL_LOCK (shutdown_funcs);
 _DBUS_DECLARE_GLOBAL_LOCK (system_users);
-/* 10-15 */
 _DBUS_DECLARE_GLOBAL_LOCK (message_cache);
+/* 10-14 */
 _DBUS_DECLARE_GLOBAL_LOCK (shared_connections);
 _DBUS_DECLARE_GLOBAL_LOCK (win_fds);
 _DBUS_DECLARE_GLOBAL_LOCK (sid_atom_cache);
 _DBUS_DECLARE_GLOBAL_LOCK (machine_uuid);
+
+#if !DBUS_USE_SYNC
+_DBUS_DECLARE_GLOBAL_LOCK (atomic);
 #define _DBUS_N_GLOBAL_LOCKS (15)
+#else
+#define _DBUS_N_GLOBAL_LOCKS (14)
+#endif
 
 dbus_bool_t _dbus_threads_init_debug (void);
 
index 07db1c5..42aa967 100644 (file)
@@ -2180,23 +2180,8 @@ _dbus_parse_uid (const DBusString      *uid_str,
   return TRUE;
 }
 
-
+#if !DBUS_USE_SYNC
 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
-
-#if DBUS_USE_ATOMIC_INT_486_COND
-/* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
-/* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
-static inline dbus_int32_t
-atomic_exchange_and_add (DBusAtomic            *atomic,
-                         volatile dbus_int32_t  val)
-{
-  register dbus_int32_t result;
-
-  __asm__ __volatile__ ("lock; xaddl %0,%1"
-                        : "=r" (result), "=m" (atomic->value)
-                       : "0" (val), "m" (atomic->value));
-  return result;
-}
 #endif
 
 /**
@@ -2204,14 +2189,12 @@ atomic_exchange_and_add (DBusAtomic            *atomic,
  *
  * @param atomic pointer to the integer to increment
  * @returns the value before incrementing
- *
- * @todo implement arch-specific faster atomic ops
  */
 dbus_int32_t
 _dbus_atomic_inc (DBusAtomic *atomic)
 {
-#if DBUS_USE_ATOMIC_INT_486_COND
-  return atomic_exchange_and_add (atomic, 1);
+#if DBUS_USE_SYNC
+  return __sync_add_and_fetch(&atomic->value, 1)-1;
 #else
   dbus_int32_t res;
   _DBUS_LOCK (atomic);
@@ -2227,14 +2210,12 @@ _dbus_atomic_inc (DBusAtomic *atomic)
  *
  * @param atomic pointer to the integer to decrement
  * @returns the value before decrementing
- *
- * @todo implement arch-specific faster atomic ops
  */
 dbus_int32_t
 _dbus_atomic_dec (DBusAtomic *atomic)
 {
-#if DBUS_USE_ATOMIC_INT_486_COND
-  return atomic_exchange_and_add (atomic, -1);
+#if DBUS_USE_SYNC
+  return __sync_sub_and_fetch(&atomic->value, 1)+1;
 #else
   dbus_int32_t res;
   
index 00c1a4b..cb9c723 100644 (file)
@@ -424,7 +424,9 @@ init_locks (void)
     LOCK_ADDR (pending_call_slots),
     LOCK_ADDR (server_slots),
     LOCK_ADDR (message_slots),
+#if !DBUS_USE_SYNC
     LOCK_ADDR (atomic),
+#endif
     LOCK_ADDR (bus),
     LOCK_ADDR (bus_datas),
     LOCK_ADDR (shutdown_funcs),