From 7544a87f135c194395e525c7ca6123f4fd9f51ea Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 16 Jul 2005 19:29:00 -0700 Subject: [PATCH] gcc.c (MFWRAP_SPEC): Don't wrap pthread_join or pthread_exit. * gcc.c (MFWRAP_SPEC): Don't wrap pthread_join or pthread_exit. * acinclude.m4: New file. * configure.ac: Invoke LIBMUDFLAP_CHECK_TLS. * configure, config.h.in, Makefile.in, testsuite/Makefile.in: Rebuild. * mf-hooks1.c (__mf_0fn_malloc): Move body from ... (__mf_0fn_calloc): ... here. * mf-hooks3.c (struct pthread_info): Remove. (__mf_pthread_info, __mf_pthread_info_idx): Remove. (LIBMUDFLAPTH_THREADS_MAX): Set to 1021. (struct mf_thread_data): New. (mf_thread_data, mf_thread_data_lock): New. (__mf_allocate_blank_threadinfo): Remove. (__mf_find_threadinfo): Rewrite and simplify. Only use if TLS is not available. (__mf_state_perthread): Remove. (__mf_get_state, __mf_set_state): New. (__mf_pthread_cleanup): Use &errno, rather than saved pointer. Update mf_thread_data killing procedure. (__mf_pthread_spawner): Similarly. (__mf_0fn_pthread_create): Only use wrapper if necessary. Remove code to allocate thread stack space. (__mf_0fn_pthread_join, pthread_join): Remove. (__mf_0fn_pthread_exit, pthread_exit): Remove. * mf-impl.h (dyn_pthread_join, dyn_pthread_exit): Remove. (__mf_state_1): Rename from __mf_state; use TLS when available. (__mf_get_state, __mf_set_state): New. Update all users. * mf-runtime.c (begin_recursion_protect1): New. (BEGIN_RECURSION_PROTECT): Use it. (__mf_state_1): Rename from __mf_state; use TLS when available. (threads_active_p): Remove. (__mf_usage): Compute it directly. From-SVN: r102108 --- gcc/ChangeLog | 4 + gcc/gcc.c | 2 +- libmudflap/ChangeLog | 33 ++ libmudflap/Makefile.in | 31 +- libmudflap/acinclude.m4 | 72 ++++ libmudflap/aclocal.m4 | 447 ++++++--------------- libmudflap/config.h.in | 3 + libmudflap/configure | 133 ++++++- libmudflap/configure.ac | 3 + libmudflap/mf-hooks1.c | 34 +- libmudflap/mf-hooks3.c | 648 +++++++++---------------------- libmudflap/mf-impl.h | 27 +- libmudflap/mf-runtime.c | 45 ++- libmudflap/testsuite/Makefile.in | 9 +- 14 files changed, 637 insertions(+), 854 deletions(-) create mode 100644 libmudflap/acinclude.m4 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b5e551c2b1c..2f8eeba2ac3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2005-07-16 Richard Henderson + + * gcc.c (MFWRAP_SPEC): Don't wrap pthread_join or pthread_exit. + 2005-07-16 Danny Berlin Kenneth Zadeck diff --git a/gcc/gcc.c b/gcc/gcc.c index 5317516165c..a701d2c52f2 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -598,7 +598,7 @@ proper position among the other output files. */ #define MFWRAP_SPEC " %{static: %{fmudflap|fmudflapth: \ --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\ --wrap=mmap --wrap=munmap --wrap=alloca\ -} %{fmudflapth: --wrap=pthread_create --wrap=pthread_join --wrap=pthread_exit\ +} %{fmudflapth: --wrap=pthread_create\ }} %{fmudflap|fmudflapth: --wrap=main}" #endif #ifndef MFLIB_SPEC diff --git a/libmudflap/ChangeLog b/libmudflap/ChangeLog index 8e39393bc05..f9f13800468 100644 --- a/libmudflap/ChangeLog +++ b/libmudflap/ChangeLog @@ -1,3 +1,36 @@ +2005-07-16 Richard Henderson + + * acinclude.m4: New file. + * configure.ac: Invoke LIBMUDFLAP_CHECK_TLS. + * configure, config.h.in, Makefile.in, testsuite/Makefile.in: Rebuild. + * mf-hooks1.c (__mf_0fn_malloc): Move body from ... + (__mf_0fn_calloc): ... here. + * mf-hooks3.c (struct pthread_info): Remove. + (__mf_pthread_info, __mf_pthread_info_idx): Remove. + (LIBMUDFLAPTH_THREADS_MAX): Set to 1021. + (struct mf_thread_data): New. + (mf_thread_data, mf_thread_data_lock): New. + (__mf_allocate_blank_threadinfo): Remove. + (__mf_find_threadinfo): Rewrite and simplify. Only use if TLS is + not available. + (__mf_state_perthread): Remove. + (__mf_get_state, __mf_set_state): New. + (__mf_pthread_cleanup): Use &errno, rather than saved pointer. + Update mf_thread_data killing procedure. + (__mf_pthread_spawner): Similarly. + (__mf_0fn_pthread_create): Only use wrapper if necessary. Remove + code to allocate thread stack space. + (__mf_0fn_pthread_join, pthread_join): Remove. + (__mf_0fn_pthread_exit, pthread_exit): Remove. + * mf-impl.h (dyn_pthread_join, dyn_pthread_exit): Remove. + (__mf_state_1): Rename from __mf_state; use TLS when available. + (__mf_get_state, __mf_set_state): New. Update all users. + * mf-runtime.c (begin_recursion_protect1): New. + (BEGIN_RECURSION_PROTECT): Use it. + (__mf_state_1): Rename from __mf_state; use TLS when available. + (threads_active_p): Remove. + (__mf_usage): Compute it directly. + 2005-06-19 Ulrich Weigand * testsuite/libmudflap.c/externs-1.c (main): Add return statement. diff --git a/libmudflap/Makefile.in b/libmudflap/Makefile.in index dfd433afe43..24fa22102d4 100644 --- a/libmudflap/Makefile.in +++ b/libmudflap/Makefile.in @@ -1,8 +1,8 @@ -# Makefile.in generated by automake 1.9.3 from Makefile.am. +# Makefile.in generated by automake 1.9.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004 Free Software Foundation, Inc. +# 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -49,8 +49,9 @@ DIST_COMMON = $(am__configure_deps) $(include_HEADERS) \ $(top_srcdir)/configure ChangeLog subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/../libtool.m4 \ - $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ + $(top_srcdir)/../config/lead-dot.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/../libtool.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ @@ -463,7 +464,13 @@ uninstall-includeHEADERS: # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): - @set fnord $$MAKEFLAGS; amf=$$2; \ + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ @@ -475,7 +482,7 @@ $(RECURSIVE_TARGETS): local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ @@ -483,7 +490,13 @@ $(RECURSIVE_TARGETS): mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: - @set fnord $$MAKEFLAGS; amf=$$2; \ + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ @@ -504,7 +517,7 @@ maintainer-clean-recursive: local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ @@ -579,7 +592,7 @@ distclean-tags: distdir: $(DISTFILES) $(am__remove_distdir) mkdir $(distdir) - $(mkdir_p) $(distdir)/.. $(distdir)/testsuite + $(mkdir_p) $(distdir)/.. $(distdir)/../config $(distdir)/testsuite @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ diff --git a/libmudflap/acinclude.m4 b/libmudflap/acinclude.m4 new file mode 100644 index 00000000000..4308f508d84 --- /dev/null +++ b/libmudflap/acinclude.m4 @@ -0,0 +1,72 @@ +dnl Check whether the target supports TLS. +AC_DEFUN([LIBMUDFLAP_CHECK_TLS], [ + LIBMUDFLAP_ENABLE(tls, yes, [Use thread-local storage]) + AC_CACHE_CHECK([whether the target supports thread-local storage], + have_tls, [ + AC_RUN_IFELSE([__thread int a; int b; int main() { return a = b; }], + [dnl If the test case passed with dynamic linking, try again with + dnl static linking. This fails at least with some older Red Hat + dnl releases. + save_LDFLAGS="$LDFLAGS" + LDFLAGS="-static $LDFLAGS" + AC_RUN_IFELSE([__thread int a; int b; int main() { return a = b; }], + [have_tls=yes], [have_tls=no], []) + LDFLAGS="$save_LDFLAGS"], + [have_tls=no], + [AC_COMPILE_IFELSE([__thread int foo;], [have_tls=yes], [have_tls=no])] + )]) + if test "$enable_tls $have_tls" = "yes yes"; then + AC_DEFINE(HAVE_TLS, 1, + [Define to 1 if the target supports thread-local storage.]) + fi]) + +dnl ---------------------------------------------------------------------- +dnl This whole bit snagged from libgfortran. + +sinclude(../libtool.m4) +dnl The lines below arrange for aclocal not to bring an installed +dnl libtool.m4 into aclocal.m4, while still arranging for automake to +dnl add a definition of LIBTOOL to Makefile.in. +ifelse(,,,[AC_SUBST(LIBTOOL) +AC_DEFUN([AM_PROG_LIBTOOL]) +AC_DEFUN([AC_LIBTOOL_DLOPEN]) +AC_DEFUN([AC_PROG_LD]) +]) + +dnl ---------------------------------------------------------------------- +dnl This whole bit snagged from libstdc++-v3. + +dnl +dnl LIBMUDFLAP_ENABLE +dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING) +dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING, permit a|b|c) +dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING, SHELL-CODE-HANDLER) +dnl +dnl See docs/html/17_intro/configury.html#enable for documentation. +dnl +m4_define([LIBMUDFLAP_ENABLE],[dnl +m4_define([_g_switch],[--enable-$1])dnl +m4_define([_g_help],[AC_HELP_STRING(_g_switch$3,[$4 @<:@default=$2@:>@])])dnl + AC_ARG_ENABLE($1,_g_help, + m4_bmatch([$5], + [^permit ], + [[ + case "$enableval" in + m4_bpatsubst([$5],[permit ])) ;; + *) AC_MSG_ERROR(Unknown argument to enable/disable $1) ;; + dnl Idea for future: generate a URL pointing to + dnl "onlinedocs/configopts.html#whatever" + esac + ]], + [^$], + [[ + case "$enableval" in + yes|no) ;; + *) AC_MSG_ERROR(Argument to enable/disable $1 must be yes or no) ;; + esac + ]], + [[$5]]), + [enable_]m4_bpatsubst([$1],-,_)[=][$2]) +m4_undefine([_g_switch])dnl +m4_undefine([_g_help])dnl +]) diff --git a/libmudflap/aclocal.m4 b/libmudflap/aclocal.m4 index 99613bff133..95667ef84c1 100644 --- a/libmudflap/aclocal.m4 +++ b/libmudflap/aclocal.m4 @@ -1,7 +1,7 @@ -# generated automatically by aclocal 1.9.3 -*- Autoconf -*- +# generated automatically by aclocal 1.9.5 -*- Autoconf -*- -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 -# Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -11,23 +11,11 @@ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. -# -*- Autoconf -*- -# Copyright (C) 2002, 2003 Free Software Foundation, Inc. -# Generated from amversion.in; do not edit by hand. - -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- @@ -40,26 +28,15 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"]) # Call AM_AUTOMAKE_VERSION so it can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], - [AM_AUTOMAKE_VERSION([1.9.3])]) + [AM_AUTOMAKE_VERSION([1.9.5])]) -# AM_AUX_DIR_EXPAND +# AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001, 2003 Free Software Foundation, Inc. - -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to @@ -106,26 +83,16 @@ AC_PREREQ([2.50])dnl am_aux_dir=`cd $ac_aux_dir && pwd` ]) -# AM_CONDITIONAL -*- Autoconf -*- +# AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997, 2000, 2001, 2003, 2004 Free Software Foundation, Inc. +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 6 +# serial 7 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- @@ -149,26 +116,15 @@ AC_CONFIG_COMMANDS_PRE( Usually this means the macro was only invoked conditionally.]]) fi])]) -# serial 7 -*- Autoconf -*- -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - +# serial 8 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, @@ -177,7 +133,6 @@ fi])]) # CC etc. in the Makefile, will ask for an AC_PROG_CC use... - # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. @@ -317,27 +272,16 @@ AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH]) ]) -# Generate code to set up dependency tracking. -*- Autoconf -*- +# Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 -# Free Software Foundation, Inc. +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -#serial 2 +#serial 3 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ @@ -396,30 +340,19 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) -# Do all the work for Automake. -*- Autoconf -*- +# Do all the work for Automake. -*- Autoconf -*- -# This macro actually does too much some checks are only needed if -# your package does certain things. But this isn't really a big deal. - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. -# 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 2, or (at your option) -# any later version. +# serial 12 -# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 11 +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) @@ -521,87 +454,31 @@ for _am_header in $config_headers :; do done echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. - -# Copyright (C) 2001, 2003 Free Software Foundation, Inc. - -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl install_sh=${install_sh-"$am_aux_dir/install-sh"} AC_SUBST(install_sh)]) -# -*- Autoconf -*- -# Copyright (C) 2003 Free Software Foundation, Inc. - -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 1 - -# Check whether the underlying file-system supports filenames -# with a leading dot. For instance MS-DOS doesn't. -AC_DEFUN([AM_SET_LEADING_DOT], -[rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null -AC_SUBST([am__leading_dot])]) - -# Add --enable-maintainer-mode option to configure. +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering -# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004 +# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 3 +# serial 4 AC_DEFUN([AM_MAINTAINER_MODE], [AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) @@ -620,26 +497,15 @@ AC_DEFUN([AM_MAINTAINER_MODE], AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) -# Check to see how 'make' treats includes. -*- Autoconf -*- +# Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. +# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 2 +# serial 3 # AM_MAKE_INCLUDE() # ----------------- @@ -683,27 +549,16 @@ AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) -# -*- Autoconf -*- +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. -# Copyright (C) 1997, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. - -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 3 +# serial 4 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ @@ -729,27 +584,16 @@ else fi ]) +# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + # AM_PROG_MKDIR_P # --------------- # Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise. - -# Copyright (C) 2003, 2004 Free Software Foundation, Inc. - -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - +# # Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories # created by `make install' are always world readable, even if the # installer happens to have an overly restrictive umask (e.g. 077). @@ -803,25 +647,14 @@ else fi AC_SUBST([mkdir_p])]) -# Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004 +# Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005 # Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 4 +# serial 5 # AM_ENABLE_MULTILIB([MAKEFILE], [REL-TO-TOP-SRCDIR]) # --------------------------------------------------- @@ -872,26 +705,15 @@ multi_basedir="$multi_basedir" CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} CC="$CC"])])dnl -# Helper functions for option handling. -*- Autoconf -*- +# Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. +# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 2 +# serial 3 # _AM_MANGLE_OPTION(NAME) # ----------------------- @@ -916,28 +738,16 @@ AC_DEFUN([_AM_SET_OPTIONS], AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 +# Free Software Foundation, Inc. # -# Check to make sure that the build environment is sane. -# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. -# Copyright (C) 1996, 1997, 2000, 2001, 2003 Free Software Foundation, Inc. - -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 3 +# serial 4 # AM_SANITY_CHECK # --------------- @@ -980,25 +790,14 @@ Check your system clock]) fi AC_MSG_RESULT(yes)]) +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + # AM_PROG_INSTALL_STRIP - -# Copyright (C) 2001, 2003 Free Software Foundation, Inc. - -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - +# --------------------- # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip @@ -1021,25 +820,13 @@ AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004 Free Software Foundation, Inc. - -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 1 +# Copyright (C) 2004, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. +# serial 2 # _AM_PROG_TAR(FORMAT) # -------------------- @@ -1127,4 +914,6 @@ AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR -m4_include([../libtool.m4]) +m4_include([../config/depstand.m4]) +m4_include([../config/lead-dot.m4]) +m4_include([acinclude.m4]) diff --git a/libmudflap/config.h.in b/libmudflap/config.h.in index 7685b575c26..b14e2e90121 100644 --- a/libmudflap/config.h.in +++ b/libmudflap/config.h.in @@ -222,6 +222,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_WAIT_H +/* Define to 1 if the target supports thread-local storage. */ +#undef HAVE_TLS + /* union semun defined in sys/ipc.h or sys/sem.h */ #undef HAVE_UNION_SEMUN diff --git a/libmudflap/configure b/libmudflap/configure index ab7d2272d0a..03b3be5d30a 100755 --- a/libmudflap/configure +++ b/libmudflap/configure @@ -850,6 +850,8 @@ Optional Features: --enable-static=PKGS build static libraries default=yes --enable-fast-install=PKGS optimize for fast installation default=yes --disable-libtool-lock avoid locking (might break parallel builds) + _g_switchUse thread-local storage + [default=yes] Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -5831,7 +5833,7 @@ test x"$pic_mode" = xno && libtool_flags="$libtool_flags --prefer-non-pic" case $host in *-*-irix6*) # Find out which ABI we are using. - echo '#line 5834 "configure"' > conftest.$ac_ext + echo '#line 5836 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -6898,6 +6900,135 @@ else multilib_arg= fi +# See if we support thread-local storage. + + # Check whether --enable-tls or --disable-tls was given. +if test "${enable_tls+set}" = set; then + enableval="$enable_tls" + + case "$enableval" in + yes|no) ;; + *) { { echo "$as_me:$LINENO: error: Argument to enable/disable tls must be yes or no" >&5 +echo "$as_me: error: Argument to enable/disable tls must be yes or no" >&2;} + { (exit 1); exit 1; }; } ;; + esac + +else + enable_tls=yes +fi; + + echo "$as_me:$LINENO: checking whether the target supports thread-local storage" >&5 +echo $ECHO_N "checking whether the target supports thread-local storage... $ECHO_C" >&6 +if test "${have_tls+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + cat >conftest.$ac_ext <<_ACEOF +__thread int foo; +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + have_tls=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +have_tls=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +else + cat >conftest.$ac_ext <<_ACEOF +__thread int a; int b; int main() { return a = b; } +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + save_LDFLAGS="$LDFLAGS" + LDFLAGS="-static $LDFLAGS" + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +__thread int a; int b; int main() { return a = b; } +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + have_tls=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +have_tls=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + LDFLAGS="$save_LDFLAGS" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +have_tls=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $have_tls" >&5 +echo "${ECHO_T}$have_tls" >&6 + if test "$enable_tls $have_tls" = "yes yes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TLS 1 +_ACEOF + + fi + ac_config_files="$ac_config_files Makefile testsuite/Makefile testsuite/mfconfig.exp" cat >confcache <<\_ACEOF diff --git a/libmudflap/configure.ac b/libmudflap/configure.ac index 60c2c7fcedd..58a7c739b91 100644 --- a/libmudflap/configure.ac +++ b/libmudflap/configure.ac @@ -229,5 +229,8 @@ else multilib_arg= fi +# See if we support thread-local storage. +LIBMUDFLAP_CHECK_TLS + AC_CONFIG_FILES([Makefile testsuite/Makefile testsuite/mfconfig.exp]) AC_OUTPUT diff --git a/libmudflap/mf-hooks1.c b/libmudflap/mf-hooks1.c index 6f9d159e461..9460e443498 100644 --- a/libmudflap/mf-hooks1.c +++ b/libmudflap/mf-hooks1.c @@ -79,7 +79,19 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA void * __mf_0fn_malloc (size_t c) { - /* fprintf (stderr, "0fn malloc c=%lu\n", c); */ + enum foo { BS = 4096, NB=10 }; + static char bufs[NB][BS]; + static unsigned bufs_used[NB]; + unsigned i; + + for (i=0; i and Graydon Hoare @@ -52,14 +52,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include #include #include -#include -#include #include #include #include -#include -#include -#include +#include #include "mf-runtime.h" #include "mf-impl.h" @@ -68,276 +64,214 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #error "Do not compile this file with -fmudflap!" #endif - -/* Multithreading support hooks. */ - - - #ifndef LIBMUDFLAPTH #error "pthreadstuff is to be included only in libmudflapth" #endif +/* ??? Why isn't this done once in the header files. */ +DECLARE(void *, malloc, size_t sz); +DECLARE(void, free, void *ptr); +DECLARE(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr, + void * (*start) (void *), void *arg); -/* Describe a thread (dead or alive). */ -struct pthread_info +/* Multithreading support hooks. */ + + +#ifndef HAVE_TLS +/* We don't have TLS. Ordinarily we could use pthread keys, but since we're + commandeering malloc/free that presents a few problems. The first is that + we'll recurse from __mf_get_state to pthread_setspecific to malloc back to + __mf_get_state during thread startup. This can be solved with clever uses + of a mutex. The second problem is that thread shutdown is indistinguishable + from thread startup, since libpthread is deallocating our state variable. + I've no good solution for this. + + Which leaves us to handle this mess by totally by hand. */ + +/* Yes, we want this prime. If pthread_t is a pointer, it's almost always + page aligned, and if we use a smaller power of 2, this results in "%N" + being the worst possible hash -- all threads hash to zero. */ +#define LIBMUDFLAPTH_THREADS_MAX 1021 + +struct mf_thread_data { - short used_p; /* Is this slot in use? */ - short dead_p; /* Is this thread dead? */ - pthread_t self; /* The thread id. */ - - /* If libmudflapth allocated the stack, store its adjusted base/size. */ - void *stack; - size_t stack_size; - /* The _alloc fields store unadjusted values from the moment of allocation. */ - void *stack_alloc; - size_t stack_size_alloc; - - int *thread_errno; - enum __mf_state_enum state; + pthread_t self; + unsigned char used_p; + unsigned char state; }; +static struct mf_thread_data mf_thread_data[LIBMUDFLAPTH_THREADS_MAX]; +static pthread_mutex_t mf_thread_data_lock = PTHREAD_MUTEX_INITIALIZER; + +/* Try to identify the main thread when filling in mf_thread_data. We + should always be called at least once from the main thread before + any new threads are spawned. */ +static int main_seen_p; + +#define PTHREAD_HASH(p) ((unsigned long) (p) % LIBMUDFLAPTH_THREADS_MAX) + +static struct mf_thread_data * +__mf_find_threadinfo (int alloc) +{ + pthread_t self = pthread_self (); + unsigned long hash = PTHREAD_HASH (self); + unsigned long rehash; + +#ifdef __alpha__ + /* Alpha has the loosest memory ordering rules of all. We need a memory + barrier to flush the reorder buffer before considering a *read* of a + shared variable. Since we're not always taking a lock, we have to do + this by hand. */ + __sync_synchronize (); +#endif + + rehash = hash; + while (1) + { + if (mf_thread_data[rehash].used_p && mf_thread_data[rehash].self == self) + return &mf_thread_data[rehash]; + + rehash += 7; + if (rehash >= LIBMUDFLAPTH_THREADS_MAX) + rehash -= LIBMUDFLAPTH_THREADS_MAX; + if (rehash == hash) + break; + } + + if (alloc) + { + pthread_mutex_lock (&mf_thread_data_lock); + + rehash = hash; + while (1) + { + if (!mf_thread_data[rehash].used_p) + { + mf_thread_data[rehash].self = self; + __sync_synchronize (); + mf_thread_data[rehash].used_p = 1; + + pthread_mutex_unlock (&mf_thread_data_lock); + return &mf_thread_data[rehash]; + } + + rehash += 7; + if (rehash >= LIBMUDFLAPTH_THREADS_MAX) + rehash -= LIBMUDFLAPTH_THREADS_MAX; + if (rehash == hash) + break; + } + + pthread_mutex_unlock (&mf_thread_data_lock); + } + + return NULL; +} + +enum __mf_state_enum +__mf_get_state (void) +{ + struct mf_thread_data *data = __mf_find_threadinfo (0); + if (data) + return data->state; + + /* The main thread needs to default to active state, so that the global + constructors are processed in the active state. Child threads should + be considered to be in the reentrant state, so that we don't wind up + doing Screwy Things inside the thread library; it'll get reset to + active state in __mf_pthread_spawner before user code is invoked. + + The trickiest bit here is that the LinuxThreads pthread_manager thread + should *always* be considered to be reentrant, so that none of our + hooks actually do anything. Why? Because that thread isn't a real + thread from the point of view of the thread library, and so lots of + stuff isn't initialized, leading to SEGV very quickly. Even calling + pthread_self is a bit suspect, but it happens to work. */ + + if (main_seen_p) + return reentrant; + else + { + main_seen_p = 1; + data = __mf_find_threadinfo (1); + data->state = active; + return active; + } +} + +void +__mf_set_state (enum __mf_state_enum new_state) +{ + struct mf_thread_data *data = __mf_find_threadinfo (1); + data->state = new_state; +} +#endif + +/* The following two functions are used only with __mf_opts.heur_std_data. + We're interested in recording the location of the thread-local errno + variable. + + Note that this doesn't handle TLS references in general; we have no + visibility into __tls_get_data for when that memory is allocated at + runtime. Hopefully we get to see the malloc or mmap operation that + eventually allocates the backing store. */ /* Describe the startup information for a new user thread. */ -struct pthread_start_info +struct mf_thread_start_info { /* The user's thread entry point and argument. */ void * (*user_fn)(void *); void *user_arg; - - /* Set by user thread when this startup struct may be disposed of. */ - struct pthread_info *thread_info; }; - - -/* To avoid dynamic memory allocation, use static array to store these - thread description structs. The second (_idx) array is used as a - simple caching hash table, mapping PTHREAD_HASH(thread) to its - index in __mf_pthread_info[]. */ - -#define LIBMUDFLAPTH_THREADS_MAX 1024 -static struct pthread_info __mf_pthread_info[LIBMUDFLAPTH_THREADS_MAX]; -static unsigned __mf_pthread_info_idx[LIBMUDFLAPTH_THREADS_MAX]; -#define PTHREAD_HASH(p) ((unsigned) (p) % LIBMUDFLAPTH_THREADS_MAX) - - -/* Find any old empty entry in __mf_pthread_info; mark it used and - return it. Return NULL if there are no more available slots. */ -struct pthread_info* -__mf_allocate_blank_threadinfo (unsigned* idx) -{ - static unsigned probe = LIBMUDFLAPTH_THREADS_MAX-1; - unsigned probe_at_start = probe; - static pthread_mutex_t mutex = -#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP - PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; -#else - PTHREAD_MUTEX_INITIALIZER; -#endif - int rc; - - rc = pthread_mutex_lock (& mutex); - assert (rc == 0); - - /* Look for a blank spot starting one past the last one we found. */ - do - { - probe = (probe + 1) % LIBMUDFLAPTH_THREADS_MAX; - struct pthread_info* pi = & __mf_pthread_info [probe]; - if (! pi->used_p) - { - /* memset (pi, 0, sizeof (*pi)); */ - pi->used_p = 1; - if (idx != NULL) *idx = probe; - /* VERBOSE_TRACE ("allocated threadinfo slot %u\n", probe); */ - rc = pthread_mutex_unlock (& mutex); - assert (rc == 0); - return pi; - } - } - while (probe != probe_at_start); - - rc = pthread_mutex_unlock (& mutex); - assert (rc == 0); - return NULL; -} - - -/* Find and return the pthread_info struct for the current thread. - There might already be one in __mf_pthread_info for this thread, in - which case return it. There may not be one (if this is a main - thread, an auxiliary -lpthread manager, or an actual user thread - making an early call into libmudflap. In these cases, create a new - entry. If not it's not the main thread, put it into reentrant - initial state. - - NB: VERBOSE_TRACE type functions are not generally safe to call - from this context, since a new thread might just be "booting up", - making printf unsafe to call. -*/ -static struct pthread_info* -__mf_find_threadinfo () -{ - pthread_t it = pthread_self (); - unsigned *hash = & __mf_pthread_info_idx [PTHREAD_HASH (it)]; - struct pthread_info *result = NULL; - static pthread_t last; - static int main_thread_seen_p; - - /* Check out the lookup cache; failing that, do a linear search - around the table. */ - { - struct pthread_info* pi = & __mf_pthread_info [*hash]; - unsigned i; - - if (pi->used_p && pi->self == it) - result = pi; - else for (i = 0; i < LIBMUDFLAPTH_THREADS_MAX; i++) - { - struct pthread_info* pi2 = & __mf_pthread_info [i]; - if (pi2->used_p && pi2->self == it) - { - *hash = i; - result = pi2; - break; - } - } - } - - if (result == NULL) - { - /* Create a __mf_pthread_info record for the main thread. It's - different from the auto-recognized worker bees because for - example we can assume that it's a fully stack/errno-equipped - thread. */ - - /* This must be the main thread, until now unseen in libmudflap. */ - unsigned *hash = & __mf_pthread_info_idx [PTHREAD_HASH (it)]; - struct pthread_info* pi = __mf_allocate_blank_threadinfo (hash); - assert (pi != NULL); - assert (pi->used_p); - result = pi; - result->self = it; - - if (! main_thread_seen_p) - { - result->state = active; - /* NB: leave result->thread_errno unset, as main thread's errno - has already been registered in __mf_init. */ - /* NB: leave stack-related fields unset, to avoid - deallocation. */ - main_thread_seen_p = 1; - /* VERBOSE_TRACE ("identified self as main thread\n"); */ - } - else - { - result->state = reentrant; - /* NB: leave result->thread_errno unset, as worker thread's - errno is unlikely to be used, and user threads fill them - in during __mf_pthread_spawn(). */ - /* NB: leave stack-related fields unset, leaving pthread_create - to fill them in for user threads, leaving them empty for - other threads. */ - /* VERBOSE_TRACE ("identified self as new aux or user thread\n"); */ - } - } - - if (last != it) - { - /* - VERBOSE_TRACE ("found threadinfo for %u, slot %u\n", - (unsigned) it, - (unsigned) *hash); - */ - last = it; - } - - assert (result != NULL); - assert (result->self == it); - - return result; -} - - - -/* Return a pointer to the per-thread __mf_state variable. */ -enum __mf_state_enum * -__mf_state_perthread () -{ - assert (! __mf_starting_p); - return & (__mf_find_threadinfo()->state); -} - - static void __mf_pthread_cleanup (void *arg) { - struct pthread_info *pi = arg; + if (__mf_opts.heur_std_data) + __mf_unregister (&errno, sizeof (errno), __MF_TYPE_GUESS); - /* XXX: This unregistration is not safe on platforms where distinct - threads share errno (or at least its virtual address). */ - if (pi->thread_errno != NULL) - __mf_unregister (pi->thread_errno, sizeof (int), __MF_TYPE_GUESS); - - /* XXX: Only detached threads should designate themselves as dead - here. Non-detached threads are marked dead after their - personalized pthread_join() call. */ - pi->state = reentrant; - pi->dead_p = 1; - - VERBOSE_TRACE ("thread pi %p exiting\n", pi); +#ifndef HAVE_TLS + struct mf_thread_data *data = __mf_find_threadinfo (0); + if (data) + data->used_p = 0; +#endif } static void * __mf_pthread_spawner (void *arg) { - struct pthread_info *pi = __mf_find_threadinfo (); void *result = NULL; - /* Turn off reentrancy indications. */ - assert (pi->state == reentrant); - pi->state = active; - - VERBOSE_TRACE ("new user thread\n"); +#ifndef HAVE_TLS + __mf_set_state (active); +#endif + /* NB: We could use __MF_TYPE_STATIC here, but we guess that the thread + errno is coming out of some dynamically allocated pool that we already + know of as __MF_TYPE_HEAP. */ if (__mf_opts.heur_std_data) - { - pi->thread_errno = & errno; - __mf_register (pi->thread_errno, sizeof (int), - __MF_TYPE_GUESS, "errno area (thread)"); - /* NB: we could use __MF_TYPE_STATIC above, but we guess that - the thread errno is coming out of some dynamically allocated - pool that we already know of as __MF_TYPE_HEAP. */ - } + __mf_register (&errno, sizeof (errno), __MF_TYPE_GUESS, + "errno area (thread)"); /* We considered using pthread_key_t objects instead of these cleanup stacks, but they were less cooperative with the interposed malloc hooks in libmudflap. */ - pthread_cleanup_push (& __mf_pthread_cleanup, pi); + /* ??? The pthread_key_t problem is solved above... */ + pthread_cleanup_push (__mf_pthread_cleanup, NULL); - /* Call user thread */ - { - /* Extract given entry point and argument. */ - struct pthread_start_info *psi = arg; - void * (*user_fn)(void *) = psi->user_fn; - void *user_arg = psi->user_arg; + /* Extract given entry point and argument. */ + struct mf_thread_start_info *psi = arg; + void * (*user_fn)(void *) = psi->user_fn; + void *user_arg = psi->user_arg; + CALL_REAL (free, arg); - /* Signal the main thread to resume. */ - psi->thread_info = pi; - - result = (*user_fn)(user_arg); - } + result = (*user_fn)(user_arg); pthread_cleanup_pop (1 /* execute */); - /* NB: there is a slight race here. The pthread_info field will now - say this thread is dead, but it may still be running .. right - here. We try to check for this possibility using the - pthread_kill test below. */ - return result; } @@ -357,245 +291,31 @@ __mf_0fn_pthread_create (pthread_t *thr, const pthread_attr_t *attr, WRAPPER(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr, void * (*start) (void *), void *arg) { - DECLARE(int, munmap, void *p, size_t l); - DECLARE(void *, mmap, void *p, size_t l, int prot, int flags, int fd, off_t of); - DECLARE(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr, - void * (*start) (void *), void *arg); - int result; - pthread_attr_t override_attr; - void *override_stack; - size_t override_stacksize; - void *override_stack_alloc = (void *) 0; - size_t override_stacksize_alloc = 0; - unsigned i; + int result, need_wrapper = 0; TRACE ("pthread_create\n"); - /* Garbage-collect dead threads' stacks. */ - LOCKTH (); - for (i = 0; i < LIBMUDFLAPTH_THREADS_MAX; i++) +#ifndef HAVE_TLS + need_wrapper = 1; +#endif + need_wrapper |= __mf_opts.heur_std_data != 0; + + if (need_wrapper) { - struct pthread_info *pi = & __mf_pthread_info [i]; - if (! pi->used_p) - continue; - if (! pi->dead_p) - continue; + struct mf_thread_start_info *si = CALL_REAL (malloc, sizeof (*si)); - /* VERBOSE_TRACE ("thread %u pi %p stack cleanup deferred (%u)\n", - (unsigned) pi->self, pi, pi->dead_p); */ + /* Fill in startup-control fields. */ + si->user_fn = start; + si->user_arg = arg; - /* Delay actual deallocation by a few cycles, try to discourage the - race mentioned at the end of __mf_pthread_spawner(). */ - if (pi->dead_p) - pi->dead_p ++; - if (pi->dead_p >= 10 /* XXX */) - { - if (pi->stack) - CALL_REAL (munmap, pi->stack_alloc, pi->stack_size_alloc); - - VERBOSE_TRACE ("slot %u freed, stack %p\n", i, pi->stack_alloc); - memset (pi, 0, sizeof (*pi)); - - /* One round of garbage collection is enough. */ - break; - } + /* Actually create the thread. */ + result = CALL_REAL (pthread_create, thr, attr, __mf_pthread_spawner, si); } - UNLOCKTH (); - - /* Let's allocate a stack for this thread, if one is not already - supplied by the caller. We don't want to let e.g. the - linuxthreads manager thread do this allocation. */ - if (attr != NULL) - override_attr = *attr; else - pthread_attr_init (& override_attr); - - /* Get supplied attributes, if any. */ - /* XXX: consider using POSIX2K attr_getstack() */ - if (pthread_attr_getstackaddr (& override_attr, & override_stack) != 0 || - pthread_attr_getstacksize (& override_attr, & override_stacksize) != 0) { - override_stack = NULL; - override_stacksize = 0; + /* If we're not handling heur_std_data, nothing special to do. */ + result = CALL_REAL (pthread_create, thr, attr, start, arg); } - /* Do we need to allocate the new thread's stack? */ - if (__mf_opts.thread_stack && override_stack == NULL) - { - uintptr_t alignment = 256; /* power of two */ - - /* Perturb the initial stack addresses slightly, to encourage - threads to have nonconflicting entries in the lookup cache - for their tracked stack objects. */ - static unsigned perturb = 0; - const unsigned perturb_delta = 32; - const unsigned perturb_count = 16; - perturb += perturb_delta; - if (perturb > perturb_delta*perturb_count) perturb = 0; - - /* Use glibc x86 defaults */ -/* Should have been defined in */ -#ifndef PTHREAD_STACK_MIN -#define PTHREAD_STACK_MIN 65536 -#endif - override_stacksize = max (PTHREAD_STACK_MIN, __mf_opts.thread_stack * 1024); - - -#if defined(MAP_ANONYMOUS) -#define MF_MAP_ANON MAP_ANONYMOUS -#elif defined(MAP_ANON) -#define MF_MAP_ANON MAP_ANON -#endif - -#ifndef MAP_FAILED -#define MAP_FAILED ((void *) -1) -#endif - -#ifdef MF_MAP_ANON - override_stack = CALL_REAL (mmap, NULL, override_stacksize, - PROT_READ|PROT_WRITE, - MAP_PRIVATE|MF_MAP_ANON, - 0, 0); -#else - /* Try mapping /dev/zero instead. */ - { - static int zerofd = -1; - if (zerofd == -1) - zerofd = open ("/dev/zero", O_RDWR); - if (zerofd == -1) - override_stack = MAP_FAILED; - else - override_stack = CALL_REAL (mmap, NULL, override_stacksize, - PROT_READ|PROT_WRITE, - MAP_PRIVATE, zerofd, 0); - } -#endif - - if (override_stack == 0 || override_stack == MAP_FAILED) - { - errno = EAGAIN; - return -1; - } - - VERBOSE_TRACE ("thread stack alloc %p size %lu\n", - override_stack, (unsigned long) override_stacksize); - - /* Save the original allocated values for later deallocation. */ - override_stack_alloc = override_stack; - override_stacksize_alloc = override_stacksize; - - /* The stackaddr pthreads attribute is a candidate stack pointer. - It must point near the top or the bottom of this buffer, depending - on whether stack grows downward or upward, and suitably aligned. - On the x86, it grows down, so we set stackaddr near the top. */ - /* XXX: port logic */ - override_stack = (void *) - (((uintptr_t) override_stack + override_stacksize - alignment - perturb) - & (~(uintptr_t)(alignment-1))); - - /* XXX: consider using POSIX2K attr_setstack() */ - if (pthread_attr_setstackaddr (& override_attr, override_stack) != 0 || - pthread_attr_setstacksize (& override_attr, - override_stacksize - alignment - perturb) != 0) - { - /* This should not happen. */ - CALL_REAL (munmap, override_stack, override_stacksize); - errno = EAGAIN; - return -1; - } - } - - /* Actually start the child thread. */ - { - struct pthread_start_info psi; - struct pthread_info *pi = NULL; - - /* Fill in startup-control fields. */ - psi.user_fn = start; - psi.user_arg = arg; - psi.thread_info = NULL; - - /* Actually create the thread. */ - __mf_state = reentrant; - result = CALL_REAL (pthread_create, thr, & override_attr, - & __mf_pthread_spawner, (void *) & psi); - __mf_state = active; - /* We also hook pthread_join/pthread_exit to get into reentrant - mode during thread shutdown/cleanup. */ - - /* Wait until child thread has progressed far enough into its - __mf_pthread_spawner() call. */ - while (1) /* XXX: timeout? */ - { - volatile struct pthread_start_info *psip = & psi; - pi = psip->thread_info; - if (pi != NULL) - break; - sched_yield (); - } - - /* Fill in remaining fields in pthread_info. */ - pi->stack = override_stack; - pi->stack_size = override_stacksize; - pi->stack_alloc = override_stack_alloc; - pi->stack_size_alloc = override_stacksize_alloc; - /* XXX: this might be too late for future heuristics that attempt - to use thread stack bounds. We may need to put the new thread - to sleep. */ - } - - - /* May need to clean up if we created a pthread_attr_t of our own. */ - if (attr == NULL) - pthread_attr_destroy (& override_attr); /* NB: this shouldn't deallocate stack */ - return result; } - - - -#if PIC -/* A special bootstrap variant. */ -int -__mf_0fn_pthread_join (pthread_t thr, void **rc) -{ - return -1; -} -#endif - - -#undef pthread_join -WRAPPER(int, pthread_join, pthread_t thr, void **rc) -{ - DECLARE(int, pthread_join, pthread_t thr, void **rc); - int result; - - TRACE ("pthread_join\n"); - __mf_state = reentrant; - result = CALL_REAL (pthread_join, thr, rc); - __mf_state = active; - - return result; -} - - -#if PIC -/* A special bootstrap variant. */ -void -__mf_0fn_pthread_exit (void *rc) -{ -} -#endif - - -#undef pthread_exit -WRAPPER(void, pthread_exit, void *rc) -{ - DECLARE(void, pthread_exit, void *rc); - - TRACE ("pthread_exit\n"); - /* __mf_state = reentrant; */ - CALL_REAL (pthread_exit, rc); - /* NOTREACHED */ - exit (0); /* Satisfy noreturn attribute of pthread_exit. */ -} diff --git a/libmudflap/mf-impl.h b/libmudflap/mf-impl.h index 47abdf602e7..53c25b392ca 100644 --- a/libmudflap/mf-impl.h +++ b/libmudflap/mf-impl.h @@ -207,9 +207,7 @@ enum __mf_dynamic_index dyn_munmap, dyn_realloc, dyn_INITRESOLVE, /* Marker for last init-time resolution. */ #ifdef LIBMUDFLAPTH - dyn_pthread_create, - dyn_pthread_join, - dyn_pthread_exit + dyn_pthread_create #endif }; @@ -233,12 +231,25 @@ extern pthread_mutex_t __mf_biglock; #define UNLOCKTH() do {} while (0) #endif -#ifdef LIBMUDFLAPTH -extern enum __mf_state_enum *__mf_state_perthread (); -#define __mf_state (* __mf_state_perthread ()) +#if defined(LIBMUDFLAPTH) && !defined(HAVE_TLS) +extern enum __mf_state_enum __mf_get_state (void); +extern void __mf_set_state (enum __mf_state_enum); #else -extern enum __mf_state_enum __mf_state; +# ifdef LIBMUDFLAPTH +extern __thread enum __mf_state_enum __mf_state_1; +# else +extern enum __mf_state_enum __mf_state_1; +# endif +static inline enum __mf_state_enum __mf_get_state (void) +{ + return __mf_state_1; +} +static inline void __mf_set_state (enum __mf_state_enum s) +{ + __mf_state_1 = s; +} #endif + extern int __mf_starting_p; extern struct __mf_options __mf_opts; @@ -362,7 +373,7 @@ ret __mfwrap_ ## fname (__VA_ARGS__) { \ return CALL_BACKUP(fname, __VA_ARGS__); \ } \ - else if (UNLIKELY (__mf_state == reentrant)) \ + else if (UNLIKELY (__mf_get_state () == reentrant)) \ { \ extern unsigned long __mf_reentrancy; \ __mf_reentrancy ++; \ diff --git a/libmudflap/mf-runtime.c b/libmudflap/mf-runtime.c index 317aeaef521..af584e773d9 100644 --- a/libmudflap/mf-runtime.c +++ b/libmudflap/mf-runtime.c @@ -141,20 +141,25 @@ static void mfsplay_tree_rebalance (mfsplay_tree sp); #define __MF_VIOL_WATCH 5 /* Protect against recursive calls. */ -#define BEGIN_RECURSION_PROTECT() do { \ - if (UNLIKELY (__mf_state == reentrant)) { \ - write (2, "mf: erroneous reentrancy detected in `", 38); \ - write (2, __PRETTY_FUNCTION__, strlen(__PRETTY_FUNCTION__)); \ - write (2, "'\n", 2); \ - abort (); } \ - __mf_state = reentrant; \ - } while (0) -#define END_RECURSION_PROTECT() do { \ - __mf_state = active; \ - } while (0) +static void +begin_recursion_protect1 (const char *pf) +{ + if (__mf_get_state () == reentrant) + { + write (2, "mf: erroneous reentrancy detected in `", 38); + write (2, pf, strlen(pf)); + write (2, "'\n", 2); \ + abort (); + } + __mf_set_state (reentrant); +} +#define BEGIN_RECURSION_PROTECT() \ + begin_recursion_protect1 (__PRETTY_FUNCTION__) +#define END_RECURSION_PROTECT() \ + __mf_set_state (active) /* ------------------------------------------------------------------------ */ /* Required globals. */ @@ -169,14 +174,15 @@ unsigned char __mf_lc_shift = LOOKUP_CACHE_SHIFT_DFL; #define LOOKUP_CACHE_SIZE (__mf_lc_mask + 1) struct __mf_options __mf_opts; - int __mf_starting_p = 1; -#ifndef LIBMUDFLAPTH -enum __mf_state_enum __mf_state = active; -#else -/* See __mf_state_perthread() in mf-hooks.c. */ -#endif +#ifdef LIBMUDFLAPTH +#ifdef HAVE_TLS +__thread enum __mf_state_enum __mf_state_1 = active; +#endif +#else +enum __mf_state_enum __mf_state_1 = active; +#endif #ifdef LIBMUDFLAPTH pthread_mutex_t __mf_biglock = @@ -196,7 +202,6 @@ pthread_mutex_t __mf_biglock = #else #define pthread_join NULL #endif -const void *threads_active_p = (void *) pthread_join; #endif @@ -442,7 +447,7 @@ __mf_usage () "any of the following options. Use `-no-OPTION' to disable options.\n" "\n", #if HAVE_PTHREAD_H - (threads_active_p ? "multi-threaded " : "single-threaded "), + (pthread_join ? "multi-threaded " : "single-threaded "), #else "", #endif @@ -2211,7 +2216,7 @@ __mf_sigusr1_respond () if (__mf_sigusr1_received > __mf_sigusr1_handled) { __mf_sigusr1_handled ++; - assert (__mf_state == reentrant); + assert (__mf_get_state () == reentrant); __mfu_report (); handler_installed = 0; /* We may need to re-enable signal; this might be a SysV library. */ } diff --git a/libmudflap/testsuite/Makefile.in b/libmudflap/testsuite/Makefile.in index 69f0161b0d3..a3f386dc868 100644 --- a/libmudflap/testsuite/Makefile.in +++ b/libmudflap/testsuite/Makefile.in @@ -1,8 +1,8 @@ -# Makefile.in generated by automake 1.9.3 from Makefile.am. +# Makefile.in generated by automake 1.9.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004 Free Software Foundation, Inc. +# 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -40,8 +40,9 @@ subdir = testsuite DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(srcdir)/mfconfig.exp.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/../libtool.m4 \ - $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ + $(top_srcdir)/../config/lead-dot.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/../libtool.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs