]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
configure.ac: Check for support of __atomic extensions.
authorIan Lance Taylor <iant@google.com>
Tue, 19 Nov 2013 01:09:47 +0000 (01:09 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 19 Nov 2013 01:09:47 +0000 (01:09 +0000)
* configure.ac: Check for support of __atomic extensions.
* internal.h: Declare or #define atomic functions for use in
backtrace code.
* atomic.c: New file.
* dwarf.c (dwarf_lookup_pc): Use atomic functions.
(dwarf_fileline, backtrace_dwarf_add): Likewise.
* elf.c (elf_add_syminfo_data, elf_syminfo): Likewise.
(backtrace_initialize): Likewise.
* fileline.c (fileline_initialize): Likewise.
* Makefile.am (libbacktrace_la_SOURCES): Add atomic.c.
* configure, config.h.in, Makefile.in: Rebuild.

From-SVN: r204994

libbacktrace/ChangeLog
libbacktrace/Makefile.am
libbacktrace/Makefile.in
libbacktrace/atomic.c [new file with mode: 0644]
libbacktrace/config.h.in
libbacktrace/configure
libbacktrace/configure.ac
libbacktrace/dwarf.c
libbacktrace/elf.c
libbacktrace/fileline.c
libbacktrace/internal.h

index c06194df3e48369673d79312b5ffaeca8f57f0da..134d9a71752c4d8e9dab0b8900ddfd74466d52a7 100644 (file)
@@ -1,3 +1,17 @@
+2013-11-18  Ian Lance Taylor  <iant@google.com>
+
+       * configure.ac: Check for support of __atomic extensions.
+       * internal.h: Declare or #define atomic functions for use in
+       backtrace code.
+       * atomic.c: New file.
+       * dwarf.c (dwarf_lookup_pc): Use atomic functions.
+       (dwarf_fileline, backtrace_dwarf_add): Likewise.
+       * elf.c (elf_add_syminfo_data, elf_syminfo): Likewise.
+       (backtrace_initialize): Likewise.
+       * fileline.c (fileline_initialize): Likewise.
+       * Makefile.am (libbacktrace_la_SOURCES): Add atomic.c.
+       * configure, config.h.in, Makefile.in: Rebuild.
+
 2013-11-18  Jakub Jelinek  <jakub@redhat.com>
 
        * elf.c (SHN_UNDEF): Define.
index 035986bbf96c19c55b33dbbb54f12a302b1e1b85..20dbde480c5d8f970eb844a852d31c6ecb8712f3 100644 (file)
@@ -40,6 +40,7 @@ noinst_LTLIBRARIES = libbacktrace.la
 
 libbacktrace_la_SOURCES = \
        backtrace.h \
+       atomic.c \
        dwarf.c \
        fileline.c \
        internal.h \
index 971406bf6da89df0b6599a11aadd31c6f7c80451..a1e144aca172bd0d7da1963f0bc8de572c405ceb 100644 (file)
@@ -16,7 +16,7 @@
 @SET_MAKE@
 
 # Makefile.am -- Backtrace Makefile.
-# Copyright (C) 2012 Free Software Foundation, Inc.
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
 
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are
@@ -93,8 +93,8 @@ CONFIG_CLEAN_FILES = backtrace-supported.h
 CONFIG_CLEAN_VPATH_FILES =
 LTLIBRARIES = $(noinst_LTLIBRARIES)
 am__DEPENDENCIES_1 =
-am_libbacktrace_la_OBJECTS = dwarf.lo fileline.lo posix.lo print.lo \
-       state.lo
+am_libbacktrace_la_OBJECTS = atomic.lo dwarf.lo fileline.lo posix.lo \
+       print.lo state.lo
 libbacktrace_la_OBJECTS = $(am_libbacktrace_la_OBJECTS)
 @NATIVE_TRUE@am__EXEEXT_1 = btest$(EXEEXT)
 @NATIVE_TRUE@am_btest_OBJECTS = btest-btest.$(OBJEXT)
@@ -258,6 +258,7 @@ AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)
 noinst_LTLIBRARIES = libbacktrace.la
 libbacktrace_la_SOURCES = \
        backtrace.h \
