Hi Mark, For the call to __libdw_intern_next_unit in __libdw_findcu, I have updated the locking to the per struct drawf lock. Although I have not encountered a data race report regarding the call to __libdw_intern_next_unit in dwarf_formref_die, I have also placed the updated locking there as well. On Thu, Oct 12, 2023 at 5:03 PM Mark Wielaard wrote: > Hi Heather, > > On Tue, Oct 10, 2023 at 03:42:57PM +0200, Mark Wielaard wrote: > > From: Heather McIntyre > > > > * libdw/libdw_findcu.c (findcu_cb): Use eu_tsearch. > > (__libdw_findcu): Use eu_tfind and next_tucu_offset_lock. > > (__libdw_findcu_addr): Use eu_tfind. > > (__libdw_find_split_dbg_addr): Likewise. > > > > Signed-off-by: Heather S. McIntyre > > Signed-off-by: Mark Wielaard > > --- > > libdw/libdw_findcu.c | 54 ++++++++++++++++++++++++++++---------------- > > 1 file changed, 35 insertions(+), 19 deletions(-) > > > > diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c > > index ed744231..e546fb0f 100644 > > --- a/libdw/libdw_findcu.c > > +++ b/libdw/libdw_findcu.c > > @@ -32,9 +32,13 @@ > > #endif > > > > #include > > -#include > > +#include > > #include "libdwP.h" > > > > +/* __libdw_findcu modifies "&dbg->next_tu_offset : > &dbg->next_cu_offset". > > + May read or write, so mutual exclusion is enforced to prevent a > race. */ > > +rwlock_define(static, next_tucu_offset_lock); > > + > > Could this be a per struct Dwarf lock? > > > static int > > findcu_cb (const void *arg1, const void *arg2) > > { > > @@ -213,7 +217,7 @@ __libdw_intern_next_unit (Dwarf *dbg, bool > debug_types) > > > > Dwarf_Sig8_Hash_insert (&dbg->sig8_hash, unit_id8, newp); > > > > /* Add the new entry to the search tree. */ > > - if (tsearch (newp, tree, findcu_cb) == NULL) > > + if (eu_tsearch (newp, tree, findcu_cb) == NULL) > > { > > /* Something went wrong. Undo the operation. */ > > *offsetp = oldoff; > > This is OK since when __libdw_intern_next_unit is called from > __libdw_findcu the next_tucu_offset_lock is held. > > But there is also a call to __libdw_intern_next_unit from > dwarf_formref_die. So there should also be a lock there? > > > @@ -234,28 +238,40 @@ __libdw_findcu (Dwarf *dbg, Dwarf_Off start, bool > v4_debug_types) > > > > /* Maybe we already know that CU. */ > > struct Dwarf_CU fake = { .start = start, .end = 0 }; > > - struct Dwarf_CU **found = tfind (&fake, tree, findcu_cb); > > + struct Dwarf_CU **found = eu_tfind (&fake, tree, findcu_cb); > > + struct Dwarf_CU *result = NULL; > > + > > if (found != NULL) > > return *found; > > > > - if (start < *next_offset) > > - { > > - __libdw_seterrno (DWARF_E_INVALID_DWARF); > > - return NULL; > > - } > > + rwlock_wrlock(next_tucu_offset_lock); > > > > - /* No. Then read more CUs. */ > > - while (1) > > + if (start < *next_offset) > > + __libdw_seterrno (DWARF_E_INVALID_DWARF); > > + else > > { > > - struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, > v4_debug_types); > > - if (newp == NULL) > > - return NULL; > > + /* No. Then read more CUs. */ > > + while (1) > > + { > > + struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, > > + > v4_debug_types); > > + if (newp == NULL) > > + { > > + result = NULL; > > + break; > > + } > > > > - /* Is this the one we are looking for? */ > > - if (start < *next_offset || start == newp->start) > > - return newp; > > + /* Is this the one we are looking for? */ > > + if (start < *next_offset || start == newp->start) > > + { > > + result = newp; > > + break; > > + } > > + } > > } > > - /* NOTREACHED */ > > + > > + rwlock_unlock(next_tucu_offset_lock); > > + return result; > > } > > This look OK. > > > struct Dwarf_CU * > > @@ -283,7 +299,7 @@ __libdw_findcu_addr (Dwarf *dbg, void *addr) > > return NULL; > > > > struct Dwarf_CU fake = { .start = start, .end = 0 }; > > - struct Dwarf_CU **found = tfind (&fake, tree, findcu_cb); > > + struct Dwarf_CU **found = eu_tfind (&fake, tree, findcu_cb); > > > > if (found != NULL) > > return *found; > > @@ -298,7 +314,7 @@ __libdw_find_split_dbg_addr (Dwarf *dbg, void *addr) > > /* XXX Assumes split DWARF only has CUs in main IDX_debug_info. */ > > Elf_Data fake_data = { .d_buf = addr, .d_size = 0 }; > > Dwarf fake = { .sectiondata[IDX_debug_info] = &fake_data }; > > - Dwarf **found = tfind (&fake, &dbg->split_tree, __libdw_finddbg_cb); > > + Dwarf **found = eu_tfind (&fake, &dbg->split_tree, > __libdw_finddbg_cb); > > > > if (found != NULL) > > return *found; > > OK. > > Thanks, > > Mark >