mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
Compare commits
15 Commits
gdb-10.2-r
...
users/cbie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12f4dc41bf | ||
|
|
6f509f2489 | ||
|
|
f445b98611 | ||
|
|
65ffb7c552 | ||
|
|
4a7dabea39 | ||
|
|
e4efbf384e | ||
|
|
9ca863ae09 | ||
|
|
15ae80b467 | ||
|
|
b0ca8b4f16 | ||
|
|
af2deea454 | ||
|
|
fe29e1fcde | ||
|
|
d14a705ab9 | ||
|
|
530c45db24 | ||
|
|
a7231e9d1c | ||
|
|
bb749d8ae3 |
106
gdb/ChangeLog
106
gdb/ChangeLog
@@ -1,3 +1,109 @@
|
||||
2019-10-19 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* gdbsupport/thread-pool.c (thread_pool::set_thread_count): Set
|
||||
name of worker thread.
|
||||
* gdbsupport/common.m4 (GDB_AC_COMMON): Check for
|
||||
pthread_setname_np.
|
||||
* configure, config.in: Rebuild.
|
||||
|
||||
2019-10-19 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* python/python.c (class gdbpy_gil): New.
|
||||
(struct gdbpy_event): Add constructor, destructor, operator().
|
||||
(gdbpy_post_event): Use run_on_main_thread.
|
||||
(gdbpy_initialize_events): Remove.
|
||||
(do_start_initialization): Update.
|
||||
|
||||
2019-10-19 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* NEWS: Add entry.
|
||||
* maint.c (_initialize_maint_cmds): Add "worker-threads" maint
|
||||
commands. Call update_thread_pool_size.
|
||||
(update_thread_pool_size, maintenance_set_worker_threads): New
|
||||
functions.
|
||||
(n_worker_threads): New global.
|
||||
|
||||
2019-10-19 Christian Biesinger <cbiesinger@google.com>
|
||||
Tom Tromey <tom@tromey.com>
|
||||
|
||||
* minsyms.c (minimal_symbol_reader::install): Use
|
||||
parallel_for_each.
|
||||
* gdbsupport/parallel-for.h: New file.
|
||||
* Makefile.in (HFILES_NO_SRCDIR): Add gdbsupport/parallel-for.h.
|
||||
|
||||
2019-10-19 Christian Biesinger <cbiesinger@google.com>
|
||||
Tom Tromey <tom@tromey.com>
|
||||
|
||||
* gdbsupport/thread-pool.h: New file.
|
||||
* gdbsupport/thread-pool.c: New file.
|
||||
* Makefile.in (COMMON_SFILES): Add thread-pool.c.
|
||||
(HFILES_NO_SRCDIR): Add thread-pool.h.
|
||||
|
||||
2019-10-19 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.
|
||||
(async_init_signals): Install SIGSEGV handler.
|
||||
* cp-support.c (gdb_demangle_jmp_buf): Change type. Now
|
||||
thread-local.
|
||||
(report_failed_demangle): New function.
|
||||
(gdb_demangle): Make core_dump_allowed atomic. Remove signal
|
||||
handler-setting code, instead use segv_handler. Run warning code
|
||||
on main thread.
|
||||
|
||||
2019-10-19 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* unittests/main-thread-selftests.c: New file.
|
||||
* Makefile.in (SUBDIR_UNITTESTS_SRCS): Add
|
||||
main-thread-selftests.c.
|
||||
* ser-event.h (run_on_main_thread): Declare.
|
||||
* ser-event.c (runnable_event, runnables, runnable_mutex): New
|
||||
globals.
|
||||
(run_events, run_on_main_thread, _initialize_ser_event): New
|
||||
functions.
|
||||
|
||||
2019-10-19 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* main.c (setup_alternate_signal_stack): Remove.
|
||||
(captured_main_1): Use gdb::alternate_signal_stack.
|
||||
* gdbsupport/alt-stack.h: New file.
|
||||
|
||||
2019-10-19 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* gdbsupport/signals-state-save-restore.c (original_signal_mask):
|
||||
Remove comment.
|
||||
(save_original_signals_state, restore_original_signals_state): Use
|
||||
gdb_sigmask.
|
||||
* linux-nat.c (block_child_signals, restore_child_signals_mask)
|
||||
(_initialize_linux_nat): Use gdb_sigmask.
|
||||
* guile/guile.c (_initialize_guile): Use block_signals.
|
||||
* Makefile.in (HFILES_NO_SRCDIR): Add gdb-sigmask.h.
|
||||
* gdbsupport/gdb-sigmask.h: New file.
|
||||
* event-top.c (async_sigtstp_handler): Use gdb_sigmask.
|
||||
* cp-support.c (gdb_demangle): Use gdb_sigmask.
|
||||
* gdbsupport/common.m4 (GDB_AC_COMMON): Check for
|
||||
pthread_sigmask.
|
||||
* configure, config.in: Rebuild.
|
||||
* gdbsupport/block-signals.h: New file.
|
||||
|
||||
2019-10-19 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* acinclude.m4: Include ax_pthread.m4.
|
||||
* Makefile.in (PTHREAD_CFLAGS, PTHREAD_LIBS): New variables.
|
||||
(INTERNAL_CFLAGS_BASE): Use PTHREAD_CFLAGS.
|
||||
(CLIBS): Use PTHREAD_LIBS.
|
||||
(aclocal_m4_deps): Add ax_pthread.m4.
|
||||
* config.in, configure: Rebuild.
|
||||
* gdbsupport/common.m4 (GDB_AC_COMMON): Check for std::thread.
|
||||
|
||||
2019-10-19 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* symtab.h (struct minimal_symbol) <name_set>: New member.
|
||||
* minsyms.c (minimal_symbol_reader::record_full): Copy name.
|
||||
Don't call symbol_set_names.
|
||||
(minimal_symbol_reader::install): Call symbol_set_names.
|
||||
|
||||
2019-11-10 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* tui/tui-wingeneral.c (tui_unhighlight_win): Use can_box.
|
||||
|
||||
@@ -210,6 +210,9 @@ WERROR_CFLAGS = @WERROR_CFLAGS@
|
||||
GDB_WARN_CFLAGS = $(WARN_CFLAGS)
|
||||
GDB_WERROR_CFLAGS = $(WERROR_CFLAGS)
|
||||
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
|
||||
RDYNAMIC = @RDYNAMIC@
|
||||
|
||||
# Where is the INTL library? Typically in ../intl.
|
||||
@@ -430,6 +433,7 @@ SUBDIR_UNITTESTS_SRCS = \
|
||||
unittests/optional-selftests.c \
|
||||
unittests/parse-connection-spec-selftests.c \
|
||||
unittests/ptid-selftests.c \
|
||||
unittests/main-thread-selftests.c \
|
||||
unittests/mkdir-recursive-selftests.c \
|
||||
unittests/rsp-low-selftests.c \
|
||||
unittests/scoped_fd-selftests.c \
|
||||
@@ -580,7 +584,7 @@ INTERNAL_CFLAGS_BASE = \
|
||||
$(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) $(ZLIBINC) \
|
||||
$(BFD_CFLAGS) $(INCLUDE_CFLAGS) $(LIBDECNUMBER_CFLAGS) \
|
||||
$(INTL_CFLAGS) $(INCGNU) $(ENABLE_CFLAGS) $(INTERNAL_CPPFLAGS) \
|
||||
$(SRCHIGH_CFLAGS) $(TOP_CFLAGS)
|
||||
$(SRCHIGH_CFLAGS) $(TOP_CFLAGS) $(PTHREAD_CFLAGS)
|
||||
INTERNAL_WARN_CFLAGS = $(INTERNAL_CFLAGS_BASE) $(GDB_WARN_CFLAGS)
|
||||
INTERNAL_CFLAGS = $(INTERNAL_WARN_CFLAGS) $(GDB_WERROR_CFLAGS)
|
||||
|
||||
@@ -594,7 +598,7 @@ LDFLAGS = @LDFLAGS@
|
||||
# PROFILE_CFLAGS is _not_ included, however, because we use monstartup.
|
||||
INTERNAL_LDFLAGS = \
|
||||
$(CXXFLAGS) $(GLOBAL_CFLAGS) $(MH_LDFLAGS) \
|
||||
$(LDFLAGS) $(CONFIG_LDFLAGS)
|
||||
$(LDFLAGS) $(CONFIG_LDFLAGS) $(PTHREAD_CFLAGS)
|
||||
|
||||
# Libraries and corresponding dependencies for compiling gdb.
|
||||
# XM_CLIBS, defined in *config files, have host-dependent libs.
|
||||
@@ -605,7 +609,7 @@ CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(LIBCTF) $(ZLIB) \
|
||||
@LIBS@ @GUILE_LIBS@ @PYTHON_LIBS@ \
|
||||
$(LIBEXPAT) $(LIBLZMA) $(LIBBABELTRACE) $(LIBIPT) \
|
||||
$(LIBIBERTY) $(WIN32LIBS) $(LIBGNU) $(LIBICONV) $(LIBMPFR) \
|
||||
$(SRCHIGH_LIBS) $(LIBXXHASH)
|
||||
$(SRCHIGH_LIBS) $(LIBXXHASH) $(PTHREAD_LIBS)
|
||||
CDEPS = $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) $(LIBCTF) \
|
||||
$(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(LIBGNU)
|
||||
|
||||
@@ -989,6 +993,7 @@ COMMON_SFILES = \
|
||||
gdbsupport/signals.c \
|
||||
gdbsupport/signals-state-save-restore.c \
|
||||
gdbsupport/tdesc.c \
|
||||
gdbsupport/thread-pool.c \
|
||||
gdbsupport/xml-utils.c \
|
||||
complaints.c \
|
||||
completer.c \
|
||||
@@ -1468,6 +1473,7 @@ HFILES_NO_SRCDIR = \
|
||||
gdbsupport/fileio.h \
|
||||
gdbsupport/format.h \
|
||||
gdbsupport/gdb-dlfcn.h \
|
||||
gdbsupport/gdb-sigmask.h \
|
||||
gdbsupport/gdb_assert.h \
|
||||
gdbsupport/gdb_binary_search.h \
|
||||
gdbsupport/gdb_tilde_expand.h \
|
||||
@@ -1481,6 +1487,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 \
|
||||
@@ -1490,6 +1497,7 @@ HFILES_NO_SRCDIR = \
|
||||
gdbsupport/signals-state-save-restore.h \
|
||||
gdbsupport/symbol.h \
|
||||
gdbsupport/tdesc.h \
|
||||
gdbsupport/thread-pool.h \
|
||||
gdbsupport/version.h \
|
||||
gdbsupport/x86-xstate.h \
|
||||
gdbsupport/xml-utils.h \
|
||||
@@ -2061,7 +2069,8 @@ aclocal_m4_deps = \
|
||||
../config/depstand.m4 \
|
||||
../config/lcmessage.m4 \
|
||||
../config/codeset.m4 \
|
||||
../config/zlib.m4
|
||||
../config/zlib.m4 \
|
||||
../config/ax_pthread.m4
|
||||
|
||||
$(srcdir)/aclocal.m4: @MAINTAINER_MODE_TRUE@ $(aclocal_m4_deps)
|
||||
cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
|
||||
|
||||
7
gdb/NEWS
7
gdb/NEWS
@@ -146,6 +146,13 @@ set style highlight background COLOR
|
||||
set style highlight intensity VALUE
|
||||
Control the styling of highlightings.
|
||||
|
||||
maint set worker-threads
|
||||
maint show worker-threads
|
||||
Control the number of worker threads that can be used by GDB. The
|
||||
default is "unlimited", which lets GDB choose a number that is
|
||||
reasonable. Currently worker threads are only used when demangling
|
||||
the names of linker symbols.
|
||||
|
||||
maint set test-settings KIND
|
||||
maint show test-settings KIND
|
||||
A set of commands used by the testsuite for exercising the settings
|
||||
|
||||
@@ -73,6 +73,8 @@ m4_include(ptrace.m4)
|
||||
|
||||
m4_include(ax_cxx_compile_stdcxx.m4)
|
||||
|
||||
m4_include([../config/ax_pthread.m4])
|
||||
|
||||
## ----------------------------------------- ##
|
||||
## ANSIfy the C compiler whenever possible. ##
|
||||
## From Franc,ois Pinard ##
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
#undef CRAY_STACKSEG_END
|
||||
|
||||
/* Define to 1 if std::thread works. */
|
||||
#undef CXX_STD_THREAD
|
||||
|
||||
/* Define to 1 if using `alloca.c'. */
|
||||
#undef C_ALLOCA
|
||||
|
||||
@@ -336,6 +339,15 @@
|
||||
/* Define if <sys/procfs.h> has psaddr_t. */
|
||||
#undef HAVE_PSADDR_T
|
||||
|
||||
/* Have PTHREAD_PRIO_INHERIT. */
|
||||
#undef HAVE_PTHREAD_PRIO_INHERIT
|
||||
|
||||
/* Define to 1 if you have the `pthread_setname_np' function. */
|
||||
#undef HAVE_PTHREAD_SETNAME_NP
|
||||
|
||||
/* Define to 1 if you have the `pthread_sigmask' function. */
|
||||
#undef HAVE_PTHREAD_SIGMASK
|
||||
|
||||
/* Define to 1 if you have the `ptrace64' function. */
|
||||
#undef HAVE_PTRACE64
|
||||
|
||||
@@ -625,6 +637,10 @@
|
||||
/* Define to 1 if the "%ll" format works to print long longs. */
|
||||
#undef PRINTF_HAS_LONG_LONG
|
||||
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
#undef PTHREAD_CREATE_JOINABLE
|
||||
|
||||
/* Define to the type of arg 1 for ptrace. */
|
||||
#undef PTRACE_TYPE_ARG1
|
||||
|
||||
|
||||
850
gdb/configure
vendored
850
gdb/configure
vendored
@@ -702,6 +702,11 @@ SYSTEM_GDBINIT
|
||||
TARGET_SYSTEM_ROOT
|
||||
CONFIG_LDFLAGS
|
||||
RDYNAMIC
|
||||
PTHREAD_CFLAGS
|
||||
PTHREAD_LIBS
|
||||
PTHREAD_CC
|
||||
ax_pthread_config
|
||||
SED
|
||||
ALLOCA
|
||||
LTLIBIPT
|
||||
LIBIPT
|
||||
@@ -2515,6 +2520,73 @@ fi
|
||||
as_fn_set_status $ac_retval
|
||||
|
||||
} # ac_fn_cxx_try_link
|
||||
|
||||
# ac_fn_cxx_check_func LINENO FUNC VAR
|
||||
# ------------------------------------
|
||||
# Tests whether FUNC exists, setting the cache variable VAR accordingly
|
||||
ac_fn_cxx_check_func ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
|
||||
$as_echo_n "checking for $2... " >&6; }
|
||||
if eval \${$3+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
|
||||
For example, HP-UX 11i <limits.h> declares gettimeofday. */
|
||||
#define $2 innocuous_$2
|
||||
|
||||
/* System header to define __stub macros and hopefully few prototypes,
|
||||
which can conflict with char $2 (); below.
|
||||
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
|
||||
<limits.h> exists even on freestanding compilers. */
|
||||
|
||||
#ifdef __STDC__
|
||||
# include <limits.h>
|
||||
#else
|
||||
# include <assert.h>
|
||||
#endif
|
||||
|
||||
#undef $2
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char $2 ();
|
||||
/* The GNU C library defines this for functions which it implements
|
||||
to always fail with ENOSYS. Some functions are actually named
|
||||
something starting with __ and the normal name is an alias. */
|
||||
#if defined __stub_$2 || defined __stub___$2
|
||||
choke me
|
||||
#endif
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return $2 ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_cxx_try_link "$LINENO"; then :
|
||||
eval "$3=yes"
|
||||
else
|
||||
eval "$3=no"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
fi
|
||||
eval ac_res=\$$3
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
$as_echo "$ac_res" >&6; }
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
|
||||
} # ac_fn_cxx_check_func
|
||||
cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
@@ -13130,6 +13202,75 @@ _ACEOF
|
||||
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
|
||||
$as_echo_n "checking for a sed that does not truncate output... " >&6; }
|
||||
if ${ac_cv_path_SED+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
|
||||
for ac_i in 1 2 3 4 5 6 7; do
|
||||
ac_script="$ac_script$as_nl$ac_script"
|
||||
done
|
||||
echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
|
||||
{ ac_script=; unset ac_script;}
|
||||
if test -z "$SED"; then
|
||||
ac_path_SED_found=false
|
||||
# Loop through the user's path and test for each of PROGNAME-LIST
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_prog in sed gsed; do
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
|
||||
as_fn_executable_p "$ac_path_SED" || continue
|
||||
# Check for GNU ac_path_SED and select it if it is found.
|
||||
# Check for GNU $ac_path_SED
|
||||
case `"$ac_path_SED" --version 2>&1` in
|
||||
*GNU*)
|
||||
ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
|
||||
*)
|
||||
ac_count=0
|
||||
$as_echo_n 0123456789 >"conftest.in"
|
||||
while :
|
||||
do
|
||||
cat "conftest.in" "conftest.in" >"conftest.tmp"
|
||||
mv "conftest.tmp" "conftest.in"
|
||||
cp "conftest.in" "conftest.nl"
|
||||
$as_echo '' >> "conftest.nl"
|
||||
"$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
|
||||
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
|
||||
as_fn_arith $ac_count + 1 && ac_count=$as_val
|
||||
if test $ac_count -gt ${ac_path_SED_max-0}; then
|
||||
# Best one so far, save it but keep looking for a better one
|
||||
ac_cv_path_SED="$ac_path_SED"
|
||||
ac_path_SED_max=$ac_count
|
||||
fi
|
||||
# 10*(2^10) chars as input seems more than enough
|
||||
test $ac_count -gt 10 && break
|
||||
done
|
||||
rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
|
||||
esac
|
||||
|
||||
$ac_path_SED_found && break 3
|
||||
done
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
if test -z "$ac_cv_path_SED"; then
|
||||
as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
|
||||
fi
|
||||
else
|
||||
ac_cv_path_SED=$SED
|
||||
fi
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
|
||||
$as_echo "$ac_cv_path_SED" >&6; }
|
||||
SED="$ac_cv_path_SED"
|
||||
rm -f conftest.sed
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
|
||||
$as_echo_n "checking for ANSI C header files... " >&6; }
|
||||
@@ -13515,6 +13656,715 @@ cat >>confdefs.h <<_ACEOF
|
||||
_ACEOF
|
||||
|
||||
|
||||
# Check for std::thread. This does not work on some platforms, like
|
||||
# mingw and DJGPP.
|
||||
ac_ext=cpp
|
||||
ac_cpp='$CXXCPP $CPPFLAGS'
|
||||
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
ax_pthread_ok=no
|
||||
|
||||
# We used to check for pthread.h first, but this fails if pthread.h
|
||||
# requires special compiler flags (e.g. on Tru64 or Sequent).
|
||||
# It gets checked for in the link test anyway.
|
||||
|
||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
||||
# etcetera environment variables, and if threads linking works using
|
||||
# them:
|
||||
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
|
||||
ax_pthread_save_CC="$CC"
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
if test "x$PTHREAD_CC" != "x"; then :
|
||||
CC="$PTHREAD_CC"
|
||||
fi
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS" >&5
|
||||
$as_echo_n "checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_join ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_join ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ax_pthread_ok=yes
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5
|
||||
$as_echo "$ax_pthread_ok" >&6; }
|
||||
if test "x$ax_pthread_ok" = "xno"; then
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
fi
|
||||
CC="$ax_pthread_save_CC"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
fi
|
||||
|
||||
# We must check for the threads library under a number of different
|
||||
# names; the ordering is very important because some systems
|
||||
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
||||
# libraries is broken (non-POSIX).
|
||||
|
||||
# Create a list of thread flags to try. Items starting with a "-" are
|
||||
# C compiler flags, and other items are library names, except for "none"
|
||||
# which indicates that we try without any flags at all, and "pthread-config"
|
||||
# which is a program returning the flags for the Pth emulation library.
|
||||
|
||||
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||
|
||||
# The ordering *is* (sometimes) important. Some notes on the
|
||||
# individual items follow:
|
||||
|
||||
# pthreads: AIX (must check this before -lpthread)
|
||||
# none: in case threads are in libc; should be tried before -Kthread and
|
||||
# other compiler flags to prevent continual compiler warnings
|
||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
|
||||
# (Note: HP C rejects this with "bad form for `-t' option")
|
||||
# -pthreads: Solaris/gcc (Note: HP C also rejects)
|
||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||
# doesn't hurt to check since this sometimes defines pthreads and
|
||||
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
|
||||
# is present but should not be used directly; and before -mthreads,
|
||||
# because the compiler interprets this as "-mt" + "-hreads")
|
||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||
# pthread: Linux, etcetera
|
||||
# --thread-safe: KAI C++
|
||||
# pthread-config: use pthread-config program (for GNU Pth library)
|
||||
|
||||
case $host_os in
|
||||
|
||||
freebsd*)
|
||||
|
||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||
|
||||
ax_pthread_flags="-kthread lthread $ax_pthread_flags"
|
||||
;;
|
||||
|
||||
hpux*)
|
||||
|
||||
# From the cc(1) man page: "[-mt] Sets various -D flags to enable
|
||||
# multi-threading and also sets -lpthread."
|
||||
|
||||
ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
|
||||
;;
|
||||
|
||||
openedition*)
|
||||
|
||||
# IBM z/OS requires a feature-test macro to be defined in order to
|
||||
# enable POSIX threads at all, so give the user a hint if this is
|
||||
# not set. (We don't define these ourselves, as they can affect
|
||||
# other portions of the system API in unpredictable ways.)
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
|
||||
AX_PTHREAD_ZOS_MISSING
|
||||
# endif
|
||||
|
||||
_ACEOF
|
||||
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
||||
$EGREP "AX_PTHREAD_ZOS_MISSING" >/dev/null 2>&1; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&5
|
||||
$as_echo "$as_me: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&2;}
|
||||
fi
|
||||
rm -f conftest*
|
||||
|
||||
;;
|
||||
|
||||
solaris*)
|
||||
|
||||
# On Solaris (at least, for some versions), libc contains stubbed
|
||||
# (non-functional) versions of the pthreads routines, so link-based
|
||||
# tests will erroneously succeed. (N.B.: The stubs are missing
|
||||
# pthread_cleanup_push, or rather a function called by this macro,
|
||||
# so we could check for that, but who knows whether they'll stub
|
||||
# that too in a future libc.) So we'll check first for the
|
||||
# standard Solaris way of linking pthreads (-mt -lpthread).
|
||||
|
||||
ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags"
|
||||
;;
|
||||
esac
|
||||
|
||||
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
|
||||
|
||||
if test "x$GCC" = "xyes"; then :
|
||||
ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"
|
||||
fi
|
||||
|
||||
# The presence of a feature test macro requesting re-entrant function
|
||||
# definitions is, on some systems, a strong hint that pthreads support is
|
||||
# correctly enabled
|
||||
|
||||
case $host_os in
|
||||
darwin* | hpux* | linux* | osf* | solaris*)
|
||||
ax_pthread_check_macro="_REENTRANT"
|
||||
;;
|
||||
|
||||
aix*)
|
||||
ax_pthread_check_macro="_THREAD_SAFE"
|
||||
;;
|
||||
|
||||
*)
|
||||
ax_pthread_check_macro="--"
|
||||
;;
|
||||
esac
|
||||
if test "x$ax_pthread_check_macro" = "x--"; then :
|
||||
ax_pthread_check_cond=0
|
||||
else
|
||||
ax_pthread_check_cond="!defined($ax_pthread_check_macro)"
|
||||
fi
|
||||
|
||||
# Are we compiling with Clang?
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC is Clang" >&5
|
||||
$as_echo_n "checking whether $CC is Clang... " >&6; }
|
||||
if ${ax_cv_PTHREAD_CLANG+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ax_cv_PTHREAD_CLANG=no
|
||||
# Note that Autoconf sets GCC=yes for Clang as well as GCC
|
||||
if test "x$GCC" = "xyes"; then
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
|
||||
# if defined(__clang__) && defined(__llvm__)
|
||||
AX_PTHREAD_CC_IS_CLANG
|
||||
# endif
|
||||
|
||||
_ACEOF
|
||||
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
||||
$EGREP "AX_PTHREAD_CC_IS_CLANG" >/dev/null 2>&1; then :
|
||||
ax_cv_PTHREAD_CLANG=yes
|
||||
fi
|
||||
rm -f conftest*
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG" >&5
|
||||
$as_echo "$ax_cv_PTHREAD_CLANG" >&6; }
|
||||
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
|
||||
|
||||
ax_pthread_clang_warning=no
|
||||
|
||||
# Clang needs special handling, because older versions handle the -pthread
|
||||
# option in a rather... idiosyncratic way
|
||||
|
||||
if test "x$ax_pthread_clang" = "xyes"; then
|
||||
|
||||
# Clang takes -pthread; it has never supported any other flag
|
||||
|
||||
# (Note 1: This will need to be revisited if a system that Clang
|
||||
# supports has POSIX threads in a separate library. This tends not
|
||||
# to be the way of modern systems, but it's conceivable.)
|
||||
|
||||
# (Note 2: On some systems, notably Darwin, -pthread is not needed
|
||||
# to get POSIX threads support; the API is always present and
|
||||
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
|
||||
# -pthread does define _REENTRANT, and while the Darwin headers
|
||||
# ignore this macro, third-party headers might not.)
|
||||
|
||||
PTHREAD_CFLAGS="-pthread"
|
||||
PTHREAD_LIBS=
|
||||
|
||||
ax_pthread_ok=yes
|
||||
|
||||
# However, older versions of Clang make a point of warning the user
|
||||
# that, in an invocation where only linking and no compilation is
|
||||
# taking place, the -pthread option has no effect ("argument unused
|
||||
# during compilation"). They expect -pthread to be passed in only
|
||||
# when source code is being compiled.
|
||||
#
|
||||
# Problem is, this is at odds with the way Automake and most other
|
||||
# C build frameworks function, which is that the same flags used in
|
||||
# compilation (CFLAGS) are also used in linking. Many systems
|
||||
# supported by AX_PTHREAD require exactly this for POSIX threads
|
||||
# support, and in fact it is often not straightforward to specify a
|
||||
# flag that is used only in the compilation phase and not in
|
||||
# linking. Such a scenario is extremely rare in practice.
|
||||
#
|
||||
# Even though use of the -pthread flag in linking would only print
|
||||
# a warning, this can be a nuisance for well-run software projects
|
||||
# that build with -Werror. So if the active version of Clang has
|
||||
# this misfeature, we search for an option to squash it.
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread" >&5
|
||||
$as_echo_n "checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread... " >&6; }
|
||||
if ${ax_cv_PTHREAD_CLANG_NO_WARN_FLAG+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
|
||||
# Create an alternate version of $ac_link that compiles and
|
||||
# links in two steps (.c -> .o, .o -> exe) instead of one
|
||||
# (.c -> exe), because the warning occurs only in the second
|
||||
# step
|
||||
ax_pthread_save_ac_link="$ac_link"
|
||||
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
|
||||
ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"`
|
||||
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
|
||||
if test "x$ax_pthread_try" = "xunknown"; then :
|
||||
break
|
||||
fi
|
||||
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
|
||||
ac_link="$ax_pthread_save_ac_link"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
int main(void){return 0;}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_link="$ax_pthread_2step_ac_link"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
int main(void){return 0;}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
break
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
done
|
||||
ac_link="$ax_pthread_save_ac_link"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
if test "x$ax_pthread_try" = "x"; then :
|
||||
ax_pthread_try=no
|
||||
fi
|
||||
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&5
|
||||
$as_echo "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&6; }
|
||||
|
||||
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
|
||||
no | unknown) ;;
|
||||
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
|
||||
esac
|
||||
|
||||
fi # $ax_pthread_clang = yes
|
||||
|
||||
if test "x$ax_pthread_ok" = "xno"; then
|
||||
for ax_pthread_try_flag in $ax_pthread_flags; do
|
||||
|
||||
case $ax_pthread_try_flag in
|
||||
none)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5
|
||||
$as_echo_n "checking whether pthreads work without any flags... " >&6; }
|
||||
;;
|
||||
|
||||
-mt,pthread)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with -mt -lpthread" >&5
|
||||
$as_echo_n "checking whether pthreads work with -mt -lpthread... " >&6; }
|
||||
PTHREAD_CFLAGS="-mt"
|
||||
PTHREAD_LIBS="-lpthread"
|
||||
;;
|
||||
|
||||
-*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $ax_pthread_try_flag" >&5
|
||||
$as_echo_n "checking whether pthreads work with $ax_pthread_try_flag... " >&6; }
|
||||
PTHREAD_CFLAGS="$ax_pthread_try_flag"
|
||||
;;
|
||||
|
||||
pthread-config)
|
||||
# Extract the first word of "pthread-config", so it can be a program name with args.
|
||||
set dummy pthread-config; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_ax_pthread_config+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$ax_pthread_config"; then
|
||||
ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_ax_pthread_config="yes"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no"
|
||||
fi
|
||||
fi
|
||||
ax_pthread_config=$ac_cv_prog_ax_pthread_config
|
||||
if test -n "$ax_pthread_config"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5
|
||||
$as_echo "$ax_pthread_config" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
if test "x$ax_pthread_config" = "xno"; then :
|
||||
continue
|
||||
fi
|
||||
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
||||
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
||||
;;
|
||||
|
||||
*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$ax_pthread_try_flag" >&5
|
||||
$as_echo_n "checking for the pthreads library -l$ax_pthread_try_flag... " >&6; }
|
||||
PTHREAD_LIBS="-l$ax_pthread_try_flag"
|
||||
;;
|
||||
esac
|
||||
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
|
||||
# Check for various functions. We must include pthread.h,
|
||||
# since some functions may be macros. (On the Sequent, we
|
||||
# need a special flag -Kthread to make this header compile.)
|
||||
# We check for pthread_join because it is in -lpthread on IRIX
|
||||
# while pthread_create is in libc. We check for pthread_attr_init
|
||||
# due to DEC craziness with -lpthreads. We check for
|
||||
# pthread_cleanup_push because it is one of the few pthread
|
||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
||||
# We try pthread_create on general principles.
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <pthread.h>
|
||||
# if $ax_pthread_check_cond
|
||||
# error "$ax_pthread_check_macro must be defined"
|
||||
# endif
|
||||
static void routine(void *a) { a = 0; }
|
||||
static void *start_routine(void *a) { return a; }
|
||||
int
|
||||
main ()
|
||||
{
|
||||
pthread_t th; pthread_attr_t attr;
|
||||
pthread_create(&th, 0, start_routine, 0);
|
||||
pthread_join(th, 0);
|
||||
pthread_attr_init(&attr);
|
||||
pthread_cleanup_push(routine, 0);
|
||||
pthread_cleanup_pop(0) /* ; */
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ax_pthread_ok=yes
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5
|
||||
$as_echo "$ax_pthread_ok" >&6; }
|
||||
if test "x$ax_pthread_ok" = "xyes"; then :
|
||||
break
|
||||
fi
|
||||
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
done
|
||||
fi
|
||||
|
||||
# Various other checks:
|
||||
if test "x$ax_pthread_ok" = "xyes"; then
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
|
||||
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5
|
||||
$as_echo_n "checking for joinable pthread attribute... " >&6; }
|
||||
if ${ax_cv_PTHREAD_JOINABLE_ATTR+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ax_cv_PTHREAD_JOINABLE_ATTR=unknown
|
||||
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <pthread.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int attr = $ax_pthread_attr; return attr /* ; */
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
done
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_JOINABLE_ATTR" >&5
|
||||
$as_echo "$ax_cv_PTHREAD_JOINABLE_ATTR" >&6; }
|
||||
if test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
|
||||
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
|
||||
test "x$ax_pthread_joinable_attr_defined" != "xyes"; then :
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define PTHREAD_CREATE_JOINABLE $ax_cv_PTHREAD_JOINABLE_ATTR
|
||||
_ACEOF
|
||||
|
||||
ax_pthread_joinable_attr_defined=yes
|
||||
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether more special flags are required for pthreads" >&5
|
||||
$as_echo_n "checking whether more special flags are required for pthreads... " >&6; }
|
||||
if ${ax_cv_PTHREAD_SPECIAL_FLAGS+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ax_cv_PTHREAD_SPECIAL_FLAGS=no
|
||||
case $host_os in
|
||||
solaris*)
|
||||
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
|
||||
;;
|
||||
esac
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_SPECIAL_FLAGS" >&5
|
||||
$as_echo "$ax_cv_PTHREAD_SPECIAL_FLAGS" >&6; }
|
||||
if test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
|
||||
test "x$ax_pthread_special_flags_added" != "xyes"; then :
|
||||
PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
|
||||
ax_pthread_special_flags_added=yes
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5
|
||||
$as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; }
|
||||
if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <pthread.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int i = PTHREAD_PRIO_INHERIT;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ax_cv_PTHREAD_PRIO_INHERIT=yes
|
||||
else
|
||||
ax_cv_PTHREAD_PRIO_INHERIT=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5
|
||||
$as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; }
|
||||
if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
|
||||
test "x$ax_pthread_prio_inherit_defined" != "xyes"; then :
|
||||
|
||||
$as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h
|
||||
|
||||
ax_pthread_prio_inherit_defined=yes
|
||||
|
||||
fi
|
||||
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
|
||||
# More AIX lossage: compile with *_r variant
|
||||
if test "x$GCC" != "xyes"; then
|
||||
case $host_os in
|
||||
aix*)
|
||||
case "x/$CC" in #(
|
||||
x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) :
|
||||
#handle absolute path differently from PATH based program lookup
|
||||
case "x$CC" in #(
|
||||
x/*) :
|
||||
if as_fn_executable_p ${CC}_r; then :
|
||||
PTHREAD_CC="${CC}_r"
|
||||
fi ;; #(
|
||||
*) :
|
||||
for ac_prog in ${CC}_r
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_PTHREAD_CC+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$PTHREAD_CC"; then
|
||||
ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_PTHREAD_CC="$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
PTHREAD_CC=$ac_cv_prog_PTHREAD_CC
|
||||
if test -n "$PTHREAD_CC"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5
|
||||
$as_echo "$PTHREAD_CC" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
test -n "$PTHREAD_CC" && break
|
||||
done
|
||||
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
|
||||
;;
|
||||
esac ;; #(
|
||||
*) :
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||
if test "x$ax_pthread_ok" = "xyes"; then
|
||||
threads=yes
|
||||
:
|
||||
else
|
||||
ax_pthread_ok=no
|
||||
threads=no
|
||||
fi
|
||||
ac_ext=cpp
|
||||
ac_cpp='$CXXCPP $CPPFLAGS'
|
||||
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
|
||||
|
||||
if test "$threads" = "yes"; then
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
save_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$PTHREAD_CFLAGS $save_CFLAGS"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::thread" >&5
|
||||
$as_echo_n "checking for std::thread... " >&6; }
|
||||
if ${gdb_cv_cxx_std_thread+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <thread>
|
||||
void callback() { }
|
||||
int
|
||||
main ()
|
||||
{
|
||||
std::thread t(callback);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||
gdb_cv_cxx_std_thread=yes
|
||||
else
|
||||
gdb_cv_cxx_std_thread=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_cxx_std_thread" >&5
|
||||
$as_echo "$gdb_cv_cxx_std_thread" >&6; }
|
||||
|
||||
# This check must be here, while LIBS includes any necessary
|
||||
# threading library.
|
||||
for ac_func in pthread_sigmask pthread_setname_np
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CXXFLAGS="$save_CXXFLAGS"
|
||||
fi
|
||||
if test $gdb_cv_cxx_std_thread = yes; then
|
||||
|
||||
$as_echo "#define CXX_STD_THREAD 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sigsetjmp" >&5
|
||||
$as_echo_n "checking for sigsetjmp... " >&6; }
|
||||
if ${gdb_cv_func_sigsetjmp+:} false; then :
|
||||
|
||||
142
gdb/cp-support.c
142
gdb/cp-support.c
@@ -37,6 +37,10 @@
|
||||
#include "gdbsupport/gdb_setjmp.h"
|
||||
#include "safe-ctype.h"
|
||||
#include "gdbsupport/selftest.h"
|
||||
#include "gdbsupport/gdb-sigmask.h"
|
||||
#include <atomic>
|
||||
#include "event-top.h"
|
||||
#include "ser-event.h"
|
||||
|
||||
#define d_left(dc) (dc)->u.s_binary.left
|
||||
#define d_right(dc) (dc)->u.s_binary.right
|
||||
@@ -1476,11 +1480,11 @@ static bool catch_demangler_crashes = true;
|
||||
|
||||
/* Stack context and environment for demangler crash recovery. */
|
||||
|
||||
static SIGJMP_BUF gdb_demangle_jmp_buf;
|
||||
static thread_local SIGJMP_BUF *gdb_demangle_jmp_buf;
|
||||
|
||||
/* If nonzero, attempt to dump core from the signal handler. */
|
||||
|
||||
static int gdb_demangle_attempt_core_dump = 1;
|
||||
static std::atomic<bool> gdb_demangle_attempt_core_dump;
|
||||
|
||||
/* Signal handler for gdb_demangle. */
|
||||
|
||||
@@ -1492,10 +1496,46 @@ gdb_demangle_signal_handler (int signo)
|
||||
if (fork () == 0)
|
||||
dump_core ();
|
||||
|
||||
gdb_demangle_attempt_core_dump = 0;
|
||||
gdb_demangle_attempt_core_dump = false;
|
||||
}
|
||||
|
||||
SIGLONGJMP (gdb_demangle_jmp_buf, signo);
|
||||
SIGLONGJMP (*gdb_demangle_jmp_buf, signo);
|
||||
}
|
||||
|
||||
/* A helper for gdb_demangle that reports a demangling failure. */
|
||||
|
||||
static void
|
||||
report_failed_demangle (const char *name, bool core_dump_allowed,
|
||||
int crash_signal)
|
||||
{
|
||||
static bool error_reported = false;
|
||||
|
||||
if (!error_reported)
|
||||
{
|
||||
std::string short_msg
|
||||
= string_printf (_("unable to demangle '%s' "
|
||||
"(demangler failed with signal %d)"),
|
||||
name, crash_signal);
|
||||
|
||||
std::string long_msg
|
||||
= string_printf ("%s:%d: %s: %s", __FILE__, __LINE__,
|
||||
"demangler-warning", short_msg.c_str ());
|
||||
|
||||
target_terminal::scoped_restore_terminal_state term_state;
|
||||
target_terminal::ours_for_output ();
|
||||
|
||||
begin_line ();
|
||||
if (core_dump_allowed)
|
||||
fprintf_unfiltered (gdb_stderr,
|
||||
_("%s\nAttempting to dump core.\n"),
|
||||
long_msg.c_str ());
|
||||
else
|
||||
warn_cant_dump_core (long_msg.c_str ());
|
||||
|
||||
demangler_warning (__FILE__, __LINE__, "%s", short_msg.c_str ());
|
||||
|
||||
error_reported = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1509,45 +1549,27 @@ gdb_demangle (const char *name, int options)
|
||||
int crash_signal = 0;
|
||||
|
||||
#ifdef HAVE_WORKING_FORK
|
||||
#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
|
||||
struct sigaction sa, old_sa;
|
||||
#else
|
||||
sighandler_t ofunc;
|
||||
#endif
|
||||
static int core_dump_allowed = -1;
|
||||
|
||||
if (core_dump_allowed == -1)
|
||||
{
|
||||
core_dump_allowed = can_dump_core (LIMIT_CUR);
|
||||
|
||||
if (!core_dump_allowed)
|
||||
gdb_demangle_attempt_core_dump = 0;
|
||||
}
|
||||
scoped_restore restore_segv
|
||||
= make_scoped_restore (&thread_local_segv_handler,
|
||||
catch_demangler_crashes
|
||||
? gdb_demangle_signal_handler
|
||||
: nullptr);
|
||||
|
||||
bool core_dump_allowed = gdb_demangle_attempt_core_dump;
|
||||
SIGJMP_BUF jmp_buf;
|
||||
scoped_restore restore_jmp_buf
|
||||
= make_scoped_restore (&gdb_demangle_jmp_buf, &jmp_buf);
|
||||
if (catch_demangler_crashes)
|
||||
{
|
||||
#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
|
||||
sa.sa_handler = gdb_demangle_signal_handler;
|
||||
sigemptyset (&sa.sa_mask);
|
||||
#ifdef HAVE_SIGALTSTACK
|
||||
sa.sa_flags = SA_ONSTACK;
|
||||
#else
|
||||
sa.sa_flags = 0;
|
||||
#endif
|
||||
sigaction (SIGSEGV, &sa, &old_sa);
|
||||
#else
|
||||
ofunc = signal (SIGSEGV, gdb_demangle_signal_handler);
|
||||
#endif
|
||||
|
||||
/* The signal handler may keep the signal blocked when we longjmp out
|
||||
of it. If we have sigprocmask, we can use it to unblock the signal
|
||||
afterwards and we can avoid the performance overhead of saving the
|
||||
signal mask just in case the signal gets triggered. Otherwise, just
|
||||
tell sigsetjmp to save the mask. */
|
||||
#ifdef HAVE_SIGPROCMASK
|
||||
crash_signal = SIGSETJMP (gdb_demangle_jmp_buf, 0);
|
||||
crash_signal = SIGSETJMP (*gdb_demangle_jmp_buf, 0);
|
||||
#else
|
||||
crash_signal = SIGSETJMP (gdb_demangle_jmp_buf, 1);
|
||||
crash_signal = SIGSETJMP (*gdb_demangle_jmp_buf, 1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -1558,53 +1580,28 @@ gdb_demangle (const char *name, int options)
|
||||
#ifdef HAVE_WORKING_FORK
|
||||
if (catch_demangler_crashes)
|
||||
{
|
||||
#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
|
||||
sigaction (SIGSEGV, &old_sa, NULL);
|
||||
#else
|
||||
signal (SIGSEGV, ofunc);
|
||||
#endif
|
||||
|
||||
if (crash_signal != 0)
|
||||
{
|
||||
static int error_reported = 0;
|
||||
|
||||
{
|
||||
#ifdef HAVE_SIGPROCMASK
|
||||
/* If we got the signal, SIGSEGV may still be blocked; restore it. */
|
||||
sigset_t segv_sig_set;
|
||||
sigemptyset (&segv_sig_set);
|
||||
sigaddset (&segv_sig_set, SIGSEGV);
|
||||
sigprocmask (SIG_UNBLOCK, &segv_sig_set, NULL);
|
||||
gdb_sigmask (SIG_UNBLOCK, &segv_sig_set, NULL);
|
||||
#endif
|
||||
|
||||
if (!error_reported)
|
||||
{
|
||||
std::string short_msg
|
||||
= string_printf (_("unable to demangle '%s' "
|
||||
"(demangler failed with signal %d)"),
|
||||
name, crash_signal);
|
||||
/* If there was a failure, we can't report it here, because
|
||||
we might be in a background thread. Instead, arrange for
|
||||
the reporting to happen on the main thread. */
|
||||
std::string copy = name;
|
||||
run_on_main_thread ([=] ()
|
||||
{
|
||||
report_failed_demangle (copy.c_str (), core_dump_allowed,
|
||||
crash_signal);
|
||||
});
|
||||
|
||||
std::string long_msg
|
||||
= string_printf ("%s:%d: %s: %s", __FILE__, __LINE__,
|
||||
"demangler-warning", short_msg.c_str ());
|
||||
|
||||
target_terminal::scoped_restore_terminal_state term_state;
|
||||
target_terminal::ours_for_output ();
|
||||
|
||||
begin_line ();
|
||||
if (core_dump_allowed)
|
||||
fprintf_unfiltered (gdb_stderr,
|
||||
_("%s\nAttempting to dump core.\n"),
|
||||
long_msg.c_str ());
|
||||
else
|
||||
warn_cant_dump_core (long_msg.c_str ());
|
||||
|
||||
demangler_warning (__FILE__, __LINE__, "%s", short_msg.c_str ());
|
||||
|
||||
error_reported = 1;
|
||||
}
|
||||
|
||||
result = NULL;
|
||||
}
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2211,4 +2208,7 @@ display the offending symbol."),
|
||||
selftests::register_test ("cp_remove_params",
|
||||
selftests::test_cp_remove_params);
|
||||
#endif
|
||||
|
||||
if (!can_dump_core (LIMIT_CUR))
|
||||
gdb_demangle_attempt_core_dump = false;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
2019-10-19 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* gdb.texinfo (Maintenance Commands): Document new maint
|
||||
commands.
|
||||
|
||||
2019-10-31 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
|
||||
* gdb.texinfo (Symbols): Document new 'info module variables' and
|
||||
|
||||
@@ -37841,6 +37841,21 @@ with the DWARF frame unwinders enabled.
|
||||
|
||||
If DWARF frame unwinders are not supported for a particular target
|
||||
architecture, then enabling this flag does not cause them to be used.
|
||||
|
||||
@kindex maint set worker-threads
|
||||
@kindex maint show worker-threads
|
||||
@item maint set worker-threads
|
||||
@item maint show worker-threads
|
||||
Control the number of worker threads that may be used by @value{GDBN}.
|
||||
On capable hosts, @value{GDBN} may use multiple threads to speed up
|
||||
certain CPU-intensive operations, such as demangling symbol names.
|
||||
While the number of threads used by @value{GDBN} may vary, this
|
||||
command can be used to set an upper bound on this number. The default
|
||||
is @code{unlimited}, which lets @value{GDBN} choose a reasonable
|
||||
number. Note that this only controls worker threads started by
|
||||
@value{GDBN} itself; libraries used by @value{GDBN} may start threads
|
||||
of their own.
|
||||
|
||||
@kindex maint set profile
|
||||
@kindex maint show profile
|
||||
@cindex profiling GDB
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "gdbsupport/buffer.h"
|
||||
#include "ser-event.h"
|
||||
#include "gdb_select.h"
|
||||
#include "gdbsupport/gdb-sigmask.h"
|
||||
|
||||
/* readline include files. */
|
||||
#include "readline/readline.h"
|
||||
@@ -847,6 +848,45 @@ gdb_readline_no_editing_callback (gdb_client_data client_data)
|
||||
}
|
||||
|
||||
|
||||
/* See event-top.h. */
|
||||
|
||||
thread_local void (*thread_local_segv_handler) (int);
|
||||
|
||||
static void handle_sigsegv (int sig);
|
||||
|
||||
/* Install the SIGSEGV handler. */
|
||||
static void
|
||||
install_handle_sigsegv ()
|
||||
{
|
||||
#if defined (HAVE_SIGACTION)
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = handle_sigsegv;
|
||||
sigemptyset (&sa.sa_mask);
|
||||
#ifdef HAVE_SIGALTSTACK
|
||||
sa.sa_flags = SA_ONSTACK;
|
||||
#else
|
||||
sa.sa_flags = 0;
|
||||
#endif
|
||||
sigaction (SIGSEGV, &sa, nullptr);
|
||||
#else
|
||||
signal (SIGSEGV, handle_sigsegv);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Handler for SIGSEGV. */
|
||||
|
||||
static void
|
||||
handle_sigsegv (int sig)
|
||||
{
|
||||
install_handle_sigsegv ();
|
||||
|
||||
if (thread_local_segv_handler == nullptr)
|
||||
abort ();
|
||||
thread_local_segv_handler (sig);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The serial event associated with the QUIT flag. set_quit_flag sets
|
||||
this, and check_quit_flag clears it. Used by interruptible_select
|
||||
to be able to do interruptible I/O with no race with the SIGINT
|
||||
@@ -914,6 +954,8 @@ async_init_signals (void)
|
||||
sigtstp_token =
|
||||
create_async_signal_handler (async_sigtstp_handler, NULL);
|
||||
#endif
|
||||
|
||||
install_handle_sigsegv ();
|
||||
}
|
||||
|
||||
/* See defs.h. */
|
||||
@@ -1127,7 +1169,7 @@ async_sigtstp_handler (gdb_client_data arg)
|
||||
sigset_t zero;
|
||||
|
||||
sigemptyset (&zero);
|
||||
sigprocmask (SIG_SETMASK, &zero, 0);
|
||||
gdb_sigmask (SIG_SETMASK, &zero, 0);
|
||||
}
|
||||
#elif HAVE_SIGSETMASK
|
||||
sigsetmask (0);
|
||||
|
||||
@@ -70,4 +70,10 @@ extern void gdb_rl_callback_handler_install (const char *prompt);
|
||||
currently installed. */
|
||||
extern void gdb_rl_callback_handler_reinstall (void);
|
||||
|
||||
/* The SIGSEGV handler for this thread, or NULL if there is none. GDB
|
||||
always installs a global SIGSEGV handler, and then lets threads
|
||||
indicate their interest in handling the signal by setting this
|
||||
thread-local variable. */
|
||||
extern thread_local void (*thread_local_segv_handler) (int);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
2019-10-19 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* configure, config.in: Rebuild.
|
||||
|
||||
2019-10-19 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* remote-utils.c (block_unblock_async_io): Use gdb_sigmask.
|
||||
* linux-low.c (linux_wait_for_event_filtered, linux_async): Use
|
||||
gdb_sigmask.
|
||||
* configure, config.in: Rebuild.
|
||||
|
||||
2019-10-19 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* Makefile.in (PTHREAD_CFLAGS, PTHREAD_LIBS): New variables.
|
||||
(INTERNAL_CFLAGS_BASE): Use PTHREAD_CFLAGS.
|
||||
(GDBSERVER_LIBS): Use PTHREAD_LIBS.
|
||||
* acinclude.m4: Include ax_pthread.m4.
|
||||
* config.in, configure: Rebuild.
|
||||
|
||||
2019-11-06 Christian Biesinger <cbiesinger@google.com>
|
||||
|
||||
* linux-tdep.c (linux_info_proc): Use strtok_r instead of strtok.
|
||||
|
||||
@@ -139,9 +139,12 @@ CFLAGS = @CFLAGS@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
|
||||
# INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros.
|
||||
INTERNAL_CFLAGS_BASE = ${CXXFLAGS} ${GLOBAL_CFLAGS} \
|
||||
${PROFILE_CFLAGS} ${INCLUDE_CFLAGS} ${CPPFLAGS}
|
||||
${PROFILE_CFLAGS} ${INCLUDE_CFLAGS} ${CPPFLAGS} $(PTHREAD_CFLAGS)
|
||||
INTERNAL_WARN_CFLAGS = ${INTERNAL_CFLAGS_BASE} $(WARN_CFLAGS)
|
||||
INTERNAL_CFLAGS = ${INTERNAL_WARN_CFLAGS} $(WERROR_CFLAGS) -DGDBSERVER
|
||||
|
||||
@@ -303,7 +306,7 @@ GDBREPLAY_OBS = \
|
||||
utils.o \
|
||||
version.o
|
||||
|
||||
GDBSERVER_LIBS = @GDBSERVER_LIBS@
|
||||
GDBSERVER_LIBS = @GDBSERVER_LIBS@ $(PTHREAD_LIBS)
|
||||
XM_CLIBS = @LIBS@
|
||||
CDEPS = $(srcdir)/proc-service.list
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ m4_include(../ax_cxx_compile_stdcxx.m4)
|
||||
dnl For GDB_AC_SELFTEST.
|
||||
m4_include(../selftest.m4)
|
||||
|
||||
m4_include([../../config/ax_pthread.m4])
|
||||
|
||||
dnl Check for existence of a type $1 in libthread_db.h
|
||||
dnl Based on BFD_HAVE_SYS_PROCFS_TYPE in bfd/bfd.m4.
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
*/
|
||||
#undef CRAY_STACKSEG_END
|
||||
|
||||
/* Define to 1 if std::thread works. */
|
||||
#undef CXX_STD_THREAD
|
||||
|
||||
/* Define to 1 if using `alloca.c'. */
|
||||
#undef C_ALLOCA
|
||||
|
||||
@@ -189,6 +192,15 @@
|
||||
/* Define if <thread_db.h> has psaddr_t. */
|
||||
#undef HAVE_PSADDR_T
|
||||
|
||||
/* Have PTHREAD_PRIO_INHERIT. */
|
||||
#undef HAVE_PTHREAD_PRIO_INHERIT
|
||||
|
||||
/* Define to 1 if you have the `pthread_setname_np' function. */
|
||||
#undef HAVE_PTHREAD_SETNAME_NP
|
||||
|
||||
/* Define to 1 if you have the `pthread_sigmask' function. */
|
||||
#undef HAVE_PTHREAD_SIGMASK
|
||||
|
||||
/* Define if the target supports PTRACE_GETFPXREGS for extended register
|
||||
access. */
|
||||
#undef HAVE_PTRACE_GETFPXREGS
|
||||
@@ -337,6 +349,10 @@
|
||||
/* Additional package description */
|
||||
#undef PKGVERSION
|
||||
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
#undef PTHREAD_CREATE_JOINABLE
|
||||
|
||||
/* Define to the type of arg 1 for ptrace. */
|
||||
#undef PTRACE_TYPE_ARG1
|
||||
|
||||
|
||||
896
gdb/gdbserver/configure
vendored
896
gdb/gdbserver/configure
vendored
@@ -636,6 +636,11 @@ WERROR_CFLAGS
|
||||
WARN_CFLAGS
|
||||
ustinc
|
||||
ustlibs
|
||||
PTHREAD_CFLAGS
|
||||
PTHREAD_LIBS
|
||||
PTHREAD_CC
|
||||
ax_pthread_config
|
||||
SED
|
||||
ALLOCA
|
||||
CCDEPMODE
|
||||
CONFIG_SRC_SUBDIR
|
||||
@@ -1967,6 +1972,119 @@ $as_echo "$ac_res" >&6; }
|
||||
|
||||
} # ac_fn_c_check_decl
|
||||
|
||||
# ac_fn_cxx_try_link LINENO
|
||||
# -------------------------
|
||||
# Try to link conftest.$ac_ext, and return whether this succeeded.
|
||||
ac_fn_cxx_try_link ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { { ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo"; } >&5
|
||||
(eval "$ac_link") 2>conftest.err
|
||||
ac_status=$?
|
||||
if test -s conftest.err; then
|
||||
grep -v '^ *+' conftest.err >conftest.er1
|
||||
cat conftest.er1 >&5
|
||||
mv -f conftest.er1 conftest.err
|
||||
fi
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest$ac_exeext && {
|
||||
test "$cross_compiling" = yes ||
|
||||
test -x conftest$ac_exeext
|
||||
}; then :
|
||||
ac_retval=0
|
||||
else
|
||||
$as_echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_retval=1
|
||||
fi
|
||||
# Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
|
||||
# created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
|
||||
# interfere with the next link command; also delete a directory that is
|
||||
# left behind by Apple's compiler. We do this before executing the actions.
|
||||
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
as_fn_set_status $ac_retval
|
||||
|
||||
} # ac_fn_cxx_try_link
|
||||
|
||||
# ac_fn_cxx_check_func LINENO FUNC VAR
|
||||
# ------------------------------------
|
||||
# Tests whether FUNC exists, setting the cache variable VAR accordingly
|
||||
ac_fn_cxx_check_func ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
|
||||
$as_echo_n "checking for $2... " >&6; }
|
||||
if eval \${$3+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
|
||||
For example, HP-UX 11i <limits.h> declares gettimeofday. */
|
||||
#define $2 innocuous_$2
|
||||
|
||||
/* System header to define __stub macros and hopefully few prototypes,
|
||||
which can conflict with char $2 (); below.
|
||||
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
|
||||
<limits.h> exists even on freestanding compilers. */
|
||||
|
||||
#ifdef __STDC__
|
||||
# include <limits.h>
|
||||
#else
|
||||
# include <assert.h>
|
||||
#endif
|
||||
|
||||
#undef $2
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char $2 ();
|
||||
/* The GNU C library defines this for functions which it implements
|
||||
to always fail with ENOSYS. Some functions are actually named
|
||||
something starting with __ and the normal name is an alias. */
|
||||
#if defined __stub_$2 || defined __stub___$2
|
||||
choke me
|
||||
#endif
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return $2 ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_cxx_try_link "$LINENO"; then :
|
||||
eval "$3=yes"
|
||||
else
|
||||
eval "$3=no"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
fi
|
||||
eval ac_res=\$$3
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
$as_echo "$ac_res" >&6; }
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
|
||||
} # ac_fn_cxx_check_func
|
||||
|
||||
# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
|
||||
# --------------------------------------------
|
||||
# Tries to find the compile-time value of EXPR in a program that includes
|
||||
@@ -6472,6 +6590,75 @@ _ACEOF
|
||||
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
|
||||
$as_echo_n "checking for a sed that does not truncate output... " >&6; }
|
||||
if ${ac_cv_path_SED+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
|
||||
for ac_i in 1 2 3 4 5 6 7; do
|
||||
ac_script="$ac_script$as_nl$ac_script"
|
||||
done
|
||||
echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
|
||||
{ ac_script=; unset ac_script;}
|
||||
if test -z "$SED"; then
|
||||
ac_path_SED_found=false
|
||||
# Loop through the user's path and test for each of PROGNAME-LIST
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_prog in sed gsed; do
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
|
||||
as_fn_executable_p "$ac_path_SED" || continue
|
||||
# Check for GNU ac_path_SED and select it if it is found.
|
||||
# Check for GNU $ac_path_SED
|
||||
case `"$ac_path_SED" --version 2>&1` in
|
||||
*GNU*)
|
||||
ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
|
||||
*)
|
||||
ac_count=0
|
||||
$as_echo_n 0123456789 >"conftest.in"
|
||||
while :
|
||||
do
|
||||
cat "conftest.in" "conftest.in" >"conftest.tmp"
|
||||
mv "conftest.tmp" "conftest.in"
|
||||
cp "conftest.in" "conftest.nl"
|
||||
$as_echo '' >> "conftest.nl"
|
||||
"$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
|
||||
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
|
||||
as_fn_arith $ac_count + 1 && ac_count=$as_val
|
||||
if test $ac_count -gt ${ac_path_SED_max-0}; then
|
||||
# Best one so far, save it but keep looking for a better one
|
||||
ac_cv_path_SED="$ac_path_SED"
|
||||
ac_path_SED_max=$ac_count
|
||||
fi
|
||||
# 10*(2^10) chars as input seems more than enough
|
||||
test $ac_count -gt 10 && break
|
||||
done
|
||||
rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
|
||||
esac
|
||||
|
||||
$ac_path_SED_found && break 3
|
||||
done
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
if test -z "$ac_cv_path_SED"; then
|
||||
as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
|
||||
fi
|
||||
else
|
||||
ac_cv_path_SED=$SED
|
||||
fi
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
|
||||
$as_echo "$ac_cv_path_SED" >&6; }
|
||||
SED="$ac_cv_path_SED"
|
||||
rm -f conftest.sed
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
|
||||
$as_echo_n "checking for ANSI C header files... " >&6; }
|
||||
@@ -6857,6 +7044,715 @@ cat >>confdefs.h <<_ACEOF
|
||||
_ACEOF
|
||||
|
||||
|
||||
# Check for std::thread. This does not work on some platforms, like
|
||||
# mingw and DJGPP.
|
||||
ac_ext=cpp
|
||||
ac_cpp='$CXXCPP $CPPFLAGS'
|
||||
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
ax_pthread_ok=no
|
||||
|
||||
# We used to check for pthread.h first, but this fails if pthread.h
|
||||
# requires special compiler flags (e.g. on Tru64 or Sequent).
|
||||
# It gets checked for in the link test anyway.
|
||||
|
||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
||||
# etcetera environment variables, and if threads linking works using
|
||||
# them:
|
||||
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
|
||||
ax_pthread_save_CC="$CC"
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
if test "x$PTHREAD_CC" != "x"; then :
|
||||
CC="$PTHREAD_CC"
|
||||
fi
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS" >&5
|
||||
$as_echo_n "checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_join ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_join ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ax_pthread_ok=yes
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5
|
||||
$as_echo "$ax_pthread_ok" >&6; }
|
||||
if test "x$ax_pthread_ok" = "xno"; then
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
fi
|
||||
CC="$ax_pthread_save_CC"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
fi
|
||||
|
||||
# We must check for the threads library under a number of different
|
||||
# names; the ordering is very important because some systems
|
||||
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
||||
# libraries is broken (non-POSIX).
|
||||
|
||||
# Create a list of thread flags to try. Items starting with a "-" are
|
||||
# C compiler flags, and other items are library names, except for "none"
|
||||
# which indicates that we try without any flags at all, and "pthread-config"
|
||||
# which is a program returning the flags for the Pth emulation library.
|
||||
|
||||
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||
|
||||
# The ordering *is* (sometimes) important. Some notes on the
|
||||
# individual items follow:
|
||||
|
||||
# pthreads: AIX (must check this before -lpthread)
|
||||
# none: in case threads are in libc; should be tried before -Kthread and
|
||||
# other compiler flags to prevent continual compiler warnings
|
||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
|
||||
# (Note: HP C rejects this with "bad form for `-t' option")
|
||||
# -pthreads: Solaris/gcc (Note: HP C also rejects)
|
||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||
# doesn't hurt to check since this sometimes defines pthreads and
|
||||
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
|
||||
# is present but should not be used directly; and before -mthreads,
|
||||
# because the compiler interprets this as "-mt" + "-hreads")
|
||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||
# pthread: Linux, etcetera
|
||||
# --thread-safe: KAI C++
|
||||
# pthread-config: use pthread-config program (for GNU Pth library)
|
||||
|
||||
case $host_os in
|
||||
|
||||
freebsd*)
|
||||
|
||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||
|
||||
ax_pthread_flags="-kthread lthread $ax_pthread_flags"
|
||||
;;
|
||||
|
||||
hpux*)
|
||||
|
||||
# From the cc(1) man page: "[-mt] Sets various -D flags to enable
|
||||
# multi-threading and also sets -lpthread."
|
||||
|
||||
ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
|
||||
;;
|
||||
|
||||
openedition*)
|
||||
|
||||
# IBM z/OS requires a feature-test macro to be defined in order to
|
||||
# enable POSIX threads at all, so give the user a hint if this is
|
||||
# not set. (We don't define these ourselves, as they can affect
|
||||
# other portions of the system API in unpredictable ways.)
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
|
||||
AX_PTHREAD_ZOS_MISSING
|
||||
# endif
|
||||
|
||||
_ACEOF
|
||||
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
||||
$EGREP "AX_PTHREAD_ZOS_MISSING" >/dev/null 2>&1; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&5
|
||||
$as_echo "$as_me: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&2;}
|
||||
fi
|
||||
rm -f conftest*
|
||||
|
||||
;;
|
||||
|
||||
solaris*)
|
||||
|
||||
# On Solaris (at least, for some versions), libc contains stubbed
|
||||
# (non-functional) versions of the pthreads routines, so link-based
|
||||
# tests will erroneously succeed. (N.B.: The stubs are missing
|
||||
# pthread_cleanup_push, or rather a function called by this macro,
|
||||
# so we could check for that, but who knows whether they'll stub
|
||||
# that too in a future libc.) So we'll check first for the
|
||||
# standard Solaris way of linking pthreads (-mt -lpthread).
|
||||
|
||||
ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags"
|
||||
;;
|
||||
esac
|
||||
|
||||
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
|
||||
|
||||
if test "x$GCC" = "xyes"; then :
|
||||
ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"
|
||||
fi
|
||||
|
||||
# The presence of a feature test macro requesting re-entrant function
|
||||
# definitions is, on some systems, a strong hint that pthreads support is
|
||||
# correctly enabled
|
||||
|
||||
case $host_os in
|
||||
darwin* | hpux* | linux* | osf* | solaris*)
|
||||
ax_pthread_check_macro="_REENTRANT"
|
||||
;;
|
||||
|
||||
aix*)
|
||||
ax_pthread_check_macro="_THREAD_SAFE"
|
||||
;;
|
||||
|
||||
*)
|
||||
ax_pthread_check_macro="--"
|
||||
;;
|
||||
esac
|
||||
if test "x$ax_pthread_check_macro" = "x--"; then :
|
||||
ax_pthread_check_cond=0
|
||||
else
|
||||
ax_pthread_check_cond="!defined($ax_pthread_check_macro)"
|
||||
fi
|
||||
|
||||
# Are we compiling with Clang?
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC is Clang" >&5
|
||||
$as_echo_n "checking whether $CC is Clang... " >&6; }
|
||||
if ${ax_cv_PTHREAD_CLANG+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ax_cv_PTHREAD_CLANG=no
|
||||
# Note that Autoconf sets GCC=yes for Clang as well as GCC
|
||||
if test "x$GCC" = "xyes"; then
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
|
||||
# if defined(__clang__) && defined(__llvm__)
|
||||
AX_PTHREAD_CC_IS_CLANG
|
||||
# endif
|
||||
|
||||
_ACEOF
|
||||
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
||||
$EGREP "AX_PTHREAD_CC_IS_CLANG" >/dev/null 2>&1; then :
|
||||
ax_cv_PTHREAD_CLANG=yes
|
||||
fi
|
||||
rm -f conftest*
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG" >&5
|
||||
$as_echo "$ax_cv_PTHREAD_CLANG" >&6; }
|
||||
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
|
||||
|
||||
ax_pthread_clang_warning=no
|
||||
|
||||
# Clang needs special handling, because older versions handle the -pthread
|
||||
# option in a rather... idiosyncratic way
|
||||
|
||||
if test "x$ax_pthread_clang" = "xyes"; then
|
||||
|
||||
# Clang takes -pthread; it has never supported any other flag
|
||||
|
||||
# (Note 1: This will need to be revisited if a system that Clang
|
||||
# supports has POSIX threads in a separate library. This tends not
|
||||
# to be the way of modern systems, but it's conceivable.)
|
||||
|
||||
# (Note 2: On some systems, notably Darwin, -pthread is not needed
|
||||
# to get POSIX threads support; the API is always present and
|
||||
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
|
||||
# -pthread does define _REENTRANT, and while the Darwin headers
|
||||
# ignore this macro, third-party headers might not.)
|
||||
|
||||
PTHREAD_CFLAGS="-pthread"
|
||||
PTHREAD_LIBS=
|
||||
|
||||
ax_pthread_ok=yes
|
||||
|
||||
# However, older versions of Clang make a point of warning the user
|
||||
# that, in an invocation where only linking and no compilation is
|
||||
# taking place, the -pthread option has no effect ("argument unused
|
||||
# during compilation"). They expect -pthread to be passed in only
|
||||
# when source code is being compiled.
|
||||
#
|
||||
# Problem is, this is at odds with the way Automake and most other
|
||||
# C build frameworks function, which is that the same flags used in
|
||||
# compilation (CFLAGS) are also used in linking. Many systems
|
||||
# supported by AX_PTHREAD require exactly this for POSIX threads
|
||||
# support, and in fact it is often not straightforward to specify a
|
||||
# flag that is used only in the compilation phase and not in
|
||||
# linking. Such a scenario is extremely rare in practice.
|
||||
#
|
||||
# Even though use of the -pthread flag in linking would only print
|
||||
# a warning, this can be a nuisance for well-run software projects
|
||||
# that build with -Werror. So if the active version of Clang has
|
||||
# this misfeature, we search for an option to squash it.
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread" >&5
|
||||
$as_echo_n "checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread... " >&6; }
|
||||
if ${ax_cv_PTHREAD_CLANG_NO_WARN_FLAG+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
|
||||
# Create an alternate version of $ac_link that compiles and
|
||||
# links in two steps (.c -> .o, .o -> exe) instead of one
|
||||
# (.c -> exe), because the warning occurs only in the second
|
||||
# step
|
||||
ax_pthread_save_ac_link="$ac_link"
|
||||
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
|
||||
ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"`
|
||||
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
|
||||
if test "x$ax_pthread_try" = "xunknown"; then :
|
||||
break
|
||||
fi
|
||||
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
|
||||
ac_link="$ax_pthread_save_ac_link"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
int main(void){return 0;}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_link="$ax_pthread_2step_ac_link"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
int main(void){return 0;}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
break
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
done
|
||||
ac_link="$ax_pthread_save_ac_link"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
if test "x$ax_pthread_try" = "x"; then :
|
||||
ax_pthread_try=no
|
||||
fi
|
||||
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&5
|
||||
$as_echo "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&6; }
|
||||
|
||||
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
|
||||
no | unknown) ;;
|
||||
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
|
||||
esac
|
||||
|
||||
fi # $ax_pthread_clang = yes
|
||||
|
||||
if test "x$ax_pthread_ok" = "xno"; then
|
||||
for ax_pthread_try_flag in $ax_pthread_flags; do
|
||||
|
||||
case $ax_pthread_try_flag in
|
||||
none)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5
|
||||
$as_echo_n "checking whether pthreads work without any flags... " >&6; }
|
||||
;;
|
||||
|
||||
-mt,pthread)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with -mt -lpthread" >&5
|
||||
$as_echo_n "checking whether pthreads work with -mt -lpthread... " >&6; }
|
||||
PTHREAD_CFLAGS="-mt"
|
||||
PTHREAD_LIBS="-lpthread"
|
||||
;;
|
||||
|
||||
-*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $ax_pthread_try_flag" >&5
|
||||
$as_echo_n "checking whether pthreads work with $ax_pthread_try_flag... " >&6; }
|
||||
PTHREAD_CFLAGS="$ax_pthread_try_flag"
|
||||
;;
|
||||
|
||||
pthread-config)
|
||||
# Extract the first word of "pthread-config", so it can be a program name with args.
|
||||
set dummy pthread-config; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_ax_pthread_config+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$ax_pthread_config"; then
|
||||
ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_ax_pthread_config="yes"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no"
|
||||
fi
|
||||
fi
|
||||
ax_pthread_config=$ac_cv_prog_ax_pthread_config
|
||||
if test -n "$ax_pthread_config"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5
|
||||
$as_echo "$ax_pthread_config" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
if test "x$ax_pthread_config" = "xno"; then :
|
||||
continue
|
||||
fi
|
||||
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
||||
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
||||
;;
|
||||
|
||||
*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$ax_pthread_try_flag" >&5
|
||||
$as_echo_n "checking for the pthreads library -l$ax_pthread_try_flag... " >&6; }
|
||||
PTHREAD_LIBS="-l$ax_pthread_try_flag"
|
||||
;;
|
||||
esac
|
||||
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
|
||||
# Check for various functions. We must include pthread.h,
|
||||
# since some functions may be macros. (On the Sequent, we
|
||||
# need a special flag -Kthread to make this header compile.)
|
||||
# We check for pthread_join because it is in -lpthread on IRIX
|
||||
# while pthread_create is in libc. We check for pthread_attr_init
|
||||
# due to DEC craziness with -lpthreads. We check for
|
||||
# pthread_cleanup_push because it is one of the few pthread
|
||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
||||
# We try pthread_create on general principles.
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <pthread.h>
|
||||
# if $ax_pthread_check_cond
|
||||
# error "$ax_pthread_check_macro must be defined"
|
||||
# endif
|
||||
static void routine(void *a) { a = 0; }
|
||||
static void *start_routine(void *a) { return a; }
|
||||
int
|
||||
main ()
|
||||
{
|
||||
pthread_t th; pthread_attr_t attr;
|
||||
pthread_create(&th, 0, start_routine, 0);
|
||||
pthread_join(th, 0);
|
||||
pthread_attr_init(&attr);
|
||||
pthread_cleanup_push(routine, 0);
|
||||
pthread_cleanup_pop(0) /* ; */
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ax_pthread_ok=yes
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5
|
||||
$as_echo "$ax_pthread_ok" >&6; }
|
||||
if test "x$ax_pthread_ok" = "xyes"; then :
|
||||
break
|
||||
fi
|
||||
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
done
|
||||
fi
|
||||
|
||||
# Various other checks:
|
||||
if test "x$ax_pthread_ok" = "xyes"; then
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
|
||||
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5
|
||||
$as_echo_n "checking for joinable pthread attribute... " >&6; }
|
||||
if ${ax_cv_PTHREAD_JOINABLE_ATTR+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ax_cv_PTHREAD_JOINABLE_ATTR=unknown
|
||||
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <pthread.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int attr = $ax_pthread_attr; return attr /* ; */
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
done
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_JOINABLE_ATTR" >&5
|
||||
$as_echo "$ax_cv_PTHREAD_JOINABLE_ATTR" >&6; }
|
||||
if test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
|
||||
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
|
||||
test "x$ax_pthread_joinable_attr_defined" != "xyes"; then :
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define PTHREAD_CREATE_JOINABLE $ax_cv_PTHREAD_JOINABLE_ATTR
|
||||
_ACEOF
|
||||
|
||||
ax_pthread_joinable_attr_defined=yes
|
||||
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether more special flags are required for pthreads" >&5
|
||||
$as_echo_n "checking whether more special flags are required for pthreads... " >&6; }
|
||||
if ${ax_cv_PTHREAD_SPECIAL_FLAGS+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ax_cv_PTHREAD_SPECIAL_FLAGS=no
|
||||
case $host_os in
|
||||
solaris*)
|
||||
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
|
||||
;;
|
||||
esac
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_SPECIAL_FLAGS" >&5
|
||||
$as_echo "$ax_cv_PTHREAD_SPECIAL_FLAGS" >&6; }
|
||||
if test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
|
||||
test "x$ax_pthread_special_flags_added" != "xyes"; then :
|
||||
PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
|
||||
ax_pthread_special_flags_added=yes
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5
|
||||
$as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; }
|
||||
if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <pthread.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int i = PTHREAD_PRIO_INHERIT;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ax_cv_PTHREAD_PRIO_INHERIT=yes
|
||||
else
|
||||
ax_cv_PTHREAD_PRIO_INHERIT=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5
|
||||
$as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; }
|
||||
if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
|
||||
test "x$ax_pthread_prio_inherit_defined" != "xyes"; then :
|
||||
|
||||
$as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h
|
||||
|
||||
ax_pthread_prio_inherit_defined=yes
|
||||
|
||||
fi
|
||||
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
|
||||
# More AIX lossage: compile with *_r variant
|
||||
if test "x$GCC" != "xyes"; then
|
||||
case $host_os in
|
||||
aix*)
|
||||
case "x/$CC" in #(
|
||||
x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) :
|
||||
#handle absolute path differently from PATH based program lookup
|
||||
case "x$CC" in #(
|
||||
x/*) :
|
||||
if as_fn_executable_p ${CC}_r; then :
|
||||
PTHREAD_CC="${CC}_r"
|
||||
fi ;; #(
|
||||
*) :
|
||||
for ac_prog in ${CC}_r
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_PTHREAD_CC+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$PTHREAD_CC"; then
|
||||
ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_PTHREAD_CC="$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
PTHREAD_CC=$ac_cv_prog_PTHREAD_CC
|
||||
if test -n "$PTHREAD_CC"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5
|
||||
$as_echo "$PTHREAD_CC" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
test -n "$PTHREAD_CC" && break
|
||||
done
|
||||
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
|
||||
;;
|
||||
esac ;; #(
|
||||
*) :
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||
if test "x$ax_pthread_ok" = "xyes"; then
|
||||
threads=yes
|
||||
:
|
||||
else
|
||||
ax_pthread_ok=no
|
||||
threads=no
|
||||
fi
|
||||
ac_ext=cpp
|
||||
ac_cpp='$CXXCPP $CPPFLAGS'
|
||||
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
|
||||
|
||||
if test "$threads" = "yes"; then
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
save_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$PTHREAD_CFLAGS $save_CFLAGS"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::thread" >&5
|
||||
$as_echo_n "checking for std::thread... " >&6; }
|
||||
if ${gdb_cv_cxx_std_thread+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <thread>
|
||||
void callback() { }
|
||||
int
|
||||
main ()
|
||||
{
|
||||
std::thread t(callback);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||
gdb_cv_cxx_std_thread=yes
|
||||
else
|
||||
gdb_cv_cxx_std_thread=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_cxx_std_thread" >&5
|
||||
$as_echo "$gdb_cv_cxx_std_thread" >&6; }
|
||||
|
||||
# This check must be here, while LIBS includes any necessary
|
||||
# threading library.
|
||||
for ac_func in pthread_sigmask pthread_setname_np
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CXXFLAGS="$save_CXXFLAGS"
|
||||
fi
|
||||
if test $gdb_cv_cxx_std_thread = yes; then
|
||||
|
||||
$as_echo "#define CXX_STD_THREAD 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sigsetjmp" >&5
|
||||
$as_echo_n "checking for sigsetjmp... " >&6; }
|
||||
if ${gdb_cv_func_sigsetjmp+:} false; then :
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "gdbsupport/common-inferior.h"
|
||||
#include "nat/fork-inferior.h"
|
||||
#include "gdbsupport/environ.h"
|
||||
#include "gdbsupport/gdb-sigmask.h"
|
||||
#include "gdbsupport/scoped_restore.h"
|
||||
#ifndef ELFMAG0
|
||||
/* Don't include <linux/elf.h> here. If it got included by gdb_proc_service.h
|
||||
@@ -2689,7 +2690,7 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
|
||||
/* Make sure SIGCHLD is blocked until the sigsuspend below. Block
|
||||
all signals while here. */
|
||||
sigfillset (&block_mask);
|
||||
sigprocmask (SIG_BLOCK, &block_mask, &prev_mask);
|
||||
gdb_sigmask (SIG_BLOCK, &block_mask, &prev_mask);
|
||||
|
||||
/* Always pull all events out of the kernel. We'll randomly select
|
||||
an event LWP out of all that have events, to prevent
|
||||
@@ -2775,7 +2776,7 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
|
||||
{
|
||||
if (debug_threads)
|
||||
debug_printf ("LLW: exit (no unwaited-for LWP)\n");
|
||||
sigprocmask (SIG_SETMASK, &prev_mask, NULL);
|
||||
gdb_sigmask (SIG_SETMASK, &prev_mask, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2785,7 +2786,7 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
|
||||
if (debug_threads)
|
||||
debug_printf ("WNOHANG set, no event found\n");
|
||||
|
||||
sigprocmask (SIG_SETMASK, &prev_mask, NULL);
|
||||
gdb_sigmask (SIG_SETMASK, &prev_mask, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2794,11 +2795,11 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
|
||||
debug_printf ("sigsuspend'ing\n");
|
||||
|
||||
sigsuspend (&prev_mask);
|
||||
sigprocmask (SIG_SETMASK, &prev_mask, NULL);
|
||||
gdb_sigmask (SIG_SETMASK, &prev_mask, NULL);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
sigprocmask (SIG_SETMASK, &prev_mask, NULL);
|
||||
gdb_sigmask (SIG_SETMASK, &prev_mask, NULL);
|
||||
|
||||
current_thread = event_thread;
|
||||
|
||||
@@ -6215,7 +6216,7 @@ linux_async (int enable)
|
||||
sigemptyset (&mask);
|
||||
sigaddset (&mask, SIGCHLD);
|
||||
|
||||
sigprocmask (SIG_BLOCK, &mask, NULL);
|
||||
gdb_sigmask (SIG_BLOCK, &mask, NULL);
|
||||
|
||||
if (enable)
|
||||
{
|
||||
@@ -6223,7 +6224,7 @@ linux_async (int enable)
|
||||
{
|
||||
linux_event_pipe[0] = -1;
|
||||
linux_event_pipe[1] = -1;
|
||||
sigprocmask (SIG_UNBLOCK, &mask, NULL);
|
||||
gdb_sigmask (SIG_UNBLOCK, &mask, NULL);
|
||||
|
||||
warning ("creating event pipe failed.");
|
||||
return previous;
|
||||
@@ -6249,7 +6250,7 @@ linux_async (int enable)
|
||||
linux_event_pipe[1] = -1;
|
||||
}
|
||||
|
||||
sigprocmask (SIG_UNBLOCK, &mask, NULL);
|
||||
gdb_sigmask (SIG_UNBLOCK, &mask, NULL);
|
||||
}
|
||||
|
||||
return previous;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "gdbsupport/rsp-low.h"
|
||||
#include "gdbsupport/netstuff.h"
|
||||
#include "gdbsupport/filestuff.h"
|
||||
#include "gdbsupport/gdb-sigmask.h"
|
||||
#include <ctype.h>
|
||||
#if HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
@@ -807,7 +808,7 @@ block_unblock_async_io (int block)
|
||||
|
||||
sigemptyset (&sigio_set);
|
||||
sigaddset (&sigio_set, SIGIO);
|
||||
sigprocmask (block ? SIG_BLOCK : SIG_UNBLOCK, &sigio_set, NULL);
|
||||
gdb_sigmask (block ? SIG_BLOCK : SIG_UNBLOCK, &sigio_set, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
70
gdb/gdbsupport/alt-stack.h
Normal file
70
gdb/gdbsupport/alt-stack.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/* Temporarily install an alternate signal stack
|
||||
|
||||
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_ALT_STACK_H
|
||||
#define GDBSUPPORT_ALT_STACK_H
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
namespace gdb
|
||||
{
|
||||
|
||||
/* Try to set up an alternate signal stack for SIGSEGV handlers.
|
||||
This allows us to handle SIGSEGV signals generated when the
|
||||
normal process stack is exhausted. If this stack is not set
|
||||
up (sigaltstack is unavailable or fails) and a SIGSEGV is
|
||||
generated when the normal stack is exhausted then the program
|
||||
will behave as though no SIGSEGV handler was installed. */
|
||||
class alternate_signal_stack
|
||||
{
|
||||
public:
|
||||
alternate_signal_stack ()
|
||||
{
|
||||
#ifdef HAVE_SIGALTSTACK
|
||||
m_stack.reset ((char *) xmalloc (SIGSTKSZ));
|
||||
|
||||
stack_t stack;
|
||||
stack.ss_sp = m_stack.get ();
|
||||
stack.ss_size = SIGSTKSZ;
|
||||
stack.ss_flags = 0;
|
||||
|
||||
sigaltstack (&stack, &m_old_stack);
|
||||
#endif
|
||||
}
|
||||
|
||||
~alternate_signal_stack ()
|
||||
{
|
||||
#ifdef HAVE_SIGALTSTACK
|
||||
sigaltstack (&m_old_stack, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
DISABLE_COPY_AND_ASSIGN (alternate_signal_stack);
|
||||
|
||||
private:
|
||||
|
||||
#ifdef HAVE_SIGALTSTACK
|
||||
gdb::unique_xmalloc_ptr<char> m_stack;
|
||||
stack_t m_old_stack;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* GDBSUPPORT_ALT_STACK_H */
|
||||
65
gdb/gdbsupport/block-signals.h
Normal file
65
gdb/gdbsupport/block-signals.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* Block signals used by gdb
|
||||
|
||||
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_BLOCK_SIGNALS_H
|
||||
#define GDBSUPPORT_BLOCK_SIGNALS_H
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
namespace gdb
|
||||
{
|
||||
|
||||
/* This is an RAII class that temporarily blocks the signals needed by
|
||||
gdb. This can be used before starting a new thread to ensure that
|
||||
this thread starts with the appropriate signals blocked. */
|
||||
class block_signals
|
||||
{
|
||||
public:
|
||||
block_signals ()
|
||||
{
|
||||
#ifdef HAVE_PTHREAD_SIGMASK
|
||||
sigset_t mask;
|
||||
sigemptyset (&mask);
|
||||
sigaddset (&mask, SIGINT);
|
||||
sigaddset (&mask, SIGCHLD);
|
||||
sigaddset (&mask, SIGALRM);
|
||||
sigaddset (&mask, SIGWINCH);
|
||||
pthread_sigmask (SIG_BLOCK, &mask, &m_old_mask);
|
||||
#endif
|
||||
}
|
||||
|
||||
~block_signals ()
|
||||
{
|
||||
#ifdef HAVE_PTHREAD_SIGMASK
|
||||
pthread_sigmask (SIG_SETMASK, &m_old_mask, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
DISABLE_COPY_AND_ASSIGN (block_signals);
|
||||
|
||||
private:
|
||||
|
||||
#ifdef HAVE_PTHREAD_SIGMASK
|
||||
sigset_t m_old_mask;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* GDBSUPPORT_BLOCK_SIGNALS_H */
|
||||
@@ -37,6 +37,37 @@ AC_DEFUN([GDB_AC_COMMON], [
|
||||
|
||||
AC_CHECK_DECLS([strerror, strstr])
|
||||
|
||||
# Check for std::thread. This does not work on some platforms, like
|
||||
# mingw and DJGPP.
|
||||
AC_LANG_PUSH([C++])
|
||||
AX_PTHREAD([threads=yes], [threads=no])
|
||||
if test "$threads" = "yes"; then
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
save_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$PTHREAD_CFLAGS $save_CFLAGS"
|
||||
AC_CACHE_CHECK([for std::thread],
|
||||
gdb_cv_cxx_std_thread,
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <thread>
|
||||
void callback() { }]],
|
||||
[[std::thread t(callback);]])],
|
||||
gdb_cv_cxx_std_thread=yes,
|
||||
gdb_cv_cxx_std_thread=no)])
|
||||
|
||||
# This check must be here, while LIBS includes any necessary
|
||||
# threading library.
|
||||
AC_CHECK_FUNCS([pthread_sigmask pthread_setname_np])
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CXXFLAGS="$save_CXXFLAGS"
|
||||
fi
|
||||
if test $gdb_cv_cxx_std_thread = yes; then
|
||||
AC_DEFINE(CXX_STD_THREAD, 1,
|
||||
[Define to 1 if std::thread works.])
|
||||
fi
|
||||
AC_LANG_POP
|
||||
|
||||
dnl Check if sigsetjmp is available. Using AC_CHECK_FUNCS won't
|
||||
dnl do since sigsetjmp might only be defined as a macro.
|
||||
AC_CACHE_CHECK([for sigsetjmp], gdb_cv_func_sigsetjmp,
|
||||
|
||||
45
gdb/gdbsupport/gdb-sigmask.h
Normal file
45
gdb/gdbsupport/gdb-sigmask.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* sigprocmask wrapper for gdb
|
||||
|
||||
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_GDB_SIGMASK_H
|
||||
#define GDBSUPPORT_GDB_SIGMASK_H
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef HAVE_SIGPROCMASK
|
||||
|
||||
#ifdef HAVE_PTHREAD_SIGMASK
|
||||
#define gdb_sigmask pthread_sigmask
|
||||
#else
|
||||
#define gdb_sigmask sigprocmask
|
||||
#endif
|
||||
|
||||
#else /* HAVE_SIGPROCMASK */
|
||||
|
||||
/* Other code checks HAVE_SIGPROCMASK, but if there happened to be a
|
||||
system that only had pthread_sigmask, we could still use it with
|
||||
some extra changes. */
|
||||
#ifdef HAVE_PTHREAD_SIGMASK
|
||||
#error pthead_sigmask available without sigprocmask - please report
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_SIGPROCMASK */
|
||||
|
||||
|
||||
#endif /* GDBSUPPORT_GDB_SIGMASK_H */
|
||||
83
gdb/gdbsupport/parallel-for.h
Normal file
83
gdb/gdbsupport/parallel-for.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* 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>
|
||||
#include "gdbsupport/thread-pool.h"
|
||||
#endif
|
||||
|
||||
namespace gdb
|
||||
{
|
||||
|
||||
/* 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
|
||||
/* So we can use a local array below. */
|
||||
const size_t local_max = 16;
|
||||
size_t n_threads = std::min (thread_pool::g_thread_pool->count (),
|
||||
local_max);
|
||||
size_t n_actual_threads = 0;
|
||||
std::future<void> futures[local_max];
|
||||
|
||||
size_t n_elements = last - first;
|
||||
if (n_threads > 1 && 2 * n_threads <= n_elements)
|
||||
{
|
||||
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;
|
||||
auto task = [=] ()
|
||||
{
|
||||
callback (first, end);
|
||||
};
|
||||
|
||||
futures[i] = gdb::thread_pool::g_thread_pool->post_task (task);
|
||||
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)
|
||||
futures[i].wait ();
|
||||
#endif /* CXX_STD_THREAD */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* GDBSUPPORT_PARALLEL_FOR_H */
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "common-defs.h"
|
||||
#include "signals-state-save-restore.h"
|
||||
#include "gdbsupport/gdb-sigmask.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
@@ -25,10 +26,6 @@
|
||||
#ifdef HAVE_SIGACTION
|
||||
static struct sigaction original_signal_actions[NSIG];
|
||||
|
||||
/* Note that we use sigprocmask without worrying about threads because
|
||||
the save/restore functions are called either from main, or after a
|
||||
fork. In both cases, we know the calling process is single
|
||||
threaded. */
|
||||
static sigset_t original_signal_mask;
|
||||
#endif
|
||||
|
||||
@@ -41,7 +38,7 @@ save_original_signals_state (bool quiet)
|
||||
int i;
|
||||
int res;
|
||||
|
||||
res = sigprocmask (0, NULL, &original_signal_mask);
|
||||
res = gdb_sigmask (0, NULL, &original_signal_mask);
|
||||
if (res == -1)
|
||||
perror_with_name (("sigprocmask"));
|
||||
|
||||
@@ -110,7 +107,7 @@ restore_original_signals_state (void)
|
||||
perror_with_name (("sigaction"));
|
||||
}
|
||||
|
||||
res = sigprocmask (SIG_SETMASK, &original_signal_mask, NULL);
|
||||
res = gdb_sigmask (SIG_SETMASK, &original_signal_mask, NULL);
|
||||
if (res == -1)
|
||||
perror_with_name (("sigprocmask"));
|
||||
#endif
|
||||
|
||||
137
gdb/gdbsupport/thread-pool.c
Normal file
137
gdb/gdbsupport/thread-pool.c
Normal file
@@ -0,0 +1,137 @@
|
||||
/* Thread pool
|
||||
|
||||
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 "common-defs.h"
|
||||
#include "gdbsupport/thread-pool.h"
|
||||
#include "gdbsupport/alt-stack.h"
|
||||
#include "gdbsupport/block-signals.h"
|
||||
#include <algorithm>
|
||||
|
||||
/* On the off chance that we have the pthread library on a Windows
|
||||
host, but std::thread is not using it, avoid calling
|
||||
pthread_setname_np on Windows. */
|
||||
#ifndef _WIN32
|
||||
#ifdef HAVE_PTHREAD_SETNAME_NP
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace gdb
|
||||
{
|
||||
|
||||
/* The thread pool detach()s its threads, so that the threads will not
|
||||
prevent the process from exiting. However, it was discovered that
|
||||
if any detached threads were still waiting on a condition variable,
|
||||
then the condition variable's destructor would wait for the threads
|
||||
to exit -- defeating the purpose.
|
||||
|
||||
Allocating the thread pool on the heap and simply "leaking" it
|
||||
avoids this problem.
|
||||
*/
|
||||
thread_pool *thread_pool::g_thread_pool = new thread_pool ();
|
||||
|
||||
thread_pool::~thread_pool ()
|
||||
{
|
||||
/* Because this is a singleton, we don't need to clean up. The
|
||||
threads are detached so that they won't prevent process exit.
|
||||
And, cleaning up here would be actively harmful in at least one
|
||||
case -- see the comment by the definition of g_thread_pool. */
|
||||
}
|
||||
|
||||
void
|
||||
thread_pool::set_thread_count (size_t num_threads)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard (m_tasks_mutex);
|
||||
|
||||
/* If the new size is larger, start some new threads. */
|
||||
if (m_count < num_threads)
|
||||
{
|
||||
/* Ensure that signals used by gdb are blocked in the new
|
||||
threads. */
|
||||
block_signals blocker;
|
||||
for (size_t i = m_count; i < num_threads; ++i)
|
||||
{
|
||||
std::thread thread (&thread_pool::thread_function, this);
|
||||
#ifndef _WIN32 /* See the comment at the top of the file. */
|
||||
#ifdef HAVE_PTHREAD_SETNAME_NP
|
||||
pthread_setname_np (thread.native_handle (), "gdb worker");
|
||||
#endif
|
||||
#endif
|
||||
thread.detach ();
|
||||
}
|
||||
}
|
||||
/* If the new size is smaller, terminate some existing threads. */
|
||||
if (num_threads < m_count)
|
||||
{
|
||||
for (size_t i = num_threads; i < m_count; ++i)
|
||||
m_tasks.emplace ();
|
||||
m_tasks_cv.notify_all ();
|
||||
}
|
||||
|
||||
m_count = num_threads;
|
||||
}
|
||||
|
||||
std::future<void>
|
||||
thread_pool::post_task (std::function<void ()> func)
|
||||
{
|
||||
std::packaged_task<void ()> t (func);
|
||||
std::future<void> f = t.get_future ();
|
||||
|
||||
if (m_count == 0)
|
||||
{
|
||||
/* Just execute it now. */
|
||||
t ();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::lock_guard<std::mutex> guard (m_tasks_mutex);
|
||||
m_tasks.emplace (std::move (t));
|
||||
m_tasks_cv.notify_one ();
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
void
|
||||
thread_pool::thread_function ()
|
||||
{
|
||||
/* Ensure that SIGSEGV is delivered to an alternate signal
|
||||
stack. */
|
||||
gdb::alternate_signal_stack signal_stack;
|
||||
|
||||
while (true)
|
||||
{
|
||||
task t;
|
||||
|
||||
{
|
||||
/* We want to hold the lock while examining the task list, but
|
||||
not while invoking the task function. */
|
||||
std::unique_lock<std::mutex> guard (m_tasks_mutex);
|
||||
while (m_tasks.empty ())
|
||||
m_tasks_cv.wait (guard);
|
||||
t = std::move (m_tasks.front());
|
||||
m_tasks.pop ();
|
||||
}
|
||||
|
||||
if (!t.has_value ())
|
||||
break;
|
||||
(*t) ();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
90
gdb/gdbsupport/thread-pool.h
Normal file
90
gdb/gdbsupport/thread-pool.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* Thread pool
|
||||
|
||||
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_THREAD_POOL_H
|
||||
#define GDBSUPPORT_THREAD_POOL_H
|
||||
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <future>
|
||||
#include "gdbsupport/gdb_optional.h"
|
||||
|
||||
namespace gdb
|
||||
{
|
||||
|
||||
/* A thread pool.
|
||||
|
||||
There is a single global thread pool, see g_thread_pool. Tasks can
|
||||
be submitted to the thread pool. They will be processed in worker
|
||||
threads as time allows. */
|
||||
class thread_pool
|
||||
{
|
||||
public:
|
||||
/* The sole global thread pool. */
|
||||
static thread_pool *g_thread_pool;
|
||||
|
||||
~thread_pool ();
|
||||
DISABLE_COPY_AND_ASSIGN (thread_pool);
|
||||
|
||||
/* Set the thread count of this thread pool. By default, no threads
|
||||
are created -- the thread count must be set first. */
|
||||
void set_thread_count (size_t num_threads);
|
||||
|
||||
/* Return the number of executing threads. */
|
||||
size_t count () const
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
/* Post a task to the thread pool. A future is returned, which can
|
||||
be used to wait for the result. */
|
||||
std::future<void> post_task (std::function<void ()> func);
|
||||
|
||||
private:
|
||||
|
||||
thread_pool () = default;
|
||||
|
||||
/* The callback for each worker thread. */
|
||||
void thread_function ();
|
||||
|
||||
/* An optional is used to represent a task. If the optional is
|
||||
empty, then this means that the receiving thread should
|
||||
terminate. If the optional is non-empty, then it is an actual
|
||||
task to evaluate. */
|
||||
typedef optional<std::packaged_task<void ()>> task;
|
||||
|
||||
/* The current thread count. */
|
||||
size_t m_count = 0;
|
||||
|
||||
/* The tasks that have not been processed yet. */
|
||||
std::queue<task> m_tasks;
|
||||
|
||||
/* A condition variable and mutex that are used for communication
|
||||
between the main thread and the worker threads. */
|
||||
std::condition_variable m_tasks_cv;
|
||||
std::mutex m_tasks_mutex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* GDBSUPPORT_THREAD_POOL_H */
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "guile-internal.h"
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include "gdbsupport/block-signals.h"
|
||||
|
||||
/* The Guile version we're using.
|
||||
We *could* use the macros in libguile/version.h but that would preclude
|
||||
@@ -798,10 +799,6 @@ _initialize_guile (void)
|
||||
|
||||
#if HAVE_GUILE
|
||||
{
|
||||
#ifdef HAVE_SIGPROCMASK
|
||||
sigset_t sigchld_mask, prev_mask;
|
||||
#endif
|
||||
|
||||
/* The Python support puts the C side in module "_gdb", leaving the Python
|
||||
side to define module "gdb" which imports "_gdb". There is evidently no
|
||||
similar convention in Guile so we skip this. */
|
||||
@@ -813,25 +810,20 @@ _initialize_guile (void)
|
||||
scm_set_automatic_finalization_enabled (0);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGPROCMASK
|
||||
/* Before we initialize Guile, block SIGCHLD.
|
||||
/* Before we initialize Guile, block signals needed by gdb
|
||||
(especially SIGCHLD).
|
||||
This is done so that all threads created during Guile initialization
|
||||
have SIGCHLD blocked. PR 17247.
|
||||
Really libgc and Guile should do this, but we need to work with
|
||||
libgc 7.4.x. */
|
||||
sigemptyset (&sigchld_mask);
|
||||
sigaddset (&sigchld_mask, SIGCHLD);
|
||||
sigprocmask (SIG_BLOCK, &sigchld_mask, &prev_mask);
|
||||
#endif
|
||||
{
|
||||
gdb::block_signals blocker;
|
||||
|
||||
/* scm_with_guile is the most portable way to initialize Guile.
|
||||
Plus we need to initialize the Guile support while in Guile mode
|
||||
(e.g., called from within a call to scm_with_guile). */
|
||||
scm_with_guile (call_initialize_gdb_module, NULL);
|
||||
|
||||
#ifdef HAVE_SIGPROCMASK
|
||||
sigprocmask (SIG_SETMASK, &prev_mask, NULL);
|
||||
#endif
|
||||
/* scm_with_guile is the most portable way to initialize Guile.
|
||||
Plus we need to initialize the Guile support while in Guile mode
|
||||
(e.g., called from within a call to scm_with_guile). */
|
||||
scm_with_guile (call_initialize_gdb_module, NULL);
|
||||
}
|
||||
|
||||
/* Set Guile's backtrace to match the "set guile print-stack" default.
|
||||
[N.B. The two settings are still separate.]
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "nat/linux-namespaces.h"
|
||||
#include "gdbsupport/fileio.h"
|
||||
#include "gdbsupport/scope-exit.h"
|
||||
#include "gdbsupport/gdb-sigmask.h"
|
||||
|
||||
/* This comment documents high-level logic of this file.
|
||||
|
||||
@@ -764,7 +765,7 @@ block_child_signals (sigset_t *prev_mask)
|
||||
if (!sigismember (&blocked_mask, SIGCHLD))
|
||||
sigaddset (&blocked_mask, SIGCHLD);
|
||||
|
||||
sigprocmask (SIG_BLOCK, &blocked_mask, prev_mask);
|
||||
gdb_sigmask (SIG_BLOCK, &blocked_mask, prev_mask);
|
||||
}
|
||||
|
||||
/* Restore child signals mask, previously returned by
|
||||
@@ -773,7 +774,7 @@ block_child_signals (sigset_t *prev_mask)
|
||||
static void
|
||||
restore_child_signals_mask (sigset_t *prev_mask)
|
||||
{
|
||||
sigprocmask (SIG_SETMASK, prev_mask, NULL);
|
||||
gdb_sigmask (SIG_SETMASK, prev_mask, NULL);
|
||||
}
|
||||
|
||||
/* Mask of signals to pass directly to the inferior. */
|
||||
@@ -4564,7 +4565,7 @@ Enables printf debugging output."),
|
||||
sigaction (SIGCHLD, &sigchld_action, NULL);
|
||||
|
||||
/* Make sure we don't block SIGCHLD during a sigsuspend. */
|
||||
sigprocmask (SIG_SETMASK, NULL, &suspend_mask);
|
||||
gdb_sigmask (SIG_SETMASK, NULL, &suspend_mask);
|
||||
sigdelset (&suspend_mask, SIGCHLD);
|
||||
|
||||
sigemptyset (&blocked_mask);
|
||||
|
||||
26
gdb/main.c
26
gdb/main.c
@@ -52,6 +52,7 @@
|
||||
#ifdef GDBTK
|
||||
#include "gdbtk/generic/gdbtk.h"
|
||||
#endif
|
||||
#include "gdbsupport/alt-stack.h"
|
||||
|
||||
/* The selected interpreter. This will be used as a set command
|
||||
variable, so it should always be malloc'ed - since
|
||||
@@ -334,29 +335,6 @@ get_init_files (std::vector<std::string> *system_gdbinit,
|
||||
*local_gdbinit = localinit;
|
||||
}
|
||||
|
||||
/* Try to set up an alternate signal stack for SIGSEGV handlers.
|
||||
This allows us to handle SIGSEGV signals generated when the
|
||||
normal process stack is exhausted. If this stack is not set
|
||||
up (sigaltstack is unavailable or fails) and a SIGSEGV is
|
||||
generated when the normal stack is exhausted then the program
|
||||
will behave as though no SIGSEGV handler was installed. */
|
||||
|
||||
static void
|
||||
setup_alternate_signal_stack (void)
|
||||
{
|
||||
#ifdef HAVE_SIGALTSTACK
|
||||
stack_t ss;
|
||||
|
||||
/* FreeBSD versions older than 11.0 use char * for ss_sp instead of
|
||||
void *. This cast works with both types. */
|
||||
ss.ss_sp = (char *) xmalloc (SIGSTKSZ);
|
||||
ss.ss_size = SIGSTKSZ;
|
||||
ss.ss_flags = 0;
|
||||
|
||||
sigaltstack(&ss, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Call command_loop. */
|
||||
|
||||
/* Prevent inlining this function for the benefit of GDB's selftests
|
||||
@@ -898,7 +876,7 @@ captured_main_1 (struct captured_main_args *context)
|
||||
save_original_signals_state (quiet);
|
||||
|
||||
/* Try to set up an alternate signal stack for SIGSEGV handlers. */
|
||||
setup_alternate_signal_stack ();
|
||||
gdb::alternate_signal_stack signal_stack;
|
||||
|
||||
/* Initialize all files. */
|
||||
gdb_init (gdb_program_name);
|
||||
|
||||
48
gdb/maint.c
48
gdb/maint.c
@@ -46,6 +46,10 @@
|
||||
#include "cli/cli-setshow.h"
|
||||
#include "cli/cli-cmds.h"
|
||||
|
||||
#if CXX_STD_THREAD
|
||||
#include "gdbsupport/thread-pool.h"
|
||||
#endif
|
||||
|
||||
static void maintenance_do_deprecate (const char *, int);
|
||||
|
||||
/* Access the maintenance subcommands. */
|
||||
@@ -840,6 +844,37 @@ maintenance_set_profile_cmd (const char *args, int from_tty,
|
||||
error (_("Profiling support is not available on this system."));
|
||||
}
|
||||
#endif
|
||||
|
||||
static int n_worker_threads = -1;
|
||||
|
||||
/* Update the thread pool for the desired number of threads. */
|
||||
static void
|
||||
update_thread_pool_size ()
|
||||
{
|
||||
#if CXX_STD_THREAD
|
||||
int n_threads = n_worker_threads;
|
||||
|
||||
if (n_threads < 0)
|
||||
{
|
||||
n_threads = std::thread::hardware_concurrency ();
|
||||
if (n_threads == 0)
|
||||
{
|
||||
/* Meh. */
|
||||
n_threads = 2;
|
||||
}
|
||||
}
|
||||
|
||||
gdb::thread_pool::g_thread_pool->set_thread_count (n_threads);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
maintenance_set_worker_threads (const char *args, int from_tty,
|
||||
struct cmd_list_element *c)
|
||||
{
|
||||
update_thread_pool_size ();
|
||||
}
|
||||
|
||||
|
||||
/* If true, display time usage both at startup and for each command. */
|
||||
|
||||
@@ -1312,4 +1347,17 @@ When enabled GDB is profiled."),
|
||||
show_maintenance_profile_p,
|
||||
&maintenance_set_cmdlist,
|
||||
&maintenance_show_cmdlist);
|
||||
|
||||
add_setshow_zuinteger_unlimited_cmd ("worker-threads",
|
||||
class_maintenance,
|
||||
&n_worker_threads, _("\
|
||||
Set the number of worker threads GDB can use."), _("\
|
||||
Set the number of worker threads GDB can use."), _("\
|
||||
GDB may use multiple threads to speed up certain CPU-intensive operations,\n\
|
||||
such as demangling symbol names."),
|
||||
maintenance_set_worker_threads, NULL,
|
||||
&maintenance_set_cmdlist,
|
||||
&maintenance_show_cmdlist);
|
||||
|
||||
update_thread_pool_size ();
|
||||
}
|
||||
|
||||
134
gdb/minsyms.c
134
gdb/minsyms.c
@@ -53,6 +53,11 @@
|
||||
#include "gdbsupport/symbol.h"
|
||||
#include <algorithm>
|
||||
#include "safe-ctype.h"
|
||||
#include "gdbsupport/parallel-for.h"
|
||||
|
||||
#if CXX_STD_THREAD
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
/* See minsyms.h. */
|
||||
|
||||
@@ -136,12 +141,12 @@ msymbol_hash (const char *string)
|
||||
/* Add the minimal symbol SYM to an objfile's minsym hash table, TABLE. */
|
||||
static void
|
||||
add_minsym_to_hash_table (struct minimal_symbol *sym,
|
||||
struct minimal_symbol **table)
|
||||
struct minimal_symbol **table,
|
||||
unsigned int hash_value)
|
||||
{
|
||||
if (sym->hash_next == NULL)
|
||||
{
|
||||
unsigned int hash
|
||||
= msymbol_hash (MSYMBOL_LINKAGE_NAME (sym)) % MINIMAL_SYMBOL_HASH_SIZE;
|
||||
unsigned int hash = hash_value % MINIMAL_SYMBOL_HASH_SIZE;
|
||||
|
||||
sym->hash_next = table[hash];
|
||||
table[hash] = sym;
|
||||
@@ -152,18 +157,16 @@ add_minsym_to_hash_table (struct minimal_symbol *sym,
|
||||
TABLE. */
|
||||
static void
|
||||
add_minsym_to_demangled_hash_table (struct minimal_symbol *sym,
|
||||
struct objfile *objfile)
|
||||
struct objfile_per_bfd_storage *per_bfd,
|
||||
unsigned int hash_value)
|
||||
{
|
||||
if (sym->demangled_hash_next == NULL)
|
||||
{
|
||||
unsigned int hash = search_name_hash (MSYMBOL_LANGUAGE (sym),
|
||||
MSYMBOL_SEARCH_NAME (sym));
|
||||
|
||||
objfile->per_bfd->demangled_hash_languages.set (MSYMBOL_LANGUAGE (sym));
|
||||
per_bfd->demangled_hash_languages.set (MSYMBOL_LANGUAGE (sym));
|
||||
|
||||
struct minimal_symbol **table
|
||||
= objfile->per_bfd->msymbol_demangled_hash;
|
||||
unsigned int hash_index = hash % MINIMAL_SYMBOL_HASH_SIZE;
|
||||
= per_bfd->msymbol_demangled_hash;
|
||||
unsigned int hash_index = hash_value % MINIMAL_SYMBOL_HASH_SIZE;
|
||||
sym->demangled_hash_next = table[hash_index];
|
||||
table[hash_index] = sym;
|
||||
}
|
||||
@@ -338,6 +341,7 @@ lookup_minimal_symbol (const char *name, const char *sfile,
|
||||
objfile_debug_name (objfile));
|
||||
}
|
||||
|
||||
objfile->per_bfd->wait_for_msymbols ();
|
||||
/* Do two passes: the first over the ordinary hash table,
|
||||
and the second over the demangled hash table. */
|
||||
lookup_minimal_symbol_mangled (name, sfile, objfile,
|
||||
@@ -474,6 +478,7 @@ iterate_over_minimal_symbols
|
||||
(struct objfile *objf, const lookup_name_info &lookup_name,
|
||||
gdb::function_view<bool (struct minimal_symbol *)> callback)
|
||||
{
|
||||
objf->per_bfd->wait_for_msymbols ();
|
||||
/* The first pass is over the ordinary hash table. */
|
||||
{
|
||||
const char *name = linkage_name_str (lookup_name);
|
||||
@@ -526,6 +531,7 @@ lookup_minimal_symbol_linkage (const char *name, struct objfile *objf)
|
||||
|
||||
for (objfile *objfile : objf->separate_debug_objfiles ())
|
||||
{
|
||||
objfile->per_bfd->wait_for_msymbols ();
|
||||
for (minimal_symbol *msymbol = objfile->per_bfd->msymbol_hash[hash];
|
||||
msymbol != NULL;
|
||||
msymbol = msymbol->hash_next)
|
||||
@@ -559,6 +565,7 @@ lookup_minimal_symbol_text (const char *name, struct objfile *objf)
|
||||
if (objf == NULL || objf == objfile
|
||||
|| objf == objfile->separate_debug_objfile_backlink)
|
||||
{
|
||||
objfile->per_bfd->wait_for_msymbols ();
|
||||
for (msymbol = objfile->per_bfd->msymbol_hash[hash];
|
||||
msymbol != NULL && found_symbol.minsym == NULL;
|
||||
msymbol = msymbol->hash_next)
|
||||
@@ -606,6 +613,7 @@ lookup_minimal_symbol_by_pc_name (CORE_ADDR pc, const char *name,
|
||||
if (objf == NULL || objf == objfile
|
||||
|| objf == objfile->separate_debug_objfile_backlink)
|
||||
{
|
||||
objfile->per_bfd->wait_for_msymbols ();
|
||||
for (msymbol = objfile->per_bfd->msymbol_hash[hash];
|
||||
msymbol != NULL;
|
||||
msymbol = msymbol->hash_next)
|
||||
@@ -717,6 +725,7 @@ lookup_minimal_symbol_by_pc_section (CORE_ADDR pc_in, struct obj_section *sectio
|
||||
/* If this objfile has a minimal symbol table, go search it
|
||||
using a binary search. */
|
||||
|
||||
objfile->per_bfd->wait_for_msymbols ();
|
||||
if (objfile->per_bfd->minimal_symbol_count > 0)
|
||||
{
|
||||
int best_zero_sized = -1;
|
||||
@@ -1127,7 +1136,12 @@ minimal_symbol_reader::record_full (gdb::string_view name,
|
||||
msymbol = &m_msym_bunch->contents[m_msym_bunch_index];
|
||||
symbol_set_language (msymbol, language_auto,
|
||||
&m_objfile->per_bfd->storage_obstack);
|
||||
symbol_set_names (msymbol, name, copy_name, m_objfile->per_bfd);
|
||||
|
||||
if (copy_name)
|
||||
msymbol->name = obstack_strndup (&m_objfile->per_bfd->storage_obstack,
|
||||
name.data (), name.size ());
|
||||
else
|
||||
msymbol->name = name.data ();
|
||||
|
||||
SET_MSYMBOL_VALUE_ADDRESS (msymbol, address);
|
||||
MSYMBOL_SECTION (msymbol) = section;
|
||||
@@ -1248,28 +1262,41 @@ clear_minimal_symbol_hash_tables (struct objfile *objfile)
|
||||
}
|
||||
}
|
||||
|
||||
struct computed_hash_values
|
||||
{
|
||||
size_t name_length;
|
||||
hashval_t mangled_name_hash;
|
||||
unsigned int minsym_hash;
|
||||
unsigned int minsym_demangled_hash;
|
||||
};
|
||||
|
||||
/* Build (or rebuild) the minimal symbol hash tables. This is necessary
|
||||
after compacting or sorting the table since the entries move around
|
||||
thus causing the internal minimal_symbol pointers to become jumbled. */
|
||||
|
||||
static void
|
||||
build_minimal_symbol_hash_tables (struct objfile *objfile)
|
||||
build_minimal_symbol_hash_tables
|
||||
(struct objfile_per_bfd_storage *per_bfd,
|
||||
const std::vector<computed_hash_values>& hash_values)
|
||||
{
|
||||
int i;
|
||||
struct minimal_symbol *msym;
|
||||
|
||||
/* (Re)insert the actual entries. */
|
||||
for ((i = objfile->per_bfd->minimal_symbol_count,
|
||||
msym = objfile->per_bfd->msymbols.get ());
|
||||
i > 0;
|
||||
i--, msym++)
|
||||
int mcount = per_bfd->minimal_symbol_count;
|
||||
for ((i = 0,
|
||||
msym = per_bfd->msymbols.get ());
|
||||
i < mcount;
|
||||
i++, msym++)
|
||||
{
|
||||
msym->hash_next = 0;
|
||||
add_minsym_to_hash_table (msym, objfile->per_bfd->msymbol_hash);
|
||||
add_minsym_to_hash_table (msym, per_bfd->msymbol_hash,
|
||||
hash_values[i].minsym_hash);
|
||||
|
||||
msym->demangled_hash_next = 0;
|
||||
if (MSYMBOL_SEARCH_NAME (msym) != MSYMBOL_LINKAGE_NAME (msym))
|
||||
add_minsym_to_demangled_hash_table (msym, objfile);
|
||||
add_minsym_to_demangled_hash_table
|
||||
(msym, per_bfd, hash_values[i].minsym_demangled_hash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1290,8 +1317,11 @@ minimal_symbol_reader::install ()
|
||||
if (m_objfile->per_bfd->minsyms_read)
|
||||
return;
|
||||
|
||||
|
||||
if (m_msym_count > 0)
|
||||
{
|
||||
m_objfile->per_bfd->wait_for_msymbols ();
|
||||
|
||||
if (symtab_create_debug)
|
||||
{
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
@@ -1354,7 +1384,71 @@ minimal_symbol_reader::install ()
|
||||
m_objfile->per_bfd->minimal_symbol_count = mcount;
|
||||
m_objfile->per_bfd->msymbols = std::move (msym_holder);
|
||||
|
||||
build_minimal_symbol_hash_tables (m_objfile);
|
||||
msymbols = m_objfile->per_bfd->msymbols.get ();
|
||||
objfile_per_bfd_storage* per_bfd = m_objfile->per_bfd;
|
||||
|
||||
m_objfile->per_bfd->m_minsym_future
|
||||
= gdb::thread_pool::g_thread_pool->post_task ([msymbols, mcount,
|
||||
per_bfd] ()
|
||||
{
|
||||
#if CXX_STD_THREAD
|
||||
/* Mutex that is used when modifying or accessing the demangled
|
||||
hash table. */
|
||||
std::mutex demangled_mutex;
|
||||
#endif
|
||||
|
||||
std::vector<computed_hash_values> hash_values (mcount);
|
||||
|
||||
gdb::parallel_for_each
|
||||
(&msymbols[0], &msymbols[mcount],
|
||||
[&] (minimal_symbol *start, minimal_symbol *end)
|
||||
{
|
||||
for (minimal_symbol *msym = start; msym < end; ++msym)
|
||||
{
|
||||
size_t idx = msym - msymbols;
|
||||
hash_values[idx].name_length = strlen (msym->name);
|
||||
if (!msym->name_set)
|
||||
{
|
||||
/* This will be freed later, by symbol_set_names. */
|
||||
char *demangled_name
|
||||
= symbol_find_demangled_name (msym, msym->name);
|
||||
symbol_set_demangled_name
|
||||
(msym, demangled_name,
|
||||
&per_bfd->storage_obstack);
|
||||
msym->name_set = 1;
|
||||
|
||||
hash_values[idx].mangled_name_hash
|
||||
= fast_hash (msym->name, hash_values[idx].name_length);
|
||||
}
|
||||
hash_values[idx].minsym_hash
|
||||
= msymbol_hash (MSYMBOL_LINKAGE_NAME (msym));
|
||||
hash_values[idx].minsym_demangled_hash
|
||||
= search_name_hash (MSYMBOL_LANGUAGE (msym),
|
||||
MSYMBOL_SEARCH_NAME (msym));
|
||||
}
|
||||
{
|
||||
/* To limit how long we hold the lock, we only acquire it here
|
||||
and not while we demangle the names above. */
|
||||
#if CXX_STD_THREAD
|
||||
std::lock_guard<std::mutex> guard (demangled_mutex);
|
||||
#endif
|
||||
for (minimal_symbol *msym = start; msym < end; ++msym)
|
||||
{
|
||||
size_t idx = msym - msymbols;
|
||||
symbol_set_names
|
||||
(msym,
|
||||
gdb::string_view(msym->name,
|
||||
hash_values[idx].name_length),
|
||||
false,
|
||||
per_bfd,
|
||||
hash_values[idx].mangled_name_hash);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
build_minimal_symbol_hash_tables (per_bfd, hash_values);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1441,6 +1535,8 @@ minimal_symbol_upper_bound (struct bound_minimal_symbol minsym)
|
||||
other sections, to find the next symbol in this section with a
|
||||
different address. */
|
||||
|
||||
minsym.objfile->per_bfd->wait_for_msymbols ();
|
||||
|
||||
struct minimal_symbol *past_the_end
|
||||
= (minsym.objfile->per_bfd->msymbols.get ()
|
||||
+ minsym.objfile->per_bfd->minimal_symbol_count);
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
#include "psymtab.h"
|
||||
#include <bitset>
|
||||
#include <vector>
|
||||
#if CXX_STD_THREAD
|
||||
#include <future>
|
||||
#endif
|
||||
#include "gdbsupport/next-iterator.h"
|
||||
#include "gdbsupport/safe-iterator.h"
|
||||
#include "bcache.h"
|
||||
@@ -319,6 +322,19 @@ struct objfile_per_bfd_storage
|
||||
/* All the different languages of symbols found in the demangled
|
||||
hash table. */
|
||||
std::bitset<nr_languages> demangled_hash_languages;
|
||||
|
||||
void wait_for_msymbols() {
|
||||
#if CXX_STD_THREAD
|
||||
if (m_minsym_future.valid ())
|
||||
{
|
||||
m_minsym_future.wait ();
|
||||
m_minsym_future = std::future<void> ();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if CXX_STD_THREAD
|
||||
std::future<void> m_minsym_future;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* An iterator that first returns a parent objfile, and then each
|
||||
@@ -439,11 +455,13 @@ struct objfile
|
||||
|
||||
minimal_symbol_iterator begin () const
|
||||
{
|
||||
m_objfile->per_bfd->wait_for_msymbols ();
|
||||
return minimal_symbol_iterator (m_objfile->per_bfd->msymbols.get ());
|
||||
}
|
||||
|
||||
minimal_symbol_iterator end () const
|
||||
{
|
||||
m_objfile->per_bfd->wait_for_msymbols ();
|
||||
return minimal_symbol_iterator
|
||||
(m_objfile->per_bfd->msymbols.get ()
|
||||
+ m_objfile->per_bfd->minimal_symbol_count);
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "value.h"
|
||||
#include "language.h"
|
||||
#include "event-loop.h"
|
||||
#include "serial.h"
|
||||
#include "readline/tilde.h"
|
||||
#include "python.h"
|
||||
#include "extension-priv.h"
|
||||
@@ -940,63 +939,81 @@ gdbpy_source_script (const struct extension_language_defn *extlang,
|
||||
|
||||
/* Posting and handling events. */
|
||||
|
||||
/* A helper class to save and restore the GIL, but without touching
|
||||
the other globals that are handled by gdbpy_enter. */
|
||||
|
||||
class gdbpy_gil
|
||||
{
|
||||
public:
|
||||
|
||||
gdbpy_gil ()
|
||||
: m_state (PyGILState_Ensure ())
|
||||
{
|
||||
}
|
||||
|
||||
~gdbpy_gil ()
|
||||
{
|
||||
PyGILState_Release (m_state);
|
||||
}
|
||||
|
||||
DISABLE_COPY_AND_ASSIGN (gdbpy_gil);
|
||||
|
||||
private:
|
||||
|
||||
PyGILState_STATE m_state;
|
||||
};
|
||||
|
||||
/* A single event. */
|
||||
struct gdbpy_event
|
||||
{
|
||||
/* The Python event. This is just a callable object. */
|
||||
PyObject *event;
|
||||
/* The next event. */
|
||||
struct gdbpy_event *next;
|
||||
gdbpy_event (gdbpy_ref<> &&func)
|
||||
: m_func (func.release ())
|
||||
{
|
||||
}
|
||||
|
||||
gdbpy_event (gdbpy_event &&other)
|
||||
: m_func (other.m_func)
|
||||
{
|
||||
other.m_func = nullptr;
|
||||
}
|
||||
|
||||
gdbpy_event (const gdbpy_event &other)
|
||||
: m_func (other.m_func)
|
||||
{
|
||||
gdbpy_gil gil;
|
||||
Py_XINCREF (m_func);
|
||||
}
|
||||
|
||||
~gdbpy_event ()
|
||||
{
|
||||
gdbpy_gil gil;
|
||||
Py_XDECREF (m_func);
|
||||
}
|
||||
|
||||
gdbpy_event &operator= (const gdbpy_event &other) = delete;
|
||||
|
||||
void operator() ()
|
||||
{
|
||||
gdbpy_enter enter_py (get_current_arch (), current_language);
|
||||
|
||||
gdbpy_ref<> call_result (PyObject_CallObject (m_func, NULL));
|
||||
if (call_result == NULL)
|
||||
gdbpy_print_stack ();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/* The Python event. This is just a callable object. Note that
|
||||
this is not a gdbpy_ref<>, because we have to take particular
|
||||
care to only destroy the reference when holding the GIL. */
|
||||
PyObject *m_func;
|
||||
};
|
||||
|
||||
/* All pending events. */
|
||||
static struct gdbpy_event *gdbpy_event_list;
|
||||
/* The final link of the event list. */
|
||||
static struct gdbpy_event **gdbpy_event_list_end;
|
||||
|
||||
/* So that we can wake up the main thread even when it is blocked in
|
||||
poll(). */
|
||||
static struct serial_event *gdbpy_serial_event;
|
||||
|
||||
/* The file handler callback. This reads from the internal pipe, and
|
||||
then processes the Python event queue. This will always be run in
|
||||
the main gdb thread. */
|
||||
|
||||
static void
|
||||
gdbpy_run_events (int error, gdb_client_data client_data)
|
||||
{
|
||||
gdbpy_enter enter_py (get_current_arch (), current_language);
|
||||
|
||||
/* Clear the event fd. Do this before flushing the events list, so
|
||||
that any new event post afterwards is sure to re-awake the event
|
||||
loop. */
|
||||
serial_event_clear (gdbpy_serial_event);
|
||||
|
||||
while (gdbpy_event_list)
|
||||
{
|
||||
/* Dispatching the event might push a new element onto the event
|
||||
loop, so we update here "atomically enough". */
|
||||
struct gdbpy_event *item = gdbpy_event_list;
|
||||
gdbpy_event_list = gdbpy_event_list->next;
|
||||
if (gdbpy_event_list == NULL)
|
||||
gdbpy_event_list_end = &gdbpy_event_list;
|
||||
|
||||
gdbpy_ref<> call_result (PyObject_CallObject (item->event, NULL));
|
||||
if (call_result == NULL)
|
||||
gdbpy_print_stack ();
|
||||
|
||||
Py_DECREF (item->event);
|
||||
xfree (item);
|
||||
}
|
||||
}
|
||||
|
||||
/* Submit an event to the gdb thread. */
|
||||
static PyObject *
|
||||
gdbpy_post_event (PyObject *self, PyObject *args)
|
||||
{
|
||||
struct gdbpy_event *event;
|
||||
PyObject *func;
|
||||
int wakeup;
|
||||
|
||||
if (!PyArg_ParseTuple (args, "O", &func))
|
||||
return NULL;
|
||||
@@ -1010,36 +1027,13 @@ gdbpy_post_event (PyObject *self, PyObject *args)
|
||||
|
||||
Py_INCREF (func);
|
||||
|
||||
/* From here until the end of the function, we have the GIL, so we
|
||||
can operate on our global data structures without worrying. */
|
||||
wakeup = gdbpy_event_list == NULL;
|
||||
|
||||
event = XNEW (struct gdbpy_event);
|
||||
event->event = func;
|
||||
event->next = NULL;
|
||||
*gdbpy_event_list_end = event;
|
||||
gdbpy_event_list_end = &event->next;
|
||||
|
||||
/* Wake up gdb when needed. */
|
||||
if (wakeup)
|
||||
serial_event_set (gdbpy_serial_event);
|
||||
gdbpy_ref<> func_ref = gdbpy_ref<>::new_reference (func);
|
||||
gdbpy_event event (std::move (func_ref));
|
||||
run_on_main_thread (event);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
/* Initialize the Python event handler. */
|
||||
static int
|
||||
gdbpy_initialize_events (void)
|
||||
{
|
||||
gdbpy_event_list_end = &gdbpy_event_list;
|
||||
|
||||
gdbpy_serial_event = make_serial_event ();
|
||||
add_file_handler (serial_event_fd (gdbpy_serial_event),
|
||||
gdbpy_run_events, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This is the extension_language_ops.before_prompt "method". */
|
||||
@@ -1704,7 +1698,6 @@ do_start_initialization ()
|
||||
|| gdbpy_initialize_linetable () < 0
|
||||
|| gdbpy_initialize_thread () < 0
|
||||
|| gdbpy_initialize_inferior () < 0
|
||||
|| gdbpy_initialize_events () < 0
|
||||
|| gdbpy_initialize_eventregistry () < 0
|
||||
|| gdbpy_initialize_py_events () < 0
|
||||
|| gdbpy_initialize_event () < 0
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
#include "ser-event.h"
|
||||
#include "serial.h"
|
||||
#include "gdbsupport/filestuff.h"
|
||||
#if CXX_STD_THREAD
|
||||
#include <mutex>
|
||||
#endif
|
||||
#include "event-loop.h"
|
||||
|
||||
/* On POSIX hosts, a serial_event is basically an abstraction for the
|
||||
classical self-pipe trick.
|
||||
@@ -217,3 +221,77 @@ serial_event_clear (struct serial_event *event)
|
||||
ResetEvent (state->event);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The serial event used when posting runnables. */
|
||||
|
||||
static struct serial_event *runnable_event;
|
||||
|
||||
/* Runnables that have been posted. */
|
||||
|
||||
static std::vector<std::function<void ()>> runnables;
|
||||
|
||||
#if CXX_STD_THREAD
|
||||
|
||||
/* Mutex to hold when handling runnable_event or runnables. */
|
||||
|
||||
static std::mutex runnable_mutex;
|
||||
|
||||
#endif
|
||||
|
||||
/* Run all the queued runnables. */
|
||||
|
||||
static void
|
||||
run_events (int error, gdb_client_data client_data)
|
||||
{
|
||||
std::vector<std::function<void ()>> local;
|
||||
|
||||
/* Hold the lock while changing the globals, but not while running
|
||||
the runnables. */
|
||||
{
|
||||
#if CXX_STD_THREAD
|
||||
std::lock_guard<std::mutex> lock (runnable_mutex);
|
||||
#endif
|
||||
|
||||
/* Clear the event fd. Do this before flushing the events list,
|
||||
so that any new event post afterwards is sure to re-awaken the
|
||||
event loop. */
|
||||
serial_event_clear (runnable_event);
|
||||
|
||||
/* Move the vector in case running a runnable pushes a new
|
||||
runnable. */
|
||||
local = std::move (runnables);
|
||||
}
|
||||
|
||||
for (auto &item : local)
|
||||
{
|
||||
try
|
||||
{
|
||||
item ();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
/* Ignore exceptions in the callback. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* See ser-event.h. */
|
||||
|
||||
void
|
||||
run_on_main_thread (std::function<void ()> &&func)
|
||||
{
|
||||
#if CXX_STD_THREAD
|
||||
std::lock_guard<std::mutex> lock (runnable_mutex);
|
||||
#endif
|
||||
runnables.emplace_back (std::move (func));
|
||||
serial_event_set (runnable_event);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_ser_event ()
|
||||
{
|
||||
runnable_event = make_serial_event ();
|
||||
add_file_handler (serial_event_fd (runnable_event), run_events, nullptr);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#ifndef SER_EVENT_H
|
||||
#define SER_EVENT_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
/* This is used to be able to signal the event loop (or any other
|
||||
select/poll) of events, in a race-free manner.
|
||||
|
||||
@@ -48,4 +50,8 @@ extern void serial_event_set (struct serial_event *event);
|
||||
call is made. */
|
||||
extern void serial_event_clear (struct serial_event *event);
|
||||
|
||||
/* Send a runnable to the main thread. */
|
||||
|
||||
extern void run_on_main_thread (std::function<void ()> &&);
|
||||
|
||||
#endif
|
||||
|
||||
41
gdb/symtab.c
41
gdb/symtab.c
@@ -770,20 +770,23 @@ create_demangled_names_hash (struct objfile_per_bfd_storage *per_bfd)
|
||||
/* Choose 256 as the starting size of the hash table, somewhat arbitrarily.
|
||||
The hash table code will round this up to the next prime number.
|
||||
Choosing a much larger table size wastes memory, and saves only about
|
||||
1% in symbol reading. */
|
||||
1% in symbol reading. However, if the minsym count is already
|
||||
initialized (e.g. because symbol name setting was deferred to
|
||||
a background thread) we can initialize the hashtable with that
|
||||
count, because we will almost certainly have at least that
|
||||
many entries. If we have a nonzero number but less than 256,
|
||||
we still stay with 256 to have some space for psymbols, etc. */
|
||||
|
||||
int count = std::max (per_bfd->minimal_symbol_count, 256);
|
||||
|
||||
per_bfd->demangled_names_hash.reset (htab_create_alloc
|
||||
(256, hash_demangled_name_entry, eq_demangled_name_entry,
|
||||
(count, hash_demangled_name_entry, eq_demangled_name_entry,
|
||||
free_demangled_name_entry, xcalloc, xfree));
|
||||
}
|
||||
|
||||
/* Try to determine the demangled name for a symbol, based on the
|
||||
language of that symbol. If the language is set to language_auto,
|
||||
it will attempt to find any demangling algorithm that works and
|
||||
then set the language appropriately. The returned name is allocated
|
||||
by the demangler and should be xfree'd. */
|
||||
/* See symtab.h */
|
||||
|
||||
static char *
|
||||
char *
|
||||
symbol_find_demangled_name (struct general_symbol_info *gsymbol,
|
||||
const char *mangled)
|
||||
{
|
||||
@@ -830,7 +833,8 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
|
||||
void
|
||||
symbol_set_names (struct general_symbol_info *gsymbol,
|
||||
gdb::string_view linkage_name, bool copy_name,
|
||||
struct objfile_per_bfd_storage *per_bfd)
|
||||
struct objfile_per_bfd_storage *per_bfd,
|
||||
gdb::optional<hashval_t> hash)
|
||||
{
|
||||
struct demangled_name_entry **slot;
|
||||
|
||||
@@ -858,9 +862,11 @@ symbol_set_names (struct general_symbol_info *gsymbol,
|
||||
create_demangled_names_hash (per_bfd);
|
||||
|
||||
struct demangled_name_entry entry (linkage_name);
|
||||
if (!hash.has_value ())
|
||||
hash = hash_demangled_name_entry (&entry);
|
||||
slot = ((struct demangled_name_entry **)
|
||||
htab_find_slot (per_bfd->demangled_names_hash.get (),
|
||||
&entry, INSERT));
|
||||
htab_find_slot_with_hash (per_bfd->demangled_names_hash.get (),
|
||||
&entry, *hash, INSERT));
|
||||
|
||||
/* If this name is not in the hash table, add it. */
|
||||
if (*slot == NULL
|
||||
@@ -884,8 +890,15 @@ symbol_set_names (struct general_symbol_info *gsymbol,
|
||||
else
|
||||
linkage_name_copy = linkage_name;
|
||||
|
||||
gdb::unique_xmalloc_ptr<char> demangled_name_ptr
|
||||
(symbol_find_demangled_name (gsymbol, linkage_name_copy.data ()));
|
||||
/* The const_cast is safe because the only reason it is already
|
||||
initialized is if we purposefully set it from a background
|
||||
thread to avoid doing the work here. However, it is still
|
||||
allocated from the heap and needs to be freed by us, just
|
||||
like if we called symbol_find_demangled_name here. */
|
||||
gdb::unique_xmalloc_ptr<char> demangled_name
|
||||
(gsymbol->language_specific.demangled_name
|
||||
? const_cast<char *> (gsymbol->language_specific.demangled_name)
|
||||
: symbol_find_demangled_name (gsymbol, linkage_name_copy.data ()));
|
||||
|
||||
/* Suppose we have demangled_name==NULL, copy_name==0, and
|
||||
linkage_name_copy==linkage_name. In this case, we already have the
|
||||
@@ -919,7 +932,7 @@ symbol_set_names (struct general_symbol_info *gsymbol,
|
||||
new (*slot) demangled_name_entry
|
||||
(gdb::string_view (mangled_ptr, linkage_name.length ()));
|
||||
}
|
||||
(*slot)->demangled = std::move (demangled_name_ptr);
|
||||
(*slot)->demangled = std::move (demangled_name);
|
||||
(*slot)->language = gsymbol->language;
|
||||
}
|
||||
else if (gsymbol->language == language_unknown
|
||||
|
||||
18
gdb/symtab.h
18
gdb/symtab.h
@@ -503,6 +503,16 @@ extern void symbol_set_language (struct general_symbol_info *symbol,
|
||||
enum language language,
|
||||
struct obstack *obstack);
|
||||
|
||||
|
||||
/* Try to determine the demangled name for a symbol, based on the
|
||||
language of that symbol. If the language is set to language_auto,
|
||||
it will attempt to find any demangling algorithm that works and
|
||||
then set the language appropriately. The returned name is allocated
|
||||
by the demangler and should be xfree'd. */
|
||||
|
||||
extern char *symbol_find_demangled_name (struct general_symbol_info *gsymbol,
|
||||
const char *mangled);
|
||||
|
||||
/* Set just the linkage name of a symbol; do not try to demangle
|
||||
it. Used for constructs which do not have a mangled name,
|
||||
e.g. struct tags. Unlike SYMBOL_SET_NAMES, linkage_name must
|
||||
@@ -519,7 +529,9 @@ extern void symbol_set_language (struct general_symbol_info *symbol,
|
||||
(objfile)->per_bfd)
|
||||
extern void symbol_set_names (struct general_symbol_info *symbol,
|
||||
gdb::string_view linkage_name, bool copy_name,
|
||||
struct objfile_per_bfd_storage *per_bfd);
|
||||
struct objfile_per_bfd_storage *per_bfd,
|
||||
gdb::optional<hashval_t> hash
|
||||
= gdb::optional<hashval_t> ());
|
||||
|
||||
/* Now come lots of name accessor macros. Short version as to when to
|
||||
use which: Use SYMBOL_NATURAL_NAME to refer to the name of the
|
||||
@@ -698,6 +710,10 @@ struct minimal_symbol : public general_symbol_info
|
||||
|
||||
unsigned maybe_copied : 1;
|
||||
|
||||
/* Non-zero if this symbol ever had its demangled name set (even if
|
||||
it was set to NULL). */
|
||||
unsigned int name_set : 1;
|
||||
|
||||
/* Minimal symbols with the same hash key are kept on a linked
|
||||
list. This is the link. */
|
||||
|
||||
|
||||
80
gdb/unittests/main-thread-selftests.c
Normal file
80
gdb/unittests/main-thread-selftests.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/* Self tests for run_on_main_thread
|
||||
|
||||
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 "defs.h"
|
||||
#include "gdbsupport/selftest.h"
|
||||
#include "gdbsupport/block-signals.h"
|
||||
#include "ser-event.h"
|
||||
#include "event-loop.h"
|
||||
#if CXX_STD_THREAD
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
namespace selftests {
|
||||
namespace main_thread_tests {
|
||||
|
||||
#if CXX_STD_THREAD
|
||||
|
||||
static bool done;
|
||||
|
||||
static void
|
||||
set_done ()
|
||||
{
|
||||
run_on_main_thread ([] ()
|
||||
{
|
||||
done = true;
|
||||
});
|
||||
}
|
||||
|
||||
static void
|
||||
run_tests ()
|
||||
{
|
||||
std::thread thread;
|
||||
|
||||
done = false;
|
||||
|
||||
{
|
||||
gdb::block_signals blocker;
|
||||
|
||||
thread = std::thread (set_done);
|
||||
}
|
||||
|
||||
while (!done && gdb_do_one_event () >= 0)
|
||||
;
|
||||
|
||||
/* Actually the test will just hang, but we want to test
|
||||
something. */
|
||||
SELF_CHECK (done);
|
||||
|
||||
thread.join ();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_main_thread_selftests ()
|
||||
{
|
||||
#if CXX_STD_THREAD
|
||||
selftests::register_test ("main_thread",
|
||||
selftests::main_thread_tests::run_tests);
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user