]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Move cooked_index_worker to cooked-index-worker.[ch]
authorTom Tromey <tom@tromey.com>
Mon, 24 Mar 2025 21:34:39 +0000 (15:34 -0600)
committerTom Tromey <tom@tromey.com>
Tue, 1 Apr 2025 13:30:10 +0000 (07:30 -0600)
This moves the cooked_index_worker class to cooked-index-worker.[ch].

Approved-By: Simon Marchi <simon.marchi@efficios.com>
gdb/dwarf2/cooked-index-worker.c
gdb/dwarf2/cooked-index-worker.h
gdb/dwarf2/cooked-index.c
gdb/dwarf2/cooked-index.h

index 8a074a8952f2326d5ed0f3529fac6149ccf030fc..0ce4987658fcd2c11a704be56acbe8b40a1c8c11 100644 (file)
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "dwarf2/cooked-index-worker.h"
+#include "dwarf2/cooked-index.h"
+#include "gdbsupport/thread-pool.h"
+#include "run-on-main-thread.h"
+#include "event-top.h"
+#include "exceptions.h"
 
 /* See cooked-index-worker.h.  */
 
@@ -82,3 +87,144 @@ bool cooked_index_worker_result::cutu_reader_eq::operator()
 {
   return per_cu.index == reader->cu ()->per_cu->index;
 }
+
+/* See cooked-index.h.  */
+
+void
+cooked_index_worker::start ()
+{
+  gdb::thread_pool::g_thread_pool->post_task ([this] ()
+  {
+    try
+      {
+       do_reading ();
+      }
+    catch (const gdb_exception &exc)
+      {
+       m_failed = exc;
+       set (cooked_state::CACHE_DONE);
+      }
+
+    bfd_thread_cleanup ();
+  });
+}
+
+/* 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 = desired_state == cooked_state::CACHE_DONE;
+#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 ())
+    {
+      /* do_reading failed -- report it.  */
+      exception_print (gdb_stderr, *m_failed);
+      m_failed.reset ();
+      return done;
+    }
+
+  /* Only show a given exception a single time.  */
+  gdb::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 */
+}
+
+/* See cooked-index.h.  */
+
+void
+cooked_index_worker::write_to_cache (const cooked_index *idx,
+                                    deferred_warnings *warn) const
+{
+  if (idx != nullptr)
+    {
+      /* Writing to the index cache may cause a warning to be emitted.
+        See PR symtab/30837.  This arranges to capture all such
+        warnings.  This is safe because we know the deferred_warnings
+        object isn't in use by any other thread at this point.  */
+      scoped_restore_warning_hook defer (warn);
+      m_cache_store.store ();
+    }
+}
index 0f2fa6cb9de91516221eff5f0dd1b3ccc93873a2..514487b80d60e52fd1fbd36f010bac80b7c9d9cd 100644 (file)
 #include "dwarf2/types.h"
 #include "dwarf2/read.h"
 
