Hi Aaron,

On Fri, 2026-10-30 at 01:16 -0400, Aaron Merey wrote:
> Move cache_sections' reloc_info initialization code into new function
> cache_sections_locked, which cache_sections calls while holding
> dwfl->load_lock.
> 
> Atomics are used to acquire intitialized reloc_info without needing to
> obtain the load_lock.

Looks correct to me. cache_sections_locked now doesn't manupulate the
Dwfl_Module reloc_info structure directly.

Thanks,

Mark

> Signed-off-by: Aaron Merey <[email protected]>
> ---
>  libdwfl/derelocate.c | 53 ++++++++++++++++++++++++++++++++------------
>  1 file changed, 39 insertions(+), 14 deletions(-)
> 
> diff --git a/libdwfl/derelocate.c b/libdwfl/derelocate.c
> index 2f80b20f..f9dbbe55 100644
> --- a/libdwfl/derelocate.c
> +++ b/libdwfl/derelocate.c
> @@ -77,13 +77,11 @@ compare_secrefs (const void *a, const void *b)
>  }
>  
>  static int
> -cache_sections (Dwfl_Module *mod)
> +cache_sections_locked (Dwfl_Module *mod, struct dwfl_relocation **result)
>  {
> -  if (likely (mod->reloc_info != NULL))
> -    return mod->reloc_info->count;
> -
>    struct secref *refs = NULL;
>    size_t nrefs = 0;
> +  struct dwfl_relocation *reloc_info = NULL;
>  
>    size_t shstrndx;
>    if (unlikely (elf_getshdrstrndx (mod->main.elf, &shstrndx) < 0))
> @@ -165,8 +163,8 @@ cache_sections (Dwfl_Module *mod)
>       }
>      }
>  
> -  mod->reloc_info = malloc (offsetof (struct dwfl_relocation, refs[nrefs]));
> -  if (unlikely (mod->reloc_info == NULL))
> +  reloc_info = malloc (offsetof (struct dwfl_relocation, refs[nrefs]));
> +  if (unlikely (reloc_info == NULL))
>      goto nomem;
>  
>    struct secref **sortrefs = malloc (nrefs * sizeof sortrefs[0]);
> @@ -179,14 +177,14 @@ cache_sections (Dwfl_Module *mod)
>  
>    qsort (sortrefs, nrefs, sizeof sortrefs[0], &compare_secrefs);
>  
> -  mod->reloc_info->count = nrefs;
> +  reloc_info->count = nrefs;
>    for (size_t i = 0; i < nrefs; ++i)
>      {
> -      mod->reloc_info->refs[i].name = sortrefs[i]->name;
> -      mod->reloc_info->refs[i].scn = sortrefs[i]->scn;
> -      mod->reloc_info->refs[i].relocs = sortrefs[i]->relocs;
> -      mod->reloc_info->refs[i].start = sortrefs[i]->start;
> -      mod->reloc_info->refs[i].end = sortrefs[i]->end;
> +      reloc_info->refs[i].name = sortrefs[i]->name;
> +      reloc_info->refs[i].scn = sortrefs[i]->scn;
> +      reloc_info->refs[i].relocs = sortrefs[i]->relocs;
> +      reloc_info->refs[i].start = sortrefs[i]->start;
> +      reloc_info->refs[i].end = sortrefs[i]->end;
>        free (sortrefs[i]);
>      }
>  
> @@ -212,16 +210,20 @@ cache_sections (Dwfl_Module *mod)
>             Elf_Scn *tscn = elf_getscn (mod->main.elf, shdr->sh_info);
>             if (likely (tscn != NULL))
>               for (size_t i = 0; i < nrefs; ++i)
> -               if (mod->reloc_info->refs[i].scn == tscn)
> +               if (reloc_info->refs[i].scn == tscn)
>                   {
> -                   mod->reloc_info->refs[i].relocs = scn;
> +                   reloc_info->refs[i].relocs = scn;
>                     break;
>                   }
>           }
>       }
>      }
>  
> +  *result = reloc_info;
> +  reloc_info = NULL;
> +
>  free_refs:
> +  free (reloc_info);
>    while (refs != NULL)
>      {
>        struct secref *ref = refs;
> @@ -232,6 +234,29 @@ free_refs:
>    return nrefs;
>  }
>  
> +static int
> +cache_sections (Dwfl_Module *mod)
> +{
> +  if (likely (atomic_load_acquire (&mod->reloc_info) != NULL))
> +    return mod->reloc_info->count;
> +
> +  int count;
> +  mutex_lock (mod->dwfl->load_lock);
> +
> +  if (mod->reloc_info == NULL)
> +    {
> +      struct dwfl_relocation *reloc_info = NULL;
> +      count = cache_sections_locked (mod, &reloc_info);
> +      if (count >= 0)
> +     atomic_store_release (&mod->reloc_info, reloc_info);
> +    }
> +  else
> +    count = mod->reloc_info->count;
> +
> +  mutex_unlock (mod->dwfl->load_lock);
> +  return count;
> +}
> +
>  
>  int
>  dwfl_module_relocations (Dwfl_Module *mod)

Reply via email to