From: Janne Blomqvist Date: Thu, 6 Dec 2018 15:38:25 +0000 (+0200) Subject: Initialize backtrace state once X-Git-Tag: releases/gcc-7.5.0~741 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c11935a35ed225f448b405c93fbe4854cdf72de;p=thirdparty%2Fgcc.git Initialize backtrace state once 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 Backport from trunk PR libfortran/88137 * runtime/backtrace.c (show_backtrace): Store backtrace state in a static variable, initialize once. From-SVN: r266858 --- diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 04a627e7c8b1..0aec54a54488 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,10 @@ +2018-12-06 Janne Blomqvist + + 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. diff --git a/libgfortran/runtime/backtrace.c b/libgfortran/runtime/backtrace.c index 77dd4d5f0ac9..d7e72c80460c 100644 --- a/libgfortran/runtime/backtrace.c +++ b/libgfortran/runtime/backtrace.c @@ -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)) {