diff options
author | Tom Tromey <tom@tromey.com> | 2019-03-03 10:15:30 -0700 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2019-10-01 13:38:24 -0600 |
commit | cec2f67ef73d024dddbdf85e3546d1cf13014e68 (patch) | |
tree | d83bc4981ccfc8fe8ac6b7601411d2ea05ab8fb3 | |
parent | 8c0fae46d6693fa34b0c102cc5872e02075678c8 (diff) | |
download | binutils-gdb-cec2f67ef73d024dddbdf85e3546d1cf13014e68.tar.gz |
Demangle minsyms in parallel
This patch introduces a simple parallel for_each and changes the
minimal symbol reader to use it when computing the demangled name for
a minimal symbol. This yields a speedup when reading minimal symbols.
gdb/ChangeLog
2019-09-30 Tom Tromey <tom@tromey.com>
* minsyms.c (minimal_symbol_reader::install): Use
parallel_for_each.
* gdbsupport/parallel-for.h: New file.
* gdbsupport/parallel-for.c: New file.
* Makefile.in (HFILES_NO_SRCDIR): Add gdbsupport/parallel-for.h.
(COMMON_SFILES): Add gdbsupport/parallel-for.c.
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/Makefile.in | 2 | ||||
-rw-r--r-- | gdb/gdbsupport/parallel-for.c | 27 | ||||
-rw-r--r-- | gdb/gdbsupport/parallel-for.h | 101 | ||||
-rw-r--r-- | gdb/minsyms.c | 31 |
5 files changed, 160 insertions, 10 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 402d5432425..e2b91c613ba 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,14 @@ 2019-09-30 Tom Tromey <tom@tromey.com> + * minsyms.c (minimal_symbol_reader::install): Use + parallel_for_each. + * gdbsupport/parallel-for.h: New file. + * gdbsupport/parallel-for.c: New file. + * Makefile.in (HFILES_NO_SRCDIR): Add gdbsupport/parallel-for.h. + (COMMON_SFILES): Add gdbsupport/parallel-for.c. + +2019-09-30 Tom Tromey <tom@tromey.com> + * event-top.h (thread_local_segv_handler): Declare. * event-top.c (thread_local_segv_handler): New global. (install_handle_sigsegv, handle_sigsegv): New functions. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index d4eca61d06e..c7b9efdbbc6 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -970,6 +970,7 @@ COMMON_SFILES = \ gdbsupport/gdb_vecs.c \ gdbsupport/netstuff.c \ gdbsupport/new-op.c \ + gdbsupport/parallel-for.c \ gdbsupport/pathstuff.c \ gdbsupport/print-utils.c \ gdbsupport/ptid.c \ @@ -1469,6 +1470,7 @@ HFILES_NO_SRCDIR = \ gdbsupport/common-inferior.h \ gdbsupport/netstuff.h \ gdbsupport/host-defs.h \ + gdbsupport/parallel-for.h \ gdbsupport/pathstuff.h \ gdbsupport/print-utils.h \ gdbsupport/ptid.h \ diff --git a/gdb/gdbsupport/parallel-for.c b/gdb/gdbsupport/parallel-for.c new file mode 100644 index 00000000000..0024278bd7f --- /dev/null +++ b/gdb/gdbsupport/parallel-for.c @@ -0,0 +1,27 @@ +/* Parallel for loops + + Copyright (C) 2019 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "gdbsupport/common-defs.h" +#include "gdbsupport/parallel-for.h" + +namespace gdb +{ +/* See parallel-for.h. */ +int max_threads = -1; +} diff --git a/gdb/gdbsupport/parallel-for.h b/gdb/gdbsupport/parallel-for.h new file mode 100644 index 00000000000..60b9472e1fe --- /dev/null +++ b/gdb/gdbsupport/parallel-for.h @@ -0,0 +1,101 @@ +/* Parallel for loops + + Copyright (C) 2019 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef GDBSUPPORT_PARALLEL_FOR_H +#define GDBSUPPORT_PARALLEL_FOR_H + +#include <algorithm> +#if CXX_STD_THREAD +#include <system_error> +#include <thread> +#endif + +#include "gdbsupport/block-signals.h" + +namespace gdb +{ + +/* True if threading should be enabled. */ + +extern int max_threads; + +/* A very simple "parallel for". This splits the range of iterators + into subranges, and then passes each subrange to the callback. The + work may or may not be done in separate threads. + + This approach was chosen over having the callback work on single + items because it makes it simple for the caller to do + once-per-subrange initialization and destruction. */ + +template<class RandomIt, class RangeFunction> +void +parallel_for_each (RandomIt first, RandomIt last, RangeFunction callback) +{ +#if CXX_STD_THREAD + int n_threads = std::thread::hardware_concurrency (); + /* So we can use a local array below. */ + const int local_max = 16; + /* Be sure to handle the "unlimited" case. */ + if (max_threads >= 0 && n_threads > max_threads) + n_threads = max_threads; + if (n_threads > local_max) + n_threads = local_max; + int n_actual_threads = 0; + + std::thread threads[local_max]; + size_t n_elements = last - first; + if (n_threads > 1 && 2 * n_threads <= n_elements) + { + /* Ensure that signals used by gdb are blocked in the new + threads. */ + block_signals blocker; + + size_t elts_per_thread = n_elements / n_threads; + n_actual_threads = n_threads - 1; + for (int i = 0; i < n_actual_threads; ++i) + { + RandomIt end = first + elts_per_thread; + try + { + threads[i] = std::thread (callback, first, end); + } + catch (const std::system_error &failure) + { + /* If a thread failed to start, ignore it and fall back + to processing in the main thread. */ + n_actual_threads = i; + break; + } + first = end; + } + } +#endif /* CXX_STD_THREAD */ + + /* Process all the remaining elements in the main thread. */ + callback (first, last); + +#if CXX_STD_THREAD + for (int i = 0; i < n_actual_threads; ++i) + threads[i].join (); +#endif /* CXX_STD_THREAD */ +} + +} + +#endif /* GDBSUPPORT_PARALLEL_FOR_H */ diff --git a/gdb/minsyms.c b/gdb/minsyms.c index 2b259d39c11..84bf2bb61e2 100644 --- a/gdb/minsyms.c +++ b/gdb/minsyms.c @@ -53,6 +53,8 @@ #include "gdbsupport/symbol.h" #include <algorithm> #include "safe-ctype.h" +#include "gdbsupport/alt-stack.h" +#include "gdbsupport/parallel-for.h" /* See minsyms.h. */ @@ -1332,16 +1334,25 @@ minimal_symbol_reader::install () m_objfile->per_bfd->msymbols = std::move (msym_holder); msymbols = m_objfile->per_bfd->msymbols.get (); - for (int i = 0; i < mcount; ++i) - { - if (!msymbols[i].name_set) - { - symbol_set_names (&msymbols[i], msymbols[i].name, - strlen (msymbols[i].name), 0, - m_objfile->per_bfd); - msymbols[i].name_set = 1; - } - } + gdb::parallel_for_each + (&msymbols[0], &msymbols[mcount], + [&] (minimal_symbol *start, minimal_symbol *end) + { + /* Ensure that SIGSEGV is delivered to an alternate signal + stack. */ + gdb::alternate_signal_stack signal_stack; + + for (minimal_symbol *msym = start; msym < end; ++msym) + { + if (!msym->name_set) + { + symbol_set_names (msym, msym->name, + strlen (msym->name), 0, + m_objfile->per_bfd); + msym->name_set = 1; + } + } + }); build_minimal_symbol_hash_tables (m_objfile); } |