+#if CXX_STD_THREAD
+#include <mutex>
+#include <condition_variable>
+#endif /* CXX_STD_THREAD */
+
 using cutu_reader_up = std::unique_ptr<cutu_reader>;
 
 /* An instance of this is created when scanning DWARF to create a
@@ -131,4 +136,122 @@ private:
   addrmap_mutable m_addrmap;
 };
 
+/* The possible states of the index.  See the explanatory comment
+   before cooked_index for more details.  */
+enum class cooked_state
+{
+  /* The default state.  This is not a valid argument to 'wait'.  */
+  INITIAL,
+  /* The initial scan has completed.  The name of "main" is now
+     available (if known).  The addrmaps are usable now.
+     Finalization has started but is not complete.  */
+  MAIN_AVAILABLE,
+  /* Finalization has completed.  This means the index is fully
+     available for queries.  */
+  FINALIZED,
+  /* Writing to the index cache has finished.  */
+  CACHE_DONE,
+};
+
+/* 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.
+
+   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)
+    : m_per_objfile (per_objfile),
+      m_cache_store (global_index_cache, per_objfile->per_bfd)
+  { }
+  virtual ~cooked_index_worker ()
+  { }
+  DISABLE_COPY_AND_ASSIGN (cooked_index_worker);
+
+  /* Start reading.  */
+  void start ();
+
+  /* Wait for a particular state to be achieved.  If ALLOW_QUIT is
+     true, then the loop will check the QUIT flag.  Normally this
+     method may only be called from the main thread; however, it can
+     be called from a worker thread provided that the desired state
+     has already been attained.  (This oddity is used by the index
+     cache writer.)  */
+  bool wait (cooked_state desired_state, bool allow_quit);
+
+protected:
+
+  /* Let cooked_index call the 'set' and 'write_to_cache' methods.  */
+  friend class cooked_index;
+
+  /* Set the current state.  */
+  void set (cooked_state desired_state);
+
+  /* Write to the index cache.  */
+  void write_to_cache (const cooked_index *idx,
+                      deferred_warnings *warn) const;
+
+  /* Helper function that does the work of reading.  This must be able
+     to be run in a worker thread without problems.  */
+  virtual void do_reading () = 0;
+
+  /* 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, a vector of errors that should be printed, and a
+     parent map.
+
+     The errors are retained because GDB's I/O system is not
+     thread-safe.  run_on_main_thread could be used, but that would
+     mean the messages are printed after the prompt, which looks
+     weird.  */
+  using result_type = std::tuple<cooked_index_shard_up,
+                                complaint_collection,
+                                std::vector<gdb_exception>,
+                                parent_map>;
+
+  /* The per-objfile object.  */
+  dwarf2_per_objfile *m_per_objfile;
+  /* Result of each worker task.  */
+  std::vector<result_type> m_results;
+  /* Any warnings emitted.  This is not in 'result_type' because (for
+     the time being at least), it's only needed in do_reading, not in
+     every worker.  Note that deferred_warnings uses gdb_stderr in its
+     constructor, and this should only be done from the main thread.
+     This is enforced in the cooked_index_worker constructor.  */
+  deferred_warnings m_warnings;
+
+  /* A map of all parent maps.  Used during finalization to fix up
+     parent relationships.  */
+  parent_map_map m_all_parents_map;
+
+#if CXX_STD_THREAD
+  /* Current state of this object.  */
+  cooked_state m_state = cooked_state::INITIAL;
+  /* Mutex and condition variable used to synchronize.  */
+  std::mutex m_mutex;
+  std::condition_variable m_cond;
+#endif /* CXX_STD_THREAD */
+  /* This flag indicates whether any complaints or exceptions that
+     arose during scanning have been reported by 'wait'.  This may
+     only be modified on the main thread.  */
+  bool m_reported = false;
+  /* If set, an exception occurred during reading; in this case the
+     scanning is stopped and this exception will later be reported by
+     the 'wait' method.  */
+  std::optional<gdb_exception> m_failed;
+  /* An object used to write to the index cache.  */
+  index_cache_store_context m_cache_store;
+};
+
+using cooked_index_worker_up = std::unique_ptr<cooked_index_worker>;
+
 #endif /* GDB_DWARF2_COOKED_INDEX_WORKER_H */
index 5d205a83d0917660c40c05afd5f9e058a81d053c..a632474dff82de781b839fc507f22283bb8e8b24 100644 (file)
 #include "dwarf2/stringify.h"
 #include "dwarf2/index-cache.h"
 #include "event-top.h"
-#include "exceptions.h"
 #include "split-name.h"
 #include "observable.h"
 #include "run-on-main-thread.h"
 #include <algorithm>
 #include "gdbsupport/task-group.h"
-#include "gdbsupport/thread-pool.h"
 #include <chrono>
 #include "cli/cli-cmds.h"
 
@@ -50,147 +48,6 @@ language_requires_canonicalization (enum language lang)
          || lang == language_cplus);
 }
 