+       atomic.c \
        dwarf.c \
        fileline.c \
        internal.h \
diff --git a/libbacktrace/atomic.c b/libbacktrace/atomic.c
new file mode 100644 (file)
index 0000000..44fa552
--- /dev/null
@@ -0,0 +1,111 @@
+/* atomic.c -- Support for atomic functions if not present.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include "backtrace.h"
+#include "backtrace-supported.h"
+#include "internal.h"
+
+/* This file holds implementations of the atomic functions that are
+   used if the host compiler has the sync functions but not the atomic
+   functions, as is true of versions of GCC before 4.7.  */
+
+#if !defined (HAVE_ATOMIC_FUNCTIONS) && defined (HAVE_SYNC_FUNCTIONS)
+
+/* Do an atomic load of a pointer.  */
+
+void *
+backtrace_atomic_load_pointer (void *arg)
+{
+  void **pp;
+  void *p;
+
+  pp = (void **) arg;
+  p = *pp;
+  while (!__sync_bool_compare_and_swap (pp, p, p))
+    p = *pp;
+  return p;
+}
+
+/* Do an atomic load of an int.  */
+
+int
+backtrace_atomic_load_int (int *p)
+{
+  int i;
+
+  i = *p;
+  while (!__sync_bool_compare_and_swap (p, i, i))
+    i = *p;
+  return i;
+}
+
+/* Do an atomic store of a pointer.  */
+
+void
+backtrace_atomic_store_pointer (void *arg, void *p)
+{
+  void **pp;
+  void *old;
+
+  pp = (void **) arg;
+  old = *pp;
+  while (!__sync_bool_compare_and_swap (pp, old, p))
+    old = *pp;
+}
+
+/* Do an atomic store of a size_t value.  */
+
+void
+backtrace_atomic_store_size_t (size_t *p, size_t v)
+{
+  size_t old;
+
+  old = *p;
+  while (!__sync_bool_compare_and_swap (p, old, v))
+    old = *p;
+}
+
+/* Do an atomic store of a int value.  */
+
+void
+backtrace_atomic_store_int (int *p, int v)
+{
+  size_t old;
+
+  old = *p;
+  while (!__sync_bool_compare_and_swap (p, old, v))
+    old = *p;
+}
+
+#endif
index 48ff63fdc05d2ffe9de9437fb69b65336fcdce0e..87cb805984d4f06782ed96a509fe18a290377f33 100644 (file)
@@ -3,6 +3,9 @@
 /* ELF size: 32 or 64 */
 #undef BACKTRACE_ELF_SIZE
 
+/* Define to 1 if you have the __atomic functions */
+#undef HAVE_ATOMIC_FUNCTIONS
+
 /* Define to 1 if you have the declaration of `strnlen', and to 0 if you
    don't. */
 #undef HAVE_DECL_STRNLEN
index e6b13c0b70638a9e4c37a0554aba4d8b487b0c9e..d6bda6e67b682382578877e596c832eeb4f2b9a1 100755 (executable)
@@ -11748,6 +11748,44 @@ $as_echo "#define HAVE_SYNC_FUNCTIONS 1" >>confdefs.h
 fi
 
 
+# Test for __atomic support.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __atomic extensions" >&5
+$as_echo_n "checking __atomic extensions... " >&6; }
+if test "${libbacktrace_cv_sys_atomic+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "${with_target_subdir}"; then
+   libbacktrace_cv_sys_atomic=yes
+ else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int i;
+int
+main ()
+{
+__atomic_load_n (&i, __ATOMIC_ACQUIRE);
+                      __atomic_store_n (&i, 1, __ATOMIC_RELEASE);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  libbacktrace_cv_sys_atomic=yes
+else
+  libbacktrace_cv_sys_atomic=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_sys_atomic" >&5
+$as_echo "$libbacktrace_cv_sys_atomic" >&6; }
+if test "$libbacktrace_cv_sys_atomic" = "yes"; then
+
+$as_echo "#define HAVE_ATOMIC_FUNCTIONS 1" >>confdefs.h
+
+fi
+
 # The library needs to be able to read the executable itself.  Compile
 # a file to determine the executable format.  The awk script
 # filetype.awk prints out the file type.
