From patchwork Sun Dec 10 16:44:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 81820 Return-Path: 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 031CA3857C5E for ; Sun, 10 Dec 2023 16:46:07 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from omta034.useast.a.cloudfilter.net (omta034.useast.a.cloudfilter.net [44.202.169.33]) by sourceware.org (Postfix) with ESMTPS id 7A3723858437 for ; Sun, 10 Dec 2023 16:45:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7A3723858437 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=tromey.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tromey.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 7A3723858437 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=44.202.169.33 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702226709; cv=none; b=KT9jMZ02RLSicOGPCVf5pqARCQXcZFjnARwX5ulMX/XVA8ch+vfdq5GDbmVfIeROE0yl7kSZQCXVQx1KhITcjPfge2XVqyA1bSn/2qmWEUIkOd9WEbKxSNvRG/Valz4I45pfUdw6DBZG94Aw0SOlN26xSP8/a9CD86KAeAnlFLQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702226709; c=relaxed/simple; bh=+qCYt9qle01GOPEsXe6jFHT38TUYR2Xql4R8JwWheHs=; h=DKIM-Signature:From:Date:Subject:MIME-Version:Message-Id:To; b=Ky2q6KajdpgDi7DwX6GGKJsBetoxP8pFXFOP0vB359b1SsG7eFuA7thwuIdiZmVa65n+9GrWiygIRvPmAmEthvoop2kR0d0NeYjAWGUquOMa20n6iVAxlDhV+bZsLhUSMgc3bBZKm6qt/127T5Ix4nUk4VfNHWuUfbxlKLnGrN0= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from eig-obgw-5003a.ext.cloudfilter.net ([10.0.29.159]) by cmsmtp with ESMTPS id CGzLr6u0rjtZ3CMvZrNyDy; Sun, 10 Dec 2023 16:45:13 +0000 Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with ESMTPS id CMvQrS3vJnCfvCMvQrsyL0; Sun, 10 Dec 2023 16:45:04 +0000 X-Authority-Analysis: v=2.4 cv=KKpJsXJo c=1 sm=1 tr=0 ts=6575eb10 a=ApxJNpeYhEAb1aAlGBBbmA==:117 a=ApxJNpeYhEAb1aAlGBBbmA==:17 a=OWjo9vPv0XrRhIrVQ50Ab3nP57M=:19 a=dLZJa+xiwSxG16/P+YVxDGlgEgI=:19 a=IkcTkHD0fZMA:10 a=e2cXIFwxEfEA:10 a=Qbun_eYptAEA:10 a=YAENHxD7bNiQSPDCfLEA:9 a=QEXdDO2ut3YA:10 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=To:In-Reply-To:References:Message-Id:Content-Transfer-Encoding: Content-Type:MIME-Version:Subject:Date:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=hLqomxgwgei593FqIHbTegKMTVzR1BbGTjaslyRG/Xs=; b=QZLQseWDWN0YrQXksrLPA7g9Z2 uyYcsFbpC6H5152z2FRlsWC/ujA1M9x5IrqE5i0+qf8FVPwIGc3uCAMqlncxTwv7boak6QAIP5JeM EBGaOFGPncMac5RmUcDIZOH3k; Received: from [198.59.47.65] (port=52394 helo=[192.168.131.83]) by box5379.bluehost.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96.2) (envelope-from ) id 1rCMvP-001rpu-2U for gdb-patches@sourceware.org; Sun, 10 Dec 2023 09:45:03 -0700 From: Tom Tromey Date: Sun, 10 Dec 2023 09:44:58 -0700 Subject: [PATCH 09/17] Change cooked_index_worker to abstract base class MIME-Version: 1.0 Message-Id: <20231210-debug-names-fix-v1-9-a8f6d2525018@tromey.com> References: <20231210-debug-names-fix-v1-0-a8f6d2525018@tromey.com> In-Reply-To: <20231210-debug-names-fix-v1-0-a8f6d2525018@tromey.com> To: gdb-patches@sourceware.org X-Mailer: b4 0.12.4 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - box5379.bluehost.com X-AntiAbuse: Original Domain - sourceware.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - tromey.com X-BWhitelist: no X-Source-IP: 198.59.47.65 X-Source-L: No X-Exim-ID: 1rCMvP-001rpu-2U X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: ([192.168.131.83]) [198.59.47.65]:52394 X-Source-Auth: tom+tromey.com X-Email-Count: 10 X-Org: HG=bhshared;ORG=bluehost; X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTM3OS5ibHVlaG9zdC5jb20= X-Local-Domain: yes X-CMAE-Envelope: MS4xfN1Hbrcg+Db9DRw+Qxpwf6iQ7AjLPz9sWVZnz04CctOinp+8Pi0/IjQH8di95k3oV0aL0XDOainEicmUuHs01mz/grARDjuVM8HIENYCVsE7lrtxA+mh eHS5iAjH4pTFlBZK4fkQIFBuanozWa+hzdwck8KtCP5Vg6hVHiDxLu5l3qxOpoFn6T5EO2sLQegX9Wnv8vGE5cElJ88cdLaQEeQ= X-Spam-Status: No, score=-3024.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, JMQ_SPF_NEUTRAL, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org This changes cooked_index_worker to be an abstract base class. The base class implementation is moved to cooked-index.c, and a concrete subclass is added to read.c. This change is preparation for the new .debug_names reader, which will supply its own concrete implementation of the worker. --- gdb/dwarf2/cooked-index.c | 132 ++++++++++++++++++++++++++++++++- gdb/dwarf2/cooked-index.h | 43 ++++++----- gdb/dwarf2/read.c | 182 +++++++++++++--------------------------------- 3 files changed, 200 insertions(+), 157 deletions(-) diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c index a2bfe8e7b88..604e7526c0f 100644 --- a/gdb/dwarf2/cooked-index.c +++ b/gdb/dwarf2/cooked-index.c @@ -440,9 +440,137 @@ cooked_index_shard::find (const std::string &name, bool completing) const return range (lower, upper); } +/* See cooked-index.h. */ + +void +cooked_index_worker::start () +{ + gdb::thread_pool::g_thread_pool->post_task ([=] () + { + this->start_reading (); + }); +} + +/* See cooked-index.h. */ + +void +cooked_index_worker::start_reading () +{ + SCOPE_EXIT { bfd_thread_cleanup (); }; + + try + { + do_reading (); + } + catch (const gdb_exception &exc) + { + m_failed = exc; + set (cooked_state::CACHE_DONE); + } +} + +/* See cooked-index.h. */ + +bool +cooked_index_worker::wait (cooked_state desired_state, bool allow_quit) +{ + bool done; +#if CXX_STD_THREAD + { + std::unique_lock lock (m_mutex); + + /* This may be called from a non-main thread -- this functionality + is needed for the index cache -- but in this case we require + that the desired state already have been attained. */ + gdb_assert (is_main_thread () || desired_state <= m_state); + + while (desired_state > m_state) + { + if (allow_quit) + { + std::chrono::milliseconds duration { 15 }; + if (m_cond.wait_for (lock, duration) == std::cv_status::timeout) + QUIT; + } + else + m_cond.wait (lock); + } + done = m_state == cooked_state::CACHE_DONE; + } +#else + /* Without threads, all the work is done immediately on the main + thread, and there is never anything to wait for. */ + done = true; +#endif /* CXX_STD_THREAD */ + + /* Only the main thread is allowed to report complaints and the + like. */ + if (!is_main_thread ()) + return false; + + if (m_reported) + return done; + m_reported = true; + + if (m_failed.has_value ()) + { + /* start_reading failed -- report it. */ + exception_print (gdb_stderr, *m_failed); + m_failed.reset (); + return done; + } + + /* Only show a given exception a single time. */ + std::unordered_set seen_exceptions; + for (auto &one_result : m_results) + { + re_emit_complaints (std::get<1> (one_result)); + for (auto &one_exc : std::get<2> (one_result)) + if (seen_exceptions.insert (one_exc).second) + exception_print (gdb_stderr, one_exc); + } + + print_stats (); + + struct objfile *objfile = m_per_objfile->objfile; + dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd; + cooked_index *table + = (gdb::checked_static_cast + (per_bfd->index_table.get ())); + + auto_obstack temp_storage; + enum language lang = language_unknown; + const char *main_name = table->get_main_name (&temp_storage, &lang); + if (main_name != nullptr) + set_objfile_main_name (objfile, main_name, lang); + + /* dwarf_read_debug_printf ("Done building psymtabs of %s", */ + /* objfile_name (objfile)); */ + + return done; +} + +/* See cooked-index.h. */ + +void +cooked_index_worker::set (cooked_state desired_state) +{ + gdb_assert (desired_state != cooked_state::INITIAL); + +#if CXX_STD_THREAD + std::lock_guard guard (m_mutex); + gdb_assert (desired_state > m_state); + m_state = desired_state; + m_cond.notify_one (); +#else + /* Without threads, all the work is done immediately on the main + thread, and there is never anything to do. */ +#endif /* CXX_STD_THREAD */ +} -cooked_index::cooked_index (dwarf2_per_objfile *per_objfile) - : m_state (std::make_unique (per_objfile)), +cooked_index::cooked_index (dwarf2_per_objfile *per_objfile, + std::unique_ptr &&worker) + : m_state (std::move (worker)), m_per_bfd (per_objfile->per_bfd) { /* ACTIVE_VECTORS is not locked, and this assert ensures that this diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h index 62230cf429b..ffb7bf71e81 100644 --- a/gdb/dwarf2/cooked-index.h +++ b/gdb/dwarf2/cooked-index.h @@ -446,13 +446,21 @@ enum class cooked_state /* An object of this type controls the scanning of the DWARF. It schedules the worker tasks and tracks the current state. Once - scanning is done, this object is discarded. */ + scanning is done, this object is discarded. + + This is an abstract base class that defines the basic behavior of + scanners. Separate concrete implementations exist for scanning + .debug_names and .debug_info. */ class cooked_index_worker { public: - explicit cooked_index_worker (dwarf2_per_objfile *per_objfile); + explicit cooked_index_worker (dwarf2_per_objfile *per_objfile) + : m_per_objfile (per_objfile) + { } + virtual ~cooked_index_worker () + { } DISABLE_COPY_AND_ASSIGN (cooked_index_worker); /* Start reading. */ @@ -466,7 +474,7 @@ class cooked_index_worker cache writer.) */ bool wait (cooked_state desired_state, bool allow_quit); -private: +protected: /* Let cooked_index call the 'set' method. */ friend class cooked_index; @@ -476,21 +484,15 @@ class cooked_index_worker problems. */ void start_reading (); - /* Helper function that does most of the work for start_reading. */ - void do_reading (); - - /* After the last DWARF-reading task has finished, this function - does the remaining work to finish the scan. */ - void done_reading (); - - /* An iterator for the comp units. */ - typedef std::vector::iterator unit_iterator; + /* Helper function that does most of the work for start_reading. + This must be able to be run in a worker thread without + problems. */ + virtual void do_reading () = 0; - /* Process a batch of CUs. This may be called multiple times in - separate threads. TASK_NUMBER indicates which task this is -- - the result is stored in that slot of M_RESULTS. */ - void process_cus (size_t task_number, unit_iterator first, - unit_iterator end); + /* A callback that can print stats, if needed. This is called when + transitioning to the 'MAIN_AVAILABLE' state. */ + virtual void print_stats () + { } /* Each thread returns a tuple holding a cooked index, any collected complaints, and a vector of errors that should be printed. The @@ -503,10 +505,6 @@ class cooked_index_worker /* The per-objfile object. */ dwarf2_per_objfile *m_per_objfile; - /* A storage object for "leftovers" -- see the 'start' method, but - essentially things not parsed during the normal CU parsing - passes. */ - cooked_index_storage m_index_storage; /* Result of each worker task. */ std::vector m_results; @@ -588,7 +586,8 @@ class cooked_index : public dwarf_scanner_base object. */ using vec_type = std::vector>; - explicit cooked_index (dwarf2_per_objfile *per_objfile); + cooked_index (dwarf2_per_objfile *per_objfile, + std::unique_ptr &&worker); ~cooked_index () override; DISABLE_COPY_AND_ASSIGN (cooked_index); diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index acdb1969915..2b553bc5ac5 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -4834,32 +4834,58 @@ process_skeletonless_type_units (dwarf2_per_objfile *per_objfile, } } -cooked_index_worker::cooked_index_worker (dwarf2_per_objfile *per_objfile) - : m_per_objfile (per_objfile) +/* A subclass of cooked_index_worker that handles scanning + .debug_info. */ + +class cooked_index_debug_info : public cooked_index_worker { - gdb_assert (is_main_thread ()); +public: + cooked_index_debug_info (dwarf2_per_objfile *per_objfile) + : cooked_index_worker (per_objfile) + { + gdb_assert (is_main_thread ()); - struct objfile *objfile = per_objfile->objfile; - dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; + struct objfile *objfile = per_objfile->objfile; + dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; - dwarf_read_debug_printf ("Building psymtabs of objfile %s ...", - objfile_name (objfile)); + dwarf_read_debug_printf ("Building psymtabs of objfile %s ...", + objfile_name (objfile)); - per_bfd->map_info_sections (objfile); -} + per_bfd->map_info_sections (objfile); + } -void -cooked_index_worker::start () -{ - gdb::thread_pool::g_thread_pool->post_task ([=] () +private: + + void do_reading () override; + + void print_stats () override { - this->start_reading (); - }); -} + if (dwarf_read_debug > 0) + print_tu_stats (m_per_objfile); + } + + /* After the last DWARF-reading task has finished, this function + does the remaining work to finish the scan. */ + void done_reading (); + + /* An iterator for the comp units. */ + typedef std::vector::iterator unit_iterator; + + /* Process a batch of CUs. This may be called multiple times in + separate threads. TASK_NUMBER indicates which task this is -- + the result is stored in that slot of M_RESULTS. */ + void process_cus (size_t task_number, unit_iterator first, + unit_iterator end); + + /* A storage object for "leftovers" -- see the 'start' method, but + essentially things not parsed during the normal CU parsing + passes. */ + cooked_index_storage m_index_storage; +}; void -cooked_index_worker::process_cus (size_t task_number, unit_iterator first, - unit_iterator end) +cooked_index_debug_info::process_cus (size_t task_number, unit_iterator first, + unit_iterator end) { SCOPE_EXIT { bfd_thread_cleanup (); }; @@ -4887,7 +4913,7 @@ cooked_index_worker::process_cus (size_t task_number, unit_iterator first, } void -cooked_index_worker::done_reading () +cooked_index_debug_info::done_reading () { /* Only handle the scanning results here. Complaints and exceptions can only be dealt with on the main thread. */ @@ -4909,23 +4935,7 @@ cooked_index_worker::done_reading () } void -cooked_index_worker::start_reading () -{ - SCOPE_EXIT { bfd_thread_cleanup (); }; - - try - { - do_reading (); - } - catch (const gdb_exception &exc) - { - m_failed = exc; - set (cooked_state::CACHE_DONE); - } -} - -void -cooked_index_worker::do_reading () +cooked_index_debug_info::do_reading () { dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd; @@ -4995,102 +5005,6 @@ cooked_index_worker::do_reading () workers.start (); } -bool -cooked_index_worker::wait (cooked_state desired_state, bool allow_quit) -{ - bool done; -#if CXX_STD_THREAD - { - std::unique_lock lock (m_mutex); - - /* This may be called from a non-main thread -- this functionality - is needed for the index cache -- but in this case we require - that the desired state already have been attained. */ - gdb_assert (is_main_thread () || desired_state <= m_state); - - while (desired_state > m_state) - { - if (allow_quit) - { - std::chrono::milliseconds duration { 15 }; - if (m_cond.wait_for (lock, duration) == std::cv_status::timeout) - QUIT; - } - else - m_cond.wait (lock); - } - done = m_state == cooked_state::CACHE_DONE; - } -#else - /* Without threads, all the work is done immediately on the main - thread, and there is never anything to wait for. */ - done = true; -#endif /* CXX_STD_THREAD */ - - /* Only the main thread is allowed to report complaints and the - like. */ - if (!is_main_thread ()) - return false; - - if (m_reported) - return done; - m_reported = true; - - if (m_failed.has_value ()) - { - /* start_reading failed -- report it. */ - exception_print (gdb_stderr, *m_failed); - m_failed.reset (); - return done; - } - - /* Only show a given exception a single time. */ - std::unordered_set seen_exceptions; - for (auto &one_result : m_results) - { - re_emit_complaints (std::get<1> (one_result)); - for (auto &one_exc : std::get<2> (one_result)) - if (seen_exceptions.insert (one_exc).second) - exception_print (gdb_stderr, one_exc); - } - - if (dwarf_read_debug > 0) - print_tu_stats (m_per_objfile); - - struct objfile *objfile = m_per_objfile->objfile; - dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd; - cooked_index *table - = (gdb::checked_static_cast - (per_bfd->index_table.get ())); - - auto_obstack temp_storage; - enum language lang = language_unknown; - const char *main_name = table->get_main_name (&temp_storage, &lang); - if (main_name != nullptr) - set_objfile_main_name (objfile, main_name, lang); - - dwarf_read_debug_printf ("Done building psymtabs of %s", - objfile_name (objfile)); - - return done; -} - -void -cooked_index_worker::set (cooked_state desired_state) -{ - gdb_assert (desired_state != cooked_state::INITIAL); - -#if CXX_STD_THREAD - std::lock_guard guard (m_mutex); - gdb_assert (desired_state > m_state); - m_state = desired_state; - m_cond.notify_one (); -#else - /* Without threads, all the work is done immediately on the main - thread, and there is never anything to do. */ -#endif /* CXX_STD_THREAD */ -} - static void read_comp_units_from_section (dwarf2_per_objfile *per_objfile, struct dwarf2_section_info *section, @@ -16726,7 +16640,9 @@ start_debug_info_reader (dwarf2_per_objfile *per_objfile) /* Set the index table early so that sharing works even while scanning; and then start the scanning. */ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; - cooked_index *idx = new cooked_index (per_objfile); + std::unique_ptr worker + (new cooked_index_debug_info (per_objfile)); + cooked_index *idx = new cooked_index (per_objfile, std::move (worker)); per_bfd->index_table.reset (idx); /* Don't start reading until after 'index_table' is set. This avoids races. */