This moves the cooked_index_worker class to cooked-index-worker.[ch].
Approved-By: Simon Marchi <simon.marchi@efficios.com>
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. */
{
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 ();
+ }
+}
#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
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 */
#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"
|| 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))
{
#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.