Message ID | 20231010134300.53830-11-mark@klomp.org |
---|---|
State | Superseded |
Delegated to: | Aaron Merey |
Headers |
Return-Path: <elfutils-devel-bounces+patchwork=sourceware.org@sourceware.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5AAFA3861840 for <patchwork@sourceware.org>; Tue, 10 Oct 2023 13:44:01 +0000 (GMT) X-Original-To: elfutils-devel@sourceware.org Delivered-To: elfutils-devel@sourceware.org Received: from gnu.wildebeest.org (gnu.wildebeest.org [45.83.234.184]) by sourceware.org (Postfix) with ESMTPS id D1C55385609B for <elfutils-devel@sourceware.org>; Tue, 10 Oct 2023 13:43:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D1C55385609B Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=klomp.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=klomp.org Received: from r6.localdomain (82-217-174-174.cable.dynamic.v4.ziggo.nl [82.217.174.174]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by gnu.wildebeest.org (Postfix) with ESMTPSA id 1E42B3022F1B; Tue, 10 Oct 2023 15:43:35 +0200 (CEST) Received: by r6.localdomain (Postfix, from userid 1000) id 33BA93403F6; Tue, 10 Oct 2023 15:43:34 +0200 (CEST) From: Mark Wielaard <mark@klomp.org> To: elfutils-devel@sourceware.org Cc: hsm2@rice.edu, Mark Wielaard <mark@klomp.org> Subject: [PATCH 11/16] libdw: Add locking around __libdw_dieabbrev for dwarf_hasattr Date: Tue, 10 Oct 2023 15:42:55 +0200 Message-ID: <20231010134300.53830-11-mark@klomp.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20231010134300.53830-1-mark@klomp.org> References: <301fac87e83ebbbd677750579ae9a3429b461bdf.camel@klomp.org> <20231010134300.53830-1-mark@klomp.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-3033.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, JMQ_SPF_NEUTRAL, KAM_DMARC_STATUS, RCVD_IN_BARRACUDACENTRAL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: elfutils-devel@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Elfutils-devel mailing list <elfutils-devel.sourceware.org> List-Unsubscribe: <https://sourceware.org/mailman/options/elfutils-devel>, <mailto:elfutils-devel-request@sourceware.org?subject=unsubscribe> List-Archive: <https://sourceware.org/pipermail/elfutils-devel/> List-Post: <mailto:elfutils-devel@sourceware.org> List-Help: <mailto:elfutils-devel-request@sourceware.org?subject=help> List-Subscribe: <https://sourceware.org/mailman/listinfo/elfutils-devel>, <mailto:elfutils-devel-request@sourceware.org?subject=subscribe> Errors-To: elfutils-devel-bounces+patchwork=sourceware.org@sourceware.org |
Series |
[01/16] lib: Add new once_define and once macros to eu-config.h
|
|
Commit Message
Mark Wielaard
Oct. 10, 2023, 1:42 p.m. UTC
From: Heather McIntyre <hsm2@rice.edu> * libdw/dwarf_hasattr.c (dwarf_hasattr): Use die_abbrev_lock around __libdw_dieabbrev call. Signed-off-by: Heather S. McIntyre <hsm2@rice.edu> Signed-off-by: Mark Wielaard <mark@klomp.org> --- libdw/dwarf_hasattr.c | 9 +++++++++ 1 file changed, 9 insertions(+)
Comments
Hi Heather, On Tue, 2023-10-10 at 15:42 +0200, Mark Wielaard wrote: > From: Heather McIntyre <hsm2@rice.edu> > > * libdw/dwarf_hasattr.c (dwarf_hasattr): Use die_abbrev_lock > around __libdw_dieabbrev call. > > Signed-off-by: Heather S. McIntyre <hsm2@rice.edu> > Signed-off-by: Mark Wielaard <mark@klomp.org> > --- > libdw/dwarf_hasattr.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > > diff --git a/libdw/dwarf_hasattr.c b/libdw/dwarf_hasattr.c > index eca08394..92f8de68 100644 > --- a/libdw/dwarf_hasattr.c > +++ b/libdw/dwarf_hasattr.c > @@ -34,6 +34,10 @@ > #include <dwarf.h> > #include "libdwP.h" > > +/* dwarf_hasattr() calls __libdw_dieabbrev() in libdwP.h. > + __libdw_dieabbrev() reads/writes "die->abbrev". > + Mutual exclusion is enforced around the call to __libdw_dieabbrev to prevent a race. */ > +rwlock_define(static, die_abbrev_lock); dwarf_child, dwarf_getattrs, dwarf_haschildren and dwarf_tag also use __libdw_dieabbrev to get the Dwarf_Abbrev pointer for the given Dwarf_DIE. Shouldn't they also use such locking? Or have the locking inside __libdw_dieabbrev itself? Also there are many Dwarf_Dies which all start out "lazy" without abbrev set. So taking a global static lock, or even taking any pthread lock at all might be a big overhead. Is there some way we can do this with atomics instead? > > int > dwarf_hasattr (Dwarf_Die *die, unsigned int search_name) > @@ -41,8 +45,13 @@ dwarf_hasattr (Dwarf_Die *die, unsigned int search_name) > if (die == NULL) > return 0; > > + rwlock_wrlock(die_abbrev_lock); > + > /* Find the abbreviation entry. */ > Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL); > + > + rwlock_unlock(die_abbrev_lock); > + > if (unlikely (abbrevp == DWARF_END_ABBREV)) > { > __libdw_seterrno (DWARF_E_INVALID_DWARF);
Hi Mark, I see now that this is incomplete considering the other places that also call this function. I do agree that global locking may be heavy if 1) implemented in all of these locations, or 2) implemented directly in __libdw_dieabbrev. We could use atomics here directly in __libdw_dieabbrev. I have given this a try and it is currently passing all tests, including the new ones I added for data race detection. I know you mentioned that taking any pthread lock at all might be a big overhead, but since I implemented a per dwarf struct lock, would using that be a possibility? Assuming multiple calls to __libdw_dieabbrev will be working on different dwarf objects. On Tue, Oct 10, 2023 at 8:44 AM Mark Wielaard <mark@klomp.org> wrote: > Hi Heather, > > On Tue, 2023-10-10 at 15:42 +0200, Mark Wielaard wrote: > From: Heather McIntyre <hsm2@rice.edu> > > * libdw/dwarf_hasattr.c (dwarf_hasattr): Use die_abbrev_lock > around __libdw_dieabbrev call. > > Signed-off-by: Heather S. McIntyre <hsm2@rice.edu> > Signed-off-by: Mark Wielaard <mark@klomp.org> > --- > libdw/dwarf_hasattr.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > > diff --git a/libdw/dwarf_hasattr.c b/libdw/dwarf_hasattr.c > index eca08394..92f8de68 100644 > --- a/libdw/dwarf_hasattr.c > +++ b/libdw/dwarf_hasattr.c > @@ -34,6 +34,10 @@ > #include <dwarf.h> > #include "libdwP.h" > > +/* dwarf_hasattr() calls __libdw_dieabbrev() in libdwP.h. > + __libdw_dieabbrev() reads/writes "die->abbrev". > + Mutual exclusion is enforced around the call to __libdw_dieabbrev to > prevent a race. */ > +rwlock_define(static, die_abbrev_lock); > > dwarf_child, dwarf_getattrs, dwarf_haschildren and dwarf_tag also use > __libdw_dieabbrev to get the Dwarf_Abbrev pointer for the given > Dwarf_DIE. Shouldn't they also use such locking? Or have the locking > inside __libdw_dieabbrev itself? > > Also there are many Dwarf_Dies which all start out "lazy" without > abbrev set. So taking a global static lock, or even taking any pthread > lock at all might be a big overhead. Is there some way we can do this > with atomics instead? > > > int > dwarf_hasattr (Dwarf_Die *die, unsigned int search_name) > @@ -41,8 +45,13 @@ dwarf_hasattr (Dwarf_Die *die, unsigned int > search_name) > if (die == NULL) > return 0; > > + rwlock_wrlock(die_abbrev_lock); > + > /* Find the abbreviation entry. */ > Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL); > + > + rwlock_unlock(die_abbrev_lock); > + > if (unlikely (abbrevp == DWARF_END_ABBREV)) > { > __libdw_seterrno (DWARF_E_INVALID_DWARF); >
Hi Heather, On Tue, Oct 17, 2023 at 02:57:39PM -0500, Heather McIntyre wrote: > I see now that this is incomplete considering the other places that also > call this function. I do agree that global locking may be heavy if 1) > implemented in all of these locations, or 2) implemented directly in > __libdw_dieabbrev. We could use atomics here directly in __libdw_dieabbrev. > I have given this a try and it is currently passing all tests, including > the new ones I added for data race detection. > > I know you mentioned that taking any pthread lock at all might be a big > overhead, but since I implemented a per dwarf struct lock, would using that > be a possibility? Assuming multiple calls to __libdw_dieabbrev will be > working on different dwarf objects. I have been thinking about this issue and I think we made a mistake in designing how a Dwarf_Die is lazy initialized. The abbrev field of a Dwarf_Die is only set when needed by calling __libdw_dieabbrev, which means we need some kind of locking or atomic swapping whenever we try to use that field. I assume the idea originally was that calling __libdw_dieabbrev is fairly "heavy" (it is, potentially reading the whole .debug_abbrev for the CU). So we try to postpone it till it is really needed. But in practice it is always needed. Without the abbrev field set you can just call dwarf_dieoffset, dwarf_cuoffset, dwarf_diecu and dwarf_getabbrev. In theory you could avoid adding the abbrev for the initial CU DIE for a Dwarf_CU when you are iterating over all CUs and know you don't need the CU without inspecting the initial CU DIE. But the Dwarf_Abbrev_Hash for the Dwarf_CU will already be initialized. And normally the abbrev for the first DIE will also be the first abbrev, so searching for it should be really quick. So I think setting the Dwarf_Die abbrev field lazy is not really helpful and makes the code needlessly complex. If we set the abbrev field when a Dwarf_Die is created we can simplify the code and don't need all this locking when we just want to access the field. This of course is still a lot of coding, we'll have to check every place that initializes a new Dwarf_Die. Which will have to call __libdw_dieabbrev directly. But I think that will not need any extra locking because the Dwarf_Abbrev_Hash used is already thread-safe (it was written by Srđan Milaković also from Rice University). What do you think? Cheers, Mark
diff --git a/libdw/dwarf_hasattr.c b/libdw/dwarf_hasattr.c index eca08394..92f8de68 100644 --- a/libdw/dwarf_hasattr.c +++ b/libdw/dwarf_hasattr.c @@ -34,6 +34,10 @@ #include <dwarf.h> #include "libdwP.h" +/* dwarf_hasattr() calls __libdw_dieabbrev() in libdwP.h. + __libdw_dieabbrev() reads/writes "die->abbrev". + Mutual exclusion is enforced around the call to __libdw_dieabbrev to prevent a race. */ +rwlock_define(static, die_abbrev_lock); int dwarf_hasattr (Dwarf_Die *die, unsigned int search_name) @@ -41,8 +45,13 @@ dwarf_hasattr (Dwarf_Die *die, unsigned int search_name) if (die == NULL) return 0; + rwlock_wrlock(die_abbrev_lock); + /* Find the abbreviation entry. */ Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL); + + rwlock_unlock(die_abbrev_lock); + if (unlikely (abbrevp == DWARF_END_ABBREV)) { __libdw_seterrno (DWARF_E_INVALID_DWARF);