diff options
Diffstat (limited to 'gdb/dwarf2/read.c')
-rw-r--r-- | gdb/dwarf2/read.c | 152 |
1 files changed, 65 insertions, 87 deletions
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 8019179..bf982f9 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -52,6 +52,7 @@ #include "elf-bfd.h" #include "event-top.h" #include "exceptions.h" +#include "gdbsupport/parallel-for.h" #include "gdbsupport/task-group.h" #include "maint.h" #include "symtab.h" @@ -3308,6 +3309,61 @@ public: } private: + /* The task for parallel workers that index units. */ + struct parallel_indexing_worker + { + parallel_indexing_worker (const char *step_name, + cooked_index_worker_debug_info *parent) + : m_scoped_time_it (step_name, parent->m_per_command_time), + m_parent (parent) + { + } + + DISABLE_COPY_AND_ASSIGN (parallel_indexing_worker); + + ~parallel_indexing_worker () + { + bfd_thread_cleanup (); + + m_thread_storage.done_reading (m_complaint_handler.release ()); + + /* Append the results of this worker to the parent instance. */ +#if CXX_STD_THREAD + std::lock_guard<std::mutex> lock (m_parent->m_results_mutex); +#endif + m_parent->m_results.emplace_back (std::move (m_thread_storage)); + } + + void operator() (iterator_range<dwarf2_per_cu_up *> range) + { + for (auto &it : range) + this->process_one (*it); + } + + private: + void process_one (dwarf2_per_cu &unit) + { + m_thread_storage.catch_error ([&] () + { + m_parent->process_unit (&unit, m_parent->m_per_objfile, + &m_thread_storage); + }); + } + + /* Measures the execution time of this worker. */ + scoped_time_it m_scoped_time_it; + + /* Delayed complaints and errors recorded while indexing units. */ + complaint_interceptor m_complaint_handler; + std::vector<gdb_exception> m_errors; + + /* Index storage for this worker. */ + cooked_index_worker_result m_thread_storage; + + /* The instance that spawned this worker. */ + cooked_index_worker_debug_info *m_parent; + }; + void do_reading () override; /* Print collected type unit statistics. */ @@ -3350,12 +3406,6 @@ private: /* An iterator for the comp units. */ using unit_iterator = std::vector<dwarf2_per_cu_up>::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_units (size_t task_number, unit_iterator first, - unit_iterator end); - /* Process unit THIS_CU. */ void process_unit (dwarf2_per_cu *this_cu, dwarf2_per_objfile *per_objfile, cooked_index_worker_result *storage); @@ -3580,32 +3630,6 @@ cooked_index_worker_debug_info::process_skeletonless_type_units } void -cooked_index_worker_debug_info::process_units (size_t task_number, - unit_iterator first, - unit_iterator end) -{ - SCOPE_EXIT { bfd_thread_cleanup (); }; - - /* Ensure that complaints are handled correctly. */ - complaint_interceptor complaint_handler; - - std::vector<gdb_exception> errors; - cooked_index_worker_result thread_storage; - for (auto inner = first; inner != end; ++inner) - { - dwarf2_per_cu *per_cu = inner->get (); - - thread_storage.catch_error ([&] () - { - process_unit (per_cu, m_per_objfile, &thread_storage); - }); - } - - thread_storage.done_reading (complaint_handler.release ()); - m_results[task_number] = std::move (thread_storage); -} - -void cooked_index_worker_debug_info::done_reading () { /* This has to wait until we read the CUs, we need the list of DWOs. */ @@ -3630,62 +3654,16 @@ cooked_index_worker_debug_info::do_reading () m_index_storage.get_addrmap (), &m_warnings); - /* We want to balance the load between the worker threads. This is - done by using the size of each CU as a rough estimate of how - difficult it will be to operate on. This isn't ideal -- for - example if dwz is used, the early CUs will all tend to be - "included" and won't be parsed independently. However, this - heuristic works well for typical compiler output. */ - - size_t total_size = 0; - for (const auto &per_cu : per_bfd->all_units) - total_size += per_cu->length (); - - /* How many worker threads we plan to use. We may not actually use - this many. We use 1 as the minimum to avoid division by zero, - and anyway in the N==0 case the work will be done - synchronously. */ - const size_t n_worker_threads - = std::max (gdb::thread_pool::g_thread_pool->thread_count (), (size_t) 1); - - /* How much effort should be put into each worker. */ - const size_t size_per_thread - = std::max (total_size / n_worker_threads, (size_t) 1); - - /* Work is done in a task group. */ - gdb::task_group workers ([this] () - { - this->done_reading (); - }); - - auto end = per_bfd->all_units.end (); - size_t task_count = 0; - for (auto iter = per_bfd->all_units.begin (); iter != end; ) - { - auto last = iter; - /* Put all remaining CUs into the last task. */ - if (task_count == n_worker_threads - 1) - last = end; - else - { - size_t chunk_size = 0; - for (; last != end && chunk_size < size_per_thread; ++last) - chunk_size += (*last)->length (); - } - - gdb_assert (iter != last); - workers.add_task ([this, task_count, iter, last] () - { - scoped_time_it time_it ("DWARF indexing worker", m_per_command_time); - process_units (task_count, iter, last); - }); - - ++task_count; - iter = last; - } + /* Launch parallel tasks to index units. - m_results.resize (task_count); - workers.start (); + The (unfortunate) reason why we don't use + std::vector<dwarf2_per_cu_up>::iterator as the parallel-for-each iterator + type is that std::atomic won't work with that type when building with + -D_GLIBCXX_DEBUG. */ + gdb::parallel_for_each_async<1, dwarf2_per_cu_up *, parallel_indexing_worker> + (per_bfd->all_units.data (), + per_bfd->all_units.data () + per_bfd->all_units.size (), + [this] () { this->done_reading (); }, "DWARF indexing worker", this); } static void |