From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from omta34.uswest2.a.cloudfilter.net (omta34.uswest2.a.cloudfilter.net [35.89.44.33]) by sourceware.org (Postfix) with ESMTPS id C2BCE38582B5 for ; Wed, 17 Jan 2024 16:39:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C2BCE38582B5 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 C2BCE38582B5 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=35.89.44.33 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1705509584; cv=none; b=S4B7d9w0uX6YyvxnFtvO7MgXQHgdkenRaO/QE2Q7A21kbOuWyCT9upI6f+Q6tQJuDW3kTO6nSlp7oW1UsbyyszLHONyrn1Sh4sAYWyCSjFeXoPEKKo5vJqFlZZGoxbRrwpR0xCxr1LcwPjgFU9mHpO20IKYsoZ/Q4KLA7igE+9Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1705509584; c=relaxed/simple; bh=kwvCDGrwMJI6aM7JXU2EU+KIx6iFBVN3kOI1kZ8ugQs=; h=DKIM-Signature:From:Date:Subject:MIME-Version:Message-Id:To; b=ZvSye8EUOP4lUDJGKLRDB3REDODm6o882rb+3eDpdZACxOp/LbI2XsUoVp8xJfP96ah9VwPKjG9fDMrGOpP/Yggj5dFw0m7wuqFd0KbKLXghABzbVY/1EcPE9iXEYfFrMQX4qgdOIZyAN4ET0vUgFJkEBw0eJeTYTSPvi6Dl2rk= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from eig-obgw-5010a.ext.cloudfilter.net ([10.0.29.199]) by cmsmtp with ESMTPS id Q7OfrGBiZMVQiQ8x1r17yJ; Wed, 17 Jan 2024 16:39:39 +0000 Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with ESMTPS id Q8x0rZJZzbhW6Q8x0rSM6m; Wed, 17 Jan 2024 16:39:39 +0000 X-Authority-Analysis: v=2.4 cv=aLPjFJxm c=1 sm=1 tr=0 ts=65a802cb a=ApxJNpeYhEAb1aAlGBBbmA==:117 a=ApxJNpeYhEAb1aAlGBBbmA==:17 a=OWjo9vPv0XrRhIrVQ50Ab3nP57M=:19 a=dLZJa+xiwSxG16/P+YVxDGlgEgI=:19 a=IkcTkHD0fZMA:10 a=dEuoMetlWLkA: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=iPR8ssK7aaANDTuQCkn7a1Pql19jALY0RxupvYTvTvA=; b=s9eXtMCKO6vQzkx36Nz0Nxq1oz IMu/RkqWdxYQ0M5MIBcU7ieY2OH7kSQBaBS+YLVKL6kq1SErC2K5vgb8PMixlisP9Nqd6P/2UoOWJ NNGR49esXNJJ3ZVyZFgFmLg76; Received: from 97-122-68-157.hlrn.qwest.net ([97.122.68.157]:56636 helo=[192.168.0.21]) by box5379.bluehost.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96.2) (envelope-from ) id 1rQ8x0-002OXE-0J for gdb-patches@sourceware.org; Wed, 17 Jan 2024 09:39:38 -0700 From: Tom Tromey Date: Wed, 17 Jan 2024 09:39:36 -0700 Subject: [PATCH v2 08/17] Change cooked_index_worker to abstract base class MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20240117-debug-names-fix-v2-8-dbd5971a9c31@tromey.com> References: <20240117-debug-names-fix-v2-0-dbd5971a9c31@tromey.com> In-Reply-To: <20240117-debug-names-fix-v2-0-dbd5971a9c31@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: 97.122.68.157 X-Source-L: No X-Exim-ID: 1rQ8x0-002OXE-0J X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: 97-122-68-157.hlrn.qwest.net ([192.168.0.21]) [97.122.68.157]:56636 X-Source-Auth: tom+tromey.com X-Email-Count: 13 X-Org: HG=bhshared;ORG=bluehost; X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTM3OS5ibHVlaG9zdC5jb20= X-Local-Domain: yes X-CMAE-Envelope: MS4xfGjSjY+pti9V/JLlY45fAi7Fyg7F95G7TSIiN/D0KM0uu1IdcGj8zKyDc4xbMR5ZUozQO6/VJhGQv5seus9MTmtNxhyNhWst2WLexnHo3YacqhIpesKh scdT26q1D0aC74nzHYqht8njSy28hq/xhmMA4WzByed4aUtodGgrlvgUM51nqzngnOfaR7sE6WYfY2FsJ8/719YLHNYZerI4yV0= X-Spam-Status: No, score=-3022.6 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,GIT_PATCH_0,JMQ_SPF_NEUTRAL,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 List-Id: 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 | 136 ++++++++++++++++++++++++++++++++- gdb/dwarf2/cooked-index.h | 43 ++++++----- gdb/dwarf2/read.c | 186 ++++++++++++---------------------------------- 3 files changed, 204 insertions(+), 161 deletions(-) diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c index d63fd0ab5bc..97a749f97e8 100644 --- a/gdb/dwarf2/cooked-index.c +++ b/gdb/dwarf2/cooked-index.c @@ -442,9 +442,141 @@ 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; + + /* Emit warnings first, maybe they were emitted before an exception + (if any) was thrown. */ + m_warnings.emit (); + + 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 24c83b56e05..f063fe088e8 100644 --- a/gdb/dwarf2/cooked-index.h +++ b/gdb/dwarf2/cooked-index.h @@ -500,13 +500,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. */ @@ -520,7 +528,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; @@ -530,21 +538,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 @@ -557,10 +559,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; /* Any warnings emitted. This is not in 'result_type' because (for @@ -648,7 +646,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 8010c0141f5..7691fe0050b 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -4824,32 +4824,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 (); }; @@ -4877,7 +4903,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. */ @@ -4899,23 +4925,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; @@ -4986,106 +4996,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; - - /* Emit warnings first, maybe they were emitted before an exception - (if any) was thrown. */ - m_warnings.emit (); - - 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, @@ -16818,7 +16728,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. */ -- 2.43.0