index 48c86203837652e796a01e3bbaab6fc15a38ed81..f97afbc8b746ee7146e1028a7c01b54a407fcd2f 100644 (file)
@@ -194,6 +194,24 @@ if test "$libbacktrace_cv_sys_sync" = "yes"; then
 fi
 AC_SUBST(BACKTRACE_SUPPORTS_THREADS)
 
+# Test for __atomic support.
+AC_CACHE_CHECK([__atomic extensions],
+[libbacktrace_cv_sys_atomic],
+[if test -n "${with_target_subdir}"; then
+   libbacktrace_cv_sys_atomic=yes
+ else
+   AC_LINK_IFELSE(
+     [AC_LANG_PROGRAM([int i;],
+                     [__atomic_load_n (&i, __ATOMIC_ACQUIRE);
+                      __atomic_store_n (&i, 1, __ATOMIC_RELEASE);])],
+     [libbacktrace_cv_sys_atomic=yes],
+     [libbacktrace_cv_sys_atomic=no])
+ fi])
+if test "$libbacktrace_cv_sys_atomic" = "yes"; then
+  AC_DEFINE([HAVE_ATOMIC_FUNCTIONS], 1,
+           [Define to 1 if you have the __atomic functions])
+fi
+
 # The library needs to be able to read the executable itself.  Compile
 # a file to determine the executable format.  The awk script
 # filetype.awk prints out the file type.
index 501afe553d203486735a4645dc80689f03e86b8d..0aba2d3f574c26f738f362949ec53adbe31f7f80 100644 (file)
@@ -2643,12 +2643,7 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
         && pc < (entry - 1)->high)
     {
       if (state->threaded)
-       {
-         /* Use __sync_bool_compare_and_swap to do a
-            load-acquire.  */
-         while (!__sync_bool_compare_and_swap (&u->lines, lines, lines))
-           lines = u->lines;
-       }
+       lines = (struct line *) backtrace_atomic_load_pointer (&u->lines);
 
       if (lines != (struct line *) (uintptr_t) -1)
        break;
@@ -2659,13 +2654,8 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
       lines = u->lines;
     }
 
-  /* Do a load-acquire of u->lines.  */
   if (state->threaded)
-    {
-      /* Use __sync_bool_compare_and_swap to do an atomic load.  */
-      while (!__sync_bool_compare_and_swap (&u->lines, lines, lines))
-       lines = u->lines;
-    }
+    lines = backtrace_atomic_load_pointer (&u->lines);
 
   new_data = 0;
   if (lines == NULL)
@@ -2713,12 +2703,11 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
        }
       else
        {
-         __sync_bool_compare_and_swap (&u->lines_count, 0, count);
-         __sync_bool_compare_and_swap (&u->function_addrs, NULL,
-                                       function_addrs);
-         __sync_bool_compare_and_swap (&u->function_addrs_count, 0,
-                                       function_addrs_count);
-         __sync_bool_compare_and_swap (&u->lines, NULL, lines);
+         backtrace_atomic_store_size_t (&u->lines_count, count);
+         backtrace_atomic_store_pointer (&u->function_addrs, function_addrs);
+         backtrace_atomic_store_size_t (&u->function_addrs_count,
+                                        function_addrs_count);
+         backtrace_atomic_store_pointer (&u->lines, lines);
        }
     }
 