-/* See cooked-index.h.  */
-
-void
-cooked_index_worker::start ()
-{
-  gdb::thread_pool::g_thread_pool->post_task ([this] ()
-  {
-    try
-      {
-       do_reading ();
-      }
-    catch (const gdb_exception &exc)
-      {
-       m_failed = exc;
-       set (cooked_state::CACHE_DONE);
-      }
-
-    bfd_thread_cleanup ();
-  });
-}
-
-/* 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 = desired_state == cooked_state::CACHE_DONE;
-#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 ())
-    {
-      /* do_reading failed -- report it.  */
-      exception_print (gdb_stderr, *m_failed);
-      m_failed.reset ();
-      return done;
-    }
-
-  /* Only show a given exception a single time.  */
-  gdb::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 */
-}
-
-/* See cooked-index.h.  */
-
-void
-cooked_index_worker::write_to_cache (const cooked_index *idx,
-                                    deferred_warnings *warn) const
-{
-  if (idx != nullptr)
-    {
-      /* Writing to the index cache may cause a warning to be emitted.
-        See PR symtab/30837.  This arranges to capture all such
-        warnings.  This is safe because we know the deferred_warnings
-        object isn't in use by any other thread at this point.  */
-      scoped_restore_warning_hook defer (warn);
-      m_cache_store.store ();
-    }
-}
-
 cooked_index::cooked_index (cooked_index_worker_up &&worker)
   : m_state (std::move (worker))
 {
index beef8ff588f0895cf08323ded02da47df74c7c96..1848798bfad2dece70882e0d0163cacabc7ad53f 100644 (file)
 #include "gdbsupport/range-chain.h"
 #include "complaints.h"
 #include "dwarf2/cooked-index-shard.h"
-
-#if CXX_STD_THREAD
-#include <mutex>
-#include <condition_variable>
-#endif /* CXX_STD_THREAD */
-
-struct dwarf2_per_cu;
-struct dwarf2_per_bfd;
-struct index_cache_store_context;
-struct cooked_index_entry;
-
-class cooked_index;
-
-/* The possible states of the index.  See the explanatory comment
-   before cooked_index for more details.  */
-enum class cooked_state
-{
-  /* The default state.  This is not a valid argument to 'wait'.  */
-  INITIAL,
-  /* The initial scan has completed.  The name of "main" is now
-     available (if known).  The addrmaps are usable now.
-     Finalization has started but is not complete.  */
-  MAIN_AVAILABLE,
-  /* Finalization has completed.  This means the index is fully
-     available for queries.  */
-  FINALIZED,
-  /* Writing to the index cache has finished.  */
-  CACHE_DONE,
-};
-
-/* 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.
-   
-   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)
-    : m_per_objfile (per_objfile),
-      m_cache_store (global_index_cache, per_objfile->per_bfd)
-  { }
-  virtual ~cooked_index_worker ()
-  { }
-  DISABLE_COPY_AND_ASSIGN (cooked_index_worker);
-
-  /* Start reading.  */
-  void start ();
-
-  /* Wait for a particular state to be achieved.  If ALLOW_QUIT is
-     true, then the loop will check the QUIT flag.  Normally this
-     method may only be called from the main thread; however, it can
-     be called from a worker thread provided that the desired state
-     has already been attained.  (This oddity is used by the index
-     cache writer.)  */
-  bool wait (cooked_state desired_state, bool allow_quit);
-
-protected:
-
-  /* Let cooked_index call the 'set' and 'write_to_cache' methods.  */
-  friend class cooked_index;
-
-  /* Set the current state.  */
-  void set (cooked_state desired_state);
-
-  /* Write to the index cache.  */
-  void write_to_cache (const cooked_index *idx,
-                      deferred_warnings *warn) const;
-
-  /* Helper function that does the work of reading.  This must be able
-     to be run in a worker thread without problems.  */
-  virtual void do_reading () = 0;
-
-  /* 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, a vector of errors that should be printed, and a
-     parent map.
-
-     The errors are retained because GDB's I/O system is not
-     thread-safe.  run_on_main_thread could be used, but that would
-     mean the messages are printed after the prompt, which looks
-     weird.  */
-  using result_type = std::tuple<cooked_index_shard_up,
-                                complaint_collection,
-                                std::vector<gdb_exception>,
-                                parent_map>;
-
-  /* The per-objfile object.  */
-  dwarf2_per_objfile *m_per_objfile;
-  /* Result of each worker task.  */
-  std::vector<result_type> m_results;
-  /* Any warnings emitted.  This is not in 'result_type' because (for
-     the time being at least), it's only needed in do_reading, not in
-     every worker.  Note that deferred_warnings uses gdb_stderr in its
-     constructor, and this should only be done from the main thread.
-     This is enforced in the cooked_index_worker constructor.  */
-  deferred_warnings m_warnings;
-
-  /* A map of all parent maps.  Used during finalization to fix up
-     parent relationships.  */
-  parent_map_map m_all_parents_map;
-
-#if CXX_STD_THREAD
-  /* Current state of this object.  */
-  cooked_state m_state = cooked_state::INITIAL;
-  /* Mutex and condition variable used to synchronize.  */
-  std::mutex m_mutex;
-  std::condition_variable m_cond;
-#endif /* CXX_STD_THREAD */
-  /* This flag indicates whether any complaints or exceptions that
-     arose during scanning have been reported by 'wait'.  This may
-     only be modified on the main thread.  */
-  bool m_reported = false;
-  /* If set, an exception occurred during reading; in this case the
-     scanning is stopped and this exception will later be reported by
-     the 'wait' method.  */
-  std::optional<gdb_exception> m_failed;
-  /* An object used to write to the index cache.  */
-  index_cache_store_context m_cache_store;
-};
-
-using cooked_index_worker_up = std::unique_ptr<cooked_index_worker>;
+#include "dwarf2/cooked-index-worker.h"
 
 /* The main index of DIEs.