@@ -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<std::mutex> 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<gdb_exception> 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<cooked_index *>
+ (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<std::mutex> 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<cooked_index_worker> (per_objfile)),
+cooked_index::cooked_index (dwarf2_per_objfile *per_objfile,
+ std::unique_ptr<cooked_index_worker> &&worker)
+ : m_state (std::move (worker)),
m_per_bfd (per_objfile->per_bfd)
{
/* ACTIVE_VECTORS is not locked, and this assert ensures that this
@@ -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<dwarf2_per_cu_data_up>::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<result_type> m_results;
@@ -588,7 +586,8 @@ class cooked_index : public dwarf_scanner_base
object. */
using vec_type = std::vector<std::unique_ptr<cooked_index_shard>>;
- explicit cooked_index (dwarf2_per_objfile *per_objfile);
+ cooked_index (dwarf2_per_objfile *per_objfile,
+ std::unique_ptr<cooked_index_worker> &&worker);
~cooked_index () override;
DISABLE_COPY_AND_ASSIGN (cooked_index);
@@ -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<dwarf2_per_cu_data_up>::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<std::mutex> 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<gdb_exception> 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<cooked_index *>
- (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<std::mutex> 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<cooked_index_worker> 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. */