Hi Aaron,

On Wed, Feb 19, 2025 at 11:36:37PM -0500, Aaron Merey wrote:
>       * libdw/dwarf_getsrcfiles.c (dwarf_getsrcfiles): Use dwarf_lock.
>       * libdw/dwarf_getsrclines.c (dwarf_getsrclines): Ditto.
>       * libdw/dwarf_macro_getsrclines.c (dwarf_macro_getsrclines):
>         Ditto.
> 
> Signed-off-by: Aaron Merey <ame...@redhat.com>
> 
> ---
> v3 changes:
> This patch replaces v2 02/10 and v2 03/10.
> 
> The locking to dwarf_filesrc in 02/10 has been removed.  The removal of
> dwarf_filesrc locking triggered an error from helgrind that is now fixed
> by the dwarf_macro_getsrclines locking added in this patch.

That makes sense.

> On Wed, Feb 12, 2025 at 8:17 AM Mark Wielaard <m...@klomp.org> wrote:
> >
> > Hi Aaron,
> >
> > On Tue, 2025-02-04 at 16:50 -0500, Aaron Merey wrote:
> > >       * libdw/dwarf_getsrcfiles.c (dwarf_getsrcfiles): Use dwarf_lock.
> > >       * libdw/dwarf_getsrclines.c (dwarf_getsrclines): Use dwarf_lock.
> > >
> > > Signed-off-by: Aaron Merey <ame...@redhat.com>
> > > ---
> > > v2 changes: Combined from v1 patches 04/15 and 05/15.
> > >
> > >  libdw/dwarf_getsrcfiles.c | 11 +++++++----
> > >  libdw/dwarf_getsrclines.c | 25 +++++++++++++++++++------
> > >  2 files changed, 26 insertions(+), 10 deletions(-)
> >
> > OK, so here dwarf_lock is used to guard access to the Dwarf_CU fields
> > lines and files. Might it make sense to turn these into a Dwarf_CU
> > specific lock?
> 
> We could add another Dwarf_CU lock for this purpose. However we'll still
> need to use the dwarf_lock when lines or files haven't been read.  For now
> I'd prefer to keep the number of locks as low as possible and focus on
> performance improvements once we've achieved thread safety.
> 
> OTOH it shouldn't be too much work to add this cu lock so please let me
> know if you'd still like to see it added in this patch.

We should make dwarf_getsrcfiles and dwarf_getsrclines independent so
callers that onle need the file table don't need to "pay" for parsing
the whole line table. (I thought we had a bug for that, but cannot
find it now. If you also cannot find it, please let me know and I'll
file a new one.)

When we do that, we can reevaluate the locking situation.

I do think there should be lock per CU since now (especially since we
are using mutex) if you try to get the the file and/or line table for
one CU you block all threads working on other CUs in the Dwarf
Debug. So you are serializing the file/line table parsing.

