[PATCH, libfortran] PR 88137 Initialize backtrace state once
Janne Blomqvist
blomqvist.janne@gmail.com
Fri Nov 30 19:29:00 GMT 2018
On Fri, Nov 30, 2018 at 9:07 PM Thomas Schwinge <thomas@codesourcery.com>
wrote:
> Hi!
>
> On Thu, 22 Nov 2018 11:17:24 +0200, Janne Blomqvist <
> blomqvist.janne@gmail.com> wrote:
> > 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.
>
> Hmm, OK, but...
>
> > --- a/libgfortran/runtime/backtrace.c
> > +++ b/libgfortran/runtime/backtrace.c
> > @@ -146,11 +146,15 @@ full_callback (void *data, uintptr_t pc, const
> char *filename,
> > void
> > show_backtrace (bool in_signal_handler)
> > {
> > - struct backtrace_state *lbstate;
> > + /* 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;
> > struct mystate state = { 0, false, in_signal_handler };
> > -
> > - lbstate = backtrace_create_state (NULL, __gthread_active_p (),
> > - error_callback, NULL);
> > +
> > + if (!lbstate)
> > + lbstate = backtrace_create_state (NULL, __gthread_active_p (),
> > + error_callback, NULL);
>
> ... don't you still have to make sure that only one thread ever executes
> "backtrace_create_state", and writes into "lbstate" (via locking, or
> atomics, or "pthread_once", or some such)? Or is that situation (more
> than one thread entering "show_backtrace" with uninitialized "lbstate")
> not possible to happen for other reasons?
>
I thought about that, but I think it probably(?) doesn't matter.
- Two threads could race and run backtrace_create_state() in parallel, and
probably we'd waste some memory then, but that was already possible before.
- As for locking, the function can be called from a signal handler, so
pthread_mutex is out. I guess I could implement a spinlock with atomics,
but, meh, seems overkill.
- And using atomics to access lbstate, it's an aligned pointer anyway, so
while it's a race to access it, it shouldn't be possible to get a situation
with a corrupted value for the pointer, right? I could use
__atomic_load/store to access it, but that doesn't buy much in the end,
does it, since the problem is parallel initialization, and not non-atomic
access to the lbstate pointer? Or does gcc support targets with non-atomic
access to aligned pointers?
Or is there something I'm missing?
--
Janne Blomqvist
More information about the Gcc-patches
mailing list