[PATCH 2/3] libdw: Rewrite the memory handler to be thread-safe.

Mark Wielaard mark@klomp.org
Thu Oct 24 16:47:00 GMT 2019


Hi,

On Mon, 2019-10-21 at 20:00 +0200, Mark Wielaard wrote:
> I think we cannot use the atomic_load () function, but have to use
> atomic_load_explicit. So it would become:
> 
> diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
> index fc573cb3..a2e94436 100644
> --- a/libdw/dwarf_end.c
> +++ b/libdw/dwarf_end.c
> @@ -95,7 +95,10 @@ dwarf_end (Dwarf *dwarf)
>        tdestroy (dwarf->split_tree, noop_free);
>  
>        /* Free the internally allocated memory.  */
> -      struct libdw_memblock *memp = (struct libdw_memblock *)dwarf->mem_tail;
> +      struct libdw_memblock *memp;
> +      memp = (struct libdw_memblock *) (atomic_load_explicit
> +					(&dwarf->mem_tail,
> +					 memory_order_relaxed));
>        while (memp != NULL)
>  	{
>  	  struct libdw_memblock *prevp = memp->prev;

I made two more small changes to add error checking for
pthread_key_create and pthread_setspecific, even though I couldn't
trigger any of them to fail in this code, it seemed bad to just ignore
if they would fail:

diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
index f865f69c..8d137414 100644
--- a/libdw/dwarf_begin_elf.c
+++ b/libdw/dwarf_begin_elf.c
@@ -418,7 +418,12 @@ dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp)
      actual allocation.  */
   result->mem_default_size = mem_default_size;
   result->oom_handler = __libdw_oom;
-  pthread_key_create (&result->mem_key, NULL);
+  if (pthread_key_create (&result->mem_key, NULL) != 0)
+    {
+      free (result);
+      __libdw_seterrno (DWARF_E_NOMEM); /* no memory or max pthread keys.  */
+      return NULL;
+    }
   atomic_init (&result->mem_tail, (uintptr_t)NULL);
 
   if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
diff --git a/libdw/libdw_alloc.c b/libdw/libdw_alloc.c
index 78977e54..f2e74d18 100644
--- a/libdw/libdw_alloc.c
+++ b/libdw/libdw_alloc.c
@@ -54,7 +54,8 @@ __libdw_allocate (Dwarf *dbg, size_t minsize, size_t align)
 
   newp->prev = (struct libdw_memblock*)atomic_exchange_explicit(
       &dbg->mem_tail, (uintptr_t)newp, memory_order_relaxed);
-  pthread_setspecific(dbg->mem_key, newp);
+  if (pthread_setspecific (dbg->mem_key, newp) != 0)
+    dbg->oom_handler ();
 
   return (void *) result;
 }

With that I pushed it to master. Thanks a lot for this code.

To my surprise the code was actually slightly (although almost in the
noise) faster in the single threaded cases I tested. Well done!

Cheers,

Mark



More information about the Elfutils-devel mailing list