@@ -2849,11 +2838,7 @@ dwarf_fileline (struct backtrace_state *state, uintptr_t pc,
       pp = (struct dwarf_data **) (void *) &state->fileline_data;
       while (1)
        {
-         ddata = *pp;
-         /* Atomic load.  */
-         while (!__sync_bool_compare_and_swap (pp, ddata, ddata))
-           ddata = *pp;
-
+         ddata = backtrace_atomic_load_pointer (pp);
          if (ddata == NULL)
            break;
 
@@ -2985,10 +2970,7 @@ backtrace_dwarf_add (struct backtrace_state *state,
            {
              struct dwarf_data *p;
 
-             /* Atomic load.  */
-             p = *pp;
-             while (!__sync_bool_compare_and_swap (pp, p, p))
-               p = *pp;
+             p = backtrace_atomic_load_pointer (pp);
 
              if (p == NULL)
                break;
index 659b349f73b7cc7acac6a60c6466f15881c91ffe..981ce7f831c48e156f7fba1281351e273cb48b21 100644 (file)
@@ -442,10 +442,7 @@ elf_add_syminfo_data (struct backtrace_state *state,
            {
              struct elf_syminfo_data *p;
 
-             /* Atomic load.  */
-             p = *pp;
-             while (!__sync_bool_compare_and_swap (pp, p, p))
-               p = *pp;
+             p = backtrace_atomic_load_pointer (pp);
 
              if (p == NULL)
                break;
@@ -490,11 +487,7 @@ elf_syminfo (struct backtrace_state *state, uintptr_t addr,
       pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
       while (1)
        {
-         edata = *pp;
-         /* Atomic load.  */
-         while (!__sync_bool_compare_and_swap (pp, edata, edata))
-           edata = *pp;
-
+         edata = backtrace_atomic_load_pointer (pp);
          if (edata == NULL)
            break;
 
@@ -902,7 +895,6 @@ backtrace_initialize (struct backtrace_state *state, int descriptor,
 {
   int found_sym;
   int found_dwarf;
-  syminfo elf_syminfo_fn;
   fileline elf_fileline_fn;
   struct phdr_data pd;
 
@@ -919,18 +911,19 @@ backtrace_initialize (struct backtrace_state *state, int descriptor,
 
   dl_iterate_phdr (phdr_callback, (void *) &pd);
 
-  elf_syminfo_fn = found_sym ? elf_syminfo : elf_nosyms;
   if (!state->threaded)
     {
-      if (state->syminfo_fn == NULL || found_sym)
-       state->syminfo_fn = elf_syminfo_fn;
+      if (found_sym)
+       state->syminfo_fn = elf_syminfo;
+      else if (state->syminfo_fn == NULL)
+       state->syminfo_fn = elf_nosyms;
     }
   else
     {
-      __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, elf_syminfo_fn);
       if (found_sym)
-       __sync_bool_compare_and_swap (&state->syminfo_fn, elf_nosyms,
-                                     elf_syminfo_fn);
+       backtrace_atomic_store_pointer (&state->syminfo_fn, elf_syminfo);
+      else
+       __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, elf_nosyms);
     }
 
   if (!state->threaded)
@@ -942,11 +935,7 @@ backtrace_initialize (struct backtrace_state *state, int descriptor,
     {
       fileline current_fn;
 
-      /* Atomic load.  */
-      current_fn = state->fileline_fn;
-      while (!__sync_bool_compare_and_swap (&state->fileline_fn, current_fn,
-                                           current_fn))
-       current_fn = state->fileline_fn;
+      current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
       if (current_fn == NULL || current_fn == elf_nodebug)
        *fileline_fn = elf_fileline_fn;
     }
index e5c39be8e0e406ac34b6ab970c1ea6d3ea01b9a9..cc063f52c0d3d566cf0a3faa256c5b9fd6c86b99 100644 (file)
@@ -58,15 +58,10 @@ fileline_initialize (struct backtrace_state *state,
   int called_error_callback;
   int descriptor;
 
-  failed = state->fileline_initialization_failed;
-
-  if (state->threaded)
-    {
-      /* Use __sync_bool_compare_and_swap to do an atomic load.  */
-      while (!__sync_bool_compare_and_swap
-            (&state->fileline_initialization_failed, failed, failed))
-       failed = state->fileline_initialization_failed;
-    }
+  if (!state->threaded)
+    failed = state->fileline_initialization_failed;
+  else
+    failed = backtrace_atomic_load_int (&state->fileline_initialization_failed);
 
   if (failed)
     {
@@ -74,13 +69,10 @@ fileline_initialize (struct backtrace_state *state,
       return 0;
     }
 
-  fileline_fn = state->fileline_fn;
-  if (state->threaded)
-    {
-      while (!__sync_bool_compare_and_swap (&state->fileline_fn, fileline_fn,
-                                           fileline_fn))
-       fileline_fn = state->fileline_fn;
-    }
+  if (!state->threaded)
+    fileline_fn = state->fileline_fn;
+  else
+    fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
   if (fileline_fn != NULL)
     return 1;
 
@@ -151,8 +143,7 @@ fileline_initialize (struct backtrace_state *state,
       if (!state->threaded)
        state->fileline_initialization_failed = 1;
       else
-       __sync_bool_compare_and_swap (&state->fileline_initialization_failed,
-                                     0, failed);
+       backtrace_atomic_store_int (&state->fileline_initialization_failed, 1);
       return 0;
     }
 
@@ -160,15 +151,10 @@ fileline_initialize (struct backtrace_state *state,
     state->fileline_fn = fileline_fn;
   else
     {
-      __sync_bool_compare_and_swap (&state->fileline_fn, NULL, fileline_fn);
-
-      /* At this point we know that state->fileline_fn is not NULL.
-        Either we stored our value, or some other thread stored its
-        value.  If some other thread stored its value, we leak the
-        one we just initialized.  Either way, state->fileline_fn is
-        initialized.  The compare_and_swap is a full memory barrier,
-        so we should have full access to that value even if it was
-        created by another thread.  */
+      backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn);
+
+      /* Note that if two threads initialize at once, one of the data
+        sets may be leaked.  */
     }
 
   return 1;
index 1ea664a0bcdbc76bd628a7f414b7a147b591ea7e..c93e89f36f45587a6ab1984fbbfeb98c59e23a54 100644 (file)
@@ -65,7 +65,48 @@ POSSIBILITY OF SUCH DAMAGE.  */
 #define __sync_lock_test_and_set(A, B) (abort(), 0)
 #define __sync_lock_release(A) abort()
 
-#endif /* !defined(HAVE_SYNC_FUNCTIONS) */
+#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
+
+#ifdef HAVE_ATOMIC_FUNCTIONS
+
+/* We have the atomic builtin functions.  */
+
+#define backtrace_atomic_load_pointer(p) \
+    __atomic_load_n ((p), __ATOMIC_ACQUIRE)
+#define backtrace_atomic_load_int(p) \
+    __atomic_load_n ((p), __ATOMIC_ACQUIRE)
+#define backtrace_atomic_store_pointer(p, v) \
+    __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+#define backtrace_atomic_store_size_t(p, v) \
+    __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+#define backtrace_atomic_store_int(p, v) \
+    __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+
+#else /* !defined (HAVE_ATOMIC_FUNCTIONS) */
+#ifdef HAVE_SYNC_FUNCTIONS
+
+/* We have the sync functions but not the atomic functions.  Define
+   the atomic ones in terms of the sync ones.  */
+
+extern void *backtrace_atomic_load_pointer (void *);
+extern int backtrace_atomic_load_int (int *);
+extern void backtrace_atomic_store_pointer (void *, void *);
+extern void backtrace_atomic_store_size_t (size_t *, size_t);
+extern void backtrace_atomic_store_int (int *, int);
+
+#else /* !defined (HAVE_SYNC_FUNCTIONS) */
+
+/* We have neither the sync nor the atomic functions.  These will
+   never be called.  */
+
+#define backtrace_atomic_load_pointer(p) (abort(), 0)
+#define backtrace_atomic_load_int(p) (abort(), 0)
+#define backtrace_atomic_store_pointer(p, v) abort()
+#define backtrace_atomic_store_size_t(p, v) abort()
+#define backtrace_atomic_store_int(p, v) abort()
+
+#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
+#endif /* !defined (HAVE_ATOMIC_FUNCTIONS) */
 
 /* The type of the function that collects file/line information.  This
    is like backtrace_pcinfo.  */