> diff --git a/libdw/dwarf_getsrcfiles.c b/libdw/dwarf_getsrcfiles.c
> index 24e4b7d2..3029ce69 100644
> --- a/libdw/dwarf_getsrcfiles.c
> +++ b/libdw/dwarf_getsrcfiles.c
> @@ -47,9 +47,10 @@ dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, 
> size_t *nfiles)
>      }
>  
>    int res = -1;
> +  struct Dwarf_CU *const cu = cudie->cu;
> +  mutex_lock (cudie->cu->dbg->dwarf_lock);
>  
>    /* Get the information if it is not already known.  */
> -  struct Dwarf_CU *const cu = cudie->cu;
>    if (cu->files == NULL)
>      {
>        /* For split units there might be a simple file table (without lines).
> @@ -96,7 +97,10 @@ dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, 
> size_t *nfiles)
>         Dwarf_Off debug_line_offset;
>         if (__libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE,
>                              NULL, &debug_line_offset) == NULL)
> -         return -1;
> +         {
> +           mutex_unlock (cudie->cu->dbg->dwarf_lock);
> +           return -1;
> +         }
>  
>         res = __libdw_getsrcfiles (cu->dbg, debug_line_offset,
>                                    __libdw_getcompdir (cudie),
> @@ -115,8 +119,7 @@ dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, 
> size_t *nfiles)
>       *nfiles = cu->files->nfiles;
>      }
>  
> -  // XXX Eventually: unlocking here.
> -
> +  mutex_unlock (cudie->cu->dbg->dwarf_lock);
>    return res;
>  }
>  INTDEF (dwarf_getsrcfiles)

This looks correct. Minor nit about if { } indenting, which should be:

  if (...)
    {
      x;
    }

> diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
> index da78db67..c2e686b1 100644
> --- a/libdw/dwarf_getsrclines.c
> +++ b/libdw/dwarf_getsrclines.c
> @@ -1442,8 +1442,10 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines 
> **lines, size_t *nlines)
>        return -1;
>      }
>  
> -  /* Get the information if it is not already known.  */
>    struct Dwarf_CU *const cu = cudie->cu;
> +  mutex_lock (cu->dbg->dwarf_lock);
> +
> +  /* Get the information if it is not already known.  */
>    if (cu->lines == NULL)
>      {
>        /* For split units always pick the lines from the skeleton.  */
> @@ -1464,10 +1466,13 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines 
> **lines, size_t *nlines)
>                 *lines = cu->lines;
>                 *nlines = cu->lines->nlines;
>               }
> +
> +           mutex_unlock (cu->dbg->dwarf_lock);
>             return res;
>           }
>  
>         __libdw_seterrno (DWARF_E_NO_DEBUG_LINE);
> +       mutex_unlock (cu->dbg->dwarf_lock);
>         return -1;
>       }
>  
> @@ -1485,21 +1490,29 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines 
> **lines, size_t *nlines)
>        Dwarf_Off debug_line_offset;
>        if (__libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE,
>                          NULL, &debug_line_offset) == NULL)
> -     return -1;
> +     {
> +       mutex_unlock (cu->dbg->dwarf_lock);
> +       return -1;
> +     }
>  
>        if (__libdw_getsrclines (cu->dbg, debug_line_offset,
>                              __libdw_getcompdir (cudie),
>                              cu->address_size, &cu->lines, &cu->files) < 0)
> -     return -1;
> +     {
> +       mutex_unlock (cu->dbg->dwarf_lock);
> +       return -1;
> +     }
>      }
>    else if (cu->lines == (void *) -1l)
> -    return -1;
> +    {
> +      mutex_unlock (cu->dbg->dwarf_lock);
> +      return -1;
> +    }
>  
>    *lines = cu->lines;
>    *nlines = cu->lines->nlines;
>  
> -  // XXX Eventually: unlocking here.
> -
> +  mutex_unlock (cu->dbg->dwarf_lock);
>    return 0;
>  }
>  INTDEF(dwarf_getsrclines)

This also looks correct. Same nit about if { } indenting.

> diff --git a/libdw/dwarf_macro_getsrcfiles.c b/libdw/dwarf_macro_getsrcfiles.c
> index 5e02935d..8d7c2d03 100644
> --- a/libdw/dwarf_macro_getsrcfiles.c
> +++ b/libdw/dwarf_macro_getsrcfiles.c
> @@ -41,6 +41,8 @@ dwarf_macro_getsrcfiles (Dwarf *dbg, Dwarf_Macro *macro,
>  
>    /* macro is declared NN */
>    Dwarf_Macro_Op_Table *const table = macro->table;
> +
> +  mutex_lock (table->dbg->dwarf_lock);
>    if (table->files == NULL)
>      {
>        Dwarf_Off line_offset = table->line_offset;
> @@ -48,6 +50,7 @@ dwarf_macro_getsrcfiles (Dwarf *dbg, Dwarf_Macro *macro,
>       {
>         *files = NULL;
>         *nfiles = 0;
> +       mutex_unlock (table->dbg->dwarf_lock);
>         return 0;
>       }
>  
> @@ -79,6 +82,7 @@ dwarf_macro_getsrcfiles (Dwarf *dbg, Dwarf_Macro *macro,
>       table->files = (void *) -1;
>      }
>  
> +  mutex_unlock (table->dbg->dwarf_lock);
>    if (table->files == (void *) -1)
>      return -1;

This feels like the lock is dropped too early. You are
accessing/comparing table->files after the lock is dropped. I would
extend it to the end of the function.

  if (table->files == (void *) -1)
    {
      mutex_unlock (table->dbg->dwarf_lock);
      return -1;
    }

  *files = table->files;
  *nfiles = table->files->nfiles;
  mutex_unlock (table->dbg->dwarf_lock);
  return 0;

Cheers,

Mark

Reply via email to