From: Aaron Merey Date: Fri, 29 Aug 2025 23:00:33 +0000 (-0400) Subject: revise abbrev_lock X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9fda28c16ad0d9bc832e4473c54e4100250844b6;p=thirdparty%2Felfutils.git revise abbrev_lock --- diff --git a/libdw/Makefile.am b/libdw/Makefile.am index c98fe31f..030ec933 100644 --- a/libdw/Makefile.am +++ b/libdw/Makefile.am @@ -109,7 +109,8 @@ libdw_so_LIBS = ../libebl/libebl_pic.a ../backends/libebl_backends_pic.a \ ../libcpu/libcpu_pic.a libdw_pic.a ../libdwelf/libdwelf_pic.a \ ../libdwfl/libdwfl_pic.a ../libdwfl_stacktrace/libdwfl_stacktrace_pic.a libdw_so_DEPS = ../lib/libeu.a ../libelf/libelf.so -libdw_so_LDLIBS = $(libdw_so_DEPS) -ldl -lz $(argp_LDADD) $(fts_LIBS) $(obstack_LIBS) $(zip_LIBS) -pthread +libdw_so_LDLIBS = $(libdw_so_DEPS) -ldl -lz $(argp_LDADD) $(fts_LIBS) \ + $(obstack_LIBS) $(zip_LIBS) -pthread -latomic libdw.so: $(srcdir)/libdw.map $(libdw_so_LIBS) $(libdw_so_DEPS) $(AM_V_CCLD)$(LINK) $(dso_LDFLAGS) -o $@ \ -Wl,--soname,$@.$(VERSION),--enable-new-dtags \ diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c index 63e2805d..f5cabde0 100644 --- a/libdw/dwarf_begin_elf.c +++ b/libdw/dwarf_begin_elf.c @@ -359,8 +359,8 @@ valid_p (Dwarf *result) result->fake_loc_cu->version = 4; result->fake_loc_cu->split = NULL; eu_search_tree_init (&result->fake_loc_cu->locs_tree); - rwlock_init (result->fake_loc_cu->abbrev_lock); rwlock_init (result->fake_loc_cu->split_lock); + mutex_init (result->fake_loc_cu->abbrev_lock); mutex_init (result->fake_loc_cu->src_lock); mutex_init (result->fake_loc_cu->str_off_base_lock); mutex_init (result->fake_loc_cu->intern_lock); @@ -392,8 +392,8 @@ valid_p (Dwarf *result) result->fake_loclists_cu->version = 5; result->fake_loclists_cu->split = NULL; eu_search_tree_init (&result->fake_loclists_cu->locs_tree); - rwlock_init (result->fake_loclists_cu->abbrev_lock); rwlock_init (result->fake_loclists_cu->split_lock); + mutex_init (result->fake_loclists_cu->abbrev_lock); mutex_init (result->fake_loclists_cu->src_lock); mutex_init (result->fake_loclists_cu->str_off_base_lock); mutex_init (result->fake_loclists_cu->intern_lock); @@ -430,8 +430,8 @@ valid_p (Dwarf *result) result->fake_addr_cu->version = 5; result->fake_addr_cu->split = NULL; eu_search_tree_init (&result->fake_addr_cu->locs_tree); - rwlock_init (result->fake_addr_cu->abbrev_lock); rwlock_init (result->fake_addr_cu->split_lock); + mutex_init (result->fake_addr_cu->abbrev_lock); mutex_init (result->fake_addr_cu->src_lock); mutex_init (result->fake_addr_cu->str_off_base_lock); mutex_init (result->fake_addr_cu->intern_lock); diff --git a/libdw/dwarf_decl_file.c b/libdw/dwarf_decl_file.c index 1b91a4e9..03040e12 100644 --- a/libdw/dwarf_decl_file.c +++ b/libdw/dwarf_decl_file.c @@ -50,7 +50,8 @@ dwarf_decl_file (Dwarf_Die *die) Dwarf_Files *files; size_t nfiles; - if (INTUSE(dwarf_getsrcfiles) (&CUDIE (attr_mem.cu), &files, &nfiles) != 0) + Dwarf_Die cudie = CUDIE (attr_mem.cu); + if (INTUSE(dwarf_getsrcfiles) (&cudie, &files, &nfiles) != 0) return NULL; if (idx >= nfiles) diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c index 979b1168..fa27b19e 100644 --- a/libdw/dwarf_end.c +++ b/libdw/dwarf_end.c @@ -63,8 +63,8 @@ cu_free (void *arg) struct Dwarf_CU *p = (struct Dwarf_CU *) arg; eu_search_tree_fini (&p->locs_tree, noop_free); - rwlock_fini (p->abbrev_lock); rwlock_fini (p->split_lock); + mutex_fini (p->abbrev_lock); mutex_fini (p->src_lock); mutex_fini (p->str_off_base_lock); mutex_fini (p->intern_lock); diff --git a/libdw/dwarf_getscopevar.c b/libdw/dwarf_getscopevar.c index 7b1416f3..306ccae0 100644 --- a/libdw/dwarf_getscopevar.c +++ b/libdw/dwarf_getscopevar.c @@ -40,7 +40,8 @@ static int getfiles (Dwarf_Die *die, Dwarf_Files **files) { - return INTUSE(dwarf_getsrcfiles) (&CUDIE (die->cu), files, NULL); + Dwarf_Die cudie = CUDIE (die->cu); + return INTUSE(dwarf_getsrcfiles) (&cudie, files, NULL); } /* Fetch an attribute that should have a constant integer form. */ diff --git a/libdw/dwarf_tag.c b/libdw/dwarf_tag.c index 218382a1..7daa4813 100644 --- a/libdw/dwarf_tag.c +++ b/libdw/dwarf_tag.c @@ -53,15 +53,19 @@ __libdw_findabbrev (struct Dwarf_CU *cu, unsigned int code) /* Find the next entry. It gets automatically added to the hash table. */ + mutex_lock (cu->abbrev_lock); abb = __libdw_getabbrev (cu->dbg, cu, cu->last_abbrev_offset, &length); + if (abb == NULL || abb == DWARF_END_ABBREV) { /* Make sure we do not try to search for it again. */ cu->last_abbrev_offset = (size_t) -1l; + mutex_unlock (cu->abbrev_lock); return DWARF_END_ABBREV; } cu->last_abbrev_offset += length; + mutex_unlock (cu->abbrev_lock); /* Is this the code we are looking for? */ if (abb->code == code) diff --git a/libdw/libdwP.h b/libdw/libdwP.h index b77db142..900cc5c6 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -455,14 +455,14 @@ struct Dwarf_CU Don't access directly, call __libdw_cu_locs_base. */ Dwarf_Off locs_base; - /* Synchronize access to the abbrev member of a Dwarf_Die that - refers to this Dwarf_CU. Covers __libdw_die_abbrev. */ - rwlock_define(, abbrev_lock); - /* Synchronize access to the split member of this Dwarf_CU. Covers __libdw_find_split_unit. */ rwlock_define(, split_lock); + /* Synchronize access to the last_abbrev_offset member of a Dwarf_Die + that refers to this Dwarf_CU. */ + mutex_define(, abbrev_lock); + /* Synchronize access to the lines and files members. Covers dwarf_getsrclines and dwarf_getsrcfiles. */ mutex_define(, src_lock); @@ -823,41 +823,44 @@ static inline Dwarf_Abbrev * __nonnull_attribute__ (1) __libdw_dieabbrev (Dwarf_Die *die, const unsigned char **readp) { + Dwarf_Abbrev *end_abbrev = DWARF_END_ABBREV; + Dwarf_Abbrev *expected = (Dwarf_Abbrev *) NULL; + if (unlikely (die->cu == NULL)) { - die->abbrev = DWARF_END_ABBREV; - return DWARF_END_ABBREV; + __atomic_compare_exchange_n (&die->abbrev, &expected, end_abbrev, false, + __ATOMIC_RELEASE, __ATOMIC_ACQUIRE); + return end_abbrev; } - rwlock_wrlock (die->cu->abbrev_lock); + Dwarf_Abbrev *abbrev = __atomic_load_n (&die->abbrev, __ATOMIC_ACQUIRE); + if (abbrev != NULL && readp == NULL) + return abbrev; - /* Do we need to get the abbreviation, or need to read after the code? */ - if (die->abbrev == NULL || readp != NULL) + /* We need to get the abbreviation or need to read after the code. */ + unsigned int code; + const unsigned char *addr = die->addr; + if (addr >= (const unsigned char *) die->cu->endp) { - /* Get the abbreviation code. */ - unsigned int code; - const unsigned char *addr = die->addr; - - if (addr >= (const unsigned char *) die->cu->endp) - { - die->abbrev = DWARF_END_ABBREV; - rwlock_unlock (die->cu->abbrev_lock); - return DWARF_END_ABBREV; - } + __atomic_compare_exchange_n (&die->abbrev, &expected, end_abbrev, false, + __ATOMIC_RELEASE, __ATOMIC_ACQUIRE); + return end_abbrev; + } - get_uleb128 (code, addr, die->cu->endp); - if (readp != NULL) - *readp = addr; + /* Get the abbreviation code. */ + get_uleb128 (code, addr, die->cu->endp); + if (readp != NULL) + *readp = addr; - /* Find the abbreviation. */ - if (die->abbrev == NULL) - die->abbrev = __libdw_findabbrev (die->cu, code); - } + if (abbrev != NULL) + return abbrev; - Dwarf_Abbrev *result = die->abbrev; - rwlock_unlock (die->cu->abbrev_lock); + /* Find the abbreviation. */ + abbrev = __libdw_findabbrev (die->cu, code); + __atomic_compare_exchange_n (&die->abbrev, &expected, abbrev, false, + __ATOMIC_RELEASE, __ATOMIC_ACQUIRE); - return result; + return abbrev; } /* Helper functions for form handling. */ diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c index 59267343..a1f700d3 100644 --- a/libdw/libdw_findcu.c +++ b/libdw/libdw_findcu.c @@ -177,8 +177,8 @@ __libdw_intern_next_unit (Dwarf *dbg, bool debug_types) newp->startp = data->d_buf + newp->start; newp->endp = data->d_buf + newp->end; eu_search_tree_init (&newp->locs_tree); - rwlock_init (newp->abbrev_lock); rwlock_init (newp->split_lock); + mutex_init (newp->abbrev_lock); mutex_init (newp->src_lock); mutex_init (newp->str_off_base_lock); mutex_init (newp->intern_lock);