]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Initialize backtrace state once
authorJanne Blomqvist <jb@gcc.gnu.org>
Thu, 6 Dec 2018 15:38:25 +0000 (17:38 +0200)
committerJanne Blomqvist <jb@gcc.gnu.org>
Thu, 6 Dec 2018 15:38:25 +0000 (17:38 +0200)
From backtrace.h for backtrace_create_state:

   Calling this function allocates resources that can not be freed.
   There is no backtrace_free_state function.  The state is used to
   cache information that is expensive to recompute.  Programs are
   expected to call this function at most once and to save the return
   value for all later calls to backtrace functions.

So instead of calling backtrace_create_state every time we wish to
show a backtrace, do it once and store the result in a static
variable.  libbacktrace allows multiple threads to access the state,
so no need to use TLS, but use atomic load/store to access the static
variable.

Regtested on x86_64-pc-linux-gnu.

libgfortran/ChangeLog:

2018-12-06  Janne Blomqvist  <jb@gcc.gnu.org>

Backport from trunk
PR libfortran/88137
* runtime/backtrace.c (show_backtrace): Store backtrace state in a
static variable, initialize once.

From-SVN: r266858

libgfortran/ChangeLog
libgfortran/runtime/backtrace.c

index 04a627e7c8b1374a76ab69669b0eea9977cf3c11..0aec54a54488dd1e15e4221a724488b6fcd1370f 100644 (file)
@@ -1,3 +1,10 @@
+2018-12-06  Janne Blomqvist  <jb@gcc.gnu.org>
+
+       Backport from trunk
+       PR libfortran/88137
+       * runtime/backtrace.c (show_backtrace): Store backtrace state in a
+       static variable, initialize once.
+
 2018-12-06  Release Manager
 
        * GCC 7.4.0 released.
index 77dd4d5f0ac999e2016f7933696e0913f520e4b5..d7e72c80460c85e9721ca532f0de6d94969bc878 100644 (file)
@@ -135,14 +135,23 @@ full_callback (void *data, uintptr_t pc, const char *filename,
 void
 show_backtrace (bool in_signal_handler)
 {
+  /* Note that libbacktrace allows the state to be accessed from
+     multiple threads, so we don't need to use a TLS variable for the
+     state here.  */
+  static struct backtrace_state *lbstate_saved;
   struct backtrace_state *lbstate;
   struct mystate state = { 0, false, in_signal_handler };
-  lbstate = backtrace_create_state (NULL, __gthread_active_p (),
-                                   error_callback, NULL);
 
-  if (lbstate == NULL)
-    return;
+  lbstate = __atomic_load_n (&lbstate_saved, __ATOMIC_RELAXED);
+  if (!lbstate)
+    {
+      lbstate = backtrace_create_state (NULL, __gthread_active_p (),
+                                       error_callback, NULL);
+      if (lbstate)
+       __atomic_store_n (&lbstate_saved, lbstate, __ATOMIC_RELAXED);
+      else
+       return;
+    }
 
   if (!BACKTRACE_SUPPORTED || (in_signal_handler && BACKTRACE_USES_MALLOC))
     {