Hi Heather, On Tue, Oct 10, 2023 at 03:42:57PM +0200, Mark Wielaard wrote: > From: Heather McIntyre <h...@rice.edu> > > * 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 <h...@rice.edu> > Signed-off-by: Mark Wielaard <m...@klomp.org> > --- > 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 <assert.h> > -#include <search.h> > +#include <eu-search.h> > #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