diff -Nru google-perftools-2.1/aclocal.m4 google-perftools-2.2.1/aclocal.m4 --- google-perftools-2.1/aclocal.m4 2013-07-30 11:12:28.000000000 +0200 +++ google-perftools-2.2.1/aclocal.m4 2014-06-22 00:52:48.000000000 +0200 @@ -1,4 +1,4 @@ -# generated automatically by aclocal 1.13.3 -*- Autoconf -*- +# generated automatically by aclocal 1.14.1 -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. @@ -32,10 +32,10 @@ # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.13' +[am__api_version='1.14' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.13.3], [], +m4_if([$1], [1.14.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -51,7 +51,7 @@ # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.13.3])dnl +[AM_AUTOMAKE_VERSION([1.14.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) @@ -418,6 +418,12 @@ # 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. +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- @@ -526,6 +532,48 @@ AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not @@ -534,7 +582,6 @@ m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) - # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. @@ -596,6 +643,42 @@ rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996-2013 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_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless 'enable' is passed literally. +# For symmetry, 'disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], + [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], + am_maintainer_other[ make rules and dependencies not useful + (and sometimes confusing) to the casual installer])], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. @@ -646,38 +729,6 @@ rm -f confinc confmf ]) -# Copyright (C) 1999-2013 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_CC_C_O -# -------------- -# Like AC_PROG_CC_C_O, but changed for automake. -AC_DEFUN([AM_PROG_CC_C_O], -[AC_REQUIRE([AC_PROG_CC_C_O])dnl -AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -AC_REQUIRE_AUX_FILE([compile])dnl -# FIXME: we rely on the cache variable name because -# there is no other way. -set dummy $CC -am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` -eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o -if test "$am_t" != yes; then - # Losing compiler, so override with the script. - # FIXME: It is wrong to rewrite CC. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__CC in this case, - # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" - CC="$am_aux_dir/compile $CC" -fi -dnl Make sure AC_PROG_CC is never called again, or it will override our -dnl setting of CC. -m4_define([AC_PROG_CC], - [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) -]) - # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. @@ -748,6 +799,70 @@ AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) +# Copyright (C) 1999-2013 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_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2013 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_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. diff -Nru google-perftools-2.1/config.guess google-perftools-2.2.1/config.guess --- google-perftools-2.1/config.guess 2013-07-30 11:12:29.000000000 +0200 +++ google-perftools-2.2.1/config.guess 2014-06-22 00:52:50.000000000 +0200 @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2013 Free Software Foundation, Inc. +# Copyright 1992-2014 Free Software Foundation, Inc. -timestamp='2013-05-16' +timestamp='2014-03-23' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -50,7 +50,7 @@ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2013 Free Software Foundation, Inc. +Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -149,7 +149,7 @@ LIBC=gnu #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac @@ -826,7 +826,7 @@ *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; - i*:MSYS*:*) + *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) @@ -969,10 +969,10 @@ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; - or1k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} exit ;; - or32:Linux:*:*) + or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) @@ -995,6 +995,12 @@ ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; @@ -1254,16 +1260,26 @@ if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; @@ -1355,154 +1371,6 @@ exit ;; esac -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - cat >&2 <. # @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='gperftools' PACKAGE_TARNAME='gperftools' -PACKAGE_VERSION='2.1' -PACKAGE_STRING='gperftools 2.1' +PACKAGE_VERSION='2.2.1' +PACKAGE_STRING='gperftools 2.2.1' PACKAGE_BUGREPORT='google-perftools@googlegroups.com' PACKAGE_URL='' @@ -653,6 +653,8 @@ OSX_TRUE MINGW_FALSE MINGW_TRUE +HAVE_PTHREAD_DESPITE_ASKING_FOR_FALSE +HAVE_PTHREAD_DESPITE_ASKING_FOR_TRUE PTHREAD_CFLAGS PTHREAD_LIBS PTHREAD_CC @@ -725,6 +727,9 @@ TC_VERSION_PATCH TC_VERSION_MINOR TC_VERSION_MAJOR +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V @@ -804,11 +809,13 @@ ac_user_opts=' enable_option_checking enable_silent_rules +enable_maintainer_mode enable_cpu_profiler enable_heap_profiler enable_heap_checker enable_debugalloc enable_minimal +enable_stacktrace_via_backtrace enable_dependency_tracking enable_shared enable_static @@ -1372,7 +1379,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures gperftools 2.1 to adapt to many kinds of systems. +\`configure' configures gperftools 2.2.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1442,7 +1449,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of gperftools 2.1:";; + short | recursive ) echo "Configuration of gperftools 2.2.1:";; esac cat <<\_ACEOF @@ -1452,12 +1459,18 @@ --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") + --enable-maintainer-mode + enable make rules and dependencies not useful (and + sometimes confusing) to the casual installer --disable-cpu-profiler do not build the cpu profiler --disable-heap-profiler do not build the heap profiler --disable-heap-checker do not build the heap checker --disable-debugalloc do not build versions of libs with debugalloc --enable-minimal build only tcmalloc-minimal (and maybe tcmalloc-minimal-debug) + --enable-stacktrace-via-backtrace + enable use of backtrace() for stacktrace capturing + (may deadlock) --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking @@ -1558,7 +1571,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -gperftools configure 2.1 +gperftools configure 2.2.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2148,7 +2161,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by gperftools $as_me 2.1, which was +It was created by gperftools $as_me 2.2.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2501,8 +2514,8 @@ # Update this value for every release! (A:B:C will map to foo.so.(A-C).C.B) # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -TCMALLOC_SO_VERSION=5:2:1 -PROFILER_SO_VERSION=3:2:3 +TCMALLOC_SO_VERSION=6:2:2 +PROFILER_SO_VERSION=4:1:4 @@ -2611,7 +2624,7 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac -am__api_version='1.13' +am__api_version='1.14' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or @@ -3097,7 +3110,7 @@ # Define the identity of the package. PACKAGE='gperftools' - VERSION='2.1' + VERSION='2.2.1' cat >>confdefs.h <<_ACEOF @@ -3148,9 +3161,75 @@ +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + ac_config_headers="$ac_config_headers src/config.h" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + + # Export the version information (for tc_version and friends) TC_VERSION_MAJOR=`expr "$PACKAGE_VERSION" : '\([0-9]*\)'` TC_VERSION_MINOR=`expr "$PACKAGE_VERSION" : '[0-9]*\.\([0-9]*\)'` @@ -3219,6 +3298,11 @@ enable_heap_profiler=no enable_heap_checker=no fi +# Check whether --enable-stacktrace-via-backtrace was given. +if test "${enable_stacktrace_via_backtrace+set}" = set; then : + enableval=$enable_stacktrace_via_backtrace; enable_backtrace=yes +fi + # Checks for programs. @@ -4459,6 +4543,65 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +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 + + depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 @@ -4732,131 +4875,6 @@ GCC_FALSE= fi # let the Makefile know if we're gcc -if test "x$CC" != xcc; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 -$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 -$as_echo_n "checking whether cc understands -c and -o together... " >&6; } -fi -set dummy $CC; ac_cc=`$as_echo "$2" | - sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` -if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -# Make sure it works both with $CC and with simple cc. -# We do the test twice because some compilers refuse to overwrite an -# existing .o file with -o, though they will create one. -ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' -rm -f conftest2.* -if { { 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_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && - test -f conftest2.$ac_objext && { { 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_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; -then - eval ac_cv_prog_cc_${ac_cc}_c_o=yes - if test "x$CC" != xcc; then - # Test first that cc exists at all. - if { ac_try='cc -c conftest.$ac_ext >&5' - { { 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_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' - rm -f conftest2.* - if { { 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_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && - test -f conftest2.$ac_objext && { { 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_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; - then - # cc works too. - : - else - # cc exists but doesn't like -o. - eval ac_cv_prog_cc_${ac_cc}_c_o=no - fi - fi - fi -else - eval ac_cv_prog_cc_${ac_cc}_c_o=no -fi -rm -f core conftest* - -fi -if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h - -fi - -# FIXME: we rely on the cache variable name because -# there is no other way. -set dummy $CC -am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` -eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o -if test "$am_t" != yes; then - # Losing compiler, so override with the script. - # FIXME: It is wrong to rewrite CC. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__CC in this case, - # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" - CC="$am_aux_dir/compile $CC" -fi - # shrug: autogen.sh suddenly needs this for some reason # Check if we have an objcopy installed that supports -W @@ -7331,7 +7349,7 @@ rm -rf conftest* ;; -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext @@ -7356,7 +7374,10 @@ ;; esac ;; - ppc64-*linux*|powerpc64-*linux*) + powerpc64le-*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -7375,7 +7396,10 @@ x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - ppc*-*linux*|powerpc*-*linux*) + powerpcle-*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) @@ -16505,6 +16529,7 @@ pc_fields="$pc_fields uc_mcontext.gregs[REG_EIP]" # Linux (i386) pc_fields="$pc_fields uc_mcontext.gregs[REG_RIP]" # Linux (x86_64) pc_fields="$pc_fields uc_mcontext.sc_ip" # Linux (ia64) + pc_fields="$pc_fields uc_mcontext.pc" # Linux (mips) pc_fields="$pc_fields uc_mcontext.uc_regs->gregs[PT_NIP]" # Linux (ppc) pc_fields="$pc_fields uc_mcontext.gregs[R15]" # Linux (arm old [untested]) pc_fields="$pc_fields uc_mcontext.arm_pc" # Linux (arm arch 5) @@ -16668,7 +16693,7 @@ fi -# We want to link in libunwind if it exists +# We want to link in libunwind or libexecinfo if it exists { $as_echo "$as_me:${as_lineno-$LINENO}: checking for backtrace in -lunwind" >&5 $as_echo_n "checking for backtrace in -lunwind... " >&6; } if ${ac_cv_lib_unwind_backtrace+:} false; then : @@ -16708,9 +16733,50 @@ if test "x$ac_cv_lib_unwind_backtrace" = xyes; then : UNWIND_LIBS=-lunwind else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for backtrace in -lexecinfo" >&5 +$as_echo_n "checking for backtrace in -lexecinfo... " >&6; } +if ${ac_cv_lib_execinfo_backtrace+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lexecinfo $LIBS" +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 backtrace (); +int +main () +{ +return backtrace (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_execinfo_backtrace=yes +else + ac_cv_lib_execinfo_backtrace=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_execinfo_backtrace" >&5 +$as_echo "$ac_cv_lib_execinfo_backtrace" >&6; } +if test "x$ac_cv_lib_execinfo_backtrace" = xyes; then : + UNWIND_LIBS=-lexecinfo +else UNWIND_LIBS= fi +fi + # On x86_64, instead of libunwind, we can choose to compile with frame-pointers. @@ -16730,6 +16796,8 @@ fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for x86 without frame pointers" >&5 +$as_echo_n "checking for x86 without frame pointers... " >&6; } # Some x86_64 systems do not insert frame pointers by default. # We want to see if the current system is one of those. cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -16770,7 +16838,11 @@ : fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - if test "$is_x86_64" = yes && ! grep 'mov.*rsp.*rbp' fp.s >/dev/null 2>&1; then +x86_no_fp_by_default=no +if test "$is_x86_64" = yes && ! grep 'mov.*rsp.*rbp' fp.s >/dev/null 2>&1; then : + x86_no_fp_by_default=yes +fi + if test "$x86_no_fp_by_default" = yes; then X86_64_AND_NO_FP_BY_DEFAULT_TRUE= X86_64_AND_NO_FP_BY_DEFAULT_FALSE='#' else @@ -16780,6 +16852,9 @@ rm fp.s CFLAGS="$OLD_CFLAGS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $x86_no_fp_by_default" >&5 +$as_echo "$x86_no_fp_by_default" >&6; } + # We need to know if we're i386 so we can turn on -mmms, which is not # on by default for i386 (it is for x86_64). @@ -17022,15 +17097,19 @@ # And mingw also does compile __thread but resultant code actually # fails to work correctly at least in some not so ancient version: # http://mingw-users.1079350.n2.nabble.com/gcc-4-4-multi-threaded-exception-handling-amp-thread-specifier-not-working-td3440749.html +# +# Also it was reported that earlier gcc versions for mips compile +# __thread but it doesn't really work { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __thread" >&5 $as_echo_n "checking for __thread... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) || (__GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ < 2)) +#if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) || (__GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ < 2)) #error gcc has this bug: http://gcc.gnu.org/ml/gcc-bugs/2006-09/msg02275.html -#endif -#if defined(__MINGW32__) -#error mingw doesn't really support tls +#elif defined(__MINGW32__) +#error mingw doesnt really support tls +#elif defined(__APPLE__) +#error OSX __thread support is known to call malloc which makes it unsafe to use from malloc replacement #endif int @@ -17774,6 +17853,62 @@ + +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 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthread symbols are available in C++ without including pthread.h" >&5 +$as_echo_n "checking whether pthread symbols are available in C++ without including pthread.h... " >&6; } +acx_pthread_despite_asking_for=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + +int +main () +{ + + pthread_t th; pthread_join(th, 0); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + acx_pthread_despite_asking_for=yes + +$as_echo "#define HAVE_PTHREAD_DESPITE_ASKING_FOR 1" >>confdefs.h + + $as_echo "#define HAVE_PTHREAD 1" >>confdefs.h + + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_despite_asking_for" >&5 +$as_echo "$acx_pthread_despite_asking_for" >&6; } +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 + + + if test x"$acx_pthread_despite_asking_for" = xyes; then + HAVE_PTHREAD_DESPITE_ASKING_FOR_TRUE= + HAVE_PTHREAD_DESPITE_ASKING_FOR_FALSE='#' +else + HAVE_PTHREAD_DESPITE_ASKING_FOR_TRUE='#' + HAVE_PTHREAD_DESPITE_ASKING_FOR_FALSE= +fi + + # Find out what namespace 'normal' STL code lives in { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler implements namespaces" >&5 $as_echo_n "checking whether the compiler implements namespaces... " >&6; } @@ -17959,6 +18094,20 @@ ;; esac +if test "x$enable_backtrace" = xyes; then + ac_fn_c_check_decl "$LINENO" "backtrace" "ac_cv_have_decl_backtrace" "#include +" +if test "x$ac_cv_have_decl_backtrace" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_BACKTRACE $ac_have_decl +_ACEOF + +fi # For windows, this has a non-trivial value (__declspec(export)), but any # system that uses configure wants this to be the empty string. @@ -18196,6 +18345,10 @@ am__EXEEXT_FALSE= fi +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -18236,6 +18389,10 @@ as_fn_error $? "conditional \"HAVE_W_NO_UNUSED_RESULT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${HAVE_PTHREAD_DESPITE_ASKING_FOR_TRUE}" && test -z "${HAVE_PTHREAD_DESPITE_ASKING_FOR_FALSE}"; then + as_fn_error $? "conditional \"HAVE_PTHREAD_DESPITE_ASKING_FOR\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MINGW_TRUE}" && test -z "${MINGW_FALSE}"; then as_fn_error $? "conditional \"MINGW\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -18665,7 +18822,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by gperftools $as_me 2.1, which was +This file was extended by gperftools $as_me 2.2.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -18731,7 +18888,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -gperftools config.status 2.1 +gperftools config.status 2.2.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -20764,3 +20921,15 @@ $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi + +if test "$x86_no_fp_by_default" = yes && test "x$enable_frame_pointers" != xyes && test "x$UNWIND_LIBS" = x && test "x$enable_minimal" != xyes; then : + if test "x$enable_backtrace" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No frame pointers and no libunwind. Expect backtrace capturing and unittests to fail" >&5 +$as_echo "$as_me: WARNING: No frame pointers and no libunwind. Expect backtrace capturing and unittests to fail" >&2;} +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "No frame pointers and no libunwind. The compilation will fail +See \`config.log' for more details" "$LINENO" 5; } +fi +fi diff -Nru google-perftools-2.1/configure.ac google-perftools-2.2.1/configure.ac --- google-perftools-2.1/configure.ac 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/configure.ac 2014-06-22 00:52:34.000000000 +0200 @@ -2,13 +2,13 @@ ## In general, the safest way to proceed is to run ./autogen.sh # make sure we're interpreted by some minimal autoconf -AC_PREREQ([2.68]) +AC_PREREQ([2.59]) -AC_INIT([gperftools],[2.1],[google-perftools@googlegroups.com]) +AC_INIT([gperftools],[2.2.1],[google-perftools@googlegroups.com]) # Update this value for every release! (A:B:C will map to foo.so.(A-C).C.B) # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -TCMALLOC_SO_VERSION=5:2:1 -PROFILER_SO_VERSION=3:2:3 +TCMALLOC_SO_VERSION=6:2:2 +PROFILER_SO_VERSION=4:1:4 AC_SUBST(TCMALLOC_SO_VERSION) AC_SUBST(PROFILER_SO_VERSION) @@ -21,6 +21,8 @@ AM_INIT_AUTOMAKE([dist-zip]) AC_CONFIG_HEADERS([src/config.h]) +AM_MAINTAINER_MODE() + # Export the version information (for tc_version and friends) TC_VERSION_MAJOR=`expr "$PACKAGE_VERSION" : '\([[0-9]]*\)'` TC_VERSION_MINOR=`expr "$PACKAGE_VERSION" : '[[0-9]]*\.\([[0-9]]*\)'` @@ -79,6 +81,11 @@ enable_heap_profiler=no enable_heap_checker=no fi +AC_ARG_ENABLE([stacktrace-via-backtrace], + [AS_HELP_STRING([--enable-stacktrace-via-backtrace], + [enable use of backtrace() for stacktrace capturing (may deadlock)])], + [enable_backtrace=yes], + []) # Checks for programs. @@ -99,7 +106,7 @@ [gpt_cv_objcopy_weaken=no]) AM_CONDITIONAL(HAVE_OBJCOPY_WEAKEN, test $gpt_cv_objcopy_weaken = yes) -LT_INIT([]) +AC_PROG_LIBTOOL AC_C_INLINE AX_C___ATTRIBUTE__ @@ -204,8 +211,9 @@ # Some tests test the behavior of .so files, and only make sense for dynamic. AM_CONDITIONAL(ENABLE_STATIC, test "$enable_static" = yes) -# We want to link in libunwind if it exists -AC_CHECK_LIB(unwind, backtrace, UNWIND_LIBS=-lunwind, UNWIND_LIBS=) +# We want to link in libunwind or libexecinfo if it exists +AC_CHECK_LIB(unwind, backtrace, UNWIND_LIBS=-lunwind, + [AC_CHECK_LIB(execinfo, backtrace, UNWIND_LIBS=-lexecinfo, UNWIND_LIBS=)]) AC_SUBST(UNWIND_LIBS) # On x86_64, instead of libunwind, we can choose to compile with frame-pointers. @@ -215,6 +223,7 @@ , enable_frame_pointers=no) AM_CONDITIONAL(ENABLE_FRAME_POINTERS, test "$enable_frame_pointers" = yes) +AC_MSG_CHECKING([for x86 without frame pointers]) # Some x86_64 systems do not insert frame pointers by default. # We want to see if the current system is one of those. AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [return __x86_64__ == 1 ? 0 : 1])], @@ -225,10 +234,14 @@ # We do our own determination of success/failure in the grep, below. AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int f(int x) {return x;}], [return f(0);])], [:], [:]) +x86_no_fp_by_default=no +AS_IF([test "$is_x86_64" = yes && ! grep 'mov.*rsp.*rbp' fp.s >/dev/null 2>&1], [x86_no_fp_by_default=yes]) AM_CONDITIONAL(X86_64_AND_NO_FP_BY_DEFAULT, - test "$is_x86_64" = yes && ! grep 'mov.*rsp.*rbp' fp.s >/dev/null 2>&1) + test "$x86_no_fp_by_default" = yes) rm fp.s CFLAGS="$OLD_CFLAGS" +AC_MSG_RESULT([$x86_no_fp_by_default]) + # We need to know if we're i386 so we can turn on -mmms, which is not # on by default for i386 (it is for x86_64). @@ -299,12 +312,16 @@ # And mingw also does compile __thread but resultant code actually # fails to work correctly at least in some not so ancient version: # http://mingw-users.1079350.n2.nabble.com/gcc-4-4-multi-threaded-exception-handling-amp-thread-specifier-not-working-td3440749.html +# +# Also it was reported that earlier gcc versions for mips compile +# __thread but it doesn't really work AC_MSG_CHECKING([for __thread]) -AC_LINK_IFELSE([AC_LANG_PROGRAM([#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) || (__GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ < 2)) +AC_LINK_IFELSE([AC_LANG_PROGRAM([#if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) || (__GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ < 2)) #error gcc has this bug: http://gcc.gnu.org/ml/gcc-bugs/2006-09/msg02275.html -#endif -#if defined(__MINGW32__) -#error mingw doesn't really support tls +#elif defined(__MINGW32__) +#error mingw doesnt really support tls +#elif defined(__APPLE__) +#error OSX __thread support is known to call malloc which makes it unsafe to use from malloc replacement #endif ], [static __thread int p = 0])], [AC_DEFINE(HAVE_TLS, 1, @@ -345,6 +362,26 @@ # In fact, a lot of the code in this directory depends on pthreads ACX_PTHREAD +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +AC_MSG_CHECKING([whether pthread symbols are available in C++ without including pthread.h]) +acx_pthread_despite_asking_for=no +AC_LINK_IFELSE( + [AC_LANG_PROGRAM([ + #include + #include + ],[ + pthread_t th; pthread_join(th, 0); + ])],[ + acx_pthread_despite_asking_for=yes + AC_DEFINE(HAVE_PTHREAD_DESPITE_ASKING_FOR, 1, [defined to 1 if pthread symbols are exposed even without include pthread.h]) + AC_DEFINE(HAVE_PTHREAD, 1, []) + ]) +AC_MSG_RESULT([$acx_pthread_despite_asking_for]) +AC_LANG_RESTORE + +AM_CONDITIONAL(HAVE_PTHREAD_DESPITE_ASKING_FOR, test x"$acx_pthread_despite_asking_for" = xyes) + # Find out what namespace 'normal' STL code lives in AC_CXX_STL_NAMESPACE @@ -362,6 +399,9 @@ ;; esac +if test "x$enable_backtrace" = xyes; then + AC_CHECK_DECLS([backtrace], [], [], [#include ]) +fi # For windows, this has a non-trivial value (__declspec(export)), but any # system that uses configure wants this to be the empty string. @@ -436,3 +476,8 @@ AC_CONFIG_FILES([Makefile src/gperftools/tcmalloc.h src/windows/gperftools/tcmalloc.h]) AC_OUTPUT + +AS_IF([test "$x86_no_fp_by_default" = yes && test "x$enable_frame_pointers" != xyes && test "x$UNWIND_LIBS" = x && test "x$enable_minimal" != xyes], + [AS_IF([test "x$enable_backtrace" = xyes], + [AC_MSG_WARN([No frame pointers and no libunwind. Expect backtrace capturing and unittests to fail])], + [AC_MSG_FAILURE([No frame pointers and no libunwind. The compilation will fail])])]) diff -Nru google-perftools-2.1/debian/changelog google-perftools-2.2.1/debian/changelog --- google-perftools-2.1/debian/changelog 2014-09-08 00:10:10.000000000 +0200 +++ google-perftools-2.2.1/debian/changelog 2014-09-08 00:10:11.000000000 +0200 @@ -1,3 +1,12 @@ +google-perftools (2.2.1-0.1) unstable; urgency=medium + + * Non-maintainer upload + * New upstream release. (Closes: #757149) + * Updated watch file + * Added ppc64el, arm64 architectures (Closes: #737677) + + -- Hilko Bengen Sun, 07 Sep 2014 21:22:29 +0200 + google-perftools (2.1-2) unstable; urgency=low * Now builds with automake 1.11. (Closes: #724381) diff -Nru google-perftools-2.1/debian/control google-perftools-2.2.1/debian/control --- google-perftools-2.1/debian/control 2014-09-08 00:10:10.000000000 +0200 +++ google-perftools-2.2.1/debian/control 2014-09-08 00:10:11.000000000 +0200 @@ -11,7 +11,7 @@ Package: libgoogle-perftools-dev Section: libdevel -Architecture: i386 amd64 powerpc armel armhf +Architecture: i386 amd64 powerpc ppc64el arm64 armel armhf Depends: ${misc:Depends}, libgoogle-perftools4 (= ${binary:Version}), libtcmalloc-minimal4 (= ${binary:Version}), libunwind8-dev [amd64] Description: libraries for CPU and heap analysis, plus an efficient thread-caching malloc The gperftools, previously called google-perftools, package contains some @@ -22,7 +22,7 @@ Package: libtcmalloc-minimal4 Section: libs -Architecture: i386 amd64 powerpc armel armhf +Architecture: i386 amd64 powerpc ppc64el arm64 armel armhf Depends: ${shlibs:Depends}, ${misc:Depends} Description: efficient thread-caching malloc The gperftools, previously called google-perftools, package contains some @@ -32,7 +32,7 @@ Package: libtcmalloc-minimal4-dbg Section: debug Priority: extra -Architecture: i386 amd64 powerpc armel armhf +Architecture: i386 amd64 powerpc ppc64el arm64 armel armhf Depends: ${misc:Depends}, libtcmalloc-minimal4 (= ${binary:Version}) Description: efficient thread-caching malloc Contains debugging symbols for libtcmalloc-minimal4. @@ -43,7 +43,7 @@ Package: libgoogle-perftools4 Section: libs -Architecture: i386 amd64 powerpc armel armhf +Architecture: i386 amd64 powerpc ppc64el arm64 armel armhf Depends: libtcmalloc-minimal4 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} Conflicts: libgoogle-perftools0 Description: libraries for CPU and heap analysis, plus an efficient thread-caching malloc @@ -55,7 +55,7 @@ Package: libgoogle-perftools4-dbg Section: debug Priority: extra -Architecture: i386 amd64 powerpc armel armhf +Architecture: i386 amd64 powerpc ppc64el arm64 armel armhf Depends: ${misc:Depends}, libgoogle-perftools4 (= ${binary:Version}) Description: libraries for CPU and heap analysis, plus an efficient thread-caching malloc Contains debugging symbols for libgoogle-perftools4. diff -Nru google-perftools-2.1/debian/watch google-perftools-2.2.1/debian/watch --- google-perftools-2.1/debian/watch 2014-09-08 00:10:10.000000000 +0200 +++ google-perftools-2.2.1/debian/watch 2014-09-08 00:10:11.000000000 +0200 @@ -1,7 +1,2 @@ -# Example watch control file for uscan -# Rename this file to "watch" and then you can run the "uscan" command -# to check for upstream updates and more. -# Site Directory Pattern Version Script -# http://prdownloads.sourceforge.net/goog-perftools/ version=3 -http://code.google.com/p/gperftools/downloads/list?can=1 .*/gperftools-(\d[\d\.]*)\.tar\.gz +https://code.google.com/p/gperftools/ https://.*/gperftools-(\d[\d\.]*)\.tar\.gz diff -Nru google-perftools-2.1/doc/pprof.see_also google-perftools-2.2.1/doc/pprof.see_also --- google-perftools-2.1/doc/pprof.see_also 1970-01-01 01:00:00.000000000 +0100 +++ google-perftools-2.2.1/doc/pprof.see_also 2013-05-25 23:42:55.000000000 +0200 @@ -0,0 +1,11 @@ +[see also] +Further documentation for +.B pprof +is maintained as a web page called +.B cpu_profiler.html +and is likely installed at one of the following locations: +.IP +.B /usr/share/gperftools/cpu_profiler.html +.br +.B /usr/local/share/gperftools/cpu_profiler.html +.PP diff -Nru google-perftools-2.1/doc/tcmalloc.html google-perftools-2.2.1/doc/tcmalloc.html --- google-perftools-2.1/doc/tcmalloc.html 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/doc/tcmalloc.html 2013-09-09 17:03:30.000000000 +0200 @@ -86,9 +86,9 @@ back from a thread-local cache into the central data structures.

-

TCMalloc treats objects with size <= 32K ("small" objects) +

TCMalloc treats objects with size <= 256K ("small" objects) differently from larger objects. Large objects are allocated directly -from the central heap using a page-level allocator (a page is a 4K +from the central heap using a page-level allocator (a page is a 8K aligned region of memory). I.e., a large object is always page-aligned and occupies an integral number of pages.

@@ -99,8 +99,8 @@

Small Object Allocation

-

Each small object size maps to one of approximately 60 allocatable -size-classes. For example, all allocations in the range 833 to 1024 +

Each small object size maps to one of approximately 88 allocatable +size-classes. For example, all allocations in the range 961 to 1024 bytes are rounded up to 1024. The size-classes are spaced so that small sizes are separated by 8 bytes, larger sizes by 16 bytes, even larger sizes by 32 bytes, and so forth. The maximal spacing is @@ -198,12 +198,12 @@

Large Object Allocation

-

A large object size (> 32K) is rounded up to a page size (4K) +

A large object size (> 256K) is rounded up to a page size (8K) and is handled by a central page heap. The central page heap is again -an array of free lists. For i < 256, the +an array of free lists. For i < 128, the kth entry is a free list of runs that consist of -k pages. The 256th entry is a free list of -runs that have length >= 256 pages:

+k pages. The 128th entry is a free list of +runs that have length >= 128 pages:

An allocation for k pages is satisfied by looking in @@ -238,9 +238,9 @@

In a 32-bit address space, the central array is represented by a a 2-level radix tree where the root contains 32 entries and each leaf -contains 2^15 entries (a 32-bit address spave has 2^20 4K pages, and -the first level of tree divides the 2^20 pages by 2^5). This leads to -a starting memory usage of 128KB of space (2^15*4 bytes) for the +contains 2^14 entries (a 32-bit address space has 2^19 8K pages, and +the first level of tree divides the 2^19 pages by 2^5). This leads to +a starting memory usage of 64KB of space (2^14*4 bytes) for the central array, which seems acceptable.

On 64-bit machines, we use a 3-level radix tree.

diff -Nru google-perftools-2.1/gperftools.sln google-perftools-2.2.1/gperftools.sln --- google-perftools-2.1/gperftools.sln 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/gperftools.sln 2013-09-22 03:14:21.000000000 +0200 @@ -100,6 +100,11 @@ ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "system-alloc_unittest", "vsprojects\system-alloc_unittest\system-alloc_unittest.vcproj", "{387F753A-0312-4A7B-A1D6-B2795E832E96}" + ProjectSection(ProjectDependencies) = postProject + {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F} = {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F} + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -190,6 +195,10 @@ {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Debug.Build.0 = Debug|Win32 {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Release.ActiveCfg = Release|Win32 {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Release.Build.0 = Release|Win32 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Debug.ActiveCfg = Debug|Win32 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Debug.Build.0 = Debug|Win32 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Release.ActiveCfg = Release|Win32 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff -Nru google-perftools-2.1/libtool google-perftools-2.2.1/libtool --- google-perftools-2.1/libtool 2013-07-30 11:12:45.000000000 +0200 +++ google-perftools-2.2.1/libtool 2014-06-22 00:53:07.000000000 +0200 @@ -1,8 +1,8 @@ #! /bin/sh # libtool - Provide generalized library-building support services. -# Generated automatically by config.status (gperftools) 2.1 -# Libtool was configured on host chi: +# Generated automatically by config.status (gperftools) 2.2.1 +# Libtool was configured on host beta.altoros.corp: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, @@ -272,10 +272,10 @@ hardcode_into_libs=yes # Compile-time system search path for libraries. -sys_lib_search_path_spec="/usr/lib/gcc/x86_64-linux-gnu/4.8 /usr/lib/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib " +sys_lib_search_path_spec="/usr/lib/gcc/i586-linux-gnu/4.9 /usr/lib/i386-linux-gnu /usr/lib /lib/i386-linux-gnu /lib " # Run-time system search path for libraries. -sys_lib_dlsearch_path_spec="/lib /usr/lib /lib/i386-linux-gnu /usr/lib/i386-linux-gnu /lib/i486-linux-gnu /usr/lib/i486-linux-gnu /usr/local/lib /lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu /lib32 /usr/lib32 /libx32 /usr/libx32 " +sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/local/lib /usr/lib/i386-linux-gnu/libfakeroot /lib/i386-linux-gnu /usr/lib/i386-linux-gnu /lib/i486-linux-gnu /usr/lib/i486-linux-gnu /usr/local/lib /lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu /lib64 /usr/lib64 /libx32 /usr/libx32 " # Whether dlopen is supported. dlopen_support=unknown @@ -292,7 +292,7 @@ # The linker used to build libraries. -LD="/usr/bin/ld -m elf_x86_64" +LD="/usr/bin/ld -m elf_i386" # How to create reloadable object files. reload_flag=" -r" @@ -513,7 +513,7 @@ # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) -# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.3 +# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.7 # automake: $automake_version # autoconf: $autoconf_version # @@ -523,7 +523,7 @@ PROGRAM=libtool PACKAGE=libtool -VERSION="2.4.2 Debian-2.4.2-1.3" +VERSION="2.4.2 Debian-2.4.2-1.7" TIMESTAMP="" package_revision=1.3337 @@ -10099,7 +10099,7 @@ # ### BEGIN LIBTOOL TAG CONFIG: CXX # The linker used to build libraries. -LD="/usr/bin/ld -m elf_x86_64" +LD="/usr/bin/ld -m elf_i386" # How to create reloadable object files. reload_flag=" -r" @@ -10230,17 +10230,17 @@ hardcode_action=immediate # The directories searched by this compiler when creating a shared library. -compiler_lib_search_dirs="/usr/lib/gcc/x86_64-linux-gnu/4.8 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /usr/lib/gcc/x86_64-linux-gnu/4.8/../../.." +compiler_lib_search_dirs="/usr/lib/gcc/i586-linux-gnu/4.9 /usr/lib/gcc/i586-linux-gnu/4.9/../../../i386-linux-gnu /usr/lib/gcc/i586-linux-gnu/4.9/../../../../lib /lib/i386-linux-gnu /lib/../lib /usr/lib/i386-linux-gnu /usr/lib/../lib /usr/lib/gcc/i586-linux-gnu/4.9/../../.." # Dependencies to place before and after the objects being linked to # create a shared library. -predep_objects="/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbeginS.o" -postdep_objects="/usr/lib/gcc/x86_64-linux-gnu/4.8/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o" +predep_objects="/usr/lib/gcc/i586-linux-gnu/4.9/../../../i386-linux-gnu/crti.o /usr/lib/gcc/i586-linux-gnu/4.9/crtbeginS.o" +postdep_objects="/usr/lib/gcc/i586-linux-gnu/4.9/crtendS.o /usr/lib/gcc/i586-linux-gnu/4.9/../../../i386-linux-gnu/crtn.o" predeps="" postdeps="-lstdc++ -lm -lgcc_s -lc -lgcc_s" # The library search path used internally by the compiler when linking # a shared library. -compiler_lib_search_path="-L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.." +compiler_lib_search_path="-L/usr/lib/gcc/i586-linux-gnu/4.9 -L/usr/lib/gcc/i586-linux-gnu/4.9/../../../i386-linux-gnu -L/usr/lib/gcc/i586-linux-gnu/4.9/../../../../lib -L/lib/i386-linux-gnu -L/lib/../lib -L/usr/lib/i386-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/i586-linux-gnu/4.9/../../.." # ### END LIBTOOL TAG CONFIG: CXX diff -Nru google-perftools-2.1/ltmain.sh google-perftools-2.2.1/ltmain.sh --- google-perftools-2.1/ltmain.sh 2013-07-30 11:12:25.000000000 +0200 +++ google-perftools-2.2.1/ltmain.sh 2014-06-22 00:52:45.000000000 +0200 @@ -70,7 +70,7 @@ # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) -# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.3 +# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.7 # automake: $automake_version # autoconf: $autoconf_version # @@ -80,7 +80,7 @@ PROGRAM=libtool PACKAGE=libtool -VERSION="2.4.2 Debian-2.4.2-1.3" +VERSION="2.4.2 Debian-2.4.2-1.7" TIMESTAMP="" package_revision=1.3337 diff -Nru google-perftools-2.1/m4/libtool.m4 google-perftools-2.2.1/m4/libtool.m4 --- google-perftools-2.1/m4/libtool.m4 2013-07-30 11:12:25.000000000 +0200 +++ google-perftools-2.2.1/m4/libtool.m4 2014-06-22 00:52:45.000000000 +0200 @@ -1312,7 +1312,7 @@ rm -rf conftest* ;; -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext @@ -1333,7 +1333,10 @@ ;; esac ;; - ppc64-*linux*|powerpc64-*linux*) + powerpc64le-*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -1352,7 +1355,10 @@ x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - ppc*-*linux*|powerpc*-*linux*) + powerpcle-*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) diff -Nru google-perftools-2.1/m4/pc_from_ucontext.m4 google-perftools-2.2.1/m4/pc_from_ucontext.m4 --- google-perftools-2.1/m4/pc_from_ucontext.m4 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/m4/pc_from_ucontext.m4 2013-09-09 17:03:30.000000000 +0200 @@ -25,6 +25,7 @@ pc_fields="$pc_fields uc_mcontext.gregs[[REG_EIP]]" # Linux (i386) pc_fields="$pc_fields uc_mcontext.gregs[[REG_RIP]]" # Linux (x86_64) pc_fields="$pc_fields uc_mcontext.sc_ip" # Linux (ia64) + pc_fields="$pc_fields uc_mcontext.pc" # Linux (mips) pc_fields="$pc_fields uc_mcontext.uc_regs->gregs[[PT_NIP]]" # Linux (ppc) pc_fields="$pc_fields uc_mcontext.gregs[[R15]]" # Linux (arm old [untested]) pc_fields="$pc_fields uc_mcontext.arm_pc" # Linux (arm arch 5) diff -Nru google-perftools-2.1/Makefile.am google-perftools-2.2.1/Makefile.am --- google-perftools-2.1/Makefile.am 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/Makefile.am 2014-06-22 00:34:32.000000000 +0200 @@ -17,6 +17,8 @@ # This is mostly based on configure options AM_CXXFLAGS = +NO_BUILTIN_CXXFLAGS = + # These are good warnings to turn on by default. We also tell gcc # that malloc, free, realloc, mmap, etc. are not builtins (these flags # are supported since gcc 3.1.1). gcc doesn't think most of them are @@ -30,6 +32,8 @@ -fno-builtin-memalign -fno-builtin-posix_memalign \ -fno-builtin-valloc -fno-builtin-pvalloc +NO_BUILTIN_CXXFLAGS += -fno-builtin + # On i386, -mmmx is needed for the mmx-based instructions in # atomicops-internal-x86.h. Also as of gcc 4.6, -fomit-frame-pointer # is the default. Since we must always have frame pointers for I386 @@ -188,6 +192,7 @@ $(LOGGING_INCLUDES) SYSINFO_INCLUDES = src/base/sysinfo.h \ + src/getenv_safe.h \ src/base/logging.h \ src/base/commandlineflags.h \ src/base/cycleclock.h \ @@ -214,6 +219,7 @@ noinst_LTLIBRARIES += libwindows.la libwindows_la_SOURCES = $(WINDOWS_INCLUDES) \ src/windows/port.cc \ + src/windows/system-alloc.cc \ src/windows/ia32_modrm_map.cc \ src/windows/ia32_opcode_map.cc \ src/windows/mini_disassembler.cc \ @@ -233,7 +239,9 @@ src/base/atomicops-internals-linuxppc.h \ src/base/atomicops-internals-arm-generic.h \ src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-gcc.h \ src/base/atomicops-internals-x86.h noinst_LTLIBRARIES += libspinlock.la libspinlock_la_SOURCES = src/base/spinlock.cc \ @@ -262,7 +270,11 @@ # patch_functions.cc #includes tcmalloc.cc, so no need to link it in. TCMALLOC_CC = # windows has its own system for threads and system memory allocation. +if HAVE_PTHREAD_DESPITE_ASKING_FOR +MAYBE_THREADS_CC = src/maybe_threads.cc +else MAYBE_THREADS_CC = +endif SYSTEM_ALLOC_CC = else !MINGW # spinlock is the only code that uses atomicops. @@ -334,13 +346,16 @@ if WITH_STACK_TRACE ### The header files we use. We divide into categories based on directory -S_STACKTRACE_INCLUDES = src/stacktrace_config.h \ +S_STACKTRACE_INCLUDES = src/stacktrace_impl_setup-inl.h \ src/stacktrace_generic-inl.h \ src/stacktrace_libunwind-inl.h \ src/stacktrace_arm-inl.h \ src/stacktrace_powerpc-inl.h \ + src/stacktrace_powerpc-darwin-inl.h \ + src/stacktrace_powerpc-linux-inl.h \ src/stacktrace_x86-inl.h \ src/stacktrace_win32-inl.h \ + src/stacktrace_instrument-inl.h \ src/base/elf_mem_image.h \ src/base/vdso_support.h @@ -521,7 +536,7 @@ tcmalloc_minimal_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \ src/tests/testutil.h src/tests/testutil.cc \ $(TCMALLOC_UNITTEST_INCLUDES) -tcmalloc_minimal_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_minimal_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) tcmalloc_minimal_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) # We want libtcmalloc last on the link line, but due to a bug in # libtool involving convenience libs, they need to come last on the @@ -536,13 +551,13 @@ TESTS += tcmalloc_minimal_large_unittest WINDOWS_PROJECTS += vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj tcmalloc_minimal_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc -tcmalloc_minimal_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_minimal_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) tcmalloc_minimal_large_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) tcmalloc_minimal_large_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) TESTS += tcmalloc_minimal_large_heap_fragmentation_unittest tcmalloc_minimal_large_heap_fragmentation_unittest_SOURCES = src/tests/large_heap_fragmentation_unittest.cc -tcmalloc_minimal_large_heap_fragmentation_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_minimal_large_heap_fragmentation_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) tcmalloc_minimal_large_heap_fragmentation_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) tcmalloc_minimal_large_heap_fragmentation_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) @@ -582,11 +597,12 @@ addressmap_unittest_CXXFLAGS = -g $(AM_CXXFLAGS) addressmap_unittest_LDADD = liblogging.la +WINDOWS_PROJECTS += vsprojects/system-alloc_unittest/system-alloc_unittest.vcproj if !MINGW TESTS += system_alloc_unittest system_alloc_unittest_SOURCES = src/config_for_unittests.h \ src/tests/system-alloc_unittest.cc -system_alloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +system_alloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) system_alloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) system_alloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) endif !MINGW @@ -601,7 +617,7 @@ TESTS += frag_unittest WINDOWS_PROJECTS += vsprojects/frag_unittest/frag_unittest.vcproj frag_unittest_SOURCES = src/tests/frag_unittest.cc src/config_for_unittests.h -frag_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +frag_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) frag_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) frag_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) @@ -610,7 +626,7 @@ markidle_unittest_SOURCES = src/tests/markidle_unittest.cc \ src/config_for_unittests.h \ src/tests/testutil.h src/tests/testutil.cc -markidle_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +markidle_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) markidle_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) markidle_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) @@ -660,7 +676,7 @@ malloc_extension_c_test_CFLAGS += -ansi endif GCC malloc_extension_c_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) -malloc_extension_c_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +malloc_extension_c_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) -lstdc++ endif !ENABLE_STATIC endif !MINGW @@ -671,7 +687,7 @@ src/tcmalloc.h \ src/config_for_unittests.h \ src/tests/testutil.h src/tests/testutil.cc -memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) memalign_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) memalign_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) endif !OSX @@ -694,7 +710,7 @@ src/config_for_unittests.h \ src/base/logging.h \ src/pagemap.h -pagemap_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +pagemap_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) pagemap_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) pagemap_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) @@ -703,7 +719,7 @@ realloc_unittest_SOURCES = src/tests/realloc_unittest.cc \ src/config_for_unittests.h \ src/base/logging.h -realloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +realloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) realloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) realloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) @@ -720,7 +736,7 @@ thread_dealloc_unittest_SOURCES = src/tests/thread_dealloc_unittest.cc \ src/config_for_unittests.h \ src/tests/testutil.h src/tests/testutil.cc -thread_dealloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +thread_dealloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) thread_dealloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) @@ -827,7 +843,7 @@ # This is the sub-program used by debugallocation_test.sh noinst_PROGRAMS += debugallocation_test debugallocation_test_SOURCES = src/tests/debugallocation_test.cc -debugallocation_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +debugallocation_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) debugallocation_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) debugallocation_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS) endif WITH_STACK_TRACE @@ -851,7 +867,8 @@ src/base/stl_allocator.h \ src/base/sysinfo.h \ src/base/thread_lister.h \ - src/heap-profile-table.h + src/heap-profile-table.h \ + src/heap-profile-stats.h SG_TCMALLOC_INCLUDES = src/gperftools/heap-profiler.h \ src/gperftools/heap-checker.h TCMALLOC_INCLUDES = $(S_TCMALLOC_INCLUDES) $(SG_TCMALLOC_MINIMAL_INCLUDES) \ @@ -920,7 +937,7 @@ src/tcmalloc.h \ src/tests/testutil.h src/tests/testutil.cc \ $(TCMALLOC_UNITTEST_INCLUDES) -tcmalloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) tcmalloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) # We want libtcmalloc last on the link line, but due to a bug in # libtool involving convenience libs, they need to come last on the @@ -941,7 +958,7 @@ tcmalloc_both_unittest_srcs = src/tests/tcmalloc_unittest.cc \ src/tests/testutil.h src/tests/testutil.cc \ $(TCMALLOC_UNITTEST_INCLUDES) -tcmalloc_both_unittest_cflags = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_both_unittest_cflags = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) tcmalloc_both_unittest_lflags = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) if WITH_CPU_PROFILER # We want libtcmalloc last on the link line, but due to a bug in @@ -967,13 +984,13 @@ TESTS += tcmalloc_large_unittest tcmalloc_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc -tcmalloc_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) tcmalloc_large_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) tcmalloc_large_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) TESTS += tcmalloc_large_heap_fragmentation_unittest tcmalloc_large_heap_fragmentation_unittest_SOURCES = src/tests/large_heap_fragmentation_unittest.cc -tcmalloc_large_heap_fragmentation_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_large_heap_fragmentation_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) tcmalloc_large_heap_fragmentation_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) tcmalloc_large_heap_fragmentation_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) @@ -1038,7 +1055,7 @@ src/gperftools/heap-profiler.h heap_profiler_unittest_SOURCES = src/tests/heap-profiler_unittest.cc \ $(HEAP_PROFILER_UNITTEST_INCLUDES) -heap_profiler_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +heap_profiler_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) heap_profiler_unittest_LDFLAGS = -g $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) heap_profiler_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) @@ -1080,7 +1097,7 @@ $(LOGGING_INCLUDES) heap_checker_unittest_SOURCES = src/tests/heap-checker_unittest.cc \ $(HEAP_CHECKER_UNITTEST_INCLUDES) -heap_checker_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +heap_checker_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) heap_checker_unittest_LDFLAGS = -g $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) # We want libtcmalloc last on the link line, but due to a bug in # libtool involving convenience libs, they need to come last on the @@ -1406,5 +1423,6 @@ $(SCRIPTS) libtool \ src/windows/get_mangled_names.cc src/windows/override_functions.cc \ src/windows/config.h src/windows/gperftools/tcmalloc.h \ + doc/pprof.see_also src/windows/TODO \ $(WINDOWS_PROJECTS) \ src/solaris/libstdc++.la diff -Nru google-perftools-2.1/Makefile.in google-perftools-2.2.1/Makefile.in --- google-perftools-2.1/Makefile.in 2013-07-30 11:12:29.000000000 +0200 +++ google-perftools-2.2.1/Makefile.in 2014-06-22 00:52:50.000000000 +0200 @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.3 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -100,27 +100,28 @@ @GCC_TRUE@ -fno-builtin-memalign -fno-builtin-posix_memalign \ @GCC_TRUE@ -fno-builtin-valloc -fno-builtin-pvalloc +@GCC_TRUE@am__append_3 = -fno-builtin # On i386, -mmmx is needed for the mmx-based instructions in # atomicops-internal-x86.h. Also as of gcc 4.6, -fomit-frame-pointer # is the default. Since we must always have frame pointers for I386 # in order to generate backtraces we now specify -fno-omit-frame-pointer # by default. -@GCC_TRUE@@I386_TRUE@am__append_3 = -mmmx -fno-omit-frame-pointer -@HAVE_W_NO_UNUSED_RESULT_TRUE@am__append_4 = -Wno-unused-result +@GCC_TRUE@@I386_TRUE@am__append_4 = -mmmx -fno-omit-frame-pointer +@HAVE_W_NO_UNUSED_RESULT_TRUE@am__append_5 = -Wno-unused-result # These are x86-specific, having to do with frame-pointers. In # particular, some x86_64 systems do not insert frame pointers by # default (all i386 systems that I know of, do. I don't know about # non-x86 chips). We need to tell perftools what to do about that. -@ENABLE_FRAME_POINTERS_TRUE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@am__append_5 = -fno-omit-frame-pointer -@ENABLE_FRAME_POINTERS_FALSE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@am__append_6 = -DNO_FRAME_POINTER -@MINGW_TRUE@am__append_7 = -Wl,-u__tcmalloc +@ENABLE_FRAME_POINTERS_TRUE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@am__append_6 = -fno-omit-frame-pointer +@ENABLE_FRAME_POINTERS_FALSE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@am__append_7 = -DNO_FRAME_POINTER +@MINGW_TRUE@am__append_8 = -Wl,-u__tcmalloc TESTS = low_level_alloc_unittest$(EXEEXT) atomicops_unittest$(EXEEXT) \ $(am__EXEEXT_9) tcmalloc_minimal_unittest$(EXEEXT) \ tcmalloc_minimal_large_unittest$(EXEEXT) \ tcmalloc_minimal_large_heap_fragmentation_unittest$(EXEEXT) \ - $(am__append_17) addressmap_unittest$(EXEEXT) $(am__EXEEXT_10) \ + $(am__append_18) addressmap_unittest$(EXEEXT) $(am__EXEEXT_10) \ packed_cache_test$(EXEEXT) frag_unittest$(EXEEXT) \ markidle_unittest$(EXEEXT) \ current_allocated_bytes_test$(EXEEXT) \ @@ -129,38 +130,38 @@ pagemap_unittest$(EXEEXT) realloc_unittest$(EXEEXT) \ stack_trace_table_test$(EXEEXT) \ thread_dealloc_unittest$(EXEEXT) $(am__EXEEXT_13) \ - $(am__EXEEXT_14) $(am__EXEEXT_15) $(am__append_29) \ - $(am__append_39) $(am__EXEEXT_16) $(am__EXEEXT_17) \ - $(am__EXEEXT_18) $(am__append_49) $(am__EXEEXT_19) \ - $(am__append_58) $(am__append_60) $(am__EXEEXT_20) \ + $(am__EXEEXT_14) $(am__EXEEXT_15) $(am__append_30) \ + $(am__append_40) $(am__EXEEXT_16) $(am__EXEEXT_17) \ + $(am__EXEEXT_18) $(am__append_50) $(am__EXEEXT_19) \ + $(am__append_59) $(am__append_61) $(am__EXEEXT_20) \ $(am__EXEEXT_21) noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \ $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_22) bin_PROGRAMS = -@MINGW_TRUE@am__append_8 = libwindows.la libspinlock.la +@MINGW_TRUE@am__append_9 = libwindows.la libspinlock.la # We also need to tell mingw that sysinfo.cc needs shlwapi.lib. # (We do this via a #pragma for msvc, but need to do it here for mingw). -@MINGW_TRUE@am__append_9 = -lshlwapi -@MINGW_FALSE@am__append_10 = libspinlock.la -@WITH_STACK_TRACE_TRUE@am__append_11 = $(SG_STACKTRACE_INCLUDES) +@MINGW_TRUE@am__append_10 = -lshlwapi +@MINGW_FALSE@am__append_11 = libspinlock.la +@WITH_STACK_TRACE_TRUE@am__append_12 = $(SG_STACKTRACE_INCLUDES) ### Making the library -@WITH_STACK_TRACE_TRUE@am__append_12 = libstacktrace.la +@WITH_STACK_TRACE_TRUE@am__append_13 = libstacktrace.la ### Unittests -@WITH_STACK_TRACE_TRUE@am__append_13 = stacktrace_unittest +@WITH_STACK_TRACE_TRUE@am__append_14 = stacktrace_unittest ### Documentation -@WITH_STACK_TRACE_TRUE@am__append_14 = doc/pprof_remote_servers.html +@WITH_STACK_TRACE_TRUE@am__append_15 = doc/pprof_remote_servers.html # Let unittests find pprof if they need to run it -@WITH_STACK_TRACE_TRUE@am__append_15 = PPROF_PATH=$(top_srcdir)/src/pprof +@WITH_STACK_TRACE_TRUE@am__append_16 = PPROF_PATH=$(top_srcdir)/src/pprof # On MSVC, we need our own versions of addr2line and nm to work with pprof. # This is a slight abuse of WINDOWS_PROJECTS, but not much -@WITH_STACK_TRACE_TRUE@am__append_16 = \ +@WITH_STACK_TRACE_TRUE@am__append_17 = \ @WITH_STACK_TRACE_TRUE@ vsprojects/nm-pdb/nm-pdb.vcproj \ @WITH_STACK_TRACE_TRUE@ vsprojects/addr2line-pdb/addr2line-pdb.vcproj \ @WITH_STACK_TRACE_TRUE@ src/windows/nm-pdb.c \ @@ -172,41 +173,41 @@ # libraries anyway (so can't be LD_PRELOADed) -- in fact, anybody who # chooses not to build shared libraries won't be able to run this test. # TODO(csilvers): figure out how to nix ".exe" or otherwise work under mingw -@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_17 = maybe_threads_unittest.sh$(EXEEXT) -@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_18 = $(maybe_threads_unittest_sh_SOURCES) -@MINGW_TRUE@am__append_19 = src/windows/port.h src/windows/port.cc -@MINGW_FALSE@am__append_20 = system_alloc_unittest +@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_18 = maybe_threads_unittest.sh$(EXEEXT) +@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_19 = $(maybe_threads_unittest_sh_SOURCES) +@MINGW_TRUE@am__append_20 = src/windows/port.h src/windows/port.cc +@MINGW_FALSE@am__append_21 = system_alloc_unittest # This doesn't work with static linkage, because libtcmalloc.a isn't # happy with C linkage (it misses the stdc++ library). Likewise with # mingw, which links foo.a even though it doesn't set ENABLE_STATIC. # TODO(csilvers): set enable_static=true in configure.ac:36? -@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_21 = malloc_extension_c_test +@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_22 = malloc_extension_c_test # -ansi here is just to help ensure the code is bog-standard C. -@ENABLE_STATIC_FALSE@@GCC_TRUE@@MINGW_FALSE@am__append_22 = -ansi -@MINGW_FALSE@@OSX_FALSE@am__append_23 = memalign_unittest +@ENABLE_STATIC_FALSE@@GCC_TRUE@@MINGW_FALSE@am__append_23 = -ansi +@MINGW_FALSE@@OSX_FALSE@am__append_24 = memalign_unittest ### ------- tcmalloc_minimal_debug (thread-caching malloc with debugallocation) # Like tcmalloc.cc, debugallocation.cc needs exceptions to fulfill its # API. Luckily, we can reuse everything else from tcmalloc_minimal. -@WITH_DEBUGALLOC_TRUE@am__append_24 = libtcmalloc_minimal_debug.la @WITH_DEBUGALLOC_TRUE@am__append_25 = libtcmalloc_minimal_debug.la +@WITH_DEBUGALLOC_TRUE@am__append_26 = libtcmalloc_minimal_debug.la ### Unittests -@WITH_DEBUGALLOC_TRUE@am__append_26 = tcmalloc_minimal_debug_unittest \ +@WITH_DEBUGALLOC_TRUE@am__append_27 = tcmalloc_minimal_debug_unittest \ @WITH_DEBUGALLOC_TRUE@ malloc_extension_debug_test -@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@am__append_27 = memalign_debug_unittest -@WITH_DEBUGALLOC_TRUE@am__append_28 = realloc_debug_unittest +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@am__append_28 = memalign_debug_unittest +@WITH_DEBUGALLOC_TRUE@am__append_29 = realloc_debug_unittest # debugallocation_test checks that we print a proper stacktrace when # debug-allocs fail, so we can't run it if we don't have stacktrace info. -@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_29 = debugallocation_test.sh$(EXEEXT) -@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_30 = $(debugallocation_test_sh_SOURCES) +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_30 = debugallocation_test.sh$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_31 = $(debugallocation_test_sh_SOURCES) # This is the sub-program used by debugallocation_test.sh -@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_31 = debugallocation_test -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_32 = $(SG_TCMALLOC_INCLUDES) +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_32 = debugallocation_test +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_33 = $(SG_TCMALLOC_INCLUDES) ### Making the library @@ -214,24 +215,24 @@ # for all files in this library -- except tcmalloc.cc which needs them # to fulfill its API. Automake doesn't allow per-file CXXFLAGS, so we need # to separate into two libraries. -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_33 = libtcmalloc_internal.la -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_34 = libtcmalloc.la -@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_35 = $(HEAP_CHECKER_SOURCES) -@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_36 = -DNO_HEAP_CHECK +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_34 = libtcmalloc_internal.la +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_35 = libtcmalloc.la +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_36 = $(HEAP_CHECKER_SOURCES) @WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_37 = -DNO_HEAP_CHECK -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_38 = libtcmalloc.la +@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_38 = -DNO_HEAP_CHECK +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_39 = libtcmalloc.la ### Unittests -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_39 = tcmalloc_unittest.sh$(EXEEXT) -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_40 = $(tcmalloc_unittest_sh_SOURCES) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_40 = tcmalloc_unittest.sh$(EXEEXT) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_41 = $(tcmalloc_unittest_sh_SOURCES) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(sampling_test_sh_SOURCES) # This is the sub-program used by sampling_test.sh # The -g is so pprof can get symbol information. -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_41 = tcmalloc_unittest \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_42 = tcmalloc_unittest \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test -@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_42 = tcmalloc_both_unittest -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_43 = \ +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_43 = tcmalloc_both_unittest +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_44 = \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_large_unittest \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_large_heap_fragmentation_unittest \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ raw_printer_test \ @@ -242,74 +243,74 @@ # on, which it's not by default. Use the "standard" value of 2^19. # These unittests often need to run binaries. They're in the current dir -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_44 = TCMALLOC_SAMPLE_PARAMETER=524288 \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_45 = TCMALLOC_SAMPLE_PARAMETER=524288 \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ BINDIR=. \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ TMPDIR=/tmp/perftools -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_45 = vsprojects/sampler_test/sampler_test.vcproj +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_46 = vsprojects/sampler_test/sampler_test.vcproj # Tests the compatibility include-headers in google/. Requires a function # defined in the heap-profiler, which is why the test lives here. -@WITH_HEAP_PROFILER_TRUE@am__append_46 = \ +@WITH_HEAP_PROFILER_TRUE@am__append_47 = \ @WITH_HEAP_PROFILER_TRUE@ heap-profiler_unittest.sh$(EXEEXT) \ @WITH_HEAP_PROFILER_TRUE@ simple_compat_test -@WITH_HEAP_PROFILER_TRUE@am__append_47 = $(heap_profiler_unittest_sh_SOURCES) +@WITH_HEAP_PROFILER_TRUE@am__append_48 = $(heap_profiler_unittest_sh_SOURCES) # These are sub-programs used by heap-profiler_unittest.sh -@WITH_HEAP_PROFILER_TRUE@am__append_48 = heap-profiler_unittest -@WITH_HEAP_CHECKER_TRUE@am__append_49 = \ +@WITH_HEAP_PROFILER_TRUE@am__append_49 = heap-profiler_unittest +@WITH_HEAP_CHECKER_TRUE@am__append_50 = \ @WITH_HEAP_CHECKER_TRUE@ heap-checker_unittest.sh$(EXEEXT) \ @WITH_HEAP_CHECKER_TRUE@ heap-checker-death_unittest.sh$(EXEEXT) -@WITH_HEAP_CHECKER_TRUE@am__append_50 = \ +@WITH_HEAP_CHECKER_TRUE@am__append_51 = \ @WITH_HEAP_CHECKER_TRUE@ $(heap_checker_unittest_sh_SOURCES) \ @WITH_HEAP_CHECKER_TRUE@ $(top_srcdir)/$(heap_checker_death_unittest_sh_SOURCES) # These are sub-programs used by heap-checker_unittest.sh -@WITH_HEAP_CHECKER_TRUE@am__append_51 = heap-checker_unittest +@WITH_HEAP_CHECKER_TRUE@am__append_52 = heap-checker_unittest ### Documentation (above and beyond tcmalloc_minimal documentation) -@WITH_HEAP_PROFILER_TRUE@am__append_52 = doc/heapprofile.html doc/heap-example1.png -@WITH_HEAP_CHECKER_TRUE@am__append_53 = doc/heap_checker.html +@WITH_HEAP_PROFILER_TRUE@am__append_53 = doc/heapprofile.html doc/heap-example1.png +@WITH_HEAP_CHECKER_TRUE@am__append_54 = doc/heap_checker.html ### ------- tcmalloc with debugallocation -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_54 = libtcmalloc_debug.la @WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_55 = libtcmalloc_debug.la +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_56 = libtcmalloc_debug.la ### Unittests -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_56 = tcmalloc_debug_unittest \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_57 = tcmalloc_debug_unittest \ @WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_debug_test \ @WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_debug_test.sh$(EXEEXT) # This is the sub-program using by sampling_debug_test.sh # The -g is so pprof can get symbol information. -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_57 = sampling_debug_test -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_58 = heap-profiler_debug_unittest.sh$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_58 = sampling_debug_test +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_59 = heap-profiler_debug_unittest.sh$(EXEEXT) # These are sub-programs used by heap-profiler_debug_unittest.sh -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_59 = heap-profiler_debug_unittest -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_60 = heap-checker_debug_unittest.sh$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_60 = heap-profiler_debug_unittest +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_61 = heap-checker_debug_unittest.sh$(EXEEXT) # These are sub-programs used by heap-checker_debug_unittest.sh -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_61 = heap-checker_debug_unittest -@WITH_CPU_PROFILER_TRUE@am__append_62 = $(SG_CPU_PROFILER_INCLUDES) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_62 = heap-checker_debug_unittest +@WITH_CPU_PROFILER_TRUE@am__append_63 = $(SG_CPU_PROFILER_INCLUDES) ### Making the library -@WITH_CPU_PROFILER_TRUE@am__append_63 = libprofiler.la +@WITH_CPU_PROFILER_TRUE@am__append_64 = libprofiler.la ### Unittests -@WITH_CPU_PROFILER_TRUE@am__append_64 = getpc_test \ +@WITH_CPU_PROFILER_TRUE@am__append_65 = getpc_test \ @WITH_CPU_PROFILER_TRUE@ profiledata_unittest \ @WITH_CPU_PROFILER_TRUE@ profile_handler_unittest \ @WITH_CPU_PROFILER_TRUE@ profiler_unittest.sh$(EXEEXT) -@WITH_CPU_PROFILER_TRUE@am__append_65 = $(profiler_unittest_sh_SOURCES) +@WITH_CPU_PROFILER_TRUE@am__append_66 = $(profiler_unittest_sh_SOURCES) # These are sub-programs used by profiler_unittest.sh -@WITH_CPU_PROFILER_TRUE@am__append_66 = profiler1_unittest profiler2_unittest profiler3_unittest \ +@WITH_CPU_PROFILER_TRUE@am__append_67 = profiler1_unittest profiler2_unittest profiler3_unittest \ @WITH_CPU_PROFILER_TRUE@ profiler4_unittest @WITH_CPU_PROFILER_FALSE@profiler2_unittest_DEPENDENCIES = ### Documentation -@WITH_CPU_PROFILER_TRUE@am__append_67 = doc/cpuprofile.html \ +@WITH_CPU_PROFILER_TRUE@am__append_68 = doc/cpuprofile.html \ @WITH_CPU_PROFILER_TRUE@ doc/cpuprofile-fileformat.html \ @WITH_CPU_PROFILER_TRUE@ doc/pprof-test-big.gif \ @WITH_CPU_PROFILER_TRUE@ doc/pprof-test.gif \ @@ -324,9 +325,9 @@ # works fine for .so files, it does not for .a files. The easiest way # around this -- and I've tried a bunch of the hard ways -- is to just # to create another set of libraries that has both functionality in it. -@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_68 = libtcmalloc_and_profiler.la -@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_69 = tcmalloc_and_profiler_unittest -@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_70 = libtcmalloc_and_profiler.la +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_69 = libtcmalloc_and_profiler.la +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_70 = tcmalloc_and_profiler_unittest +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_71 = libtcmalloc_and_profiler.la subdir = . DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \ $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ @@ -419,6 +420,8 @@ src/base/synchronization_profiling.h \ src/base/atomicops-internals-arm-generic.h \ src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h \ src/base/dynamic_annotations.h src/third_party/valgrind.h \ src/gperftools/profiler.h src/gperftools/stacktrace.h @WITH_CPU_PROFILER_TRUE@am__objects_2 = $(am__objects_1) \ @@ -448,7 +451,9 @@ src/base/spinlock_posix-inl.h \ src/base/synchronization_profiling.h \ src/base/atomicops-internals-arm-generic.h \ - src/base/atomicops-internals-arm-v6plus.h + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h @MINGW_FALSE@am_libspinlock_la_OBJECTS = spinlock.lo \ @MINGW_FALSE@ spinlock_internal.lo atomicops-internals-x86.lo \ @MINGW_FALSE@ $(am__objects_1) @@ -462,11 +467,14 @@ @WITH_STACK_TRACE_TRUE@ $(am__DEPENDENCIES_1) $(LIBSPINLOCK) am__libstacktrace_la_SOURCES_DIST = src/stacktrace.cc \ src/base/elf_mem_image.cc src/base/vdso_support.cc \ - src/stacktrace_config.h src/stacktrace_generic-inl.h \ + src/stacktrace_impl_setup-inl.h src/stacktrace_generic-inl.h \ src/stacktrace_libunwind-inl.h src/stacktrace_arm-inl.h \ - src/stacktrace_powerpc-inl.h src/stacktrace_x86-inl.h \ - src/stacktrace_win32-inl.h src/base/elf_mem_image.h \ - src/base/vdso_support.h src/gperftools/stacktrace.h + src/stacktrace_powerpc-inl.h \ + src/stacktrace_powerpc-darwin-inl.h \ + src/stacktrace_powerpc-linux-inl.h src/stacktrace_x86-inl.h \ + src/stacktrace_win32-inl.h src/stacktrace_instrument-inl.h \ + src/base/elf_mem_image.h src/base/vdso_support.h \ + src/gperftools/stacktrace.h @WITH_STACK_TRACE_TRUE@am__objects_4 = $(am__objects_1) \ @WITH_STACK_TRACE_TRUE@ $(am__objects_1) @WITH_STACK_TRACE_TRUE@am_libstacktrace_la_OBJECTS = stacktrace.lo \ @@ -497,7 +505,9 @@ src/base/spinlock_posix-inl.h \ src/base/synchronization_profiling.h \ src/base/atomicops-internals-arm-generic.h \ - src/base/atomicops-internals-arm-v6plus.h src/tcmalloc_guard.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ src/base/commandlineflags.h src/base/basictypes.h \ src/pagemap.h src/sampler.h src/central_freelist.h \ src/linked_list.h src/libc_override.h \ @@ -514,7 +524,8 @@ src/base/linux_syscall_support.h src/base/linuxthreads.h \ src/base/stl_allocator.h src/base/sysinfo.h \ src/base/thread_lister.h src/heap-profile-table.h \ - src/gperftools/malloc_hook.h src/gperftools/malloc_hook_c.h \ + src/heap-profile-stats.h src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ src/gperftools/malloc_extension.h \ src/gperftools/malloc_extension_c.h \ src/gperftools/heap-profiler.h src/gperftools/heap-checker.h \ @@ -561,7 +572,9 @@ src/base/spinlock_posix-inl.h \ src/base/synchronization_profiling.h \ src/base/atomicops-internals-arm-generic.h \ - src/base/atomicops-internals-arm-v6plus.h src/tcmalloc_guard.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ src/base/commandlineflags.h src/base/basictypes.h \ src/pagemap.h src/sampler.h src/central_freelist.h \ src/linked_list.h src/libc_override.h \ @@ -578,7 +591,8 @@ src/base/linux_syscall_support.h src/base/linuxthreads.h \ src/base/stl_allocator.h src/base/sysinfo.h \ src/base/thread_lister.h src/heap-profile-table.h \ - src/gperftools/malloc_hook.h src/gperftools/malloc_hook_c.h \ + src/heap-profile-stats.h src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ src/gperftools/malloc_extension.h \ src/gperftools/malloc_extension_c.h \ src/gperftools/heap-profiler.h src/gperftools/heap-checker.h \ @@ -627,7 +641,9 @@ src/base/spinlock_posix-inl.h \ src/base/synchronization_profiling.h \ src/base/atomicops-internals-arm-generic.h \ - src/base/atomicops-internals-arm-v6plus.h src/tcmalloc_guard.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ src/base/commandlineflags.h src/base/basictypes.h \ src/pagemap.h src/sampler.h src/central_freelist.h \ src/linked_list.h src/libc_override.h \ @@ -644,7 +660,8 @@ src/base/linux_syscall_support.h src/base/linuxthreads.h \ src/base/stl_allocator.h src/base/sysinfo.h \ src/base/thread_lister.h src/heap-profile-table.h \ - src/gperftools/malloc_hook.h src/gperftools/malloc_hook_c.h \ + src/heap-profile-stats.h src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ src/gperftools/malloc_extension.h \ src/gperftools/malloc_extension_c.h \ src/gperftools/heap-profiler.h src/gperftools/heap-checker.h \ @@ -683,7 +700,9 @@ src/base/spinlock_posix-inl.h \ src/base/synchronization_profiling.h \ src/base/atomicops-internals-arm-generic.h \ - src/base/atomicops-internals-arm-v6plus.h src/tcmalloc_guard.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ src/base/commandlineflags.h src/base/basictypes.h \ src/pagemap.h src/sampler.h src/central_freelist.h \ src/linked_list.h src/libc_override.h \ @@ -703,11 +722,13 @@ src/base/googleinit.h src/base/linux_syscall_support.h \ src/base/linuxthreads.h src/base/stl_allocator.h \ src/base/sysinfo.h src/base/thread_lister.h \ - src/heap-profile-table.h src/gperftools/heap-profiler.h \ - src/gperftools/heap-checker.h src/base/low_level_alloc.cc \ - src/heap-profile-table.cc src/heap-profiler.cc \ - src/raw_printer.cc src/memory_region_map.cc + src/heap-profile-table.h src/heap-profile-stats.h \ + src/gperftools/heap-profiler.h src/gperftools/heap-checker.h \ + src/base/low_level_alloc.cc src/heap-profile-table.cc \ + src/heap-profiler.cc src/raw_printer.cc \ + src/memory_region_map.cc @MINGW_FALSE@am__objects_17 = libtcmalloc_internal_la-system-alloc.lo +@HAVE_PTHREAD_DESPITE_ASKING_FOR_TRUE@@MINGW_TRUE@am__objects_18 = libtcmalloc_internal_la-maybe_threads.lo @MINGW_FALSE@am__objects_18 = \ @MINGW_FALSE@ libtcmalloc_internal_la-maybe_threads.lo am__objects_19 = $(am__objects_6) $(am__objects_1) $(am__objects_1) @@ -754,7 +775,9 @@ src/base/spinlock_posix-inl.h \ src/base/synchronization_profiling.h \ src/base/atomicops-internals-arm-generic.h \ - src/base/atomicops-internals-arm-v6plus.h src/tcmalloc_guard.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ src/base/commandlineflags.h src/base/basictypes.h \ src/pagemap.h src/sampler.h src/central_freelist.h \ src/linked_list.h src/libc_override.h \ @@ -793,7 +816,9 @@ src/base/spinlock_posix-inl.h \ src/base/synchronization_profiling.h \ src/base/atomicops-internals-arm-generic.h \ - src/base/atomicops-internals-arm-v6plus.h src/tcmalloc_guard.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ src/base/commandlineflags.h src/base/basictypes.h \ src/pagemap.h src/sampler.h src/central_freelist.h \ src/linked_list.h src/libc_override.h \ @@ -837,7 +862,9 @@ src/base/spinlock_posix-inl.h \ src/base/synchronization_profiling.h \ src/base/atomicops-internals-arm-generic.h \ - src/base/atomicops-internals-arm-v6plus.h src/tcmalloc_guard.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ src/base/commandlineflags.h src/base/basictypes.h \ src/pagemap.h src/sampler.h src/central_freelist.h \ src/linked_list.h src/libc_override.h \ @@ -854,6 +881,7 @@ src/gperftools/stacktrace.h @MINGW_FALSE@am__objects_22 = \ @MINGW_FALSE@ libtcmalloc_minimal_internal_la-system-alloc.lo +@HAVE_PTHREAD_DESPITE_ASKING_FOR_TRUE@@MINGW_TRUE@am__objects_23 = libtcmalloc_minimal_internal_la-maybe_threads.lo @MINGW_FALSE@am__objects_23 = \ @MINGW_FALSE@ libtcmalloc_minimal_internal_la-maybe_threads.lo am_libtcmalloc_minimal_internal_la_OBJECTS = \ @@ -883,14 +911,16 @@ src/windows/mingw.h src/windows/mini_disassembler.h \ src/windows/mini_disassembler_types.h \ src/windows/preamble_patcher.h src/windows/port.cc \ - src/windows/ia32_modrm_map.cc src/windows/ia32_opcode_map.cc \ + src/windows/system-alloc.cc src/windows/ia32_modrm_map.cc \ + src/windows/ia32_opcode_map.cc \ src/windows/mini_disassembler.cc \ src/windows/patch_functions.cc src/windows/preamble_patcher.cc \ src/windows/preamble_patcher_with_stub.cc @MINGW_TRUE@am_libwindows_la_OBJECTS = $(am__objects_1) port.lo \ -@MINGW_TRUE@ ia32_modrm_map.lo ia32_opcode_map.lo \ -@MINGW_TRUE@ mini_disassembler.lo patch_functions.lo \ -@MINGW_TRUE@ preamble_patcher.lo preamble_patcher_with_stub.lo +@MINGW_TRUE@ system-alloc.lo ia32_modrm_map.lo \ +@MINGW_TRUE@ ia32_opcode_map.lo mini_disassembler.lo \ +@MINGW_TRUE@ patch_functions.lo preamble_patcher.lo \ +@MINGW_TRUE@ preamble_patcher_with_stub.lo libwindows_la_OBJECTS = $(am_libwindows_la_OBJECTS) @MINGW_TRUE@am_libwindows_la_rpath = @WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__EXEEXT_1 = debugallocation_test$(EXEEXT) @@ -936,7 +966,7 @@ tcmalloc_minimal_unittest$(EXEEXT) \ tcmalloc_minimal_large_unittest$(EXEEXT) \ tcmalloc_minimal_large_heap_fragmentation_unittest$(EXEEXT) \ - $(am__append_17) addressmap_unittest$(EXEEXT) $(am__EXEEXT_10) \ + $(am__append_18) addressmap_unittest$(EXEEXT) $(am__EXEEXT_10) \ packed_cache_test$(EXEEXT) frag_unittest$(EXEEXT) \ markidle_unittest$(EXEEXT) \ current_allocated_bytes_test$(EXEEXT) \ @@ -945,10 +975,10 @@ pagemap_unittest$(EXEEXT) realloc_unittest$(EXEEXT) \ stack_trace_table_test$(EXEEXT) \ thread_dealloc_unittest$(EXEEXT) $(am__EXEEXT_13) \ - $(am__EXEEXT_14) $(am__EXEEXT_15) $(am__append_29) \ - $(am__append_39) $(am__EXEEXT_16) $(am__EXEEXT_17) \ - $(am__EXEEXT_18) $(am__append_49) $(am__EXEEXT_19) \ - $(am__append_58) $(am__append_60) $(am__EXEEXT_20) \ + $(am__EXEEXT_14) $(am__EXEEXT_15) $(am__append_30) \ + $(am__append_40) $(am__EXEEXT_16) $(am__EXEEXT_17) \ + $(am__EXEEXT_18) $(am__append_50) $(am__EXEEXT_19) \ + $(am__append_59) $(am__append_61) $(am__EXEEXT_20) \ $(am__EXEEXT_21) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am__addressmap_unittest_SOURCES_DIST = \ @@ -1115,9 +1145,12 @@ src/base/spinlock_posix-inl.h \ src/base/synchronization_profiling.h \ src/base/atomicops-internals-arm-generic.h \ - src/base/atomicops-internals-arm-v6plus.h src/base/logging.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/base/logging.h \ src/base/commandlineflags.h src/base/dynamic_annotations.h \ src/third_party/valgrind.h +@HAVE_PTHREAD_DESPITE_ASKING_FOR_TRUE@@MINGW_TRUE@am__objects_28 = low_level_alloc_unittest-maybe_threads.$(OBJEXT) @MINGW_FALSE@am__objects_28 = \ @MINGW_FALSE@ low_level_alloc_unittest-maybe_threads.$(OBJEXT) am__objects_29 = $(am__objects_1) $(am__objects_1) @@ -1450,10 +1483,12 @@ $(stack_trace_table_test_LDFLAGS) $(LDFLAGS) -o $@ am__stacktrace_unittest_SOURCES_DIST = \ src/tests/stacktrace_unittest.cc src/config_for_unittests.h \ - src/base/commandlineflags.h src/stacktrace_config.h \ + src/base/commandlineflags.h src/stacktrace_impl_setup-inl.h \ src/stacktrace_generic-inl.h src/stacktrace_libunwind-inl.h \ src/stacktrace_arm-inl.h src/stacktrace_powerpc-inl.h \ - src/stacktrace_x86-inl.h src/stacktrace_win32-inl.h \ + src/stacktrace_powerpc-darwin-inl.h \ + src/stacktrace_powerpc-linux-inl.h src/stacktrace_x86-inl.h \ + src/stacktrace_win32-inl.h src/stacktrace_instrument-inl.h \ src/base/elf_mem_image.h src/base/vdso_support.h \ src/gperftools/stacktrace.h src/base/logging.h \ src/base/basictypes.h src/base/dynamic_annotations.h \ @@ -2113,6 +2148,7 @@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -2210,8 +2246,9 @@ AM_CPPFLAGS = -I$(top_srcdir)/src $(am__append_1) # This is mostly based on configure options -AM_CXXFLAGS = $(am__append_2) $(am__append_3) $(am__append_4) \ - $(am__append_5) $(am__append_6) +AM_CXXFLAGS = $(am__append_2) $(am__append_4) $(am__append_5) \ + $(am__append_6) $(am__append_7) +NO_BUILTIN_CXXFLAGS = $(am__append_3) # The -no-undefined flag allows libtool to generate shared libraries for # Cygwin and MinGW. LIBSTDCXX_LA_LINKER_FLAG is used to fix a Solaris bug. @@ -2230,7 +2267,7 @@ # accomplishes its tasks via patching, leaving no work for the linker # to identify, so the linker will ignore libtcmalloc by default unless # we explicitly create a dependency via -u. -TCMALLOC_FLAGS = $(am__append_7) +TCMALLOC_FLAGS = $(am__append_8) @HAVE_OBJCOPY_WEAKEN_FALSE@WEAKEN = : # If we have objcopy, make malloc/free/etc weak symbols. That way folks @@ -2248,15 +2285,15 @@ @HAVE_OBJCOPY_WEAKEN_TRUE@ -W __Znwm -W __ZnwmRKSt9nothrow_t -W __Znam -W __ZnamRKSt9nothrow_t \ @HAVE_OBJCOPY_WEAKEN_TRUE@ -W __ZdlPv -W __ZdaPv -LIBS_TO_WEAKEN = libtcmalloc_minimal.la $(am__append_25) \ - $(am__append_38) $(am__append_55) $(am__append_70) +LIBS_TO_WEAKEN = libtcmalloc_minimal.la $(am__append_26) \ + $(am__append_39) $(am__append_56) $(am__append_71) perftoolsincludedir = $(includedir)/gperftools # The .h files you want to install (that is, .h files that people # who install this package can include in their own applications.) # We'll add to this later, on a library-by-library basis -perftoolsinclude_HEADERS = $(am__append_11) \ - $(SG_TCMALLOC_MINIMAL_INCLUDES) $(am__append_32) \ - $(am__append_62) +perftoolsinclude_HEADERS = $(am__append_12) \ + $(SG_TCMALLOC_MINIMAL_INCLUDES) $(am__append_33) \ + $(am__append_63) # tcmalloc.h is a special case, because it's a .h.in file nodist_perftoolsinclude_HEADERS = src/gperftools/tcmalloc.h noinst_HEADERS = src/gperftools/tcmalloc.h.in @@ -2289,7 +2326,7 @@ # end of the world. dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \ README_windows.txt TODO doc/index.html doc/designstyle.css \ - $(am__append_14) doc/tcmalloc.html doc/overview.gif \ + $(am__append_15) doc/tcmalloc.html doc/overview.gif \ doc/pageheap.gif doc/spanmap.gif doc/threadheap.gif \ doc/t-test1.times.txt \ doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png \ @@ -2314,13 +2351,13 @@ doc/tcmalloc-opspersec.vs.size.5.threads.png \ doc/tcmalloc-opspersec.vs.size.8.threads.png doc/overview.dot \ doc/pageheap.dot doc/spanmap.dot doc/threadheap.dot \ - $(am__append_52) $(am__append_53) $(am__append_67) + $(am__append_53) $(am__append_54) $(am__append_68) # The libraries (.so's) you want to install # We'll add to this later, on a library-by-library basis -lib_LTLIBRARIES = libtcmalloc_minimal.la $(am__append_24) \ - $(am__append_34) $(am__append_54) $(am__append_63) \ - $(am__append_68) +lib_LTLIBRARIES = libtcmalloc_minimal.la $(am__append_25) \ + $(am__append_35) $(am__append_55) $(am__append_64) \ + $(am__append_69) # This is for 'convenience libraries' -- basically just a container for sources ### Making the library @@ -2329,9 +2366,9 @@ # for all files in this library -- except tcmalloc.cc which needs them # to fulfill its API. Automake doesn't allow per-file CXXFLAGS, so we need # to separate into two libraries. -noinst_LTLIBRARIES = liblogging.la libsysinfo.la $(am__append_8) \ - $(am__append_10) $(am__append_12) \ - libtcmalloc_minimal_internal.la $(am__append_33) +noinst_LTLIBRARIES = liblogging.la libsysinfo.la $(am__append_9) \ + $(am__append_11) $(am__append_13) \ + libtcmalloc_minimal_internal.la $(am__append_34) # Add this whether or not we're under MinGW, to keep the tarball complete. # Because we've commented out the test, above, we have to explicitly add @@ -2341,12 +2378,13 @@ src/windows/preamble_patcher_test.cc src/windows/shortproc.asm \ src/windows/auto_testing_hook.h \ vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj \ - $(am__append_16) \ + $(am__append_17) \ vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj \ vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj \ vsprojects/tmu-static/tmu-static.vcproj \ vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj \ vsprojects/addressmap_unittest/addressmap_unittest.vcproj \ + vsprojects/system-alloc_unittest/system-alloc_unittest.vcproj \ vsprojects/packed-cache_test/packed-cache_test.vcproj \ vsprojects/frag_unittest/frag_unittest.vcproj \ vsprojects/markidle_unittest/markidle_unittest.vcproj \ @@ -2358,14 +2396,14 @@ vsprojects/realloc_unittest/realloc_unittest.vcproj \ vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj \ vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj \ - $(am__append_45) + $(am__append_46) # TESTS_ENVIRONMENT sets environment variables for when you run unittest. # We always get "srcdir" set for free. # We'll add to this later, on a library-by-library basis. -TESTS_ENVIRONMENT = $(am__append_15) $(am__append_44) +TESTS_ENVIRONMENT = $(am__append_16) $(am__append_45) # All script tests should be added here -noinst_SCRIPTS = $(am__append_18) $(am__append_30) $(am__append_40) \ - $(am__append_47) $(am__append_50) $(am__append_65) +noinst_SCRIPTS = $(am__append_19) $(am__append_31) $(am__append_41) \ + $(am__append_48) $(am__append_51) $(am__append_66) # This is my own var, used for extra libraries I make that I need installed EXTRA_INSTALL = @@ -2384,6 +2422,7 @@ $(LOGGING_INCLUDES) SYSINFO_INCLUDES = src/base/sysinfo.h \ + src/getenv_safe.h \ src/base/logging.h \ src/base/commandlineflags.h \ src/base/cycleclock.h \ @@ -2393,7 +2432,7 @@ libsysinfo_la_SOURCES = src/base/sysinfo.cc \ $(SYSINFO_INCLUDES) -libsysinfo_la_LIBADD = $(NANOSLEEP_LIBS) $(am__append_9) +libsysinfo_la_LIBADD = $(NANOSLEEP_LIBS) $(am__append_10) # For MinGW, we use also have to use libwindows Luckily, we need the # windows.a library in exactly the same place we need spinlock.a @@ -2410,6 +2449,7 @@ @MINGW_TRUE@libwindows_la_SOURCES = $(WINDOWS_INCLUDES) \ @MINGW_TRUE@ src/windows/port.cc \ +@MINGW_TRUE@ src/windows/system-alloc.cc \ @MINGW_TRUE@ src/windows/ia32_modrm_map.cc \ @MINGW_TRUE@ src/windows/ia32_opcode_map.cc \ @MINGW_TRUE@ src/windows/mini_disassembler.cc \ @@ -2438,7 +2478,9 @@ @MINGW_TRUE@ src/base/atomicops-internals-linuxppc.h \ @MINGW_TRUE@ src/base/atomicops-internals-arm-generic.h \ @MINGW_TRUE@ src/base/atomicops-internals-arm-v6plus.h \ +@MINGW_TRUE@ src/base/atomicops-internals-mips.h \ @MINGW_TRUE@ src/base/atomicops-internals-windows.h \ +@MINGW_TRUE@ src/base/atomicops-internals-gcc.h \ @MINGW_TRUE@ src/base/atomicops-internals-x86.h @MINGW_FALSE@libspinlock_la_SOURCES = src/base/spinlock.cc \ @@ -2461,9 +2503,10 @@ # patch_functions.cc #includes tcmalloc.cc, so no need to link it in. @MINGW_TRUE@TCMALLOC_CC = -@MINGW_FALSE@MAYBE_THREADS_CC = src/maybe_threads.cc +@HAVE_PTHREAD_DESPITE_ASKING_FOR_FALSE@@MINGW_TRUE@MAYBE_THREADS_CC = # windows has its own system for threads and system memory allocation. -@MINGW_TRUE@MAYBE_THREADS_CC = +@HAVE_PTHREAD_DESPITE_ASKING_FOR_TRUE@@MINGW_TRUE@MAYBE_THREADS_CC = src/maybe_threads.cc +@MINGW_FALSE@MAYBE_THREADS_CC = src/maybe_threads.cc @MINGW_FALSE@SYSTEM_ALLOC_CC = src/system-alloc.cc @MINGW_TRUE@SYSTEM_ALLOC_CC = @MINGW_FALSE@libspinlock_la_LIBADD = $(NANOSLEEP_LIBS) @@ -2501,13 +2544,16 @@ ### ------- stack trace ### The header files we use. We divide into categories based on directory -@WITH_STACK_TRACE_TRUE@S_STACKTRACE_INCLUDES = src/stacktrace_config.h \ +@WITH_STACK_TRACE_TRUE@S_STACKTRACE_INCLUDES = src/stacktrace_impl_setup-inl.h \ @WITH_STACK_TRACE_TRUE@ src/stacktrace_generic-inl.h \ @WITH_STACK_TRACE_TRUE@ src/stacktrace_libunwind-inl.h \ @WITH_STACK_TRACE_TRUE@ src/stacktrace_arm-inl.h \ @WITH_STACK_TRACE_TRUE@ src/stacktrace_powerpc-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_powerpc-darwin-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_powerpc-linux-inl.h \ @WITH_STACK_TRACE_TRUE@ src/stacktrace_x86-inl.h \ @WITH_STACK_TRACE_TRUE@ src/stacktrace_win32-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_instrument-inl.h \ @WITH_STACK_TRACE_TRUE@ src/base/elf_mem_image.h \ @WITH_STACK_TRACE_TRUE@ src/base/vdso_support.h @@ -2624,7 +2670,7 @@ src/tests/testutil.h src/tests/testutil.cc \ $(TCMALLOC_UNITTEST_INCLUDES) -tcmalloc_minimal_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_minimal_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) tcmalloc_minimal_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) # We want libtcmalloc last on the link line, but due to a bug in # libtool involving convenience libs, they need to come last on the @@ -2637,11 +2683,11 @@ liblogging.la $(PTHREAD_LIBS) tcmalloc_minimal_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc -tcmalloc_minimal_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_minimal_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) tcmalloc_minimal_large_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) tcmalloc_minimal_large_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) tcmalloc_minimal_large_heap_fragmentation_unittest_SOURCES = src/tests/large_heap_fragmentation_unittest.cc -tcmalloc_minimal_large_heap_fragmentation_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_minimal_large_heap_fragmentation_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) tcmalloc_minimal_large_heap_fragmentation_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) tcmalloc_minimal_large_heap_fragmentation_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) @ENABLE_STATIC_FALSE@@MINGW_FALSE@maybe_threads_unittest_sh_SOURCES = src/tests/maybe_threads_unittest.sh @@ -2650,13 +2696,13 @@ $(LOGGING_INCLUDES) addressmap_unittest_SOURCES = src/tests/addressmap_unittest.cc \ - $(ADDRESSMAP_UNITTEST_INCLUDES) $(am__append_19) + $(ADDRESSMAP_UNITTEST_INCLUDES) $(am__append_20) addressmap_unittest_CXXFLAGS = -g $(AM_CXXFLAGS) addressmap_unittest_LDADD = liblogging.la @MINGW_FALSE@system_alloc_unittest_SOURCES = src/config_for_unittests.h \ @MINGW_FALSE@ src/tests/system-alloc_unittest.cc -@MINGW_FALSE@system_alloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@MINGW_FALSE@system_alloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) @MINGW_FALSE@system_alloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) @MINGW_FALSE@system_alloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) packed_cache_test_SOURCES = src/tests/packed-cache_test.cc @@ -2664,14 +2710,14 @@ packed_cache_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) packed_cache_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) frag_unittest_SOURCES = src/tests/frag_unittest.cc src/config_for_unittests.h -frag_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +frag_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) frag_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) frag_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) markidle_unittest_SOURCES = src/tests/markidle_unittest.cc \ src/config_for_unittests.h \ src/tests/testutil.h src/tests/testutil.cc -markidle_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +markidle_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) markidle_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) markidle_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) current_allocated_bytes_test_SOURCES = src/tests/current_allocated_bytes_test.cc \ @@ -2705,15 +2751,15 @@ @ENABLE_STATIC_FALSE@@MINGW_FALSE@malloc_extension_c_test_CFLAGS = \ @ENABLE_STATIC_FALSE@@MINGW_FALSE@ $(PTHREAD_CFLAGS) \ @ENABLE_STATIC_FALSE@@MINGW_FALSE@ $(AM_CFLAGS) \ -@ENABLE_STATIC_FALSE@@MINGW_FALSE@ $(am__append_22) +@ENABLE_STATIC_FALSE@@MINGW_FALSE@ $(am__append_23) @ENABLE_STATIC_FALSE@@MINGW_FALSE@malloc_extension_c_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) -@ENABLE_STATIC_FALSE@@MINGW_FALSE@malloc_extension_c_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +@ENABLE_STATIC_FALSE@@MINGW_FALSE@malloc_extension_c_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) -lstdc++ @MINGW_FALSE@@OSX_FALSE@memalign_unittest_SOURCES = src/tests/memalign_unittest.cc \ @MINGW_FALSE@@OSX_FALSE@ src/tcmalloc.h \ @MINGW_FALSE@@OSX_FALSE@ src/config_for_unittests.h \ @MINGW_FALSE@@OSX_FALSE@ src/tests/testutil.h src/tests/testutil.cc -@MINGW_FALSE@@OSX_FALSE@memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@MINGW_FALSE@@OSX_FALSE@memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) @MINGW_FALSE@@OSX_FALSE@memalign_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) @MINGW_FALSE@@OSX_FALSE@memalign_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) page_heap_test_SOURCES = src/tests/page_heap_test.cc \ @@ -2730,14 +2776,14 @@ src/base/logging.h \ src/pagemap.h -pagemap_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +pagemap_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) pagemap_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) pagemap_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) realloc_unittest_SOURCES = src/tests/realloc_unittest.cc \ src/config_for_unittests.h \ src/base/logging.h -realloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +realloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) realloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) realloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) stack_trace_table_test_SOURCES = src/tests/stack_trace_table_test.cc \ @@ -2750,7 +2796,7 @@ src/config_for_unittests.h \ src/tests/testutil.h src/tests/testutil.cc -thread_dealloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +thread_dealloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) thread_dealloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) @WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_SOURCES = src/debugallocation.cc \ @@ -2784,7 +2830,7 @@ @WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS) @WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_sh_SOURCES = src/tests/debugallocation_test.sh @WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_SOURCES = src/tests/debugallocation_test.cc -@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) @WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) @WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS) @@ -2802,7 +2848,8 @@ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/stl_allocator.h \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/sysinfo.h \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/thread_lister.h \ -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/heap-profile-table.h +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/heap-profile-table.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/heap-profile-stats.h @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@SG_TCMALLOC_INCLUDES = src/gperftools/heap-profiler.h \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/gperftools/heap-checker.h @@ -2822,17 +2869,17 @@ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(PTHREAD_CFLAGS) -DNDEBUG \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(AM_CXXFLAGS) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(NO_EXCEPTIONS) \ -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_36) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_37) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_LDFLAGS = $(PTHREAD_CFLAGS) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_LIBADD = libstacktrace.la $(PTHREAD_LIBS) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_SOURCES = \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_CC) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_INCLUDES) \ -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_35) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_36) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_CXXFLAGS = \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(PTHREAD_CFLAGS) -DNDEBUG \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(AM_CXXFLAGS) \ -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_37) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_38) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_LDFLAGS = $(PTHREAD_CFLAGS) -version-info @TCMALLOC_SO_VERSION@ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_LIBADD = libtcmalloc_internal.la $(PTHREAD_LIBS) @WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@HEAP_CHECKER_SOURCES = @@ -2856,7 +2903,7 @@ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/tests/testutil.h src/tests/testutil.cc \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_UNITTEST_INCLUDES) -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) # We want libtcmalloc last on the link line, but due to a bug in # libtool involving convenience libs, they need to come last on the @@ -2878,7 +2925,7 @@ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/tests/testutil.h src/tests/testutil.cc \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_UNITTEST_INCLUDES) -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_cflags = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_cflags = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_lflags = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) @WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_ladd = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \ @WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ liblogging.la $(PTHREAD_LIBS) @@ -2898,11 +2945,11 @@ @OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_LDFLAGS = $(tcmalloc_both_unittest_lflags) @OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_LDADD = $(tcmalloc_both_unittest_ladd) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_heap_fragmentation_unittest_SOURCES = src/tests/large_heap_fragmentation_unittest.cc -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_heap_fragmentation_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_heap_fragmentation_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_heap_fragmentation_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_heap_fragmentation_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@raw_printer_test_SOURCES = src/tests/raw_printer_test.cc @@ -2933,7 +2980,7 @@ @WITH_HEAP_PROFILER_TRUE@heap_profiler_unittest_SOURCES = src/tests/heap-profiler_unittest.cc \ @WITH_HEAP_PROFILER_TRUE@ $(HEAP_PROFILER_UNITTEST_INCLUDES) -@WITH_HEAP_PROFILER_TRUE@heap_profiler_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_TRUE@heap_profiler_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) @WITH_HEAP_PROFILER_TRUE@heap_profiler_unittest_LDFLAGS = -g $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) @WITH_HEAP_PROFILER_TRUE@heap_profiler_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) @WITH_HEAP_PROFILER_TRUE@simple_compat_test_SOURCES = src/tests/simple_compat_test.cc \ @@ -2953,7 +3000,7 @@ @WITH_HEAP_CHECKER_TRUE@heap_checker_unittest_SOURCES = src/tests/heap-checker_unittest.cc \ @WITH_HEAP_CHECKER_TRUE@ $(HEAP_CHECKER_UNITTEST_INCLUDES) -@WITH_HEAP_CHECKER_TRUE@heap_checker_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_CHECKER_TRUE@heap_checker_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) @WITH_HEAP_CHECKER_TRUE@heap_checker_unittest_LDFLAGS = -g $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) # We want libtcmalloc last on the link line, but due to a bug in # libtool involving convenience libs, they need to come last on the @@ -3109,6 +3156,7 @@ $(SCRIPTS) libtool \ src/windows/get_mangled_names.cc src/windows/override_functions.cc \ src/windows/config.h src/windows/gperftools/tcmalloc.h \ + doc/pprof.see_also src/windows/TODO \ $(WINDOWS_PROJECTS) \ src/solaris/libstdc++.la @@ -3118,7 +3166,7 @@ .SUFFIXES: .c .cc .lo .log .o .obj .test .test$(EXEEXT) .trs am--refresh: Makefile @: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -3145,20 +3193,20 @@ $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck -$(top_srcdir)/configure: $(am__configure_deps) +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) -$(ACLOCAL_M4): $(am__aclocal_m4_deps) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): src/config.h: src/stamp-h1 - @if test ! -f $@; then rm -f src/stamp-h1; else :; fi - @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) src/stamp-h1; else :; fi + @test -f $@ || rm -f src/stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) src/stamp-h1 src/stamp-h1: $(top_srcdir)/src/config.h.in $(top_builddir)/config.status @rm -f src/stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status src/config.h -$(top_srcdir)/src/config.h.in: $(am__configure_deps) +$(top_srcdir)/src/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f src/stamp-h1 touch $@ @@ -3733,6 +3781,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stacktrace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stacktrace_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysinfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system-alloc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Po@am__quote@ @@ -3760,14 +3809,14 @@ @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -4273,6 +4322,13 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o port.lo `test -f 'src/windows/port.cc' || echo '$(srcdir)/'`src/windows/port.cc +system-alloc.lo: src/windows/system-alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT system-alloc.lo -MD -MP -MF $(DEPDIR)/system-alloc.Tpo -c -o system-alloc.lo `test -f 'src/windows/system-alloc.cc' || echo '$(srcdir)/'`src/windows/system-alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/system-alloc.Tpo $(DEPDIR)/system-alloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/windows/system-alloc.cc' object='system-alloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o system-alloc.lo `test -f 'src/windows/system-alloc.cc' || echo '$(srcdir)/'`src/windows/system-alloc.cc + ia32_modrm_map.lo: src/windows/ia32_modrm_map.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ia32_modrm_map.lo -MD -MP -MF $(DEPDIR)/ia32_modrm_map.Tpo -c -o ia32_modrm_map.lo `test -f 'src/windows/ia32_modrm_map.cc' || echo '$(srcdir)/'`src/windows/ia32_modrm_map.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ia32_modrm_map.Tpo $(DEPDIR)/ia32_modrm_map.Plo @@ -6020,10 +6076,16 @@ $(am__post_remove_distdir) dist-tarZ: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir @@ -6064,9 +6126,10 @@ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ - && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + && ../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ diff -Nru google-perftools-2.1/missing google-perftools-2.2.1/missing --- google-perftools-2.1/missing 2013-07-30 11:12:29.000000000 +0200 +++ google-perftools-2.2.1/missing 2014-06-22 00:52:50.000000000 +0200 @@ -1,7 +1,7 @@ #! /bin/sh # Common wrapper for a few potentially missing GNU programs. -scriptversion=2012-06-26.16; # UTC +scriptversion=2013-10-28.13; # UTC # Copyright (C) 1996-2013 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. @@ -160,7 +160,7 @@ ;; autom4te*) echo "You might have modified some maintainer files that require" - echo "the 'automa4te' program to be rebuilt." + echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) diff -Nru google-perftools-2.1/NEWS google-perftools-2.2.1/NEWS --- google-perftools-2.1/NEWS 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/NEWS 2014-06-22 00:52:29.000000000 +0200 @@ -1,3 +1,104 @@ +== 21 Jun 2014 == + +gperftools 2.2.1 is out! + +Here's list of fixes: + +* issue-626 was closed. Which fixes initialization statically linked + tcmalloc. + +* issue 628 was closed. It adds missing header file into source + tarball. This fixes for compilation on PPC Linux. + +== 3 May 2014 == + +gperftools 2.2 is out! + +Here are notable changes since 2.2rc: + +* issue 620 (crash on windows when c runtime dll is reloaded) was + fixed + +== 19 Apr 2014 == + +gperftools 2.2rc is out! + +Here are notable changes since 2.1: + +* a number of fixes for a number compilers and platforms. Notably + Visual Studio 2013, recent mingw with c++ threads and some OSX + fixes. + +* we now have mips and mips64 support! (courtesy of Jovan Zelincevic, + Jean Lee, user xiaoyur347 and others) + +* we now have aarch64 (aka arm64) support! (contributed by Riku + Voipio) + +* there's now support for ppc64-le (by Raphael Moreira Zinsly and + Adhemerval Zanella) + +* there's now some support of uclibc (contributed by user xiaoyur347) + +* google/ headers will now give you deprecation warning. They are + deprecated since 2.0 + +* there's now new api: tc_malloc_skip_new_handler (ported from chromium + fork) + +* issue-557: added support for dumping heap profile via signal (by + Jean Lee) + +* issue-567: Petr Hosek contributed SysAllocator support for windows + +* Joonsoo Kim contributed several speedups for central freelist code + +* TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES environment variable now works + +* configure scripts are now using AM_MAINTAINER_MODE. It'll only + affect folks who modify source from .tar.gz and want automake to + automatically rebuild Makefile-s. See automake documentation for + that. + +* issue-586: detect main executable even if PIE is active (based on + patch by user themastermind1). Notably, it fixes profiler use with + ruby. + +* there is now support for switching backtrace capturing method at + runtime (via TCMALLOC_STACKTRACE_METHOD and + TCMALLOC_STACKTRACE_METHOD_VERBOSE environment variables) + +* there is new backtrace capturing method using -finstrument-functions + prologues contributed by user xiaoyur347 + +* few cases of crashes/deadlocks in profiler were addressed. See + (famous) issue-66, issue-547 and issue-579. + +* issue-464 (memory corruption in debugalloc's realloc after + memallign) is now fixed + +* tcmalloc is now able to release memory back to OS on windows + (issue-489). The code was ported from chromium fork (by a number of + authors). + +* Together with issue-489 we ported chromium's "aggressive decommit" + mode. In this mode (settable via malloc extension and via + environment variable TCMALLOC_AGGRESSIVE_DECOMMIT), free pages are + returned back to OS immediately. + +* MallocExtension::instance() is now faster (based on patch by + Adhemerval Zanella) + +* issue-610 (hangs on windows in multibyte locales) is now fixed + +The following people helped with ideas or patches (based on git log, +some contributions purely in bugtracker might be missing): Andrew +C. Morrow, yurivict, Wang YanQing, Thomas Klausner, +davide.italiano@10gen.com, Dai MIKURUBE, Joon-Sung Um, Jovan +Zelincevic, Jean Lee, Petr Hosek, Ben Avison, drussel, Joonsoo Kim, +Hannes Weisbach, xiaoyur347, Riku Voipio, Adhemerval Zanella, Raphael +Moreira Zinsly + == 30 July 2013 == gperftools 2.1 is out! diff -Nru google-perftools-2.1/src/addressmap-inl.h google-perftools-2.2.1/src/addressmap-inl.h --- google-perftools-2.1/src/addressmap-inl.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/addressmap-inl.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/base/atomicops.h google-perftools-2.2.1/src/base/atomicops.h --- google-perftools-2.1/src/base/atomicops.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/atomicops.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2006, Google Inc. * All rights reserved. * @@ -97,9 +98,13 @@ // ------------------------------------------------------------------------ #include "base/arm_instruction_set_select.h" - -// TODO(csilvers): match piii, not just __i386. Also, match k8 -#if defined(__MACH__) && defined(__APPLE__) +#define GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) + +#if defined(TCMALLOC_PREFER_GCC_ATOMICS) && defined(__GNUC__) && GCC_VERSION >= 40700 +#include "base/atomicops-internals-gcc.h" +#elif defined(__MACH__) && defined(__APPLE__) #include "base/atomicops-internals-macosx.h" #elif defined(__GNUC__) && defined(ARMV6) #include "base/atomicops-internals-arm-v6plus.h" @@ -111,12 +116,12 @@ #include "base/atomicops-internals-windows.h" #elif defined(__linux__) && defined(__PPC__) #include "base/atomicops-internals-linuxppc.h" +#elif defined(__GNUC__) && defined(__mips__) +#include "base/atomicops-internals-mips.h" +#elif defined(__GNUC__) && GCC_VERSION >= 40700 +#include "base/atomicops-internals-gcc.h" #else -// Assume x86 for now. If you need to support a new architecture and -// don't know how to implement atomic ops, you can probably get away -// with using pthreads, since atomicops is only used by spinlock.h/cc -//#error You need to implement atomic operations for this architecture -#include "base/atomicops-internals-x86.h" +#error You need to implement atomic operations for this architecture #endif // Signed type that can hold a pointer and supports the atomic ops below, as @@ -171,21 +176,6 @@ reinterpret_cast(ptr), new_value); } -// Atomically increment *ptr by "increment". Returns the new value of -// *ptr with the increment applied. This routine implies no memory -// barriers. -inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr, - AtomicWord increment) { - return NoBarrier_AtomicIncrement( - reinterpret_cast(ptr), increment); -} - -inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr, - AtomicWord increment) { - return Barrier_AtomicIncrement( - reinterpret_cast(ptr), increment); -} - inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, AtomicWord old_value, AtomicWord new_value) { @@ -263,9 +253,6 @@ Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); Atomic32 Release_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); -Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment); -Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment); Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value, Atomic32 new_value); @@ -286,8 +273,6 @@ Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value); Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value); Atomic64 Release_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value); -Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); -Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, Atomic64 old_value, diff -Nru google-perftools-2.1/src/base/atomicops-internals-arm-generic.h google-perftools-2.2.1/src/base/atomicops-internals-arm-generic.h --- google-perftools-2.1/src/base/atomicops-internals-arm-generic.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/atomicops-internals-arm-generic.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2003, Google Inc. // All rights reserved. // @@ -32,7 +33,7 @@ // // This file is an internal atomic implementation, use base/atomicops.h instead. // -// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears. +// LinuxKernelCmpxchg is from Google Gears. #ifndef BASE_ATOMICOPS_INTERNALS_ARM_GENERIC_H_ #define BASE_ATOMICOPS_INTERNALS_ARM_GENERIC_H_ @@ -101,26 +102,6 @@ return NoBarrier_AtomicExchange(ptr, new_value); } -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - for (;;) { - // Atomic exchange the old value with an incremented one. - Atomic32 old_value = *ptr; - Atomic32 new_value = old_value + increment; - if (pLinuxKernelCmpxchg(old_value, new_value, - const_cast(ptr)) == 0) { - // The exchange took place as expected. - return new_value; - } - // Otherwise, *ptr changed mid-loop and we need to retry. - } -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return Barrier_AtomicIncrement(ptr, increment); -} - inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value, Atomic32 new_value) { @@ -200,18 +181,6 @@ return NoBarrier_AtomicExchange(ptr, new_value); } -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - NotImplementedFatalError("NoBarrier_AtomicIncrement"); - return 0; -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - NotImplementedFatalError("Barrier_AtomicIncrement"); - return 0; -} - inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { NotImplementedFatalError("NoBarrier_Store"); } diff -Nru google-perftools-2.1/src/base/atomicops-internals-arm-v6plus.h google-perftools-2.2.1/src/base/atomicops-internals-arm-v6plus.h --- google-perftools-2.1/src/base/atomicops-internals-arm-v6plus.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/atomicops-internals-arm-v6plus.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2011, Google Inc. // All rights reserved. // @@ -116,39 +117,6 @@ return NoBarrier_AtomicExchange(ptr, new_value); } -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 tmp, res; - __asm__ __volatile__( - "1:\n" - "ldrex %1, [%2]\n" - "add %1, %1, %3\n" - "strex %0, %1, [%2]\n" - "teq %0, #0\n" - "bne 1b" - : "=&r" (tmp), "=&r"(res) - : "r" (ptr), "r"(increment) - : "cc", "memory"); - return res; -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 tmp, res; - __asm__ __volatile__( - "1:\n" - "ldrex %1, [%2]\n" - "add %1, %1, %3\n" - "dmb\n" - "strex %0, %1, [%2]\n" - "teq %0, #0\n" - "bne 1b" - : "=&r" (tmp), "=&r"(res) - : "r" (ptr), "r"(increment) - : "cc", "memory"); - return res; -} - inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value, Atomic32 new_value) { @@ -251,43 +219,6 @@ return NoBarrier_AtomicExchange(ptr, new_value); } -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - int store_failed; - Atomic64 res; - __asm__ __volatile__( - "1:\n" - "ldrexd %1, [%2]\n" - "adds %Q1, %Q1, %Q3\n" - "adc %R1, %R1, %R3\n" - "strexd %0, %1, [%2]\n" - "teq %0, #0\n" - "bne 1b" - : "=&r" (store_failed), "=&r"(res) - : "r" (ptr), "r"(increment) - : "cc", "memory"); - return res; -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - int store_failed; - Atomic64 res; - __asm__ __volatile__( - "1:\n" - "ldrexd %1, [%2]\n" - "adds %Q1, %Q1, %Q3\n" - "adc %R1, %R1, %R3\n" - "dmb\n" - "strexd %0, %1, [%2]\n" - "teq %0, #0\n" - "bne 1b" - : "=&r" (store_failed), "=&r"(res) - : "r" (ptr), "r"(increment) - : "cc", "memory"); - return res; -} - inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { int store_failed; Atomic64 dummy; @@ -346,18 +277,6 @@ return 0; } -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - NotImplementedFatalError("NoBarrier_AtomicIncrement"); - return 0; -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - NotImplementedFatalError("Barrier_AtomicIncrement"); - return 0; -} - inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { NotImplementedFatalError("NoBarrier_Store"); } diff -Nru google-perftools-2.1/src/base/atomicops-internals-gcc.h google-perftools-2.2.1/src/base/atomicops-internals-gcc.h --- google-perftools-2.1/src/base/atomicops-internals-gcc.h 1970-01-01 01:00:00.000000000 +0100 +++ google-perftools-2.2.1/src/base/atomicops-internals-gcc.h 2014-02-22 21:25:25.000000000 +0100 @@ -0,0 +1,203 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2014, Linaro +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// --- +// +// Author: Riku Voipio, riku.voipio@linaro.org +// +// atomic primitives implemented with gcc atomic intrinsics: +// http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html +// + +#ifndef BASE_ATOMICOPS_INTERNALS_GCC_GENERIC_H_ +#define BASE_ATOMICOPS_INTERNALS_GCC_GENERIC_H_ + +#include +#include +#include "base/basictypes.h" + +typedef int32_t Atomic32; + +namespace base { +namespace subtle { + +typedef int64_t Atomic64; + +inline void MemoryBarrier() { + __sync_synchronize(); +} + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value = old_value; + __atomic_compare_exchange_n(ptr, &prev_value, new_value, + 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); + return prev_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + return __atomic_exchange_n(const_cast(ptr), new_value, __ATOMIC_RELAXED); +} + +inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + return __atomic_exchange_n(const_cast(ptr), new_value, __ATOMIC_ACQUIRE); +} + +inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + return __atomic_exchange_n(const_cast(ptr), new_value, __ATOMIC_RELEASE); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value = old_value; + __atomic_compare_exchange_n(ptr, &prev_value, new_value, + 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); + return prev_value; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value = old_value; + __atomic_compare_exchange_n(ptr, &prev_value, new_value, + 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED); + return prev_value; +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +// 64-bit versions + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value = old_value; + __atomic_compare_exchange_n(ptr, &prev_value, new_value, + 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); + return prev_value; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + return __atomic_exchange_n(const_cast(ptr), new_value, __ATOMIC_RELAXED); +} + +inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + return __atomic_exchange_n(const_cast(ptr), new_value, __ATOMIC_ACQUIRE); +} + +inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + return __atomic_exchange_n(const_cast(ptr), new_value, __ATOMIC_RELEASE); +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value = old_value; + __atomic_compare_exchange_n(ptr, &prev_value, new_value, + 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); + return prev_value; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value = old_value; + __atomic_compare_exchange_n(ptr, &prev_value, new_value, + 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED); + return prev_value; +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + MemoryBarrier(); + return *ptr; +} + +} // namespace base::subtle +} // namespace base + +#endif // BASE_ATOMICOPS_INTERNALS_GCC_GENERIC_H_ diff -Nru google-perftools-2.1/src/base/atomicops-internals-linuxppc.h google-perftools-2.2.1/src/base/atomicops-internals-linuxppc.h --- google-perftools-2.1/src/base/atomicops-internals-linuxppc.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/atomicops-internals-linuxppc.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2008, Google Inc. * All rights reserved. * @@ -183,16 +184,6 @@ return old_value; } -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr, - Atomic32 increment) { - return OSAtomicAdd32(increment, const_cast(ptr)); -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr, - Atomic32 increment) { - return OSAtomicAdd32Barrier(increment, const_cast(ptr)); -} - inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr, Atomic32 old_value, Atomic32 new_value) { @@ -334,16 +325,6 @@ return old_value; } -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr, - Atomic64 increment) { - return OSAtomicAdd64(increment, const_cast(ptr)); -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr, - Atomic64 increment) { - return OSAtomicAdd64Barrier(increment, const_cast(ptr)); -} - inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr, Atomic64 old_value, Atomic64 new_value) { diff -Nru google-perftools-2.1/src/base/atomicops-internals-macosx.h google-perftools-2.2.1/src/base/atomicops-internals-macosx.h --- google-perftools-2.1/src/base/atomicops-internals-macosx.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/atomicops-internals-macosx.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2006, Google Inc. * All rights reserved. * @@ -147,16 +148,6 @@ return Acquire_AtomicExchange(ptr, new_value); } -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr, - Atomic32 increment) { - return OSAtomicAdd32(increment, const_cast(ptr)); -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr, - Atomic32 increment) { - return OSAtomicAdd32Barrier(increment, const_cast(ptr)); -} - inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr, Atomic32 old_value, Atomic32 new_value) { @@ -247,16 +238,6 @@ return Acquire_AtomicExchange(ptr, new_value); } -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr, - Atomic64 increment) { - return OSAtomicAdd64(increment, const_cast(ptr)); -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr, - Atomic64 increment) { - return OSAtomicAdd64Barrier(increment, const_cast(ptr)); -} - inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr, Atomic64 old_value, Atomic64 new_value) { diff -Nru google-perftools-2.1/src/base/atomicops-internals-mips.h google-perftools-2.2.1/src/base/atomicops-internals-mips.h --- google-perftools-2.1/src/base/atomicops-internals-mips.h 1970-01-01 01:00:00.000000000 +0100 +++ google-perftools-2.2.1/src/base/atomicops-internals-mips.h 2014-02-22 21:25:25.000000000 +0100 @@ -0,0 +1,323 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2013, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Author: Jovan Zelincevic +// based on atomicops-internals by Sanjay Ghemawat + +// This file is an internal atomic implementation, use base/atomicops.h instead. +// +// This code implements MIPS atomics. + +#ifndef BASE_ATOMICOPS_INTERNALS_MIPS_H_ +#define BASE_ATOMICOPS_INTERNALS_MIPS_H_ + +#if (_MIPS_ISA == _MIPS_ISA_MIPS64) +#define BASE_HAS_ATOMIC64 1 +#endif + +typedef int32_t Atomic32; + +namespace base { +namespace subtle { + +// Atomically execute: +// result = *ptr; +// if (*ptr == old_value) +// *ptr = new_value; +// return result; +// +// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". +// Always return the old value of "*ptr" +// +// This routine implies no memory barriers. +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) +{ + Atomic32 prev, tmp; + __asm__ volatile( + ".set push \n" + ".set noreorder \n" + + "1: \n" + "ll %0, %5 \n" // prev = *ptr + "bne %0, %3, 2f \n" // if (prev != old_value) goto 2 + " move %2, %4 \n" // tmp = new_value + "sc %2, %1 \n" // *ptr = tmp (with atomic check) + "beqz %2, 1b \n" // start again on atomic error + " nop \n" // delay slot nop + "2: \n" + + ".set pop \n" + : "=&r" (prev), "=m" (*ptr), + "=&r" (tmp) + : "Ir" (old_value), "r" (new_value), + "m" (*ptr) + : "memory" + ); + return prev; +} + +// Atomically store new_value into *ptr, returning the previous value held in +// *ptr. This routine implies no memory barriers. +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) +{ + Atomic32 temp, old; + __asm__ volatile( + ".set push \n" + ".set noreorder \n" + + "1: \n" + "ll %1, %2 \n" // old = *ptr + "move %0, %3 \n" // temp = new_value + "sc %0, %2 \n" // *ptr = temp (with atomic check) + "beqz %0, 1b \n" // start again on atomic error + " nop \n" // delay slot nop + + ".set pop \n" + : "=&r" (temp), "=&r" (old), + "=m" (*ptr) + : "r" (new_value), "m" (*ptr) + : "memory" + ); + return old; +} + +inline void MemoryBarrier() +{ + __asm__ volatile("sync" : : : "memory"); +} + +// "Acquire" operations +// ensure that no later memory access can be reordered ahead of the operation. +// "Release" operations ensure that no previous memory access can be reordered +// after the operation. "Barrier" operations have both "Acquire" and "Release" +// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory +// access. +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) +{ + Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + MemoryBarrier(); + return res; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) +{ + MemoryBarrier(); + Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + return res; +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) +{ + *ptr = value; +} + +inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) +{ + Atomic32 old_value = NoBarrier_AtomicExchange(ptr, new_value); + MemoryBarrier(); + return old_value; +} + +inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) +{ + MemoryBarrier(); + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) +{ + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) +{ + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) +{ + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) +{ + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) +{ + MemoryBarrier(); + return *ptr; +} + +#if (_MIPS_ISA == _MIPS_ISA_MIPS64) || (_MIPS_SIM == _MIPS_SIM_ABI64) + +typedef int64_t Atomic64; + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) +{ + Atomic64 prev, tmp; + __asm__ volatile( + ".set push \n" + ".set noreorder \n" + + "1: \n" + "lld %0, %5 \n" // prev = *ptr + "bne %0, %3, 2f \n" // if (prev != old_value) goto 2 + " move %2, %4 \n" // tmp = new_value + "scd %2, %1 \n" // *ptr = tmp (with atomic check) + "beqz %2, 1b \n" // start again on atomic error + " nop \n" // delay slot nop + "2: \n" + + ".set pop \n" + : "=&r" (prev), "=m" (*ptr), + "=&r" (tmp) + : "Ir" (old_value), "r" (new_value), + "m" (*ptr) + : "memory" + ); + return prev; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) +{ + Atomic64 temp, old; + __asm__ volatile( + ".set push \n" + ".set noreorder \n" + + "1: \n" + "lld %1, %2 \n" // old = *ptr + "move %0, %3 \n" // temp = new_value + "scd %0, %2 \n" // *ptr = temp (with atomic check) + "beqz %0, 1b \n" // start again on atomic error + " nop \n" // delay slot nop + + ".set pop \n" + : "=&r" (temp), "=&r" (old), + "=m" (*ptr) + : "r" (new_value), "m" (*ptr) + : "memory" + ); + return old; +} + +inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) +{ + Atomic64 old_value = NoBarrier_AtomicExchange(ptr, new_value); + MemoryBarrier(); + return old_value; +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) +{ + Atomic64 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + MemoryBarrier(); + return res; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) +{ + MemoryBarrier(); + Atomic64 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + return res; +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) +{ + *ptr = value; +} + +inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) +{ + MemoryBarrier(); + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) +{ + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) +{ + MemoryBarrier(); + *ptr = value; +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) +{ + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) +{ + Atomic64 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) +{ + MemoryBarrier(); + return *ptr; +} + +#endif + +} // namespace base::subtle +} // namespace base + +#endif // BASE_ATOMICOPS_INTERNALS_MIPS_H_ diff -Nru google-perftools-2.1/src/base/atomicops-internals-windows.h google-perftools-2.2.1/src/base/atomicops-internals-windows.h --- google-perftools-2.1/src/base/atomicops-internals-windows.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/atomicops-internals-windows.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2006, Google Inc. * All rights reserved. * @@ -149,18 +150,6 @@ return NoBarrier_AtomicExchange(ptr, new_value); } -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return FastInterlockedExchangeAdd( - reinterpret_cast(ptr), - static_cast(increment)) + increment; -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return Barrier_AtomicIncrement(ptr, increment); -} - } // namespace base::subtle } // namespace base @@ -305,18 +294,6 @@ return reinterpret_cast(result); } -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - return FastInterlockedExchangeAdd64( - reinterpret_cast(ptr), - static_cast(increment)) + increment; -} - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - return Barrier_AtomicIncrement(ptr, increment); -} - inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { *ptr = value; } @@ -405,45 +382,6 @@ return 0; #endif } - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { -#if 0 // Not implemented - Atomic64 temp = increment; - __asm__ __volatile__( - "0:\n\t" - "movl (%3), %%ebx\n\t" // Move 64-bit increment into - "movl 4(%3), %%ecx\n\t" // ecx:ebx - "movl (%2), %%eax\n\t" // Read contents of ptr into - "movl 4(%2), %%edx\n\t" // edx:eax - "add %%eax, %%ebx\n\t" // sum => ecx:ebx - "adc %%edx, %%ecx\n\t" // edx:eax still has old *ptr - "lock; cmpxchg8b (%2)\n\t"// Attempt cmpxchg; if *ptr - "jnz 0b\n\t" // is no longer edx:eax, loop - : "=A"(temp), "+m"(*ptr) - : "D" (ptr), "S" (&increment) - : "memory", "%ebx", "%ecx"); - // temp now contains the previous value of *ptr - return temp + increment; -#else - NotImplementedFatalError("NoBarrier_AtomicIncrement"); - return 0; -#endif -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { -#if 0 // Not implemented - Atomic64 new_val = NoBarrier_AtomicIncrement(ptr, increment); - if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { - __asm__ __volatile__("lfence" : : : "memory"); - } - return new_val; -#else - NotImplementedFatalError("Barrier_AtomicIncrement"); - return 0; -#endif -} inline void NoBarrier_Store(volatile Atomic64* ptrValue, Atomic64 value) { diff -Nru google-perftools-2.1/src/base/atomicops-internals-x86.cc google-perftools-2.2.1/src/base/atomicops-internals-x86.cc --- google-perftools-2.1/src/base/atomicops-internals-x86.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/atomicops-internals-x86.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2007, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/base/atomicops-internals-x86.h google-perftools-2.2.1/src/base/atomicops-internals-x86.h --- google-perftools-2.1/src/base/atomicops-internals-x86.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/atomicops-internals-x86.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2006, Google Inc. * All rights reserved. * @@ -104,29 +105,6 @@ return NoBarrier_AtomicExchange(ptr, new_value); } -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 temp = increment; - __asm__ __volatile__("lock; xaddl %0,%1" - : "+r" (temp), "+m" (*ptr) - : : "memory"); - // temp now holds the old value of *ptr - return temp + increment; -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 temp = increment; - __asm__ __volatile__("lock; xaddl %0,%1" - : "+r" (temp), "+m" (*ptr) - : : "memory"); - // temp now holds the old value of *ptr - if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { - __asm__ __volatile__("lfence" : : : "memory"); - } - return temp + increment; -} - inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value, Atomic32 new_value) { @@ -242,29 +220,6 @@ return NoBarrier_AtomicExchange(ptr, new_value); } -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - Atomic64 temp = increment; - __asm__ __volatile__("lock; xaddq %0,%1" - : "+r" (temp), "+m" (*ptr) - : : "memory"); - // temp now contains the previous value of *ptr - return temp + increment; -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - Atomic64 temp = increment; - __asm__ __volatile__("lock; xaddq %0,%1" - : "+r" (temp), "+m" (*ptr) - : : "memory"); - // temp now contains the previous value of *ptr - if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { - __asm__ __volatile__("lfence" : : : "memory"); - } - return temp + increment; -} - inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { *ptr = value; } @@ -377,27 +332,6 @@ return NoBarrier_AtomicExchange(ptr, new_val); } -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - Atomic64 old_val, new_val; - - do { - old_val = *ptr; - new_val = old_val + increment; - } while (__sync_val_compare_and_swap(ptr, old_val, new_val) != old_val); - - return old_val + increment; -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - Atomic64 new_val = NoBarrier_AtomicIncrement(ptr, increment); - if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { - __asm__ __volatile__("lfence" : : : "memory"); - } - return new_val; -} - inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { __asm__ __volatile__("movq %1, %%mm0\n\t" // Use mmx reg for 64-bit atomic "movq %%mm0, %0\n\t" // moves (ptr could be read-only) diff -Nru google-perftools-2.1/src/base/basictypes.h google-perftools-2.2.1/src/base/basictypes.h --- google-perftools-2.1/src/base/basictypes.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/basictypes.h 2014-03-01 20:24:54.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -345,6 +346,11 @@ # elif (defined(__arm__)) # define CACHELINE_ALIGNED __attribute__((aligned(64))) // some ARMs have shorter cache lines (ARM1176JZF-S is 32 bytes for example) but obviously 64-byte aligned implies 32-byte aligned +# elif (defined(__mips__)) +# define CACHELINE_ALIGNED __attribute__((aligned(128))) +# elif (defined(__aarch64__)) +# define CACHELINE_ALIGNED __attribute__((aligned(64))) + // implementation specific, Cortex-A53 and 57 should have 64 bytes # else # error Could not determine cache line length - unknown architecture # endif diff -Nru google-perftools-2.1/src/base/commandlineflags.h google-perftools-2.2.1/src/base/commandlineflags.h --- google-perftools-2.1/src/base/commandlineflags.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/commandlineflags.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/base/cycleclock.h google-perftools-2.2.1/src/base/cycleclock.h --- google-perftools-2.1/src/base/cycleclock.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/cycleclock.h 2014-03-01 20:24:54.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2004, Google Inc. // All rights reserved. // @@ -49,7 +50,7 @@ #include "base/arm_instruction_set_select.h" // base/sysinfo.h is really big and we don't want to include it unless // it is necessary. -#if defined(__arm__) || defined(__mips__) +#if defined(__arm__) || defined(__mips__) || defined(__aarch64__) # include "base/sysinfo.h" #endif #if defined(__MACH__) && defined(__APPLE__) @@ -66,7 +67,7 @@ extern "C" uint64 __rdtsc(); #pragma intrinsic(__rdtsc) #endif -#if defined(ARMV3) || defined(__mips__) +#if defined(ARMV3) || defined(__mips__) || defined(__aarch64__) #include #endif @@ -132,8 +133,8 @@ _asm rdtsc #elif defined(_MSC_VER) return __rdtsc(); -#elif defined(ARMV3) -#if defined(ARMV6) // V6 is the earliest arch that has a standard cyclecount +#elif defined(ARMV3) || defined(__aarch64__) +#if defined(ARMV7) // V7 is the earliest arch that has a standard cyclecount uint32 pmccntr; uint32 pmuseren; uint32 pmcntenset; diff -Nru google-perftools-2.1/src/base/dynamic_annotations.c google-perftools-2.2.1/src/base/dynamic_annotations.c --- google-perftools-2.1/src/base/dynamic_annotations.c 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/dynamic_annotations.c 2014-06-07 22:54:00.000000000 +0200 @@ -40,6 +40,7 @@ #include #include "base/dynamic_annotations.h" +#include "getenv_safe.h" // for TCMallocGetenvSafe #ifdef __GNUC__ /* valgrind.h uses gcc extensions so it won't build with other compilers */ @@ -140,23 +141,11 @@ #ifdef RUNNING_ON_VALGRIND if (RUNNING_ON_VALGRIND) return 1; #endif -#ifdef _MSC_VER - /* Visual Studio can complain about getenv, so use a windows equivalent. */ - char value[100] = "1"; /* something that is not "0" */ - int res = GetEnvironmentVariableA("RUNNING_ON_VALGRIND", - value, sizeof(value)); - /* value will remain "1" if the called failed for some reason. */ - return (res > 0 && strcmp(value, "0") != 0); -#else - /* TODO(csilvers): use GetenvBeforeMain() instead? Will need to - * change it to be extern "C". - */ - char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND"); + const char *running_on_valgrind_str = TCMallocGetenvSafe("RUNNING_ON_VALGRIND"); if (running_on_valgrind_str) { return strcmp(running_on_valgrind_str, "0") != 0; } return 0; -#endif } /* See the comments in dynamic_annotations.h */ diff -Nru google-perftools-2.1/src/base/elfcore.h google-perftools-2.2.1/src/base/elfcore.h --- google-perftools-2.1/src/base/elfcore.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/elfcore.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2005-2008, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/base/elf_mem_image.cc google-perftools-2.2.1/src/base/elf_mem_image.cc --- google-perftools-2.1/src/base/elf_mem_image.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/elf_mem_image.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/base/elf_mem_image.h google-perftools-2.2.1/src/base/elf_mem_image.h --- google-perftools-2.1/src/base/elf_mem_image.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/elf_mem_image.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/base/googleinit.h google-perftools-2.2.1/src/base/googleinit.h --- google-perftools-2.1/src/base/googleinit.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/googleinit.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/base/linux_syscall_support.h google-perftools-2.2.1/src/base/linux_syscall_support.h --- google-perftools-2.1/src/base/linux_syscall_support.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/linux_syscall_support.h 2014-04-13 03:35:40.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2005-2008, Google Inc. * All rights reserved. * @@ -84,7 +85,7 @@ * sys_futex( * sys_futex1( * sys_getcpu( - * sys_getdents( + * sys_getdents64( * sys_getppid( * sys_gettid( * sys_lseek( @@ -116,10 +117,10 @@ * 3) I left these in even though they're not used. They either * complement the above (write vs read) or are variants (rt_sigaction): * sys_fstat64 - * sys_getdents64 * sys_llseek * sys_mmap2 * sys_openat + * sys_getdents * sys_rt_sigaction * sys_rt_sigprocmask * sys_sigaddset @@ -130,11 +131,11 @@ #ifndef SYS_LINUX_SYSCALL_SUPPORT_H #define SYS_LINUX_SYSCALL_SUPPORT_H -/* We currently only support x86-32, x86-64, ARM, MIPS, and PPC/PPC64 on Linux. +/* We currently only support x86-32, x86-64, ARM, MIPS, PPC/PPC64 and Aarch64 on Linux. * Porting to other related platforms should not be difficult. */ #if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \ - defined(__mips__) || defined(__PPC__)) && defined(__linux) + defined(__mips__) || defined(__PPC__) || defined(__aarch64__)) && defined(__linux) #ifndef SYS_CPLUSPLUS #ifdef __cplusplus @@ -282,7 +283,7 @@ (8*sizeof(unsigned long))]; }; -/* include/asm-{arm,i386,mips,x86_64,ppc}/signal.h */ +/* include/asm-{arm,generic,i386,mips,x86_64,ppc}/signal.h */ struct kernel_sigaction { #ifdef __mips__ unsigned long sa_flags; @@ -373,7 +374,7 @@ }; #endif -/* include/asm-{arm,i386,mips,x86_64,ppc}/stat.h */ +/* include/asm-{arm,generic,i386,mips,x86_64,ppc}/stat.h */ #if defined(__i386__) || defined(__arm__) struct kernel_stat { /* The kernel headers suggest that st_dev and st_rdev should be 32bit @@ -466,6 +467,29 @@ int st_blocks; int st_pad4[14]; }; +#elif defined(__aarch64__) +struct kernel_stat { + unsigned long st_dev; + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned long st_rdev; + unsigned long __pad1; + long st_size; + int st_blksize; + int __pad2; + long st_blocks; + long st_atime_; + unsigned long st_atime_nsec_; + long st_mtime_; + unsigned long st_mtime_nsec_; + long st_ctime_; + unsigned long st_ctime_nsec_; + unsigned int __unused4; + unsigned int __unused5; +}; #endif @@ -675,6 +699,11 @@ #define __NR_getcpu 302 #endif /* End of powerpc defininitions */ +#elif defined(__aarch64__) +#ifndef __NR_fstatat +#define __NR_fstatat 79 +#endif +/* End of aarch64 defininitions */ #endif @@ -737,7 +766,8 @@ #endif #undef LSS_RETURN - #if (defined(__i386__) || defined(__x86_64__) || defined(__arm__)) + #if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \ + defined(__aarch64__)) /* Failing system calls return a negative result in the range of * -1..-4095. These are "errno" values with the sign inverted. */ @@ -1780,6 +1810,17 @@ long __ret, __err; { #if defined(__PPC64__) + +/* Stack frame offsets. */ +#if _CALL_ELF != 2 +#define FRAME_MIN_SIZE 112 +#define FRAME_TOC_SAVE 40 +#else +#define FRAME_MIN_SIZE 32 +#define FRAME_TOC_SAVE 24 +#endif + + register int (*__fn)(void *) __asm__ ("r3") = fn; register void *__cstack __asm__ ("r4") = child_stack; register int __flags __asm__ ("r5") = flags; @@ -1799,7 +1840,7 @@ /* set up stack frame for child */ "clrrdi %7, %7, 4\n\t" "li 0, 0\n\t" - "stdu 0, -112(%7)\n\t" + "stdu 0, -%13(%7)\n\t" /* fn, arg, child_stack are saved acrVoss the syscall */ "mr 28, %6\n\t" @@ -1825,13 +1866,18 @@ "bne- cr1, 1f\n\t" /* Do the function call */ - "std 2, 40(1)\n\t" + "std 2, %14(1)\n\t" +#if _CALL_ELF != 2 "ld 0, 0(28)\n\t" "ld 2, 8(28)\n\t" "mtctr 0\n\t" +#else + "mr 12, 28\n\t" + "mtctr 12\n\t" +#endif "mr 3, 27\n\t" "bctrl\n\t" - "ld 2, 40(1)\n\t" + "ld 2, %14(1)\n\t" /* Call _exit(r3) */ "li 0, %5\n\t" @@ -1845,7 +1891,7 @@ "i" (__NR_clone), "i" (__NR_exit), "r" (__fn), "r" (__cstack), "r" (__flags), "r" (__arg), "r" (__ptidptr), "r" (__newtls), - "r" (__ctidptr) + "r" (__ctidptr), "i" (FRAME_MIN_SIZE), "i" (FRAME_TOC_SAVE) : "cr0", "cr1", "memory", "ctr", "r0", "r29", "r27", "r28"); #else @@ -1916,6 +1962,128 @@ } LSS_RETURN(int, __ret, __err); } + #elif defined(__aarch64__) + #undef LSS_REG + #define LSS_REG(r,a) register long __x##r __asm__("x"#r) = (long)a + #undef LSS_BODY + #define LSS_BODY(type,name,args...) \ + register long __res_x0 __asm__("x0"); \ + long __res; \ + __asm__ __volatile__ ("mov x8, %1\n" \ + "svc 0x0\n" \ + : "=r"(__res_x0) \ + : "i"(__NR_##name) , ## args \ + : "memory"); \ + __res = __res_x0; \ + LSS_RETURN(type, __res) + #undef _syscall0 + #define _syscall0(type, name) \ + type LSS_NAME(name)(void) { \ + LSS_BODY(type, name); \ + } + #undef _syscall1 + #define _syscall1(type, name, type1, arg1) \ + type LSS_NAME(name)(type1 arg1) { \ + LSS_REG(0, arg1); LSS_BODY(type, name, "r"(__x0)); \ + } + #undef _syscall2 + #define _syscall2(type, name, type1, arg1, type2, arg2) \ + type LSS_NAME(name)(type1 arg1, type2 arg2) { \ + LSS_REG(0, arg1); LSS_REG(1, arg2); \ + LSS_BODY(type, name, "r"(__x0), "r"(__x1)); \ + } + #undef _syscall3 + #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ + LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ + LSS_BODY(type, name, "r"(__x0), "r"(__x1), "r"(__x2)); \ + } + #undef _syscall4 + #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ + LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ + LSS_REG(3, arg4); \ + LSS_BODY(type, name, "r"(__x0), "r"(__x1), "r"(__x2), "r"(__x3)); \ + } + #undef _syscall5 + #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5) { \ + LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ + LSS_REG(3, arg4); LSS_REG(4, arg5); \ + LSS_BODY(type, name, "r"(__x0), "r"(__x1), "r"(__x2), "r"(__x3), \ + "r"(__x4)); \ + } + #undef _syscall6 + #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5, type6 arg6) { \ + LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ + LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6); \ + LSS_BODY(type, name, "r"(__x0), "r"(__x1), "x"(__x2), "r"(__x3), \ + "r"(__x4), "r"(__x5)); \ + } + /* clone function adapted from glibc 2.18 clone.S */ + LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, + int flags, void *arg, int *parent_tidptr, + void *newtls, int *child_tidptr) { + long __res; + { + register int (*__fn)(void *) __asm__("x0") = fn; + register void *__stack __asm__("x1") = child_stack; + register int __flags __asm__("x2") = flags; + register void *__arg __asm__("x3") = arg; + register int *__ptid __asm__("x4") = parent_tidptr; + register void *__tls __asm__("x5") = newtls; + register int *__ctid __asm__("x6") = child_tidptr; + __asm__ __volatile__(/* if (fn == NULL || child_stack == NULL) + * return -EINVAL; + */ + "cbz x0,1f\n" + "cbz x1,1f\n" + + /* Push "arg" and "fn" onto the stack that will be + * used by the child. + */ + "stp x0,x3, [x1, #-16]!\n" + + "mov x0,x2\n" /* flags */ + "mov x2,x4\n" /* ptid */ + "mov x3,x5\n" /* tls */ + "mov x4,x6\n" /* ctid */ + "mov x8,%9\n" /* clone */ + + "svc 0x0\n" + + /* if (%r0 != 0) + * return %r0; + */ + "cmp x0, #0\n" + "bne 2f\n" + + /* In the child, now. Call "fn(arg)". + */ + "ldp x1, x0, [sp], #16\n" + "blr x1\n" + + /* Call _exit(%r0). + */ + "mov x8, %10\n" + "svc 0x0\n" + "1:\n" + "mov x8, %1\n" + "2:\n" + : "=r" (__res) + : "i"(-EINVAL), + "r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg), + "r"(__ptid), "r"(__tls), "r"(__ctid), + "i"(__NR_clone), "i"(__NR_exit) + : "x30", "memory"); + } + LSS_RETURN(int, __res); + } #endif #define __NR__exit __NR_exit #define __NR__gettid __NR_gettid @@ -1929,11 +2097,16 @@ LSS_INLINE _syscall4(int, futex, int*, a, int, o, int, v, struct kernel_timespec*, t) - LSS_INLINE _syscall3(int, getdents, int, f, - struct kernel_dirent*, d, int, c) #ifdef __NR_getdents64 - LSS_INLINE _syscall3(int, getdents64, int, f, - struct kernel_dirent64*, d, int, c) + LSS_INLINE _syscall3(int, getdents64, int, f, + struct kernel_dirent64*, d, int, c) +#define KERNEL_DIRENT kernel_dirent64 +#define GETDENTS sys_getdents64 +#else + LSS_INLINE _syscall3(int, getdents, int, f, + struct kernel_dirent*, d, int, c) +#define KERNEL_DIRENT kernel_dirent +#define GETDENTS sys_getdents #endif LSS_INLINE _syscall0(pid_t, getpid) LSS_INLINE _syscall0(pid_t, getppid) @@ -1955,8 +2128,6 @@ LSS_INLINE _syscall5(void*, _mremap, void*, o, size_t, os, size_t, ns, unsigned long, f, void *, a) - LSS_INLINE _syscall3(int, open, const char*, p, - int, f, int, m) LSS_INLINE _syscall2(int, prctl, int, o, long, a) LSS_INLINE _syscall4(long, ptrace, int, r, @@ -1972,15 +2143,23 @@ LSS_INLINE _syscall0(int, sched_yield) LSS_INLINE _syscall2(int, sigaltstack, const stack_t*, s, const stack_t*, o) - LSS_INLINE _syscall2(int, stat, const char*, f, - struct kernel_stat*, b) + #if defined(__NR_fstatat) + LSS_INLINE _syscall4(int, fstatat, int, d, const char *, p, + struct kernel_stat*, b, int, flags) + LSS_INLINE int LSS_NAME(stat)(const char* p, struct kernel_stat* b) { + return LSS_NAME(fstatat)(AT_FDCWD,p,b,0); + } + #else + LSS_INLINE _syscall2(int, stat, const char*, f, + struct kernel_stat*, b) + #endif LSS_INLINE _syscall3(ssize_t, write, int, f, const void *, b, size_t, c) #if defined(__NR_getcpu) LSS_INLINE _syscall3(long, getcpu, unsigned *, cpu, unsigned *, node, void *, unused); #endif - #if defined(__x86_64__) || \ + #if defined(__x86_64__) || defined(__aarch64__) || \ (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32) LSS_INLINE _syscall3(int, socket, int, d, int, t, int, p) @@ -2020,18 +2199,43 @@ return LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8); } #endif - #if defined(__x86_64__) || \ - defined(__arm__) || \ - (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32) + #if (defined(__aarch64__)) || \ + (defined(__mips__) && (_MIPS_ISA == _MIPS_ISA_MIPS64)) + LSS_INLINE _syscall6(void*, mmap, void*, s, + size_t, l, int, p, + int, f, int, d, + __off64_t, o) + LSS_INLINE int LSS_NAME(sigaction)(int signum, + const struct kernel_sigaction *act, + struct kernel_sigaction *oldact) { + return LSS_NAME(rt_sigaction)(signum, act, oldact, (KERNEL_NSIG+7)/8); + + } + LSS_INLINE int LSS_NAME(sigprocmask)(int how, + const struct kernel_sigset_t *set, + struct kernel_sigset_t *oldset) { + return LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8); + } + #endif + #ifdef __NR_wait4 LSS_INLINE _syscall4(pid_t, wait4, pid_t, p, int*, s, int, o, struct kernel_rusage*, r) LSS_INLINE pid_t LSS_NAME(waitpid)(pid_t pid, int *status, int options){ return LSS_NAME(wait4)(pid, status, options, 0); } - #endif - #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) + #else + LSS_INLINE _syscall3(pid_t, waitpid, pid_t, p, + int*, s, int, o) + #endif + #ifdef __NR_openat LSS_INLINE _syscall4(int, openat, int, d, const char *, p, int, f, int, m) + LSS_INLINE int LSS_NAME(open)(const char* p, int f, int m) { + return LSS_NAME(openat)(AT_FDCWD,p,f,m ); + } + #else + LSS_INLINE _syscall3(int, open, const char*, p, + int, f, int, m) #endif LSS_INLINE int LSS_NAME(sigemptyset)(struct kernel_sigset_t *set) { memset(&set->sig, 0, sizeof(set->sig)); @@ -2202,11 +2406,6 @@ LSS_INLINE _syscall3(int, socket, int, d, int, t, int, p) #endif - #if defined(__i386__) || defined(__PPC__) || \ - (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) - LSS_INLINE _syscall3(pid_t, waitpid, pid_t, p, - int*, s, int, o) - #endif #if defined(__mips__) /* sys_pipe() on MIPS has non-standard calling conventions, as it returns * both file handles through CPU registers. @@ -2229,6 +2428,12 @@ return 0; } } + #elif defined(__NR_pipe2) + LSS_INLINE _syscall2(int, pipe2, int *, p, + int, f ) + LSS_INLINE int LSS_NAME(pipe)( int * p) { + return LSS_NAME(pipe2)(p, 0); + } #else LSS_INLINE _syscall1(int, pipe, int *, p) #endif diff -Nru google-perftools-2.1/src/base/linuxthreads.cc google-perftools-2.2.1/src/base/linuxthreads.cc --- google-perftools-2.1/src/base/linuxthreads.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/linuxthreads.cc 2014-03-01 20:24:54.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2005-2007, Google Inc. * All rights reserved. * @@ -193,9 +194,9 @@ * In order to find the main application from the signal handler, we * need to store information about it in global variables. This is * safe, because the main application should be suspended at this - * time. If the callback ever called ResumeAllProcessThreads(), then + * time. If the callback ever called TCMalloc_ResumeAllProcessThreads(), then * we are running a higher risk, though. So, try to avoid calling - * abort() after calling ResumeAllProcessThreads. + * abort() after calling TCMalloc_ResumeAllProcessThreads. */ static volatile int *sig_pids, sig_num_threads, sig_proc, sig_marker; @@ -214,7 +215,7 @@ sys_ptrace(PTRACE_KILL, sig_pids[sig_num_threads], 0, 0); } } else if (sig_num_threads > 0) { - ResumeAllProcessThreads(sig_num_threads, (int *)sig_pids); + TCMalloc_ResumeAllProcessThreads(sig_num_threads, (int *)sig_pids); } } sig_pids = NULL; @@ -369,10 +370,10 @@ sig_num_threads = num_threads; sig_pids = pids; for (;;) { - struct kernel_dirent *entry; + struct KERNEL_DIRENT *entry; char buf[4096]; - ssize_t nbytes = sys_getdents(proc, (struct kernel_dirent *)buf, - sizeof(buf)); + ssize_t nbytes = GETDENTS(proc, (struct KERNEL_DIRENT *)buf, + sizeof(buf)); if (nbytes < 0) goto failure; else if (nbytes == 0) { @@ -388,9 +389,9 @@ } break; } - for (entry = (struct kernel_dirent *)buf; - entry < (struct kernel_dirent *)&buf[nbytes]; - entry = (struct kernel_dirent *)((char *)entry+entry->d_reclen)) { + for (entry = (struct KERNEL_DIRENT *)buf; + entry < (struct KERNEL_DIRENT *)&buf[nbytes]; + entry = (struct KERNEL_DIRENT *)((char *)entry+entry->d_reclen)) { if (entry->d_ino != 0) { const char *ptr = entry->d_name; pid_t pid; @@ -416,7 +417,7 @@ /* Check if the marker is identical to the one we created */ if (sys_stat(fname, &tmp_sb) >= 0 && marker_sb.st_ino == tmp_sb.st_ino) { - long i; + long i, j; /* Found one of our threads, make sure it is no duplicate */ for (i = 0; i < num_threads; i++) { @@ -452,28 +453,28 @@ sig_num_threads = num_threads; goto next_entry; } - /* Attaching to a process doesn't guarantee it'll stop before - * ptrace returns; you have to wait on it. Specifying __WCLONE - * means it will only wait for clone children (i.e. threads, - * not processes). - */ - while (sys_waitpid(pid, (int *)0, __WCLONE) < 0) { + while (sys_waitpid(pid, (int *)0, __WALL) < 0) { if (errno != EINTR) { - /* Assumes ECHILD */ - if (pid == ppid) { - /* The parent is not a clone */ - found_parent = true; - break; - } else { - sys_ptrace_detach(pid); - num_threads--; - sig_num_threads = num_threads; - goto next_entry; - } + sys_ptrace_detach(pid); + num_threads--; + sig_num_threads = num_threads; + goto next_entry; } } - added_entries++; + if (sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i++ != j || + sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i != j) { + /* Address spaces are distinct, even though both + * processes show the "marker". This is probably + * a forked child process rather than a thread. + */ + sys_ptrace_detach(pid); + num_threads--; + sig_num_threads = num_threads; + } else { + found_parent |= pid == ppid; + added_entries++; + } } } } @@ -496,7 +497,7 @@ * error to the caller. */ if (!found_parent) { - ResumeAllProcessThreads(num_threads, pids); + TCMalloc_ResumeAllProcessThreads(num_threads, pids); sys__exit(3); } @@ -508,7 +509,7 @@ args->err = errno; /* Callback should have resumed threads, but better safe than sorry */ - if (ResumeAllProcessThreads(num_threads, pids)) { + if (TCMalloc_ResumeAllProcessThreads(num_threads, pids)) { /* Callback forgot to resume at least one thread, report error */ args->err = EINVAL; args->result = -1; @@ -518,7 +519,7 @@ } detach_threads: /* Resume all threads prior to retrying the operation */ - ResumeAllProcessThreads(num_threads, pids); + TCMalloc_ResumeAllProcessThreads(num_threads, pids); sig_pids = NULL; num_threads = 0; sig_num_threads = num_threads; @@ -536,19 +537,19 @@ * address space, the filesystem, and the filehandles with the caller. Most * notably, it does not share the same pid and ppid; and if it terminates, * the rest of the application is still there. 'callback' is supposed to do - * or arrange for ResumeAllProcessThreads. This happens automatically, if + * or arrange for TCMalloc_ResumeAllProcessThreads. This happens automatically, if * the thread raises a synchronous signal (e.g. SIGSEGV); asynchronous * signals are blocked. If the 'callback' decides to unblock them, it must * ensure that they cannot terminate the application, or that - * ResumeAllProcessThreads will get called. + * TCMalloc_ResumeAllProcessThreads will get called. * It is an error for the 'callback' to make any library calls that could * acquire locks. Most notably, this means that most system calls have to * avoid going through libc. Also, this means that it is not legal to call * exit() or abort(). * We return -1 on error and the return value of 'callback' on success. */ -int ListAllProcessThreads(void *parameter, - ListAllProcessThreadsCallBack callback, ...) { +int TCMalloc_ListAllProcessThreads(void *parameter, + ListAllProcessThreadsCallBack callback, ...) { char altstack_mem[ALT_STACKSIZE]; struct ListerParams args; pid_t clone_pid; @@ -688,11 +689,11 @@ } /* This function resumes the list of all linux threads that - * ListAllProcessThreads pauses before giving to its callback. + * TCMalloc_ListAllProcessThreads pauses before giving to its callback. * The function returns non-zero if at least one thread was * suspended and has now been resumed. */ -int ResumeAllProcessThreads(int num_threads, pid_t *thread_pids) { +int TCMalloc_ResumeAllProcessThreads(int num_threads, pid_t *thread_pids) { int detached_at_least_one = 0; while (num_threads-- > 0) { detached_at_least_one |= sys_ptrace_detach(thread_pids[num_threads]) >= 0; diff -Nru google-perftools-2.1/src/base/linuxthreads.h google-perftools-2.2.1/src/base/linuxthreads.h --- google-perftools-2.1/src/base/linuxthreads.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/linuxthreads.h 2014-03-01 20:24:54.000000000 +0100 @@ -41,7 +41,7 @@ * related platforms should not be difficult. */ #if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \ - defined(__mips__) || defined(__PPC__)) && defined(__linux) + defined(__mips__) || defined(__PPC__) || defined(__aarch64__)) && defined(__linux) /* Define the THREADS symbol to make sure that there is exactly one core dumper * built into the library. diff -Nru google-perftools-2.1/src/base/logging.cc google-perftools-2.2.1/src/base/logging.cc --- google-perftools-2.1/src/base/logging.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/logging.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2007, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/base/logging.h google-perftools-2.2.1/src/base/logging.h --- google-perftools-2.1/src/base/logging.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/logging.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/base/low_level_alloc.cc google-perftools-2.2.1/src/base/low_level_alloc.cc --- google-perftools-2.1/src/base/low_level_alloc.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/low_level_alloc.cc 2014-06-21 21:12:02.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2006, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/base/low_level_alloc.h google-perftools-2.2.1/src/base/low_level_alloc.h --- google-perftools-2.1/src/base/low_level_alloc.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/low_level_alloc.h 2014-06-21 21:12:02.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2006, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/base/simple_mutex.h google-perftools-2.2.1/src/base/simple_mutex.h --- google-perftools-2.1/src/base/simple_mutex.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/simple_mutex.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2007, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/base/spinlock.cc google-perftools-2.2.1/src/base/spinlock.cc --- google-perftools-2.1/src/base/spinlock.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/spinlock.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2006, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/base/spinlock.h google-perftools-2.2.1/src/base/spinlock.h --- google-perftools-2.1/src/base/spinlock.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/spinlock.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2006, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/base/spinlock_internal.cc google-perftools-2.2.1/src/base/spinlock_internal.cc --- google-perftools-2.1/src/base/spinlock_internal.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/spinlock_internal.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2010, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/base/spinlock_internal.h google-perftools-2.2.1/src/base/spinlock_internal.h --- google-perftools-2.1/src/base/spinlock_internal.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/spinlock_internal.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2010, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/base/spinlock_linux-inl.h google-perftools-2.2.1/src/base/spinlock_linux-inl.h --- google-perftools-2.1/src/base/spinlock_linux-inl.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/spinlock_linux-inl.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2009, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/base/spinlock_posix-inl.h google-perftools-2.2.1/src/base/spinlock_posix-inl.h --- google-perftools-2.1/src/base/spinlock_posix-inl.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/spinlock_posix-inl.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2009, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/base/spinlock_win32-inl.h google-perftools-2.2.1/src/base/spinlock_win32-inl.h --- google-perftools-2.1/src/base/spinlock_win32-inl.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/spinlock_win32-inl.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2009, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/base/stl_allocator.h google-perftools-2.2.1/src/base/stl_allocator.h --- google-perftools-2.1/src/base/stl_allocator.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/stl_allocator.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2006, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/base/synchronization_profiling.h google-perftools-2.2.1/src/base/synchronization_profiling.h --- google-perftools-2.1/src/base/synchronization_profiling.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/synchronization_profiling.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2010, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/base/sysinfo.cc google-perftools-2.2.1/src/base/sysinfo.cc --- google-perftools-2.1/src/base/sysinfo.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/sysinfo.cc 2014-06-07 22:54:00.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2006, Google Inc. // All rights reserved. // @@ -166,6 +167,12 @@ return NULL; // env var never found } +extern "C" { + const char* TCMallocGetenvSafe(const char* name) { + return GetenvBeforeMain(name); + } +} + // This takes as an argument an environment-variable name (like // CPUPROFILE) whose value is supposed to be a file-path, and sets // path to that path, and returns true. If the env var doesn't exist, diff -Nru google-perftools-2.1/src/base/sysinfo.h google-perftools-2.2.1/src/base/sysinfo.h --- google-perftools-2.1/src/base/sysinfo.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/base/sysinfo.h 2014-04-13 03:05:37.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2006, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/base/thread_lister.c google-perftools-2.2.1/src/base/thread_lister.c --- google-perftools-2.1/src/base/thread_lister.c 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/thread_lister.c 2014-02-22 21:25:25.000000000 +0100 @@ -48,8 +48,8 @@ * or if the multi-threading code has not been ported, yet. */ -int ListAllProcessThreads(void *parameter, - ListAllProcessThreadsCallBack callback, ...) { +int TCMalloc_ListAllProcessThreads(void *parameter, + ListAllProcessThreadsCallBack callback, ...) { int rc; va_list ap; pid_t pid; @@ -70,7 +70,7 @@ return rc; } -int ResumeAllProcessThreads(int num_threads, pid_t *thread_pids) { +int TCMalloc_ResumeAllProcessThreads(int num_threads, pid_t *thread_pids) { return 1; } diff -Nru google-perftools-2.1/src/base/thread_lister.h google-perftools-2.2.1/src/base/thread_lister.h --- google-perftools-2.1/src/base/thread_lister.h 2012-02-10 03:45:37.000000000 +0100 +++ google-perftools-2.2.1/src/base/thread_lister.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +/* -*- Mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* Copyright (c) 2005-2007, Google Inc. * All rights reserved. * @@ -54,26 +55,26 @@ * address space, the filesystem, and the filehandles with the caller. Most * notably, it does not share the same pid and ppid; and if it terminates, * the rest of the application is still there. 'callback' is supposed to do - * or arrange for ResumeAllProcessThreads. This happens automatically, if + * or arrange for TCMalloc_ResumeAllProcessThreads. This happens automatically, if * the thread raises a synchronous signal (e.g. SIGSEGV); asynchronous * signals are blocked. If the 'callback' decides to unblock them, it must * ensure that they cannot terminate the application, or that - * ResumeAllProcessThreads will get called. + * TCMalloc_ResumeAllProcessThreads will get called. * It is an error for the 'callback' to make any library calls that could * acquire locks. Most notably, this means that most system calls have to * avoid going through libc. Also, this means that it is not legal to call * exit() or abort(). * We return -1 on error and the return value of 'callback' on success. */ -int ListAllProcessThreads(void *parameter, - ListAllProcessThreadsCallBack callback, ...); +int TCMalloc_ListAllProcessThreads(void *parameter, + ListAllProcessThreadsCallBack callback, ...); /* This function resumes the list of all linux threads that - * ListAllProcessThreads pauses before giving to its callback. - * The function returns non-zero if at least one thread was + * TCMalloc_ListAllProcessThreads pauses before giving to its + * callback. The function returns non-zero if at least one thread was * suspended and has now been resumed. */ -int ResumeAllProcessThreads(int num_threads, pid_t *thread_pids); +int TCMalloc_ResumeAllProcessThreads(int num_threads, pid_t *thread_pids); #ifdef __cplusplus } diff -Nru google-perftools-2.1/src/base/vdso_support.cc google-perftools-2.2.1/src/base/vdso_support.cc --- google-perftools-2.1/src/base/vdso_support.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/vdso_support.cc 2014-04-13 03:35:40.000000000 +0200 @@ -57,7 +57,6 @@ namespace base { const void *VDSOSupport::vdso_base_ = ElfMemImage::kInvalidBase; -VDSOSupport::GetCpuFn VDSOSupport::getcpu_fn_ = &InitAndGetCPU; VDSOSupport::VDSOSupport() // If vdso_base_ is still set to kInvalidBase, we got here // before VDSOSupport::Init has been called. Call it now. @@ -81,14 +80,12 @@ // Valgrind zapping. So we check for Valgrind separately. if (RunningOnValgrind()) { vdso_base_ = NULL; - getcpu_fn_ = &GetCPUViaSyscall; return NULL; } int fd = open("/proc/self/auxv", O_RDONLY); if (fd == -1) { // Kernel too old to have a VDSO. vdso_base_ = NULL; - getcpu_fn_ = &GetCPUViaSyscall; return NULL; } ElfW(auxv_t) aux; @@ -106,20 +103,6 @@ vdso_base_ = NULL; } } - GetCpuFn fn = &GetCPUViaSyscall; // default if VDSO not present. - if (vdso_base_) { - VDSOSupport vdso; - SymbolInfo info; - if (vdso.LookupSymbol("__vdso_getcpu", "LINUX_2.6", STT_FUNC, &info)) { - // Casting from an int to a pointer is not legal C++. To emphasize - // this, we use a C-style cast rather than a C++-style cast. - fn = (GetCpuFn)(info.address); - } - } - // Subtle: this code runs outside of any locks; prevent compiler - // from assigning to getcpu_fn_ more than once. - base::subtle::MemoryBarrier(); - getcpu_fn_ = fn; return vdso_base_; } @@ -128,8 +111,6 @@ const void *old_base = vdso_base_; vdso_base_ = base; image_.Init(base); - // Also reset getcpu_fn_, so GetCPU could be tested with simulated VDSO. - getcpu_fn_ = &InitAndGetCPU; return old_base; } @@ -145,33 +126,6 @@ return image_.LookupSymbolByAddress(address, info_out); } -// NOLINT on 'long' because this routine mimics kernel api. -long VDSOSupport::GetCPUViaSyscall(unsigned *cpu, void *, void *) { // NOLINT -#if defined(__NR_getcpu) - return sys_getcpu(cpu, NULL, NULL); -#else - // x86_64 never implemented sys_getcpu(), except as a VDSO call. - errno = ENOSYS; - return -1; -#endif -} - -// Use fast __vdso_getcpu if available. -long VDSOSupport::InitAndGetCPU(unsigned *cpu, void *x, void *y) { // NOLINT - Init(); - CHECK_NE(getcpu_fn_, &InitAndGetCPU); // << "Init() did not set getcpu_fn_"; - return (*getcpu_fn_)(cpu, x, y); -} - -// This function must be very fast, and may be called from very -// low level (e.g. tcmalloc). Hence I avoid things like -// GoogleOnceInit() and ::operator new. -int GetCPU(void) { - unsigned cpu; - int ret_code = (*VDSOSupport::getcpu_fn_)(&cpu, NULL, NULL); - return ret_code == 0 ? cpu : ret_code; -} - // We need to make sure VDSOSupport::Init() is called before // the main() runs, since it might do something like setuid or // chroot. If VDSOSupport diff -Nru google-perftools-2.1/src/base/vdso_support.h google-perftools-2.2.1/src/base/vdso_support.h --- google-perftools-2.1/src/base/vdso_support.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/base/vdso_support.h 2014-04-13 03:35:40.000000000 +0200 @@ -122,32 +122,9 @@ // page-aligned. static const void *vdso_base_; - // NOLINT on 'long' because these routines mimic kernel api. - // The 'cache' parameter may be used by some versions of the kernel, - // and should be NULL or point to a static buffer containing at - // least two 'long's. - static long InitAndGetCPU(unsigned *cpu, void *cache, // NOLINT 'long'. - void *unused); - static long GetCPUViaSyscall(unsigned *cpu, void *cache, // NOLINT 'long'. - void *unused); - typedef long (*GetCpuFn)(unsigned *cpu, void *cache, // NOLINT 'long'. - void *unused); - - // This function pointer may point to InitAndGetCPU, - // GetCPUViaSyscall, or __vdso_getcpu at different stages of initialization. - static GetCpuFn getcpu_fn_; - - friend int GetCPU(void); // Needs access to getcpu_fn_. - DISALLOW_COPY_AND_ASSIGN(VDSOSupport); }; -// Same as sched_getcpu() on later glibc versions. -// Return current CPU, using (fast) __vdso_getcpu@LINUX_2.6 if present, -// otherwise use syscall(SYS_getcpu,...). -// May return -1 with errno == ENOSYS if the kernel doesn't -// support SYS_getcpu. -int GetCPU(); } // namespace base #endif // HAVE_ELF_MEM_IMAGE diff -Nru google-perftools-2.1/src/central_freelist.cc google-perftools-2.2.1/src/central_freelist.cc --- google-perftools-2.1/src/central_freelist.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/central_freelist.cc 2014-06-21 22:55:10.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // @@ -257,52 +258,62 @@ } int result = 0; - void* head = NULL; - void* tail = NULL; + *start = NULL; + *end = NULL; // TODO: Prefetch multiple TCEntries? - tail = FetchFromSpansSafe(); - if (tail != NULL) { - SLL_SetNext(tail, NULL); - head = tail; - result = 1; + result = FetchFromOneSpansSafe(N, start, end); + if (result != 0) { while (result < N) { - void *t = FetchFromSpans(); - if (!t) break; - SLL_Push(&head, t); - result++; + int n; + void* head = NULL; + void* tail = NULL; + n = FetchFromOneSpans(N - result, &head, &tail); + if (!n) break; + result += n; + SLL_PushRange(start, head, tail); } } lock_.Unlock(); - *start = head; - *end = tail; return result; } -void* CentralFreeList::FetchFromSpansSafe() { - void *t = FetchFromSpans(); - if (!t) { +int CentralFreeList::FetchFromOneSpansSafe(int N, void **start, void **end) { + int result = FetchFromOneSpans(N, start, end); + if (!result) { Populate(); - t = FetchFromSpans(); + result = FetchFromOneSpans(N, start, end); } - return t; + return result; } -void* CentralFreeList::FetchFromSpans() { - if (tcmalloc::DLL_IsEmpty(&nonempty_)) return NULL; +int CentralFreeList::FetchFromOneSpans(int N, void **start, void **end) { + if (tcmalloc::DLL_IsEmpty(&nonempty_)) return 0; Span* span = nonempty_.next; ASSERT(span->objects != NULL); - span->refcount++; - void* result = span->objects; - span->objects = *(reinterpret_cast(result)); - if (span->objects == NULL) { + + int result = 0; + void *prev, *curr; + curr = span->objects; + do { + prev = curr; + curr = *(reinterpret_cast(curr)); + } while (++result < N && curr != NULL); + + if (curr == NULL) { // Move to empty list tcmalloc::DLL_Remove(span); tcmalloc::DLL_Prepend(&empty_, span); Event(span, 'E', 0); } - counter_--; + + *start = span->objects; + *end = prev; + span->objects = curr; + SLL_SetNext(*end, NULL); + span->refcount += result; + counter_ -= result; return result; } diff -Nru google-perftools-2.1/src/central_freelist.h google-perftools-2.2.1/src/central_freelist.h --- google-perftools-2.1/src/central_freelist.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/central_freelist.h 2013-12-06 21:16:47.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // @@ -113,13 +114,13 @@ // REQUIRES: lock_ is held // Remove object from cache and return. // Return NULL if no free entries in cache. - void* FetchFromSpans() EXCLUSIVE_LOCKS_REQUIRED(lock_); + int FetchFromOneSpans(int N, void **start, void **end) EXCLUSIVE_LOCKS_REQUIRED(lock_); // REQUIRES: lock_ is held // Remove object from cache and return. Fetches // from pageheap if cache is empty. Only returns // NULL on allocation failure. - void* FetchFromSpansSafe() EXCLUSIVE_LOCKS_REQUIRED(lock_); + int FetchFromOneSpansSafe(int N, void **start, void **end) EXCLUSIVE_LOCKS_REQUIRED(lock_); // REQUIRES: lock_ is held // Release a linked list of objects to spans. diff -Nru google-perftools-2.1/src/common.cc google-perftools-2.2.1/src/common.cc --- google-perftools-2.1/src/common.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/common.cc 2014-06-07 22:54:00.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // @@ -35,6 +36,7 @@ #include "common.h" #include "system-alloc.h" #include "base/spinlock.h" +#include "getenv_safe.h" // TCMallocGetenvSafe namespace tcmalloc { @@ -50,7 +52,7 @@ static inline void InitTCMallocTransferNumObjects() { if (UNLIKELY(FLAGS_tcmalloc_transfer_num_objects == 0)) { - const char *envval = getenv("TCMALLOC_TRANSFER_NUM_OBJ"); + const char *envval = TCMallocGetenvSafe("TCMALLOC_TRANSFER_NUM_OBJ"); FLAGS_tcmalloc_transfer_num_objects = !envval ? kDefaultTransferNumObjecs : strtol(envval, NULL, 10); } @@ -121,7 +123,7 @@ InitTCMallocTransferNumObjects(); // Do some sanity checking on add_amount[]/shift_amount[]/class_array[] - if (ClassIndex(0) < 0) { + if (ClassIndex(0) != 0) { Log(kCrash, __FILE__, __LINE__, "Invalid class index for size 0", ClassIndex(0)); } @@ -187,7 +189,7 @@ } // Double-check sizes just to be safe - for (size_t size = 0; size <= kMaxSize; size++) { + for (size_t size = 0; size <= kMaxSize;) { const int sc = SizeClass(size); if (sc <= 0 || sc >= kNumClasses) { Log(kCrash, __FILE__, __LINE__, @@ -202,6 +204,11 @@ Log(kCrash, __FILE__, __LINE__, "Bad (class, size, requested)", sc, s, size); } + if (size <= kMaxSmallSize) { + size += 8; + } else { + size += 128; + } } // Initialize the num_objects_to_move array. diff -Nru google-perftools-2.1/src/common.h google-perftools-2.2.1/src/common.h --- google-perftools-2.1/src/common.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/common.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/config_for_unittests.h google-perftools-2.2.1/src/config_for_unittests.h --- google-perftools-2.1/src/config_for_unittests.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/config_for_unittests.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2007, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/config.h.in google-perftools-2.2.1/src/config.h.in --- google-perftools-2.1/src/config.h.in 2013-07-30 11:12:28.000000000 +0200 +++ google-perftools-2.2.1/src/config.h.in 2014-06-22 00:52:49.000000000 +0200 @@ -17,6 +17,10 @@ /* Define to 1 if you have the header file. */ #undef HAVE_CYGWIN_SIGNAL_H +/* Define to 1 if you have the declaration of `backtrace', and to 0 if you + don't. */ +#undef HAVE_DECL_BACKTRACE + /* Define to 1 if you have the declaration of `cfree', and to 0 if you don't. */ #undef HAVE_DECL_CFREE @@ -112,6 +116,10 @@ /* Define if you have POSIX threads libraries and header files. */ #undef HAVE_PTHREAD +/* defined to 1 if pthread symbols are exposed even without include pthread.h + */ +#undef HAVE_PTHREAD_DESPITE_ASKING_FOR + /* Define to 1 if you have the header file. */ #undef HAVE_PWD_H @@ -206,9 +214,6 @@ /* Define to 'volatile' if __malloc_hook is declared volatile */ #undef MALLOC_HOOK_MAYBE_VOLATILE -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -#undef NO_MINUS_C_MINUS_O - /* Name of package */ #undef PACKAGE diff -Nru google-perftools-2.1/src/debugallocation.cc google-perftools-2.2.1/src/debugallocation.cc --- google-perftools-2.1/src/debugallocation.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/debugallocation.cc 2014-04-13 03:35:40.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2000, Google Inc. // All rights reserved. // @@ -75,6 +76,11 @@ #include "malloc_hook-inl.h" #include "symbolize.h" +// NOTE: due to #define below, tcmalloc.cc will omit tc_XXX +// definitions. So that debug implementations can be defined +// instead. We're going to use do_malloc, do_free and other do_XXX +// functions that are defined in tcmalloc.cc for actual memory +// management #define TCMALLOC_USING_DEBUGALLOCATION #include "tcmalloc.cc" @@ -140,16 +146,11 @@ static void TracePrintf(int fd, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))); -// The do_* functions are defined in tcmalloc/tcmalloc.cc, -// which is included before this file -// when TCMALLOC_FOR_DEBUGALLOCATION is defined -// TODO(csilvers): get rid of these now that we are tied to tcmalloc. -#define BASE_MALLOC_NEW do_malloc -#define BASE_MALLOC do_malloc -#define BASE_FREE do_free -#define BASE_MALLOC_STATS do_malloc_stats -#define BASE_MALLOPT do_mallopt -#define BASE_MALLINFO do_mallinfo +// Round "value" up to next "alignment" boundary. +// Requires that "alignment" be a power of two. +static intptr_t RoundUp(intptr_t value, intptr_t alignment) { + return (value + alignment - 1) & ~(alignment - 1); +} // ========================================================================= // @@ -268,7 +269,7 @@ // setting the environment variable MALLOC_CHECK_ to 1 before you // start the program (see man malloc). - // We use either BASE_MALLOC or mmap to make the actual allocation. In + // We use either do_malloc or mmap to make the actual allocation. In // order to remember which one of the two was used for any block, we store an // appropriate magic word next to the block. static const int kMagicMalloc = 0xDEADBEEF; @@ -285,7 +286,7 @@ // should together occupy a multiple of 16 bytes. (At the // moment, sizeof(size_t) == 4 or 8 depending on piii vs // k8, and 4 of those sum to 16 or 32 bytes). - // This, combined with BASE_MALLOC's alignment guarantees, + // This, combined with do_malloc's alignment guarantees, // ensures that SSE types can be stored into the returned // block, at &size2_. size_t size1_; @@ -348,8 +349,17 @@ static size_t real_malloced_size(size_t size) { return size + sizeof(MallocBlock); } + + /* + * Here we assume size of page is kMinAlign aligned, + * so if size is MALLOC_ALIGNMENT aligned too, then we could + * guarantee return address is also kMinAlign aligned, because + * mmap return address at nearby page boundary on Linux. + */ static size_t real_mmapped_size(size_t size) { - return size + MallocBlock::data_offset(); + size_t tmp = size + MallocBlock::data_offset(); + tmp = RoundUp(tmp, kMinAlign); + return tmp; } size_t real_size() { @@ -375,8 +385,8 @@ // record us as allocated in the map alloc_map_lock_.Lock(); if (!alloc_map_) { - void* p = BASE_MALLOC(sizeof(AllocMap)); - alloc_map_ = new(p) AllocMap(BASE_MALLOC, BASE_FREE); + void* p = do_malloc(sizeof(AllocMap)); + alloc_map_ = new(p) AllocMap(do_malloc, do_free); } alloc_map_->Insert(data_addr(), type); // initialize us @@ -516,14 +526,10 @@ } b = (MallocBlock*) (p + (num_pages - 1) * pagesize - sz); } else { - b = (MallocBlock*) (type == kMallocType ? - BASE_MALLOC(real_malloced_size(size)) : - BASE_MALLOC_NEW(real_malloced_size(size))); + b = (MallocBlock*) do_malloc(real_malloced_size(size)); } #else - b = (MallocBlock*) (type == kMallocType ? - BASE_MALLOC(real_malloced_size(size)) : - BASE_MALLOC_NEW(real_malloced_size(size))); + b = (MallocBlock*) do_malloc(real_malloced_size(size); #endif // It would be nice to output a diagnostic on allocation failure @@ -603,7 +609,7 @@ free_queue_lock_.Unlock(); for (int i = 0; i < num_entries; i++) { CheckForDanglingWrites(entries[i]); - BASE_FREE(entries[i].block); + do_free(entries[i].block); } num_entries = 0; free_queue_lock_.Lock(); @@ -613,7 +619,7 @@ free_queue_lock_.Unlock(); for (int i = 0; i < num_entries; i++) { CheckForDanglingWrites(entries[i]); - BASE_FREE(entries[i].block); + do_free(entries[i].block); } } @@ -729,14 +735,36 @@ " deallocated; or else a word before the object has been" " corrupted (memory stomping bug)", p); } - // If mb->offset_ is zero (common case), mb is the real header. If - // mb->offset_ is non-zero, this block was allocated by memalign, and - // mb->offset_ is the distance backwards to the real header from mb, - // which is a fake header. The following subtraction works for both zero - // and non-zero values. - return reinterpret_cast( - reinterpret_cast(mb) - mb->offset_); + // If mb->offset_ is zero (common case), mb is the real header. + // If mb->offset_ is non-zero, this block was allocated by debug + // memallign implementation, and mb->offset_ is the distance + // backwards to the real header from mb, which is a fake header. + if (mb->offset_ == 0) { + return mb; + } + + MallocBlock *main_block = reinterpret_cast( + reinterpret_cast(mb) - mb->offset_); + + if (main_block->offset_ != 0) { + RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted." + " Need 0 but got %x", + (unsigned)(main_block->offset_)); + } + if (main_block >= p) { + RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted." + " Detected main_block address overflow: %x", + (unsigned)(mb->offset_)); + } + if (main_block->size2_addr() < p) { + RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted." + " It points below it's own main_block: %x", + (unsigned)(mb->offset_)); + } + + return main_block; } + static const MallocBlock* FromRawPointer(const void* p) { // const-safe version: we just cast about return FromRawPointer(const_cast(p)); @@ -1053,11 +1081,36 @@ } virtual MallocExtension::Ownership GetOwnership(const void* p) { - if (p) { - const MallocBlock* mb = MallocBlock::FromRawPointer(p); - return TCMallocImplementation::GetOwnership(mb); + if (!p) { + // nobody owns NULL + return MallocExtension::kNotOwned; + } + + // FIXME: note that correct GetOwnership should not touch memory + // that is not owned by tcmalloc. Main implementation is using + // pagemap to discover if page in question is owned by us or + // not. But pagemap only has marks for first and last page of + // spans. Note that if p was returned out of our memalign with + // big alignment, then it will point outside of marked pages. Also + // note that FromRawPointer call below requires touching memory + // before pointer in order to handle memalign-ed chunks + // (offset_). This leaves us with two options: + // + // * do FromRawPointer first and have possibility of crashing if + // we're given not owned pointer + // + // * return incorrect ownership for those large memalign chunks + // + // I've decided to choose later, which appears to happen rarer and + // therefore is arguably a lesser evil + + MallocExtension::Ownership rv = TCMallocImplementation::GetOwnership(p); + if (rv != MallocExtension::kOwned) { + return rv; } - return MallocExtension::kNotOwned; // nobody owns NULL + + const MallocBlock* mb = MallocBlock::FromRawPointer(p); + return TCMallocImplementation::GetOwnership(mb); } virtual void GetFreeListSizes(vector* v) { @@ -1075,14 +1128,22 @@ }; -static DebugMallocImplementation debug_malloc_implementation; +static union { + char chars[sizeof(DebugMallocImplementation)]; + void *ptr; +} debug_malloc_implementation_space; REGISTER_MODULE_INITIALIZER(debugallocation, { +#if (__cplusplus >= 201103L) + COMPILE_ASSERT(alignof(debug_malloc_implementation_space) >= alignof(DebugMallocImplementation), + debug_malloc_implementation_space_is_not_properly_aligned); +#endif // Either we or valgrind will control memory management. We // register our extension if we're the winner. Otherwise let // Valgrind use its own malloc (so don't register our extension). if (!RunningOnValgrind()) { - MallocExtension::Register(&debug_malloc_implementation); + DebugMallocImplementation *impl = new (debug_malloc_implementation_space.chars) DebugMallocImplementation(); + MallocExtension::Register(impl); } }); @@ -1202,8 +1263,18 @@ // return null if (p == NULL) return NULL; - memcpy(p->data_addr(), old->data_addr(), - (old->data_size() < size) ? old->data_size() : size); + // if ptr was allocated via memalign, then old->data_size() is not + // start of user data. So we must be careful to copy only user-data + char *old_begin = (char *)old->data_addr(); + char *old_end = old_begin + old->data_size(); + + ssize_t old_ssize = old_end - (char *)ptr; + CHECK_CONDITION(old_ssize >= 0); + + size_t old_size = (size_t)old_ssize; + CHECK_CONDITION(old_size <= old->data_size()); + + memcpy(p->data_addr(), ptr, (old_size < size) ? old_size : size); MallocHook::InvokeDeleteHook(ptr); MallocHook::InvokeNewHook(p->data_addr(), size); DebugDeallocate(ptr, MallocBlock::kMallocType); @@ -1266,12 +1337,6 @@ DebugDeallocate(p, MallocBlock::kArrayNewType); } -// Round "value" up to next "alignment" boundary. -// Requires that "alignment" be a power of two. -static intptr_t RoundUp(intptr_t value, intptr_t alignment) { - return (value + alignment - 1) & ~(alignment - 1); -} - // This is mostly the same as do_memalign in tcmalloc.cc. static void *do_debug_memalign(size_t alignment, size_t size) { // Allocate >= size bytes aligned on "alignment" boundary @@ -1297,6 +1362,9 @@ // p is now end of fake header (beginning of client area), // and orig_p is the end of the real header, so offset_ // is their difference. + // + // Note that other fields of fake_hdr are initialized with + // kMagicUninitializedByte fake_hdr->set_offset(reinterpret_cast(p) - orig_p); } return p; @@ -1402,19 +1470,25 @@ // malloc_stats just falls through to the base implementation. extern "C" PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW { - BASE_MALLOC_STATS(); + do_malloc_stats(); } extern "C" PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW { - return BASE_MALLOPT(cmd, value); + return do_mallopt(cmd, value); } #ifdef HAVE_STRUCT_MALLINFO extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW { - return BASE_MALLINFO(); + return do_mallinfo(); } #endif extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW { return MallocExtension::instance()->GetAllocatedSize(ptr); } + +extern "C" PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) __THROW { + void* result = DebugAllocate(size, MallocBlock::kMallocType); + MallocHook::InvokeNewHook(result, size); + return result; +} diff -Nru google-perftools-2.1/src/getenv_safe.h google-perftools-2.2.1/src/getenv_safe.h --- google-perftools-2.1/src/getenv_safe.h 1970-01-01 01:00:00.000000000 +0100 +++ google-perftools-2.2.1/src/getenv_safe.h 2014-06-07 22:54:00.000000000 +0200 @@ -0,0 +1,63 @@ +/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- + * Copyright (c) 2014, gperftools Contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GETENV_SAFE_H +#define GETENV_SAFE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This getenv function is safe to call before the C runtime is initialized. + * On Windows, it utilizes GetEnvironmentVariable() and on unix it uses + * /proc/self/environ instead calling getenv(). It's intended to be used in + * routines that run before main(), when the state required for getenv() may + * not be set up yet. In particular, errno isn't set up until relatively late + * (after the pthreads library has a chance to make it threadsafe), and + * getenv() doesn't work until then. + * On some platforms, this call will utilize the same, static buffer for + * repeated GetenvBeforeMain() calls. Callers should not expect pointers from + * this routine to be long lived. + * Note that on unix, /proc only has the environment at the time the + * application was started, so this routine ignores setenv() calls/etc. Also + * note it only reads the first 16K of the environment. + * + * NOTE: this is version of GetenvBeforeMain that's usable from + * C. Implementation is in sysinfo.cc + */ +const char* TCMallocGetenvSafe(const char* name); + +#ifdef __cplusplus +} +#endif + +#endif diff -Nru google-perftools-2.1/src/getpc.h google-perftools-2.2.1/src/getpc.h --- google-perftools-2.1/src/getpc.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/getpc.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/google/heap-checker.h google-perftools-2.2.1/src/google/heap-checker.h --- google-perftools-2.1/src/google/heap-checker.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/google/heap-checker.h 2014-04-13 03:35:40.000000000 +0200 @@ -30,4 +30,7 @@ /* The code has moved to gperftools/. Use that include-directory for * new code. */ +#ifdef __GNUC__ +#warning "google/heap-checker.h is deprecated. Use gperftools/heap-checker.h instead" +#endif #include diff -Nru google-perftools-2.1/src/google/heap-profiler.h google-perftools-2.2.1/src/google/heap-profiler.h --- google-perftools-2.1/src/google/heap-profiler.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/google/heap-profiler.h 2014-04-13 03:35:40.000000000 +0200 @@ -31,4 +31,7 @@ /* The code has moved to gperftools/. Use that include-directory for * new code. */ +#ifdef __GNUC__ +#warning "google/heap-profiler.h is deprecated. Use gperftools/heap-profiler.h instead" +#endif #include diff -Nru google-perftools-2.1/src/google/malloc_extension_c.h google-perftools-2.2.1/src/google/malloc_extension_c.h --- google-perftools-2.1/src/google/malloc_extension_c.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/google/malloc_extension_c.h 2014-04-13 03:35:40.000000000 +0200 @@ -31,4 +31,7 @@ /* The code has moved to gperftools/. Use that include-directory for * new code. */ +#ifdef __GNUC__ +#warning "google/malloc_extension_c.h is deprecated. Use gperftools/malloc_extension_c.h instead" +#endif #include diff -Nru google-perftools-2.1/src/google/malloc_extension.h google-perftools-2.2.1/src/google/malloc_extension.h --- google-perftools-2.1/src/google/malloc_extension.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/google/malloc_extension.h 2014-04-13 03:35:40.000000000 +0200 @@ -30,4 +30,7 @@ /* The code has moved to gperftools/. Use that include-directory for * new code. */ +#ifdef __GNUC__ +#warning "google/malloc_extension.h is deprecated. Use gperftools/malloc_extension.h instead" +#endif #include diff -Nru google-perftools-2.1/src/google/malloc_hook_c.h google-perftools-2.2.1/src/google/malloc_hook_c.h --- google-perftools-2.1/src/google/malloc_hook_c.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/google/malloc_hook_c.h 2014-04-13 03:35:40.000000000 +0200 @@ -31,4 +31,7 @@ /* The code has moved to gperftools/. Use that include-directory for * new code. */ +#ifdef __GNUC__ +#warning "google/malloc_hook_c.h is deprecated. Use gperftools/malloc_hook_c.h instead" +#endif #include diff -Nru google-perftools-2.1/src/google/malloc_hook.h google-perftools-2.2.1/src/google/malloc_hook.h --- google-perftools-2.1/src/google/malloc_hook.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/google/malloc_hook.h 2014-04-13 03:35:40.000000000 +0200 @@ -30,4 +30,7 @@ /* The code has moved to gperftools/. Use that include-directory for * new code. */ +#ifdef __GNUC__ +#warning "google/malloc_hook.h is deprecated. Use gperftools/malloc_hook.h instead" +#endif #include diff -Nru google-perftools-2.1/src/google/profiler.h google-perftools-2.2.1/src/google/profiler.h --- google-perftools-2.1/src/google/profiler.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/google/profiler.h 2014-04-13 03:35:40.000000000 +0200 @@ -31,4 +31,7 @@ /* The code has moved to gperftools/. Use that include-directory for * new code. */ +#ifdef __GNUC__ +#warning "google/profiler.h is deprecated. Use gperftools/profiler.h instead" +#endif #include diff -Nru google-perftools-2.1/src/google/stacktrace.h google-perftools-2.2.1/src/google/stacktrace.h --- google-perftools-2.1/src/google/stacktrace.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/google/stacktrace.h 2014-04-13 03:35:40.000000000 +0200 @@ -30,4 +30,7 @@ /* The code has moved to gperftools/. Use that include-directory for * new code. */ +#ifdef __GNUC__ +#warning "google/stacktrace.h is deprecated. Use gperftools/stacktrace.h instead" +#endif #include diff -Nru google-perftools-2.1/src/google/tcmalloc.h google-perftools-2.2.1/src/google/tcmalloc.h --- google-perftools-2.1/src/google/tcmalloc.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/google/tcmalloc.h 2014-04-13 03:35:40.000000000 +0200 @@ -31,4 +31,7 @@ /* The code has moved to gperftools/. Use that include-directory for * new code. */ +#ifdef __GNUC__ +#warning "google/tcmalloc.h is deprecated. Use gperftools/tcmalloc.h instead" +#endif #include diff -Nru google-perftools-2.1/src/gperftools/heap-checker.h google-perftools-2.2.1/src/gperftools/heap-checker.h --- google-perftools-2.1/src/gperftools/heap-checker.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/gperftools/heap-checker.h 2014-03-29 21:29:12.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -239,9 +240,6 @@ friend void NamedTwoDisabledLeaks(); friend void* RunNamedDisabledLeaks(void*); friend void TestHeapLeakCheckerNamedDisabling(); - // TODO(csilvers): remove this one, at least - friend int main(int, char**); - // Actually implements IgnoreObject(). static void DoIgnoreObject(const void* ptr); @@ -256,15 +254,15 @@ // Helper for DoNoLeaks to ignore all objects reachable from all live data static void IgnoreAllLiveObjectsLocked(const void* self_stack_top); - // Callback we pass to ListAllProcessThreads (see thread_lister.h) + // Callback we pass to TCMalloc_ListAllProcessThreads (see thread_lister.h) // that is invoked when all threads of our process are found and stopped. // The call back does the things needed to ignore live data reachable from // thread stacks and registers for all our threads // as well as do other global-live-data ignoring // (via IgnoreNonThreadLiveObjectsLocked) // during the quiet state of all threads being stopped. - // For the argument meaning see the comment by ListAllProcessThreads. - // Here we only use num_threads and thread_pids, that ListAllProcessThreads + // For the argument meaning see the comment by TCMalloc_ListAllProcessThreads. + // Here we only use num_threads and thread_pids, that TCMalloc_ListAllProcessThreads // fills for us with the number and pids of all the threads of our process // it found and attached to. static int IgnoreLiveThreadsLocked(void* parameter, diff -Nru google-perftools-2.1/src/gperftools/heap-profiler.h google-perftools-2.2.1/src/gperftools/heap-profiler.h --- google-perftools-2.1/src/gperftools/heap-profiler.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/gperftools/heap-profiler.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2005, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/gperftools/malloc_extension.h google-perftools-2.2.1/src/gperftools/malloc_extension.h --- google-perftools-2.1/src/gperftools/malloc_extension.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/gperftools/malloc_extension.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -71,7 +72,7 @@ } // Interface to a pluggable system allocator. -class SysAllocator { +class PERFTOOLS_DLL_DECL SysAllocator { public: SysAllocator() { } diff -Nru google-perftools-2.1/src/gperftools/malloc_hook.h google-perftools-2.2.1/src/gperftools/malloc_hook.h --- google-perftools-2.1/src/gperftools/malloc_hook.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/gperftools/malloc_hook.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/gperftools/profiler.h google-perftools-2.2.1/src/gperftools/profiler.h --- google-perftools-2.1/src/gperftools/profiler.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/gperftools/profiler.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2005, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/gperftools/stacktrace.h google-perftools-2.2.1/src/gperftools/stacktrace.h --- google-perftools-2.1/src/gperftools/stacktrace.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/gperftools/stacktrace.h 2014-02-09 01:17:55.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/gperftools/tcmalloc.h.in google-perftools-2.2.1/src/gperftools/tcmalloc.h.in --- google-perftools-2.1/src/gperftools/tcmalloc.h.in 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/gperftools/tcmalloc.h.in 2014-04-13 03:35:40.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2003, Google Inc. * All rights reserved. * @@ -88,6 +89,7 @@ const char** patch) __THROW; PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW; + PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) __THROW; PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW; PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW; PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) __THROW; diff -Nru google-perftools-2.1/src/heap-checker-bcad.cc google-perftools-2.2.1/src/heap-checker-bcad.cc --- google-perftools-2.1/src/heap-checker-bcad.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/heap-checker-bcad.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/heap-checker.cc google-perftools-2.2.1/src/heap-checker.cc --- google-perftools-2.1/src/heap-checker.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/heap-checker.cc 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -285,7 +286,7 @@ // Wrapper of LowLevelAlloc for STL_Allocator and direct use. // We always access this class under held heap_checker_lock, // this allows us to in particular protect the period when threads are stopped -// at random spots with ListAllProcessThreads by heap_checker_lock, +// at random spots with TCMalloc_ListAllProcessThreads by heap_checker_lock, // w/o worrying about the lock in LowLevelAlloc::Arena. // We rely on the fact that we use an own arena with an own lock here. class HeapLeakChecker::Allocator { @@ -1043,7 +1044,7 @@ THREAD_REGS thread_regs; #define sys_ptrace(r, p, a, d) syscall(SYS_ptrace, (r), (p), (a), (d)) // We use sys_ptrace to avoid thread locking - // because this is called from ListAllProcessThreads + // because this is called from TCMalloc_ListAllProcessThreads // when all but this thread are suspended. if (sys_ptrace(PTRACE_GETREGS, thread_pids[i], NULL, &thread_regs) == 0) { // Need to use SP to get all the data from the very last stack frame: @@ -1079,7 +1080,7 @@ // Do all other liveness walking while all threads are stopped: IgnoreNonThreadLiveObjectsLocked(); // Can now resume the threads: - ResumeAllProcessThreads(num_threads, thread_pids); + TCMalloc_ResumeAllProcessThreads(num_threads, thread_pids); thread_listing_status = CALLBACK_COMPLETED; return failures; } @@ -1237,7 +1238,7 @@ } } -// Callback for ListAllProcessThreads in IgnoreAllLiveObjectsLocked below +// Callback for TCMalloc_ListAllProcessThreads in IgnoreAllLiveObjectsLocked below // to test/verify that we have just the one main thread, in which case // we can do everything in that main thread, // so that CPU profiler can collect all its samples. @@ -1248,7 +1249,7 @@ RAW_LOG(WARNING, "Have threads: Won't CPU-profile the bulk of leak " "checking work happening in IgnoreLiveThreadsLocked!"); } - ResumeAllProcessThreads(num_threads, thread_pids); + TCMalloc_ResumeAllProcessThreads(num_threads, thread_pids); return num_threads; } @@ -1290,16 +1291,17 @@ if (FLAGS_heap_check_ignore_thread_live) { // In case we are doing CPU profiling we'd like to do all the work // in the main thread, not in the special thread created by - // ListAllProcessThreads, so that CPU profiler can collect all its samples. - // The machinery of ListAllProcessThreads conflicts with the CPU profiler - // by also relying on signals and ::sigaction. - // We can do this (run everything in the main thread) safely - // only if there's just the main thread itself in our process. - // This variable reflects these two conditions: + // TCMalloc_ListAllProcessThreads, so that CPU profiler can + // collect all its samples. The machinery of + // TCMalloc_ListAllProcessThreads conflicts with the CPU profiler + // by also relying on signals and ::sigaction. We can do this + // (run everything in the main thread) safely only if there's just + // the main thread itself in our process. This variable reflects + // these two conditions: bool want_and_can_run_in_main_thread = ProfilingIsEnabledForAllThreads() && - ListAllProcessThreads(NULL, IsOneThread) == 1; - // When the normal path of ListAllProcessThreads below is taken, + TCMalloc_ListAllProcessThreads(NULL, IsOneThread) == 1; + // When the normal path of TCMalloc_ListAllProcessThreads below is taken, // we fully suspend the threads right here before any liveness checking // and keep them suspended for the whole time of liveness checking // inside of the IgnoreLiveThreadsLocked callback. @@ -1308,7 +1310,7 @@ // graph while we walk it). int r = want_and_can_run_in_main_thread ? IgnoreLiveThreadsLocked(NULL, 1, &self_thread_pid, dummy_ap) - : ListAllProcessThreads(NULL, IgnoreLiveThreadsLocked); + : TCMalloc_ListAllProcessThreads(NULL, IgnoreLiveThreadsLocked); need_to_ignore_non_thread_objects = r < 0; if (r < 0) { RAW_LOG(WARNING, "Thread finding failed with %d errno=%d", r, errno); @@ -1651,8 +1653,13 @@ // Save pid of main thread for using in naming dump files static int32 main_thread_pid = getpid(); #ifdef HAVE_PROGRAM_INVOCATION_NAME +#ifdef __UCLIBC__ +extern const char* program_invocation_name; +extern const char* program_invocation_short_name; +#else extern char* program_invocation_name; extern char* program_invocation_short_name; +#endif static const char* invocation_name() { return program_invocation_short_name; } static string invocation_path() { return program_invocation_name; } #else @@ -2206,13 +2213,14 @@ RAW_CHECK(MallocHook::AddNewHook(&NewHook), ""); RAW_CHECK(MallocHook::AddDeleteHook(&DeleteHook), ""); constructor_heap_profiling = true; - MemoryRegionMap::Init(1); + MemoryRegionMap::Init(1, /* use_buckets */ false); // Set up MemoryRegionMap with (at least) one caller stack frame to record // (important that it's done before HeapProfileTable creation below). Allocator::Init(); RAW_CHECK(heap_profile == NULL, ""); heap_profile = new(Allocator::Allocate(sizeof(HeapProfileTable))) - HeapProfileTable(&Allocator::Allocate, &Allocator::Free); + HeapProfileTable(&Allocator::Allocate, &Allocator::Free, + /* profile_mmap */ false); RAW_VLOG(10, "Starting tracking the heap"); heap_checker_on = true; } diff -Nru google-perftools-2.1/src/heap-profiler.cc google-perftools-2.2.1/src/heap-profiler.cc --- google-perftools-2.1/src/heap-profiler.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/heap-profiler.cc 2014-04-13 02:18:02.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -51,6 +52,7 @@ #include #include #include +#include #include #include @@ -190,13 +192,14 @@ RAW_DCHECK(heap_lock.IsHeld(), ""); int bytes_written = 0; if (is_on) { - if (FLAGS_mmap_profile) { - heap_profile->RefreshMMapData(); - } + HeapProfileTable::Stats const stats = heap_profile->total(); + (void)stats; // avoid an unused-variable warning in non-debug mode. bytes_written = heap_profile->FillOrderedProfile(buf, buflen - 1); - if (FLAGS_mmap_profile) { - heap_profile->ClearMMapData(); - } + // FillOrderedProfile should not reduce the set of active mmap-ed regions, + // hence MemoryRegionMap will let us remove everything we've added above: + RAW_DCHECK(stats.Equivalent(heap_profile->total()), ""); + // if this fails, we somehow removed by FillOrderedProfile + // more than we have added. } buf[bytes_written] = '\0'; RAW_DCHECK(bytes_written == strlen(buf), ""); @@ -435,7 +438,8 @@ if (FLAGS_mmap_profile) { // Ask MemoryRegionMap to record all mmap, mremap, and sbrk // call stack traces of at least size kMaxStackDepth: - MemoryRegionMap::Init(HeapProfileTable::kMaxStackDepth); + MemoryRegionMap::Init(HeapProfileTable::kMaxStackDepth, + /* use_buckets */ true); } if (FLAGS_mmap_log) { @@ -455,7 +459,7 @@ reinterpret_cast(ProfilerMalloc(kProfileBufferSize)); heap_profile = new(ProfilerMalloc(sizeof(HeapProfileTable))) - HeapProfileTable(ProfilerMalloc, ProfilerFree); + HeapProfileTable(ProfilerMalloc, ProfilerFree, FLAGS_mmap_profile); last_dump_alloc = 0; last_dump_free = 0; @@ -533,6 +537,20 @@ } } +// Signal handler that is registered when a user selectable signal +// number is defined in the environment variable HEAPPROFILESIGNAL. +static void HeapProfilerDumpSignal(int signal_number) { + (void)signal_number; + if (!heap_lock.TryLock()) { + return; + } + if (is_on && !dumping) { + DumpProfileLocked("signal"); + } + heap_lock.Unlock(); +} + + //---------------------------------------------------------------------- // Initialization/finalization code //---------------------------------------------------------------------- @@ -553,6 +571,19 @@ } #endif + char *signal_number_str = getenv("HEAPPROFILESIGNAL"); + if (signal_number_str != NULL) { + long int signal_number = strtol(signal_number_str, NULL, 10); + intptr_t old_signal_handler = reinterpret_cast(signal(signal_number, HeapProfilerDumpSignal)); + if (old_signal_handler == reinterpret_cast(SIG_ERR)) { + RAW_LOG(FATAL, "Failed to set signal. Perhaps signal number %s is invalid\n", signal_number_str); + } else if (old_signal_handler == 0) { + RAW_LOG(INFO,"Using signal %d as heap profiling switch", signal_number); + } else { + RAW_LOG(FATAL, "Signal %d already in use\n", signal_number); + } + } + HeapProfileTable::CleanupOldProfiles(fname); HeapProfilerStart(fname); diff -Nru google-perftools-2.1/src/heap-profile-stats.h google-perftools-2.2.1/src/heap-profile-stats.h --- google-perftools-2.1/src/heap-profile-stats.h 1970-01-01 01:00:00.000000000 +0100 +++ google-perftools-2.2.1/src/heap-profile-stats.h 2013-09-22 04:03:49.000000000 +0200 @@ -0,0 +1,78 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2013, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file defines structs to accumulate memory allocation and deallocation +// counts. These structs are commonly used for malloc (in HeapProfileTable) +// and mmap (in MemoryRegionMap). + +// A bucket is data structure for heap profiling to store a pair of a stack +// trace and counts of (de)allocation. Buckets are stored in a hash table +// which is declared as "HeapProfileBucket**". +// +// A hash value is computed from a stack trace. Collision in the hash table +// is resolved by separate chaining with linked lists. The links in the list +// are implemented with the member "HeapProfileBucket* next". +// +// A structure of a hash table HeapProfileBucket** bucket_table would be like: +// bucket_table[0] => NULL +// bucket_table[1] => HeapProfileBucket() => HeapProfileBucket() => NULL +// ... +// bucket_table[i] => HeapProfileBucket() => NULL +// ... +// bucket_table[n] => HeapProfileBucket() => NULL + +#ifndef HEAP_PROFILE_STATS_H_ +#define HEAP_PROFILE_STATS_H_ + +struct HeapProfileStats { + // Returns true if the two HeapProfileStats are semantically equal. + bool Equivalent(const HeapProfileStats& other) const { + return allocs - frees == other.allocs - other.frees && + alloc_size - free_size == other.alloc_size - other.free_size; + } + + int32 allocs; // Number of allocation calls. + int32 frees; // Number of free calls. + int64 alloc_size; // Total size of all allocated objects so far. + int64 free_size; // Total size of all freed objects so far. +}; + +// Allocation and deallocation statistics per each stack trace. +struct HeapProfileBucket : public HeapProfileStats { + // Longest stack trace we record. + static const int kMaxStackDepth = 32; + + uintptr_t hash; // Hash value of the stack trace. + int depth; // Depth of stack trace. + const void** stack; // Stack trace. + HeapProfileBucket* next; // Next entry in hash-table. +}; + +#endif // HEAP_PROFILE_STATS_H_ diff -Nru google-perftools-2.1/src/heap-profile-table.cc google-perftools-2.2.1/src/heap-profile-table.cc --- google-perftools-2.1/src/heap-profile-table.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/heap-profile-table.cc 2013-12-06 21:16:47.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2006, Google Inc. // All rights reserved. // @@ -99,8 +100,7 @@ //---------------------------------------------------------------------- -// Size for alloc_table_ and mmap_table_. -static const int kHashTableSize = 179999; +static const int kHashTableSize = 179999; // Size for bucket_table_. /*static*/ const int HeapProfileTable::kMaxStackDepth; //---------------------------------------------------------------------- @@ -122,62 +122,50 @@ //---------------------------------------------------------------------- -HeapProfileTable::HeapProfileTable(Allocator alloc, DeAllocator dealloc) - : alloc_(alloc), dealloc_(dealloc) { - // Initialize the overall profile stats. - memset(&total_, 0, sizeof(total_)); - - // Make the malloc table. - const int alloc_table_bytes = kHashTableSize * sizeof(*alloc_table_); - alloc_table_ = reinterpret_cast(alloc_(alloc_table_bytes)); - memset(alloc_table_, 0, alloc_table_bytes); - num_alloc_buckets_ = 0; - - // Initialize the mmap table. - mmap_table_ = NULL; - num_available_mmap_buckets_ = 0; +HeapProfileTable::HeapProfileTable(Allocator alloc, + DeAllocator dealloc, + bool profile_mmap) + : alloc_(alloc), + dealloc_(dealloc), + profile_mmap_(profile_mmap), + bucket_table_(NULL), + num_buckets_(0), + address_map_(NULL) { + // Make a hash table for buckets. + const int table_bytes = kHashTableSize * sizeof(*bucket_table_); + bucket_table_ = static_cast(alloc_(table_bytes)); + memset(bucket_table_, 0, table_bytes); - // Make malloc and mmap allocation maps. - alloc_address_map_ = + // Make an allocation map. + address_map_ = new(alloc_(sizeof(AllocationMap))) AllocationMap(alloc_, dealloc_); - mmap_address_map_ = NULL; -} -HeapProfileTable::~HeapProfileTable() { - DeallocateBucketTable(alloc_table_); - alloc_table_ = NULL; - DeallocateBucketTable(mmap_table_); - mmap_table_ = NULL; - DeallocateAllocationMap(alloc_address_map_); - alloc_address_map_ = NULL; - DeallocateAllocationMap(mmap_address_map_); - mmap_address_map_ = NULL; -} - -void HeapProfileTable::DeallocateAllocationMap(AllocationMap* allocation) { - if (allocation != NULL) { - alloc_address_map_->~AllocationMap(); - dealloc_(allocation); - } + // Initialize. + memset(&total_, 0, sizeof(total_)); + num_buckets_ = 0; } -void HeapProfileTable::DeallocateBucketTable(Bucket** table) { - if (table != NULL) { - for (int b = 0; b < kHashTableSize; b++) { - for (Bucket* x = table[b]; x != 0; /**/) { - Bucket* b = x; - x = x->next; - dealloc_(b->stack); - dealloc_(b); - } +HeapProfileTable::~HeapProfileTable() { + // Free the allocation map. + address_map_->~AllocationMap(); + dealloc_(address_map_); + address_map_ = NULL; + + // Free the hash table. + for (int i = 0; i < kHashTableSize; i++) { + for (Bucket* curr = bucket_table_[i]; curr != 0; /**/) { + Bucket* bucket = curr; + curr = curr->next; + dealloc_(bucket->stack); + dealloc_(bucket); } - dealloc_(table); } + dealloc_(bucket_table_); + bucket_table_ = NULL; } -HeapProfileTable::Bucket* HeapProfileTable::GetBucket( - int depth, const void* const key[], Bucket** table, - int* bucket_count) { +HeapProfileTable::Bucket* HeapProfileTable::GetBucket(int depth, + const void* const key[]) { // Make hash-value uintptr_t h = 0; for (int i = 0; i < depth; i++) { @@ -190,7 +178,7 @@ // Lookup stack trace in table unsigned int buck = ((unsigned int) h) % kHashTableSize; - for (Bucket* b = table[buck]; b != 0; b = b->next) { + for (Bucket* b = bucket_table_[buck]; b != 0; b = b->next) { if ((b->hash == h) && (b->depth == depth) && equal(key, key + depth, b->stack)) { @@ -207,11 +195,9 @@ b->hash = h; b->depth = depth; b->stack = kcopy; - b->next = table[buck]; - table[buck] = b; - if (bucket_count != NULL) { - ++(*bucket_count); - } + b->next = bucket_table_[buck]; + bucket_table_[buck] = b; + num_buckets_++; return b; } @@ -224,8 +210,7 @@ void HeapProfileTable::RecordAlloc( const void* ptr, size_t bytes, int stack_depth, const void* const call_stack[]) { - Bucket* b = GetBucket(stack_depth, call_stack, alloc_table_, - &num_alloc_buckets_); + Bucket* b = GetBucket(stack_depth, call_stack); b->allocs++; b->alloc_size += bytes; total_.allocs++; @@ -234,12 +219,12 @@ AllocValue v; v.set_bucket(b); // also did set_live(false); set_ignore(false) v.bytes = bytes; - alloc_address_map_->Insert(ptr, v); + address_map_->Insert(ptr, v); } void HeapProfileTable::RecordFree(const void* ptr) { AllocValue v; - if (alloc_address_map_->FindAndRemove(ptr, &v)) { + if (address_map_->FindAndRemove(ptr, &v)) { Bucket* b = v.bucket(); b->frees++; b->free_size += v.bytes; @@ -249,14 +234,14 @@ } bool HeapProfileTable::FindAlloc(const void* ptr, size_t* object_size) const { - const AllocValue* alloc_value = alloc_address_map_->Find(ptr); + const AllocValue* alloc_value = address_map_->Find(ptr); if (alloc_value != NULL) *object_size = alloc_value->bytes; return alloc_value != NULL; } bool HeapProfileTable::FindAllocDetails(const void* ptr, AllocInfo* info) const { - const AllocValue* alloc_value = alloc_address_map_->Find(ptr); + const AllocValue* alloc_value = address_map_->Find(ptr); if (alloc_value != NULL) { info->object_size = alloc_value->bytes; info->call_stack = alloc_value->bucket()->stack; @@ -270,13 +255,13 @@ const void** object_ptr, size_t* object_size) const { const AllocValue* alloc_value = - alloc_address_map_->FindInside(&AllocValueSize, max_size, ptr, object_ptr); + address_map_->FindInside(&AllocValueSize, max_size, ptr, object_ptr); if (alloc_value != NULL) *object_size = alloc_value->bytes; return alloc_value != NULL; } bool HeapProfileTable::MarkAsLive(const void* ptr) { - AllocValue* alloc = alloc_address_map_->FindMutable(ptr); + AllocValue* alloc = address_map_->FindMutable(ptr); if (alloc && !alloc->live()) { alloc->set_live(true); return true; @@ -285,7 +270,7 @@ } void HeapProfileTable::MarkAsIgnored(const void* ptr) { - AllocValue* alloc = alloc_address_map_->FindMutable(ptr); + AllocValue* alloc = address_map_->FindMutable(ptr); if (alloc) { alloc->set_ignore(true); } @@ -326,81 +311,26 @@ HeapProfileTable::Bucket** HeapProfileTable::MakeSortedBucketList() const { - Bucket** list = reinterpret_cast(alloc_(sizeof(Bucket) * - (num_alloc_buckets_ + num_available_mmap_buckets_))); + Bucket** list = static_cast(alloc_(sizeof(Bucket) * num_buckets_)); - RAW_DCHECK(mmap_table_ != NULL || num_available_mmap_buckets_ == 0, ""); - - int n = 0; - - for (int b = 0; b < kHashTableSize; b++) { - for (Bucket* x = alloc_table_[b]; x != 0; x = x->next) { - list[n++] = x; + int bucket_count = 0; + for (int i = 0; i < kHashTableSize; i++) { + for (Bucket* curr = bucket_table_[i]; curr != 0; curr = curr->next) { + list[bucket_count++] = curr; } } - RAW_DCHECK(n == num_alloc_buckets_, ""); + RAW_DCHECK(bucket_count == num_buckets_, ""); - if (mmap_table_ != NULL) { - for (int b = 0; b < kHashTableSize; b++) { - for (Bucket* x = mmap_table_[b]; x != 0; x = x->next) { - list[n++] = x; - } - } - } - RAW_DCHECK(n == num_alloc_buckets_ + num_available_mmap_buckets_, ""); - - sort(list, list + num_alloc_buckets_ + num_available_mmap_buckets_, - ByAllocatedSpace); + sort(list, list + num_buckets_, ByAllocatedSpace); return list; } -void HeapProfileTable::RefreshMMapData() { - // Make the table - static const int mmap_table_bytes = kHashTableSize * sizeof(*mmap_table_); - if (mmap_table_ == NULL) { - mmap_table_ = reinterpret_cast(alloc_(mmap_table_bytes)); - memset(mmap_table_, 0, mmap_table_bytes); - } - num_available_mmap_buckets_ = 0; - - ClearMMapData(); - mmap_address_map_ = - new(alloc_(sizeof(AllocationMap))) AllocationMap(alloc_, dealloc_); - - MemoryRegionMap::LockHolder l; - for (MemoryRegionMap::RegionIterator r = - MemoryRegionMap::BeginRegionLocked(); - r != MemoryRegionMap::EndRegionLocked(); ++r) { - Bucket* b = - GetBucket(r->call_stack_depth, r->call_stack, mmap_table_, NULL); - if (b->alloc_size == 0) { - num_available_mmap_buckets_ += 1; - } - b->allocs += 1; - b->alloc_size += r->end_addr - r->start_addr; - - AllocValue v; - v.set_bucket(b); - v.bytes = r->end_addr - r->start_addr; - mmap_address_map_->Insert(reinterpret_cast(r->start_addr), v); - } -} - -void HeapProfileTable::ClearMMapData() { - if (mmap_address_map_ != NULL) { - mmap_address_map_->Iterate(ZeroBucketCountsIterator, this); - mmap_address_map_->~AllocationMap(); - dealloc_(mmap_address_map_); - mmap_address_map_ = NULL; - } -} - void HeapProfileTable::IterateOrderedAllocContexts( AllocContextIterator callback) const { Bucket** list = MakeSortedBucketList(); AllocContextInfo info; - for (int i = 0; i < num_alloc_buckets_; ++i) { + for (int i = 0; i < num_buckets_; ++i) { *static_cast(&info) = *static_cast(list[i]); info.stack_depth = list[i]->depth; info.call_stack = list[i]->stack; @@ -432,14 +362,17 @@ memset(&stats, 0, sizeof(stats)); int bucket_length = snprintf(buf, size, "%s", kProfileHeader); if (bucket_length < 0 || bucket_length >= size) return 0; - Bucket total_with_mmap(total_); - if (mmap_table_ != NULL) { - total_with_mmap.alloc_size += MemoryRegionMap::MapSize(); - total_with_mmap.free_size += MemoryRegionMap::UnmapSize(); - } - bucket_length = UnparseBucket(total_with_mmap, buf, bucket_length, size, + bucket_length = UnparseBucket(total_, buf, bucket_length, size, " heapprofile", &stats); - for (int i = 0; i < num_alloc_buckets_; i++) { + + // Dump the mmap list first. + if (profile_mmap_) { + BufferArgs buffer(buf, bucket_length, size); + MemoryRegionMap::IterateBuckets(DumpBucketIterator, &buffer); + bucket_length = buffer.buflen; + } + + for (int i = 0; i < num_buckets_; i++) { bucket_length = UnparseBucket(*list[i], buf, bucket_length, size, "", &stats); } @@ -453,6 +386,13 @@ return bucket_length + map_length; } +// static +void HeapProfileTable::DumpBucketIterator(const Bucket* bucket, + BufferArgs* args) { + args->buflen = UnparseBucket(*bucket, args->buf, args->buflen, args->bufsize, + "", NULL); +} + inline void HeapProfileTable::DumpNonLiveIterator(const void* ptr, AllocValue* v, const DumpArgs& args) { @@ -474,17 +414,6 @@ RawWrite(args.fd, buf, len); } -inline void HeapProfileTable::ZeroBucketCountsIterator( - const void* ptr, AllocValue* v, HeapProfileTable* heap_profile) { - Bucket* b = v->bucket(); - if (b != NULL) { - b->allocs = 0; - b->alloc_size = 0; - b->free_size = 0; - b->frees = 0; - } -} - // Callback from NonLiveSnapshot; adds entry to arg->dest // if not the entry is not live and is not present in arg->base. void HeapProfileTable::AddIfNonLive(const void* ptr, AllocValue* v, @@ -549,7 +478,7 @@ HeapProfileTable::Snapshot* HeapProfileTable::TakeSnapshot() { Snapshot* s = new (alloc_(sizeof(Snapshot))) Snapshot(alloc_, dealloc_); - alloc_address_map_->Iterate(AddToSnapshot, s); + address_map_->Iterate(AddToSnapshot, s); return s; } @@ -574,7 +503,7 @@ AddNonLiveArgs args; args.dest = s; args.base = base; - alloc_address_map_->Iterate(AddIfNonLive, &args); + address_map_->Iterate(AddIfNonLive, &args); RAW_VLOG(2, "NonLiveSnapshot output: %d %d\n", int(s->total_.allocs - s->total_.frees), int(s->total_.alloc_size - s->total_.free_size)); diff -Nru google-perftools-2.1/src/heap-profile-table.h google-perftools-2.2.1/src/heap-profile-table.h --- google-perftools-2.1/src/heap-profile-table.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/heap-profile-table.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2006, Google Inc. // All rights reserved. // @@ -38,6 +39,7 @@ #include "addressmap-inl.h" #include "base/basictypes.h" #include "base/logging.h" // for RawFD +#include "heap-profile-stats.h" // Table to maintain a heap profile data inside, // i.e. the set of currently active heap memory allocations. @@ -58,18 +60,7 @@ // data types ---------------------------- // Profile stats. - struct Stats { - int32 allocs; // Number of allocation calls - int32 frees; // Number of free calls - int64 alloc_size; // Total size of all allocated objects so far - int64 free_size; // Total size of all freed objects so far - - // semantic equality - bool Equivalent(const Stats& x) const { - return allocs - frees == x.allocs - x.frees && - alloc_size - free_size == x.alloc_size - x.free_size; - } - }; + typedef HeapProfileStats Stats; // Info we can return about an allocation. struct AllocInfo { @@ -94,7 +85,7 @@ // interface --------------------------- - HeapProfileTable(Allocator alloc, DeAllocator dealloc); + HeapProfileTable(Allocator alloc, DeAllocator dealloc, bool profile_mmap); ~HeapProfileTable(); // Collect the stack trace for the function that asked to do the @@ -149,7 +140,7 @@ // Iterate over the allocation profile data calling "callback" // for every allocation. void IterateAllocs(AllocIterator callback) const { - alloc_address_map_->Iterate(MapArgsAllocIterator, callback); + address_map_->Iterate(MapArgsAllocIterator, callback); } // Allocation context profile data iteration callback @@ -187,28 +178,13 @@ // Caller must call ReleaseSnapshot() on result when no longer needed. Snapshot* NonLiveSnapshot(Snapshot* base); - // Refresh the internal mmap information from MemoryRegionMap. Results of - // FillOrderedProfile and IterateOrderedAllocContexts will contain mmap'ed - // memory regions as at calling RefreshMMapData. - void RefreshMMapData(); - - // Clear the internal mmap information. Results of FillOrderedProfile and - // IterateOrderedAllocContexts won't contain mmap'ed memory regions after - // calling ClearMMapData. - void ClearMMapData(); - private: // data types ---------------------------- // Hash table bucket to hold (de)allocation stats // for a given allocation call stack trace. - struct Bucket : public Stats { - uintptr_t hash; // Hash value of the stack trace - int depth; // Depth of stack trace - const void** stack; // Stack trace - Bucket* next; // Next entry in hash-table - }; + typedef HeapProfileBucket Bucket; // Info stored in the address map struct AllocValue { @@ -247,13 +223,30 @@ typedef AddressMap AllocationMap; + // Arguments that need to be passed DumpBucketIterator callback below. + struct BufferArgs { + BufferArgs(char* buf_arg, int buflen_arg, int bufsize_arg) + : buf(buf_arg), + buflen(buflen_arg), + bufsize(bufsize_arg) { + } + + char* buf; + int buflen; + int bufsize; + + DISALLOW_COPY_AND_ASSIGN(BufferArgs); + }; + // Arguments that need to be passed DumpNonLiveIterator callback below. struct DumpArgs { + DumpArgs(RawFD fd_arg, Stats* profile_stats_arg) + : fd(fd_arg), + profile_stats(profile_stats_arg) { + } + RawFD fd; // file to write to Stats* profile_stats; // stats to update (may be NULL) - - DumpArgs(RawFD a, Stats* d) - : fd(a), profile_stats(d) { } }; // helpers ---------------------------- @@ -274,18 +267,9 @@ const char* extra, Stats* profile_stats); - // Deallocate a given allocation map. - void DeallocateAllocationMap(AllocationMap* allocation); - - // Deallocate a given bucket table. - void DeallocateBucketTable(Bucket** table); - - // Get the bucket for the caller stack trace 'key' of depth 'depth' from a - // bucket hash map 'table' creating the bucket if needed. '*bucket_count' - // is incremented both when 'bucket_count' is not NULL and when a new - // bucket object is created. - Bucket* GetBucket(int depth, const void* const key[], Bucket** table, - int* bucket_count); + // Get the bucket for the caller stack trace 'key' of depth 'depth' + // creating the bucket if needed. + Bucket* GetBucket(int depth, const void* const key[]); // Helper for IterateAllocs to do callback signature conversion // from AllocationMap::Iterate to AllocIterator. @@ -300,18 +284,17 @@ callback(ptr, info); } + // Helper to dump a bucket. + inline static void DumpBucketIterator(const Bucket* bucket, + BufferArgs* args); + // Helper for DumpNonLiveProfile to do object-granularity // heap profile dumping. It gets passed to AllocationMap::Iterate. inline static void DumpNonLiveIterator(const void* ptr, AllocValue* v, const DumpArgs& args); - // Helper for filling size variables in buckets by zero. - inline static void ZeroBucketCountsIterator( - const void* ptr, AllocValue* v, HeapProfileTable* heap_profile); - // Helper for IterateOrderedAllocContexts and FillOrderedProfile. - // Creates a sorted list of Buckets whose length is num_alloc_buckets_ + - // num_avaliable_mmap_buckets_. + // Creates a sorted list of Buckets whose length is num_buckets_. // The caller is responsible for deallocating the returned list. Bucket** MakeSortedBucketList() const; @@ -344,25 +327,19 @@ // Overall profile stats; we use only the Stats part, // but make it a Bucket to pass to UnparseBucket. - // It doesn't contain mmap'ed regions. Bucket total_; + bool profile_mmap_; + // Bucket hash table for malloc. // We hand-craft one instead of using one of the pre-written // ones because we do not want to use malloc when operating on the table. // It is only few lines of code, so no big deal. - Bucket** alloc_table_; - int num_alloc_buckets_; - - // Bucket hash table for mmap. - // This table is filled with the information from MemoryRegionMap by calling - // RefreshMMapData. - Bucket** mmap_table_; - int num_available_mmap_buckets_; + Bucket** bucket_table_; + int num_buckets_; // Map of all currently allocated objects and mapped regions we know about. - AllocationMap* alloc_address_map_; - AllocationMap* mmap_address_map_; + AllocationMap* address_map_; DISALLOW_COPY_AND_ASSIGN(HeapProfileTable); }; diff -Nru google-perftools-2.1/src/internal_logging.cc google-perftools-2.2.1/src/internal_logging.cc --- google-perftools-2.1/src/internal_logging.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/internal_logging.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/internal_logging.h google-perftools-2.2.1/src/internal_logging.h --- google-perftools-2.1/src/internal_logging.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/internal_logging.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/libc_override_gcc_and_weak.h google-perftools-2.2.1/src/libc_override_gcc_and_weak.h --- google-perftools-2.1/src/libc_override_gcc_and_weak.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/libc_override_gcc_and_weak.h 2014-06-21 21:22:58.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2011, Google Inc. // All rights reserved. // @@ -81,13 +82,20 @@ void* pvalloc(size_t size) __THROW ALIAS(tc_pvalloc); int posix_memalign(void** r, size_t a, size_t s) __THROW ALIAS(tc_posix_memalign); +#ifndef __UCLIBC__ void malloc_stats(void) __THROW ALIAS(tc_malloc_stats); +#endif int mallopt(int cmd, int value) __THROW ALIAS(tc_mallopt); #ifdef HAVE_STRUCT_MALLINFO struct mallinfo mallinfo(void) __THROW ALIAS(tc_mallinfo); #endif size_t malloc_size(void* p) __THROW ALIAS(tc_malloc_size); +#if defined(__ANDROID__) + size_t malloc_usable_size(const void* p) __THROW + ALIAS(tc_malloc_size); +#else size_t malloc_usable_size(void* p) __THROW ALIAS(tc_malloc_size); +#endif } // extern "C" #undef ALIAS diff -Nru google-perftools-2.1/src/libc_override_glibc.h google-perftools-2.2.1/src/libc_override_glibc.h --- google-perftools-2.1/src/libc_override_glibc.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/libc_override_glibc.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2011, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/libc_override.h google-perftools-2.2.1/src/libc_override.h --- google-perftools-2.1/src/libc_override.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/libc_override.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2011, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/libc_override_osx.h google-perftools-2.2.1/src/libc_override_osx.h --- google-perftools-2.1/src/libc_override_osx.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/libc_override_osx.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2011, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/libc_override_redefine.h google-perftools-2.2.1/src/libc_override_redefine.h --- google-perftools-2.1/src/libc_override_redefine.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/libc_override_redefine.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2011, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/linked_list.h google-perftools-2.2.1/src/linked_list.h --- google-perftools-2.1/src/linked_list.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/linked_list.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/malloc_extension.cc google-perftools-2.2.1/src/malloc_extension.cc --- google-perftools-2.1/src/malloc_extension.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/malloc_extension.cc 2014-03-29 21:41:08.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -50,6 +51,7 @@ #include "gperftools/malloc_extension.h" #include "gperftools/malloc_extension_c.h" #include "maybe_threads.h" +#include "base/googleinit.h" using STL_NAMESPACE::string; using STL_NAMESPACE::vector; @@ -193,23 +195,27 @@ // The current malloc extension object. -static pthread_once_t module_init = PTHREAD_ONCE_INIT; -static MallocExtension* current_instance = NULL; +static MallocExtension* current_instance; static void InitModule() { + if (current_instance != NULL) { + return; + } current_instance = new MallocExtension; #ifndef NO_HEAP_CHECK HeapLeakChecker::IgnoreObject(current_instance); #endif } +REGISTER_MODULE_INITIALIZER(malloc_extension_init, InitModule()) + MallocExtension* MallocExtension::instance() { - perftools_pthread_once(&module_init, InitModule); + InitModule(); return current_instance; } void MallocExtension::Register(MallocExtension* implementation) { - perftools_pthread_once(&module_init, InitModule); + InitModule(); // When running under valgrind, our custom malloc is replaced with // valgrind's one and malloc extensions will not work. (Note: // callers should be responsible for checking that they are the diff -Nru google-perftools-2.1/src/malloc_hook.cc google-perftools-2.2.1/src/malloc_hook.cc --- google-perftools-2.1/src/malloc_hook.cc 2013-07-30 08:10:37.000000000 +0200 +++ google-perftools-2.2.1/src/malloc_hook.cc 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -173,18 +174,6 @@ return old_val; } -template -PtrT AtomicPtr::CompareAndSwap(PtrT old_val, PtrT new_val) { - base::subtle::MemoryBarrier(); // Release semantics. - PtrT retval = reinterpret_cast(static_cast( - base::subtle::NoBarrier_CompareAndSwap( - &data_, - reinterpret_cast(old_val), - reinterpret_cast(new_val)))); - base::subtle::MemoryBarrier(); // And acquire semantics. - return retval; -} - AtomicPtr new_hook_ = { 0 }; AtomicPtr delete_hook_ = { 0 }; AtomicPtr premmap_hook_ = { 0 }; diff -Nru google-perftools-2.1/src/malloc_hook-inl.h google-perftools-2.2.1/src/malloc_hook-inl.h --- google-perftools-2.1/src/malloc_hook-inl.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/malloc_hook-inl.h 2014-06-21 21:12:00.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -74,14 +75,6 @@ // This is a full-barrier instruction. PtrT Exchange(PtrT new_val); - // Atomically executes: - // result = data_ - // if (data_ == old_val) - // data_ = new_val; - // return result; - // This is a full-barrier instruction. - PtrT CompareAndSwap(PtrT old_val, PtrT new_val); - // Not private so that the class is an aggregate and can be // initialized by the linker. Don't access this directly. AtomicWord data_; diff -Nru google-perftools-2.1/src/malloc_hook_mmap_freebsd.h google-perftools-2.2.1/src/malloc_hook_mmap_freebsd.h --- google-perftools-2.1/src/malloc_hook_mmap_freebsd.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/malloc_hook_mmap_freebsd.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2011, Google Inc. // All rights reserved. // @@ -39,6 +40,7 @@ #include #include #include +#include // Make sure mmap doesn't get #define'd away by #undef mmap @@ -73,43 +75,11 @@ } static inline void* do_sbrk(intptr_t increment) { - void* curbrk = 0; + static void *(*libc_sbrk)(intptr_t); + if (libc_sbrk == NULL) + libc_sbrk = (void *(*)(intptr_t))dlsym(RTLD_NEXT, "sbrk"); -#if defined(__x86_64__) || defined(__amd64__) -# ifdef PIC - __asm__ __volatile__( - "movq .curbrk@GOTPCREL(%%rip), %%rdx;" - "movq (%%rdx), %%rax;" - "movq %%rax, %0;" - : "=r" (curbrk) - :: "%rdx", "%rax"); -# else - __asm__ __volatile__( - "movq .curbrk(%%rip), %%rax;" - "movq %%rax, %0;" - : "=r" (curbrk) - :: "%rax"); -# endif -#else - __asm__ __volatile__( - "movl .curbrk, %%eax;" - "movl %%eax, %0;" - : "=r" (curbrk) - :: "%eax"); -#endif - - if (increment == 0) { - return curbrk; - } - - char* prevbrk = static_cast(curbrk); - void* newbrk = prevbrk + increment; - - if (brk(newbrk) == -1) { - return reinterpret_cast(static_cast(-1)); - } - - return prevbrk; + return libc_sbrk(increment); } diff -Nru google-perftools-2.1/src/malloc_hook_mmap_linux.h google-perftools-2.2.1/src/malloc_hook_mmap_linux.h --- google-perftools-2.1/src/malloc_hook_mmap_linux.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/malloc_hook_mmap_linux.h 2014-03-01 20:24:54.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -51,7 +52,7 @@ // I test for 64-bit first so I don't have to do things like // '#if (defined(__mips__) && !defined(__MIPS64__))' as a mips32 check. -#if defined(__x86_64__) || defined(__PPC64__) || (defined(_MIPS_SIM) && _MIPS_SIM == _ABI64) +#if defined(__x86_64__) || defined(__PPC64__) || defined(__aarch64__) || (defined(_MIPS_SIM) && _MIPS_SIM == _ABI64) static inline void* do_mmap64(void *start, size_t length, int prot, int flags, @@ -201,6 +202,7 @@ return result; } +#ifndef __UCLIBC__ // libc's version: extern "C" void* __sbrk(ptrdiff_t increment); @@ -211,6 +213,8 @@ return result; } +#endif + /*static*/void* MallocHook::UnhookedMMap(void *start, size_t length, int prot, int flags, int fd, off_t offset) { void* result; diff -Nru google-perftools-2.1/src/maybe_threads.cc google-perftools-2.2.1/src/maybe_threads.cc --- google-perftools-2.1/src/maybe_threads.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/maybe_threads.cc 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -71,13 +72,26 @@ static void *perftools_pthread_specific_vals[MAX_PERTHREAD_VALS]; static int next_key; +// NOTE: it's similar to bitcast defined in basic_types.h with +// exception of ignoring sizes mismatch +template +static T2 memcpy_cast(const T1 &input) { + T2 output; + size_t s = sizeof(input); + if (sizeof(output) < s) { + s = sizeof(output); + } + memcpy(&output, &input, s); + return output; +} + int perftools_pthread_key_create(pthread_key_t *key, void (*destr_function) (void *)) { if (pthread_key_create) { return pthread_key_create(key, destr_function); } else { assert(next_key < MAX_PERTHREAD_VALS); - *key = (pthread_key_t)(next_key++); + *key = memcpy_cast(next_key++); return 0; } } @@ -86,7 +100,7 @@ if (pthread_getspecific) { return pthread_getspecific(key); } else { - return perftools_pthread_specific_vals[(int)key]; + return perftools_pthread_specific_vals[memcpy_cast(key)]; } } @@ -94,7 +108,7 @@ if (pthread_setspecific) { return pthread_setspecific(key, val); } else { - perftools_pthread_specific_vals[(int)key] = val; + perftools_pthread_specific_vals[memcpy_cast(key)] = val; return 0; } } diff -Nru google-perftools-2.1/src/maybe_threads.h google-perftools-2.2.1/src/maybe_threads.h --- google-perftools-2.1/src/maybe_threads.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/maybe_threads.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/memfs_malloc.cc google-perftools-2.2.1/src/memfs_malloc.cc --- google-perftools-2.1/src/memfs_malloc.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/memfs_malloc.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2007, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/memory_region_map.cc google-perftools-2.2.1/src/memory_region_map.cc --- google-perftools-2.1/src/memory_region_map.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/memory_region_map.cc 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2006, Google Inc. * All rights reserved. * @@ -84,9 +85,10 @@ // which (sometimes) causes mmap, which calls our hook, and so on. // We do this as follows: on a recursive call of MemoryRegionMap's // mmap/sbrk/mremap hook we record the data about the allocation in a -// static fixed-sized stack (saved_regions), when the recursion unwinds -// but before returning from the outer hook call we unwind this stack and -// move the data from saved_regions to its permanent place in the RegionSet, +// static fixed-sized stack (saved_regions and saved_buckets), when the +// recursion unwinds but before returning from the outer hook call we unwind +// this stack and move the data from saved_regions and saved_buckets to its +// permanent place in the RegionSet and "bucket_table" respectively, // which can cause more allocations and mmap-s and recursion and unwinding, // but the whole process ends eventually due to the fact that for the small // allocations we are doing LowLevelAlloc reuses one mmap call and parcels out @@ -147,6 +149,13 @@ pthread_t MemoryRegionMap::lock_owner_tid_; // GUARDED_BY(owner_lock_) int64 MemoryRegionMap::map_size_ = 0; int64 MemoryRegionMap::unmap_size_ = 0; +HeapProfileBucket** MemoryRegionMap::bucket_table_ = NULL; // GUARDED_BY(lock_) +int MemoryRegionMap::num_buckets_ = 0; // GUARDED_BY(lock_) +int MemoryRegionMap::saved_buckets_count_ = 0; // GUARDED_BY(lock_) +HeapProfileBucket MemoryRegionMap::saved_buckets_[20]; // GUARDED_BY(lock_) + +// GUARDED_BY(lock_) +const void* MemoryRegionMap::saved_buckets_keys_[20][kMaxStackDepth]; // ========================================================================= // @@ -182,7 +191,7 @@ // (or rather should we *not* use regions_ to record a hooked mmap). static bool recursive_insert = false; -void MemoryRegionMap::Init(int max_stack_depth) { +void MemoryRegionMap::Init(int max_stack_depth, bool use_buckets) { RAW_VLOG(10, "MemoryRegionMap Init"); RAW_CHECK(max_stack_depth >= 0, ""); // Make sure we don't overflow the memory in region stacks: @@ -214,6 +223,15 @@ // Can't instead use HandleSavedRegionsLocked(&DoInsertRegionLocked) before // recursive_insert = false; as InsertRegionLocked will also construct // regions_ on demand for us. + if (use_buckets) { + const int table_bytes = kHashTableSize * sizeof(*bucket_table_); + recursive_insert = true; + bucket_table_ = static_cast( + MyAllocator::Allocate(table_bytes)); + recursive_insert = false; + memset(bucket_table_, 0, table_bytes); + num_buckets_ = 0; + } Unlock(); RAW_VLOG(10, "MemoryRegionMap Init done"); } @@ -228,6 +246,19 @@ RAW_VLOG(10, "MemoryRegionMap Shutdown decrement done"); return true; } + if (bucket_table_ != NULL) { + for (int i = 0; i < kHashTableSize; i++) { + for (HeapProfileBucket* curr = bucket_table_[i]; curr != 0; /**/) { + HeapProfileBucket* bucket = curr; + curr = curr->next; + MyAllocator::Free(bucket->stack, 0); + MyAllocator::Free(bucket, 0); + } + } + MyAllocator::Free(bucket_table_, 0); + num_buckets_ = 0; + bucket_table_ = NULL; + } RAW_CHECK(MallocHook::RemoveMmapHook(&MmapHook), ""); RAW_CHECK(MallocHook::RemoveMremapHook(&MremapHook), ""); RAW_CHECK(MallocHook::RemoveSbrkHook(&SbrkHook), ""); @@ -245,6 +276,11 @@ return deleted_arena; } +bool MemoryRegionMap::IsRecordingLocked() { + RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); + return client_count_ > 0; +} + // Invariants (once libpthread_initialized is true): // * While lock_ is not held, recursion_count_ is 0 (and // lock_owner_tid_ is the previous owner, but we don't rely on @@ -336,6 +372,62 @@ return region != NULL; } +HeapProfileBucket* MemoryRegionMap::GetBucket(int depth, + const void* const key[]) { + RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); + // Make hash-value + uintptr_t hash = 0; + for (int i = 0; i < depth; i++) { + hash += reinterpret_cast(key[i]); + hash += hash << 10; + hash ^= hash >> 6; + } + hash += hash << 3; + hash ^= hash >> 11; + + // Lookup stack trace in table + unsigned int hash_index = (static_cast(hash)) % kHashTableSize; + for (HeapProfileBucket* bucket = bucket_table_[hash_index]; + bucket != 0; + bucket = bucket->next) { + if ((bucket->hash == hash) && (bucket->depth == depth) && + std::equal(key, key + depth, bucket->stack)) { + return bucket; + } + } + + // Create new bucket + const size_t key_size = sizeof(key[0]) * depth; + HeapProfileBucket* bucket; + if (recursive_insert) { // recursion: save in saved_buckets_ + const void** key_copy = saved_buckets_keys_[saved_buckets_count_]; + std::copy(key, key + depth, key_copy); + bucket = &saved_buckets_[saved_buckets_count_]; + memset(bucket, 0, sizeof(*bucket)); + ++saved_buckets_count_; + bucket->stack = key_copy; + bucket->next = NULL; + } else { + recursive_insert = true; + const void** key_copy = static_cast( + MyAllocator::Allocate(key_size)); + recursive_insert = false; + std::copy(key, key + depth, key_copy); + recursive_insert = true; + bucket = static_cast( + MyAllocator::Allocate(sizeof(HeapProfileBucket))); + recursive_insert = false; + memset(bucket, 0, sizeof(*bucket)); + bucket->stack = key_copy; + bucket->next = bucket_table_[hash_index]; + } + bucket->hash = hash; + bucket->depth = depth; + bucket_table_[hash_index] = bucket; + ++num_buckets_; + return bucket; +} + MemoryRegionMap::RegionIterator MemoryRegionMap::BeginRegionLocked() { RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); RAW_CHECK(regions_ != NULL, ""); @@ -404,6 +496,44 @@ } } +void MemoryRegionMap::RestoreSavedBucketsLocked() { + RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); + while (saved_buckets_count_ > 0) { + HeapProfileBucket bucket = saved_buckets_[--saved_buckets_count_]; + unsigned int hash_index = + static_cast(bucket.hash) % kHashTableSize; + bool is_found = false; + for (HeapProfileBucket* curr = bucket_table_[hash_index]; + curr != 0; + curr = curr->next) { + if ((curr->hash == bucket.hash) && (curr->depth == bucket.depth) && + std::equal(bucket.stack, bucket.stack + bucket.depth, curr->stack)) { + curr->allocs += bucket.allocs; + curr->alloc_size += bucket.alloc_size; + curr->frees += bucket.frees; + curr->free_size += bucket.free_size; + is_found = true; + break; + } + } + if (is_found) continue; + + const size_t key_size = sizeof(bucket.stack[0]) * bucket.depth; + const void** key_copy = static_cast( + MyAllocator::Allocate(key_size)); + std::copy(bucket.stack, bucket.stack + bucket.depth, key_copy); + HeapProfileBucket* new_bucket = static_cast( + MyAllocator::Allocate(sizeof(HeapProfileBucket))); + memset(new_bucket, 0, sizeof(*new_bucket)); + new_bucket->hash = bucket.hash; + new_bucket->depth = bucket.depth; + new_bucket->stack = key_copy; + new_bucket->next = bucket_table_[hash_index]; + bucket_table_[hash_index] = new_bucket; + ++num_buckets_; + } +} + inline void MemoryRegionMap::InsertRegionLocked(const Region& region) { RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); // We can be called recursively, because RegionSet constructor @@ -452,11 +582,31 @@ Region region; region.Create(start, size); // First get the call stack info into the local varible 'region': - const int depth = - max_stack_depth_ > 0 - ? MallocHook::GetCallerStackTrace(const_cast(region.call_stack), - max_stack_depth_, kStripFrames + 1) - : 0; + int depth = 0; + // NOTE: libunwind also does mmap and very much likely while holding + // it's own lock(s). So some threads may first take libunwind lock, + // and then take region map lock (necessary to record mmap done from + // inside libunwind). On the other hand other thread(s) may do + // normal mmap. Which would call this method to record it. Which + // would then proceed with installing that record to region map + // while holding region map lock. That may cause mmap from our own + // internal allocators, so attempt to unwind in this case may cause + // reverse order of taking libuwind and region map locks. Which is + // obvious deadlock. + // + // Thankfully, we can easily detect if we're holding region map lock + // and avoid recording backtrace in this (rare and largely + // irrelevant) case. By doing this we "declare" that thread needing + // both locks must take region map lock last. In other words we do + // not allow taking libuwind lock when we already have region map + // lock. Note, this is generally impossible when somebody tries to + // mix cpu profiling and heap checking/profiling, because cpu + // profiler grabs backtraces at arbitrary places. But at least such + // combination is rarer and less relevant. + if (max_stack_depth_ > 0 && !LockIsHeld()) { + depth = MallocHook::GetCallerStackTrace(const_cast(region.call_stack), + max_stack_depth_, kStripFrames + 1); + } region.set_call_stack_depth(depth); // record stack info fully RAW_VLOG(10, "New global region %p..%p from %p", reinterpret_cast(region.start_addr), @@ -468,6 +618,16 @@ InsertRegionLocked(region); // This will (eventually) allocate storage for and copy over the stack data // from region.call_stack_data_ that is pointed by region.call_stack(). + if (bucket_table_ != NULL) { + HeapProfileBucket* b = GetBucket(depth, region.call_stack); + ++b->allocs; + b->alloc_size += size; + if (!recursive_insert) { + recursive_insert = true; + RestoreSavedBucketsLocked(); + recursive_insert = false; + } + } Unlock(); } @@ -486,6 +646,7 @@ Region& r = saved_regions[i]; if (r.start_addr == start_addr && r.end_addr == end_addr) { // An exact match, so it's safe to remove. + RecordRegionRemovalInBucket(r.call_stack_depth, r.call_stack, size); --saved_regions_count; --put_pos; RAW_VLOG(10, ("Insta-Removing saved region %p..%p; " @@ -530,6 +691,8 @@ RAW_VLOG(12, "Deleting region %p..%p", reinterpret_cast(region->start_addr), reinterpret_cast(region->end_addr)); + RecordRegionRemovalInBucket(region->call_stack_depth, region->call_stack, + region->end_addr - region->start_addr); RegionSet::iterator d = region; ++region; regions_->erase(d); @@ -539,6 +702,8 @@ RAW_VLOG(12, "Splitting region %p..%p in two", reinterpret_cast(region->start_addr), reinterpret_cast(region->end_addr)); + RecordRegionRemovalInBucket(region->call_stack_depth, region->call_stack, + end_addr - start_addr); // Make another region for the start portion: // The new region has to be the start portion because we can't // just modify region->end_addr as it's the sorting key. @@ -552,12 +717,16 @@ RAW_VLOG(12, "Start-chopping region %p..%p", reinterpret_cast(region->start_addr), reinterpret_cast(region->end_addr)); + RecordRegionRemovalInBucket(region->call_stack_depth, region->call_stack, + end_addr - region->start_addr); const_cast(*region).set_start_addr(end_addr); } else if (start_addr > region->start_addr && start_addr < region->end_addr) { // cut from end RAW_VLOG(12, "End-chopping region %p..%p", reinterpret_cast(region->start_addr), reinterpret_cast(region->end_addr)); + RecordRegionRemovalInBucket(region->call_stack_depth, region->call_stack, + region->end_addr - start_addr); // Can't just modify region->end_addr (it's the sorting key): Region r = *region; r.set_end_addr(start_addr); @@ -580,6 +749,16 @@ Unlock(); } +void MemoryRegionMap::RecordRegionRemovalInBucket(int depth, + const void* const stack[], + size_t size) { + RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); + if (bucket_table_ == NULL) return; + HeapProfileBucket* b = GetBucket(depth, stack); + ++b->frees; + b->free_size += size; +} + void MemoryRegionMap::MmapHook(const void* result, const void* start, size_t size, int prot, int flags, @@ -618,8 +797,6 @@ } } -extern "C" void* __sbrk(ptrdiff_t increment); // defined in libc - void MemoryRegionMap::SbrkHook(const void* result, ptrdiff_t increment) { RAW_VLOG(10, "Sbrk = 0x%" PRIxPTR " of %" PRIdS "", (uintptr_t)result, increment); if (result != reinterpret_cast(-1)) { diff -Nru google-perftools-2.1/src/memory_region_map.h google-perftools-2.2.1/src/memory_region_map.h --- google-perftools-2.1/src/memory_region_map.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/memory_region_map.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2006, Google Inc. * All rights reserved. * @@ -45,6 +46,7 @@ #include "base/spinlock.h" #include "base/thread_annotations.h" #include "base/low_level_alloc.h" +#include "heap-profile-stats.h" // TODO(maxim): add a unittest: // execute a bunch of mmaps and compare memory map what strace logs @@ -72,6 +74,10 @@ // don't take the address of it! static const int kMaxStackDepth = 32; + // Size of the hash table of buckets. A structure of the bucket table is + // described in heap-profile-stats.h. + static const int kHashTableSize = 179999; + public: // interface ================================================================ @@ -87,11 +93,14 @@ // are automatically shrunk to "max_stack_depth" when they are recorded. // Init() can be called more than once w/o harm, largest max_stack_depth // will be the effective one. + // When "use_buckets" is true, then counts of mmap and munmap sizes will be + // recorded with each stack trace. If Init() is called more than once, then + // counting will be effective after any call contained "use_buckets" of true. // It will install mmap, munmap, mremap, sbrk hooks // and initialize arena_ and our hook and locks, hence one can use // MemoryRegionMap::Lock()/Unlock() to manage the locks. // Uses Lock/Unlock inside. - static void Init(int max_stack_depth); + static void Init(int max_stack_depth, bool use_buckets); // Try to shutdown this module undoing what Init() did. // Returns true iff could do full shutdown (or it was not attempted). @@ -99,6 +108,10 @@ // the number of Init() calls. static bool Shutdown(); + // Return true if MemoryRegionMap is initialized and recording, i.e. when + // then number of Init() calls are more than the number of Shutdown() calls. + static bool IsRecordingLocked(); + // Locks to protect our internal data structures. // These also protect use of arena_ if our Init() has been done. // The lock is recursive. @@ -214,6 +227,18 @@ // Returns success. Uses Lock/Unlock inside. static bool FindAndMarkStackRegion(uintptr_t stack_top, Region* result); + // Iterate over the buckets which store mmap and munmap counts per stack + // trace. It calls "callback" for each bucket, and passes "arg" to it. + template + static void IterateBuckets(void (*callback)(const HeapProfileBucket*, Type), + Type arg); + + // Get the bucket whose caller stack trace is "key". The stack trace is + // used to a depth of "depth" at most. The requested bucket is created if + // needed. + // The bucket table is described in heap-profile-stats.h. + static HeapProfileBucket* GetBucket(int depth, const void* const key[]); + private: // our internal types ============================================== // Region comparator for sorting with STL @@ -276,11 +301,11 @@ // To be accessed *only* when Lock() is held. // Hence we protect the non-recursive lock used inside of arena_ // with our recursive Lock(). This lets a user prevent deadlocks - // when threads are stopped by ListAllProcessThreads at random spots + // when threads are stopped by TCMalloc_ListAllProcessThreads at random spots // simply by acquiring our recursive Lock() before that. static RegionSet* regions_; - // Lock to protect regions_ variable and the data behind. + // Lock to protect regions_ and buckets_ variables and the data behind. static SpinLock lock_; // Lock to protect the recursive lock itself. static SpinLock owner_lock_; @@ -295,6 +320,30 @@ // Total size of all unmapped pages so far static int64 unmap_size_; + // Bucket hash table which is described in heap-profile-stats.h. + static HeapProfileBucket** bucket_table_ GUARDED_BY(lock_); + static int num_buckets_ GUARDED_BY(lock_); + + // The following members are local to MemoryRegionMap::GetBucket() + // and MemoryRegionMap::HandleSavedBucketsLocked() + // and are file-level to ensure that they are initialized at load time. + // + // These are used as temporary storage to break the infinite cycle of mmap + // calling our hook which (sometimes) causes mmap. It must be a static + // fixed-size array. The size 20 is just an expected value for safety. + // The details are described in memory_region_map.cc. + + // Number of unprocessed bucket inserts. + static int saved_buckets_count_ GUARDED_BY(lock_); + + // Unprocessed inserts (must be big enough to hold all mmaps that can be + // caused by a GetBucket call). + // Bucket has no constructor, so that c-tor execution does not interfere + // with the any-time use of the static memory behind saved_buckets. + static HeapProfileBucket saved_buckets_[20] GUARDED_BY(lock_); + + static const void* saved_buckets_keys_[20][kMaxStackDepth] GUARDED_BY(lock_); + // helpers ================================================================== // Helper for FindRegion and FindAndMarkStackRegion: @@ -308,6 +357,11 @@ // by calling insert_func on them. inline static void HandleSavedRegionsLocked( void (*insert_func)(const Region& region)); + + // Restore buckets saved in a tmp static array by GetBucket to the bucket + // table where all buckets eventually should be. + static void RestoreSavedBucketsLocked(); + // Wrapper around DoInsertRegionLocked // that handles the case of recursive allocator calls. inline static void InsertRegionLocked(const Region& region); @@ -319,6 +373,13 @@ // (called from our munmap/mremap/sbrk hooks). static void RecordRegionRemoval(const void* start, size_t size); + // Record deletion of a memory region of size "size" in a bucket whose + // caller stack trace is "key". The stack trace is used to a depth of + // "depth" at most. + static void RecordRegionRemovalInBucket(int depth, + const void* const key[], + size_t size); + // Hooks for MallocHook static void MmapHook(const void* result, const void* start, size_t size, @@ -337,4 +398,16 @@ DISALLOW_COPY_AND_ASSIGN(MemoryRegionMap); }; +template +void MemoryRegionMap::IterateBuckets( + void (*callback)(const HeapProfileBucket*, Type), Type callback_arg) { + for (int index = 0; index < kHashTableSize; index++) { + for (HeapProfileBucket* bucket = bucket_table_[index]; + bucket != NULL; + bucket = bucket->next) { + callback(bucket, callback_arg); + } + } +} + #endif // BASE_MEMORY_REGION_MAP_H_ diff -Nru google-perftools-2.1/src/packed-cache-inl.h google-perftools-2.2.1/src/packed-cache-inl.h --- google-perftools-2.1/src/packed-cache-inl.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/packed-cache-inl.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2007, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/page_heap_allocator.h google-perftools-2.2.1/src/page_heap_allocator.h --- google-perftools-2.1/src/page_heap_allocator.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/page_heap_allocator.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/page_heap.cc google-perftools-2.2.1/src/page_heap.cc --- google-perftools-2.1/src/page_heap.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/page_heap.cc 2014-06-22 00:34:32.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // @@ -65,7 +66,8 @@ pagemap_cache_(0), scavenge_counter_(0), // Start scavenging at kMaxPages list - release_index_(kMaxPages) { + release_index_(kMaxPages), + aggressive_decommit_(false) { COMPILE_ASSERT(kNumClasses <= (1 << PageMapCache::kValuebits), valuebits); DLL_Init(&large_.normal); DLL_Init(&large_.returned); @@ -152,6 +154,7 @@ // Grow the heap and try again. if (!GrowHeap(n)) { + ASSERT(stats_.unmapped_bytes+ stats_.committed_bytes==stats_.system_bytes); ASSERT(Check()); return NULL; } @@ -234,6 +237,22 @@ return leftover; } +void PageHeap::CommitSpan(Span* span) { + TCMalloc_SystemCommit(reinterpret_cast(span->start << kPageShift), + static_cast(span->length << kPageShift)); + stats_.committed_bytes += span->length << kPageShift; +} + +bool PageHeap::DecommitSpan(Span* span) { + bool rv = TCMalloc_SystemRelease(reinterpret_cast(span->start << kPageShift), + static_cast(span->length << kPageShift)); + if (rv) { + stats_.committed_bytes -= span->length << kPageShift; + } + + return rv; +} + Span* PageHeap::Carve(Span* span, Length n) { ASSERT(n > 0); ASSERT(span->location != Span::IN_USE); @@ -249,11 +268,31 @@ leftover->location = old_location; Event(leftover, 'S', extra); RecordSpan(leftover); + + // The previous span of |leftover| was just splitted -- no need to + // coalesce them. The next span of |leftover| was not previously coalesced + // with |span|, i.e. is NULL or has got location other than |old_location|. +#ifndef NDEBUG + const PageID p = leftover->start; + const Length len = leftover->length; + Span* next = GetDescriptor(p+len); + ASSERT (next == NULL || + next->location == Span::IN_USE || + next->location != leftover->location); +#endif + PrependToFreeList(leftover); // Skip coalescing - no candidates possible span->length = n; pagemap_.set(span->start + n - 1, span); } ASSERT(Check()); + if (old_location == Span::ON_RETURNED_FREELIST) { + // We need to recommit this address space. + CommitSpan(span); + } + ASSERT(span->location == Span::IN_USE); + ASSERT(span->length == n); + ASSERT(stats_.unmapped_bytes+ stats_.committed_bytes==stats_.system_bytes); return span; } @@ -270,9 +309,17 @@ Event(span, 'D', span->length); MergeIntoFreeList(span); // Coalesces if possible IncrementalScavenge(n); + ASSERT(stats_.unmapped_bytes+ stats_.committed_bytes==stats_.system_bytes); ASSERT(Check()); } +bool PageHeap::MayMergeSpans(Span *span, Span *other) { + if (aggressive_decommit_) { + return other->location != Span::IN_USE; + } + return span->location == other->location; +} + void PageHeap::MergeIntoFreeList(Span* span) { ASSERT(span->location != Span::IN_USE); @@ -281,15 +328,44 @@ // entries for the pieces we are merging together because we only // care about the pagemap entries for the boundaries. // - // Note that only similar spans are merged together. For example, - // we do not coalesce "returned" spans with "normal" spans. + // Note: depending on aggressive_decommit_ mode we allow only + // similar spans to be coalesced. + // + // The following applies if aggressive_decommit_ is enabled: + // + // Note that the adjacent spans we merge into "span" may come out of a + // "normal" (committed) list, and cleanly merge with our IN_USE span, which + // is implicitly committed. If the adjacents spans are on the "returned" + // (decommitted) list, then we must get both spans into the same state before + // or after we coalesce them. The current code always decomits. This is + // achieved by blindly decommitting the entire coalesced region, which may + // include any combination of committed and decommitted spans, at the end of + // the method. + + // TODO(jar): "Always decommit" causes some extra calls to commit when we are + // called in GrowHeap() during an allocation :-/. We need to eval the cost of + // that oscillation, and possibly do something to reduce it. + + // TODO(jar): We need a better strategy for deciding to commit, or decommit, + // based on memory usage and free heap sizes. + + uint64_t temp_committed = 0; + const PageID p = span->start; const Length n = span->length; Span* prev = GetDescriptor(p-1); - if (prev != NULL && prev->location == span->location) { + if (prev != NULL && MayMergeSpans(span, prev)) { // Merge preceding span into this span ASSERT(prev->start + prev->length == p); const Length len = prev->length; + if (aggressive_decommit_ && prev->location == Span::ON_RETURNED_FREELIST) { + // We're about to put the merge span into the returned freelist and call + // DecommitSpan() on it, which will mark the entire span including this + // one as released and decrease stats_.committed_bytes by the size of the + // merged span. To make the math work out we temporarily increase the + // stats_.committed_bytes amount. + temp_committed = prev->length << kPageShift; + } RemoveFromFreeList(prev); DeleteSpan(prev); span->start -= len; @@ -298,10 +374,14 @@ Event(span, 'L', len); } Span* next = GetDescriptor(p+n); - if (next != NULL && next->location == span->location) { + if (next != NULL && MayMergeSpans(span, next)) { // Merge next span into this span ASSERT(next->start == p+n); const Length len = next->length; + if (aggressive_decommit_ && next->location == Span::ON_RETURNED_FREELIST) { + // See the comment below 'if (prev->location ...' for explanation. + temp_committed += next->length << kPageShift; + } RemoveFromFreeList(next); DeleteSpan(next); span->length += len; @@ -309,6 +389,14 @@ Event(span, 'R', len); } + if (aggressive_decommit_) { + if (DecommitSpan(span)) { + span->location = Span::ON_RETURNED_FREELIST; + stats_.committed_bytes += temp_committed; + } else { + ASSERT(temp_committed == 0); + } + } PrependToFreeList(span); } @@ -369,8 +457,7 @@ Span* s = slist->normal.prev; ASSERT(s->location == Span::ON_NORMAL_FREELIST); - if (TCMalloc_SystemRelease(reinterpret_cast(s->start << kPageShift), - static_cast(s->length << kPageShift))) { + if (DecommitSpan(s)) { RemoveFromFreeList(s); const Length n = s->length; s->location = Span::ON_RETURNED_FREELIST; @@ -524,6 +611,7 @@ uint64_t old_system_bytes = stats_.system_bytes; stats_.system_bytes += (ask << kPageShift); + stats_.committed_bytes += (ask << kPageShift); const PageID p = reinterpret_cast(ptr) >> kPageShift; ASSERT(p > 0); @@ -545,6 +633,7 @@ Span* span = NewSpan(p, ask); RecordSpan(span); Delete(span); + ASSERT(stats_.unmapped_bytes+ stats_.committed_bytes==stats_.system_bytes); ASSERT(Check()); return true; } else { diff -Nru google-perftools-2.1/src/page_heap.h google-perftools-2.2.1/src/page_heap.h --- google-perftools-2.1/src/page_heap.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/page_heap.h 2014-06-22 00:34:32.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // @@ -142,10 +143,12 @@ // Page heap statistics struct Stats { - Stats() : system_bytes(0), free_bytes(0), unmapped_bytes(0) {} + Stats() : system_bytes(0), free_bytes(0), unmapped_bytes(0), committed_bytes(0) {} uint64_t system_bytes; // Total bytes allocated from system uint64_t free_bytes; // Total bytes on normal freelists uint64_t unmapped_bytes; // Total bytes on returned freelists + uint64_t committed_bytes; // Bytes committed, always <= system_bytes_. + }; inline Stats stats() const { return stats_; } @@ -189,6 +192,11 @@ } void CacheSizeClass(PageID p, size_t cl) const { pagemap_cache_.Put(p, cl); } + bool GetAggressiveDecommit(void) {return aggressive_decommit_;} + void SetAggressiveDecommit(bool aggressive_decommit) { + aggressive_decommit_ = aggressive_decommit; + } + private: // Allocates a big block of memory for the pagemap once we reach more than // 128MB @@ -263,6 +271,12 @@ // appropriate free list, and adjust stats. void MergeIntoFreeList(Span* span); + // Commit the span. + void CommitSpan(Span* span); + + // Decommit the span. + bool DecommitSpan(Span* span); + // Prepends span to appropriate free list, and adjusts stats. void PrependToFreeList(Span* span); @@ -282,11 +296,15 @@ // some unused spans. bool EnsureLimit(Length n, bool allowRelease = true); + bool MayMergeSpans(Span *span, Span *other); + // Number of pages to deallocate before doing more scavenging int64_t scavenge_counter_; // Index of last free list where we released memory to the OS. int release_index_; + + bool aggressive_decommit_; }; } // namespace tcmalloc diff -Nru google-perftools-2.1/src/pagemap.h google-perftools-2.2.1/src/pagemap.h --- google-perftools-2.1/src/pagemap.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/pagemap.h 2013-12-06 21:16:47.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -151,9 +152,9 @@ } void set(Number k, void* v) { - ASSERT(k >> BITS == 0); const Number i1 = k >> LEAF_BITS; const Number i2 = k & (LEAF_LENGTH-1); + ASSERT(i1 < ROOT_LENGTH); root_[i1]->values[i2] = v; } diff -Nru google-perftools-2.1/src/pprof google-perftools-2.2.1/src/pprof --- google-perftools-2.1/src/pprof 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/pprof 2014-04-13 03:35:40.000000000 +0200 @@ -71,6 +71,7 @@ use strict; use warnings; use Getopt::Long; +use Cwd; my $PPROF_VERSION = "2.0"; @@ -1078,10 +1079,15 @@ # Print profile data in packed binary format (64-bit) to standard out sub PrintProfileData { my $profile = shift; - + my $big_endian = pack("L", 1) eq pack("N", 1); # print header (64-bit style) # (zero) (header-size) (version) (sample-period) (zero) - print pack('L*', 0, 0, 3, 0, 0, 0, 1, 0, 0, 0); + if ($big_endian) { + print pack('L*', 0, 0, 0, 3, 0, 0, 0, 1, 0, 0); + } + else { + print pack('L*', 0, 0, 3, 0, 0, 0, 1, 0, 0, 0); + } foreach my $k (keys(%{$profile})) { my $count = $profile->{$k}; @@ -1090,8 +1096,14 @@ my $depth = $#addrs + 1; # int(foo / 2**32) is the only reliable way to get rid of bottom # 32 bits on both 32- and 64-bit systems. - print pack('L*', $count & 0xFFFFFFFF, int($count / 2**32)); - print pack('L*', $depth & 0xFFFFFFFF, int($depth / 2**32)); + if ($big_endian) { + print pack('L*', int($count / 2**32), $count & 0xFFFFFFFF); + print pack('L*', int($depth / 2**32), $depth & 0xFFFFFFFF); + } + else { + print pack('L*', $count & 0xFFFFFFFF, int($count / 2**32)); + print pack('L*', $depth & 0xFFFFFFFF, int($depth / 2**32)); + } foreach my $full_addr (@addrs) { my $addr = $full_addr; @@ -1102,7 +1114,12 @@ } my $low_addr = substr($addr, -8); # get last 8 hex chars my $high_addr = substr($addr, -16, 8); # get up to 8 more hex chars - print pack('L*', hex('0x' . $low_addr), hex('0x' . $high_addr)); + if ($big_endian) { + print pack('L*', hex('0x' . $high_addr), hex('0x' . $low_addr)); + } + else { + print pack('L*', hex('0x' . $low_addr), hex('0x' . $high_addr)); + } } } } @@ -4326,7 +4343,7 @@ # Split /proc/pid/maps dump into a list of libraries sub ParseLibraries { return if $main::use_symbol_page; # We don't need libraries info. - my $prog = shift; + my $prog = Cwd::abs_path(shift); my $map = shift; my $pcs = shift; @@ -4359,6 +4376,16 @@ $finish = HexExtend($2); $offset = $zero_offset; $lib = $3; + } elsif (($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(\S+)$/i) && ($4 eq $prog)) { + # PIEs and address space randomization do not play well with our + # default assumption that main executable is at lowest + # addresses. So we're detecting main executable in + # /proc/self/maps as well. + $start = HexExtend($1); + $finish = HexExtend($2); + $offset = HexExtend($3); + $lib = $4; + $lib =~ s|\\|/|g; # turn windows-style paths into unix-style paths } else { next; } @@ -4976,6 +5003,7 @@ sub GetProcedureBoundariesViaNm { my $escaped_nm_command = shift; # shell-escaped my $regexp = shift; + my $image = shift; my $symbol_table = {}; open(NM, "$escaped_nm_command |") || error("$escaped_nm_command: $!\n"); @@ -5045,6 +5073,37 @@ $symbol_table->{$routine} = [HexExtend($last_start), HexExtend($last_start)]; } + + # Verify if addr2line can find the $sep_symbol. If not, we use objdump + # to find the address for the $sep_symbol on code section which addr2line + # can find. + if (defined($sep_address)){ + my $start_val = $sep_address; + my $addr2line = $obj_tool_map{"addr2line"}; + my $cmd = ShellEscape($addr2line, "-f", "-C", "-e", $image, "-i"); + open(FINI, "echo $start_val | $cmd |") + || error("echo $start_val | $cmd: $!\n"); + $_ = ; + s/\r?\n$//g; + my $fini = $_; + close(FINI); + if ($fini ne $sep_symbol){ + my $objdump = $obj_tool_map{"objdump"}; + $cmd = ShellEscape($objdump, "-d", $image); + my $grep = ShellEscape("grep", $sep_symbol); + my $tail = ShellEscape("tail", "-n", "1"); + open(FINI, "$cmd | $grep | $tail |") + || error("$cmd | $grep | $tail: $!\n"); + s/\r//g; # turn windows-looking lines into unix-looking lines + my $data = ; + if (defined($data)){ + ($start_val, $fini) = split(/ = 1 && signal_number <= 64) { - void *old_signal_handler = reinterpret_cast(signal(signal_number, CpuProfilerSwitch)); - if (old_signal_handler == NULL) { - RAW_LOG(INFO,"Using signal %d as cpu profiling switch", signal_number); + intptr_t old_signal_handler = reinterpret_cast(signal(signal_number, CpuProfilerSwitch)); + if (old_signal_handler == 0) { + RAW_LOG(INFO,"Using signal %d as cpu profiling switch", signal_number); } else { RAW_LOG(FATAL, "Signal %d already in use\n", signal_number); } diff -Nru google-perftools-2.1/src/raw_printer.cc google-perftools-2.2.1/src/raw_printer.cc --- google-perftools-2.1/src/raw_printer.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/raw_printer.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/raw_printer.h google-perftools-2.2.1/src/raw_printer.h --- google-perftools-2.1/src/raw_printer.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/raw_printer.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/sampler.cc google-perftools-2.2.1/src/sampler.cc --- google-perftools-2.1/src/sampler.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/sampler.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/sampler.h google-perftools-2.2.1/src/sampler.h --- google-perftools-2.1/src/sampler.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/sampler.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/span.cc google-perftools-2.2.1/src/span.cc --- google-perftools-2.1/src/span.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/span.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/span.h google-perftools-2.2.1/src/span.h --- google-perftools-2.1/src/span.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/span.h 2014-06-22 00:34:32.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/stacktrace_arm-inl.h google-perftools-2.2.1/src/stacktrace_arm-inl.h --- google-perftools-2.1/src/stacktrace_arm-inl.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/stacktrace_arm-inl.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2011, Google Inc. // All rights reserved. // @@ -101,7 +102,7 @@ // int max_depth: the size of the result (and sizes) array(s) // int skip_count: how many stack pointers to skip before storing in result // void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) -int GET_STACK_TRACE_OR_FRAMES { +static int GET_STACK_TRACE_OR_FRAMES { #ifdef __GNUC__ void **sp = reinterpret_cast(__builtin_frame_address(0)); #else @@ -115,6 +116,8 @@ // stored in the stack frame. This works at least for gcc. StacktraceArmDummyFunction(); + skip_count++; // skip parent frame due to indirection in stacktrace.cc + int n = 0; while (sp && n < max_depth) { // The GetStackFrames routine is called when we are in some diff -Nru google-perftools-2.1/src/stacktrace.cc google-perftools-2.2.1/src/stacktrace.cc --- google-perftools-2.1/src/stacktrace.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/stacktrace.cc 2014-04-13 03:35:40.000000000 +0200 @@ -1,10 +1,11 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: -// +// // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above @@ -14,7 +15,7 @@ // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -53,49 +54,149 @@ // Some code may do that. #include -#include -#include "stacktrace_config.h" +#include // for getenv +#include // for strcmp +#include // for fprintf +#include "gperftools/stacktrace.h" +#include "base/commandlineflags.h" +#include "base/googleinit.h" + + +// we're using plain struct and not class to avoid any possible issues +// during initialization. Struct of pointers is easy to init at +// link-time. +struct GetStackImplementation { + int (*GetStackFramesPtr)(void** result, int* sizes, int max_depth, + int skip_count); + + int (*GetStackFramesWithContextPtr)(void** result, int* sizes, int max_depth, + int skip_count, const void *uc); + + int (*GetStackTracePtr)(void** result, int max_depth, + int skip_count); + + int (*GetStackTraceWithContextPtr)(void** result, int max_depth, + int skip_count, const void *uc); + + const char *name; +}; + +#if HAVE_DECL_BACKTRACE +#define STACKTRACE_INL_HEADER "stacktrace_generic-inl.h" +#define GST_SUFFIX generic +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_generic +#endif + +#if HAVE_LIBUNWIND_H +#define STACKTRACE_INL_HEADER "stacktrace_libunwind-inl.h" +#define GST_SUFFIX libunwind +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_libunwind +#endif // HAVE_LIBUNWIND_H + +#if defined(__i386__) || defined(__x86_64__) +#define STACKTRACE_INL_HEADER "stacktrace_x86-inl.h" +#define GST_SUFFIX x86 +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_x86 +#endif // i386 || x86_64 + +#if defined(__ppc__) || defined(__PPC__) +#if defined(__linux__) +#define STACKTRACE_INL_HEADER "stacktrace_powerpc-linux-inl.h" +#else +#define STACKTRACE_INL_HEADER "stacktrace_powerpc-darwin-inl.h" +#endif +#define GST_SUFFIX ppc +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_ppc +#endif + +#if defined(__arm__) +#define STACKTRACE_INL_HEADER "stacktrace_arm-inl.h" +#define GST_SUFFIX arm +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_arm +#endif + +#ifdef TCMALLOC_ENABLE_INSTRUMENT_STACKTRACE +#define STACKTRACE_INL_HEADER "stacktrace_instrument-inl.h" +#define GST_SUFFIX instrument +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_instrument +#endif + +// The Windows case -- probably cygwin and mingw will use one of the +// x86-includes above, but if not, we can fall back to windows intrinsics. +#if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__) +#define STACKTRACE_INL_HEADER "stacktrace_win32-inl.h" +#define GST_SUFFIX win32 +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_win32 +#endif -#if defined(STACKTRACE_INL_HEADER) +static GetStackImplementation *all_impls[] = { +#ifdef HAVE_GST_generic + &impl__generic, +#endif +#ifdef HAVE_GST_libunwind + &impl__libunwind, +#endif +#ifdef HAVE_GST_x86 + &impl__x86, +#endif +#ifdef HAVE_GST_arm + &impl__arm, +#endif +#ifdef HAVE_GST_ppc + &impl__ppc, +#endif +#ifdef HAVE_GST_instrument + &impl__instrument, +#endif +#ifdef HAVE_GST_win32 + &impl__win32, +#endif + NULL +}; -#define IS_STACK_FRAMES 0 -#define IS_WITH_CONTEXT 0 -#define GET_STACK_TRACE_OR_FRAMES \ - GetStackTrace(void **result, int max_depth, int skip_count) -#include STACKTRACE_INL_HEADER -#undef IS_STACK_FRAMES -#undef IS_WITH_CONTEXT -#undef GET_STACK_TRACE_OR_FRAMES - -#define IS_STACK_FRAMES 1 -#define IS_WITH_CONTEXT 0 -#define GET_STACK_TRACE_OR_FRAMES \ - GetStackFrames(void **result, int *sizes, int max_depth, int skip_count) -#include STACKTRACE_INL_HEADER -#undef IS_STACK_FRAMES -#undef IS_WITH_CONTEXT -#undef GET_STACK_TRACE_OR_FRAMES - -#define IS_STACK_FRAMES 0 -#define IS_WITH_CONTEXT 1 -#define GET_STACK_TRACE_OR_FRAMES \ - GetStackTraceWithContext(void **result, int max_depth, \ - int skip_count, const void *ucp) -#include STACKTRACE_INL_HEADER -#undef IS_STACK_FRAMES -#undef IS_WITH_CONTEXT -#undef GET_STACK_TRACE_OR_FRAMES - -#define IS_STACK_FRAMES 1 -#define IS_WITH_CONTEXT 1 -#define GET_STACK_TRACE_OR_FRAMES \ - GetStackFramesWithContext(void **result, int *sizes, int max_depth, \ - int skip_count, const void *ucp) -#include STACKTRACE_INL_HEADER -#undef IS_STACK_FRAMES -#undef IS_WITH_CONTEXT -#undef GET_STACK_TRACE_OR_FRAMES +// ppc and i386 implementations prefer arch-specific asm implementations. +// arm's asm implementation is broken +#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__PPC__) +#if !defined(NO_FRAME_POINTER) +#define TCMALLOC_DONT_PREFER_LIBUNWIND +#endif +#endif +#if defined(HAVE_GST_instrument) +static GetStackImplementation *get_stack_impl = &impl__instrument; +#elif defined(HAVE_GST_win32) +static GetStackImplementation *get_stack_impl = &impl__win32; +#elif defined(HAVE_GST_x86) && defined(TCMALLOC_DONT_PREFER_LIBUNWIND) +static GetStackImplementation *get_stack_impl = &impl__x86; +#elif defined(HAVE_GST_ppc) && defined(TCMALLOC_DONT_PREFER_LIBUNWIND) +static GetStackImplementation *get_stack_impl = &impl__ppc; +#elif defined(HAVE_GST_libunwind) +static GetStackImplementation *get_stack_impl = &impl__libunwind; +#elif defined(HAVE_GST_arm) +static GetStackImplementation *get_stack_impl = &impl__arm; +#elif defined(HAVE_GST_generic) +static GetStackImplementation *get_stack_impl = &impl__generic; #elif 0 // This is for the benefit of code analysis tools that may have // trouble with the computed #include above. @@ -105,6 +206,63 @@ # include "stacktrace_powerpc-inl.h" # include "stacktrace_win32-inl.h" # include "stacktrace_arm-inl.h" +# include "stacktrace_instrument-inl.h" #else -# error Cannot calculate stack trace: will need to write for your environment +#error Cannot calculate stack trace: will need to write for your environment #endif + +static int ATTRIBUTE_NOINLINE frame_forcer(int rv) { + return rv; +} + +PERFTOOLS_DLL_DECL int GetStackFrames(void** result, int* sizes, int max_depth, + int skip_count) { + return frame_forcer(get_stack_impl->GetStackFramesPtr(result, sizes, max_depth, skip_count)); +} + +PERFTOOLS_DLL_DECL int GetStackFramesWithContext(void** result, int* sizes, int max_depth, + int skip_count, const void *uc) { + return frame_forcer(get_stack_impl->GetStackFramesWithContextPtr( + result, sizes, max_depth, + skip_count, uc)); +} + +PERFTOOLS_DLL_DECL int GetStackTrace(void** result, int max_depth, + int skip_count) { + return frame_forcer(get_stack_impl->GetStackTracePtr(result, max_depth, skip_count)); +} + +PERFTOOLS_DLL_DECL int GetStackTraceWithContext(void** result, int max_depth, + int skip_count, const void *uc) { + return frame_forcer(get_stack_impl->GetStackTraceWithContextPtr( + result, max_depth, skip_count, uc)); +} + +static void init_default_stack_impl_inner(void) { + char *val = getenv("TCMALLOC_STACKTRACE_METHOD"); + if (!val || !*val) { + return; + } + for (GetStackImplementation **p = all_impls; *p; p++) { + GetStackImplementation *c = *p; + if (strcmp(c->name, val) == 0) { + get_stack_impl = c; + return; + } + } + fprintf(stderr, "Unknown or unsupported stacktrace method requested: %s. Ignoring it\n", val); +} + +static void init_default_stack_impl(void) { + init_default_stack_impl_inner(); + if (EnvToBool("TCMALLOC_STACKTRACE_METHOD_VERBOSE", false)) { + fprintf(stderr, "Chosen stacktrace method is %s\nSupported methods:\n", get_stack_impl->name); + for (GetStackImplementation **p = all_impls; *p; p++) { + GetStackImplementation *c = *p; + fprintf(stderr, "* %s\n", c->name); + } + fputs("\n", stderr); + } +} + +REGISTER_MODULE_INITIALIZER(stacktrace_init_default_stack_impl, init_default_stack_impl()); diff -Nru google-perftools-2.1/src/stacktrace_config.h google-perftools-2.2.1/src/stacktrace_config.h --- google-perftools-2.1/src/stacktrace_config.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/stacktrace_config.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,85 +0,0 @@ -// Copyright (c) 2009, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// --- -// Author: Paul Pluzhnikov -// -// Figure out which unwinder to use on a given platform. -// -// Defines STACKTRACE_INL_HEADER to the *-inl.h containing -// actual unwinder implementation. -// -// Defines STACKTRACE_SKIP_CONTEXT_ROUTINES if a separate -// GetStack{Trace,Frames}WithContext should not be provided. -// -// This header is "private" to stacktrace.cc and -// stacktrace_with_context.cc. -// -// DO NOT include it into any other files. - -#ifndef BASE_STACKTRACE_CONFIG_H_ -#define BASE_STACKTRACE_CONFIG_H_ - -// First, the i386 and x86_64 case. -#if (defined(__i386__) || defined(__x86_64__)) && __GNUC__ >= 2 -# if !defined(NO_FRAME_POINTER) -# define STACKTRACE_INL_HEADER "stacktrace_x86-inl.h" -# define STACKTRACE_SKIP_CONTEXT_ROUTINES 1 -# elif defined(HAVE_LIBUNWIND_H) // a proxy for having libunwind installed -# define STACKTRACE_INL_HEADER "stacktrace_libunwind-inl.h" -# define STACKTRACE_USES_LIBUNWIND 1 -# elif defined(__linux) -# error Cannnot calculate stack trace: need either libunwind or frame-pointers (see INSTALL file) -# else -# error Cannnot calculate stack trace: need libunwind (see INSTALL file) -# endif - -// The PowerPC case -#elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2 -# if !defined(NO_FRAME_POINTER) -# define STACKTRACE_INL_HEADER "stacktrace_powerpc-inl.h" -# else -# define STACKTRACE_INL_HEADER "stacktrace_generic-inl.h" -# endif - -// The ARM case -#elif defined(__arm__) && __GNUC__ >= 2 -# if !defined(NO_FRAME_POINTER) -# define STACKTRACE_INL_HEADER "stacktrace_arm-inl.h" -# else -# error stacktrace without frame pointer is not supported on ARM -# endif - -// The Windows case -- probably cygwin and mingw will use one of the -// x86-includes above, but if not, we can fall back to windows intrinsics. -#elif defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__) -# define STACKTRACE_INL_HEADER "stacktrace_win32-inl.h" - -#endif // all the cases -#endif // BASE_STACKTRACE_CONFIG_H_ diff -Nru google-perftools-2.1/src/stacktrace_generic-inl.h google-perftools-2.2.1/src/stacktrace_generic-inl.h --- google-perftools-2.1/src/stacktrace_generic-inl.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/stacktrace_generic-inl.h 2014-06-21 21:12:02.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -59,13 +60,13 @@ // int max_depth: the size of the result (and sizes) array(s) // int skip_count: how many stack pointers to skip before storing in result // void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) -int GET_STACK_TRACE_OR_FRAMES { +static int GET_STACK_TRACE_OR_FRAMES { static const int kStackLength = 64; void * stack[kStackLength]; int size; size = backtrace(stack, kStackLength); - skip_count++; // we want to skip the current frame as well + skip_count += 2; // we want to skip the current and it's parent frame as well int result_count = size - skip_count; if (result_count < 0) result_count = 0; diff -Nru google-perftools-2.1/src/stacktrace_impl_setup-inl.h google-perftools-2.2.1/src/stacktrace_impl_setup-inl.h --- google-perftools-2.1/src/stacktrace_impl_setup-inl.h 1970-01-01 01:00:00.000000000 +0100 +++ google-perftools-2.2.1/src/stacktrace_impl_setup-inl.h 2014-02-22 21:25:25.000000000 +0100 @@ -0,0 +1,94 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// NOTE: this is NOT to be #include-d normally. It's internal +// implementation detail of stacktrace.cc +// + +// Copyright (c) 2014, gperftools Contributors. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// --- +// Author: Aliaksey Kandratsenka +// +// based on stacktrace.cc and stacktrace_config.h by Sanjay Ghemawat +// and Paul Pluzhnikov from Google Inc + +#define SIS_CONCAT2(a, b) a##b +#define SIS_CONCAT(a, b) SIS_CONCAT2(a,b) + +#define SIS_STRINGIFY(a) SIS_STRINGIFY2(a) +#define SIS_STRINGIFY2(a) #a + +#define IS_STACK_FRAMES 0 +#define IS_WITH_CONTEXT 0 +#define GET_STACK_TRACE_OR_FRAMES \ + SIS_CONCAT(GetStackTrace_, GST_SUFFIX)(void **result, int max_depth, int skip_count) +#include STACKTRACE_INL_HEADER +#undef IS_STACK_FRAMES +#undef IS_WITH_CONTEXT +#undef GET_STACK_TRACE_OR_FRAMES + +#define IS_STACK_FRAMES 1 +#define IS_WITH_CONTEXT 0 +#define GET_STACK_TRACE_OR_FRAMES \ + SIS_CONCAT(GetStackFrames_, GST_SUFFIX)(void **result, int *sizes, int max_depth, int skip_count) +#include STACKTRACE_INL_HEADER +#undef IS_STACK_FRAMES +#undef IS_WITH_CONTEXT +#undef GET_STACK_TRACE_OR_FRAMES + +#define IS_STACK_FRAMES 0 +#define IS_WITH_CONTEXT 1 +#define GET_STACK_TRACE_OR_FRAMES \ + SIS_CONCAT(GetStackTraceWithContext_, GST_SUFFIX)(void **result, int max_depth, \ + int skip_count, const void *ucp) +#include STACKTRACE_INL_HEADER +#undef IS_STACK_FRAMES +#undef IS_WITH_CONTEXT +#undef GET_STACK_TRACE_OR_FRAMES + +#define IS_STACK_FRAMES 1 +#define IS_WITH_CONTEXT 1 +#define GET_STACK_TRACE_OR_FRAMES \ + SIS_CONCAT(GetStackFramesWithContext_, GST_SUFFIX)(void **result, int *sizes, int max_depth, \ + int skip_count, const void *ucp) +#include STACKTRACE_INL_HEADER +#undef IS_STACK_FRAMES +#undef IS_WITH_CONTEXT +#undef GET_STACK_TRACE_OR_FRAMES + +static GetStackImplementation SIS_CONCAT(impl__,GST_SUFFIX) = { + SIS_CONCAT(GetStackFrames_, GST_SUFFIX), + SIS_CONCAT(GetStackFramesWithContext_, GST_SUFFIX), + SIS_CONCAT(GetStackTrace_, GST_SUFFIX), + SIS_CONCAT(GetStackTraceWithContext_, GST_SUFFIX), + SIS_STRINGIFY(GST_SUFFIX) +}; + +#undef SIS_CONCAT2 +#undef SIS_CONCAT diff -Nru google-perftools-2.1/src/stacktrace_instrument-inl.h google-perftools-2.2.1/src/stacktrace_instrument-inl.h --- google-perftools-2.1/src/stacktrace_instrument-inl.h 1970-01-01 01:00:00.000000000 +0100 +++ google-perftools-2.2.1/src/stacktrace_instrument-inl.h 2014-02-22 21:25:25.000000000 +0100 @@ -0,0 +1,155 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2013, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// --- +// Author: Jean Lee +// based on gcc Code-Gen-Options "-finstrument-functions" listed in +// http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html . +// Should run configure with CXXFLAGS="-finstrument-functions". + +// This file is a backtrace implementation for systems : +// * The glibc implementation of backtrace() may cause a call to malloc, +// and cause a deadlock in HeapProfiler. +// * The libunwind implementation prints no backtrace. + +// The backtrace arrays are stored in "thread_back_trace" variable. +// Maybe to use thread local storage is better and should save memorys. + +#ifndef BASE_STACKTRACE_INSTRUMENT_INL_H_ +#define BASE_STACKTRACE_INSTRUMENT_INL_H_ +// Note: this file is included into stacktrace.cc more than once. +// Anything that should only be defined once should be here: + +#include +#include +#include +#include +#include "gperftools/stacktrace.h" + +#define gettid() syscall(__NR_gettid) +#ifndef __x86_64__ +#define MAX_THREAD (32768) +#else +#define MAX_THREAD (65536) +#endif +#define MAX_DEPTH (30) +#define ATTRIBUTE_NOINSTRUMENT __attribute__ ((no_instrument_function)) + +typedef struct { + int stack_depth; + void* frame[MAX_DEPTH]; +}BACK_TRACE; + +static BACK_TRACE thread_back_trace[MAX_THREAD]; +extern "C" { +void __cyg_profile_func_enter(void *func_address, + void *call_site) ATTRIBUTE_NOINSTRUMENT; +void __cyg_profile_func_enter(void *func_address, void *call_site) { + (void)func_address; + + BACK_TRACE* backtrace = thread_back_trace + gettid(); + int stack_depth = backtrace->stack_depth; + backtrace->stack_depth = stack_depth + 1; + if ( stack_depth >= MAX_DEPTH ) { + return; + } + backtrace->frame[stack_depth] = call_site; +} + +void __cyg_profile_func_exit(void *func_address, + void *call_site) ATTRIBUTE_NOINSTRUMENT; +void __cyg_profile_func_exit(void *func_address, void *call_site) { + (void)func_address; + (void)call_site; + + BACK_TRACE* backtrace = thread_back_trace + gettid(); + int stack_depth = backtrace->stack_depth; + backtrace->stack_depth = stack_depth - 1; + if ( stack_depth >= MAX_DEPTH ) { + return; + } + backtrace->frame[stack_depth] = 0; +} +} // extern "C" + +static int cyg_backtrace(void **buffer, int size) { + BACK_TRACE* backtrace = thread_back_trace + gettid(); + int stack_depth = backtrace->stack_depth; + if ( stack_depth >= MAX_DEPTH ) { + stack_depth = MAX_DEPTH; + } + int nSize = (size > stack_depth) ? stack_depth : size; + for (int i = 0; i < nSize; i++) { + buffer[i] = backtrace->frame[nSize - i - 1]; + } + + return nSize; +} + +#endif // BASE_STACKTRACE_INSTRUMENT_INL_H_ + + +// Note: this part of the file is included several times. +// Do not put globals below. + +// The following 4 functions are generated from the code below: +// GetStack{Trace,Frames}() +// GetStack{Trace,Frames}WithContext() +// +// These functions take the following args: +// void** result: the stack-trace, as an array +// int* sizes: the size of each stack frame, as an array +// (GetStackFrames* only) +// int max_depth: the size of the result (and sizes) array(s) +// int skip_count: how many stack pointers to skip before storing in result +// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) +static int GET_STACK_TRACE_OR_FRAMES { + static const int kStackLength = 64; + void * stack[kStackLength]; + int size; + memset(stack, 0, sizeof(stack)); + + size = cyg_backtrace(stack, kStackLength); + skip_count += 2; // we want to skip the current and parent frame as well + int result_count = size - skip_count; + if (result_count < 0) + result_count = 0; + if (result_count > max_depth) + result_count = max_depth; + for (int i = 0; i < result_count; i++) + result[i] = stack[i + skip_count]; + +#if IS_STACK_FRAMES + // No implementation for finding out the stack frame sizes yet. + memset(sizes, 0, sizeof(*sizes) * result_count); +#endif + + return result_count; +} diff -Nru google-perftools-2.1/src/stacktrace_libunwind-inl.h google-perftools-2.2.1/src/stacktrace_libunwind-inl.h --- google-perftools-2.1/src/stacktrace_libunwind-inl.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/stacktrace_libunwind-inl.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -57,6 +58,10 @@ // cases, we return 0 to indicate the situation. static __thread int recursive; +#if (defined(__i386__) || defined(__x86_64__)) && defined(__GNU_LIBRARY__) +#define BASE_STACKTRACE_UNW_CONTEXT_IS_UCONTEXT 1 +#endif + #endif // BASE_STACKTRACE_LIBINWIND_INL_H_ // Note: this part of the file is included several times. @@ -73,7 +78,7 @@ // int max_depth: the size of the result (and sizes) array(s) // int skip_count: how many stack pointers to skip before storing in result // void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) -int GET_STACK_TRACE_OR_FRAMES { +static int GET_STACK_TRACE_OR_FRAMES { void *ip; int n = 0; unw_cursor_t cursor; @@ -87,10 +92,27 @@ } ++recursive; +#if (IS_WITH_CONTEXT && defined(BASE_STACKTRACE_UNW_CONTEXT_IS_UCONTEXT)) + if (ucp) { + uc = *(static_cast(const_cast(ucp))); + /* this is a bit weird. profiler.cc calls us with signal's ucontext + * yet passing us 2 as skip_count and essentially assuming we won't + * use ucontext. */ + /* In order to fix that I'm going to assume that if ucp is + * non-null we're asked to ignore skip_count in case we're + * able to use ucp */ + skip_count = 0; + } else { + unw_getcontext(&uc); + skip_count += 2; // Do not include current and parent frame + } +#else unw_getcontext(&uc); + skip_count += 2; // Do not include current and parent frame +#endif + int ret = unw_init_local(&cursor, &uc); assert(ret >= 0); - skip_count++; // Do not include current frame while (skip_count--) { if (unw_step(&cursor) <= 0) { diff -Nru google-perftools-2.1/src/stacktrace_powerpc-darwin-inl.h google-perftools-2.2.1/src/stacktrace_powerpc-darwin-inl.h --- google-perftools-2.1/src/stacktrace_powerpc-darwin-inl.h 1970-01-01 01:00:00.000000000 +0100 +++ google-perftools-2.2.1/src/stacktrace_powerpc-darwin-inl.h 2014-04-13 03:35:40.000000000 +0200 @@ -0,0 +1,158 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// --- +// Produce stack trace. ABI documentation reference can be found at: +// * PowerPC32 ABI: https://www.power.org/documentation/ +// power-architecture-32-bit-abi-supplement-1-0-embeddedlinuxunified/ +// * PowerPC64 ABI: +// http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK + +#ifndef BASE_STACKTRACE_POWERPC_INL_H_ +#define BASE_STACKTRACE_POWERPC_INL_H_ +// Note: this file is included into stacktrace.cc more than once. +// Anything that should only be defined once should be here: + +#include // for uintptr_t +#include // for NULL +#include + +// Given a pointer to a stack frame, locate and return the calling +// stackframe, or return NULL if no stackframe can be found. Perform sanity +// checks (the strictness of which is controlled by the boolean parameter +// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned. +template +static void **NextStackFrame(void **old_sp) { + void **new_sp = (void **) *old_sp; + + // Check that the transition from frame pointer old_sp to frame + // pointer new_sp isn't clearly bogus + if (STRICT_UNWINDING) { + // With the stack growing downwards, older stack frame must be + // at a greater address that the current one. + if (new_sp <= old_sp) return NULL; + // Assume stack frames larger than 100,000 bytes are bogus. + if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL; + } else { + // In the non-strict mode, allow discontiguous stack frames. + // (alternate-signal-stacks for example). + if (new_sp == old_sp) return NULL; + // And allow frames upto about 1MB. + if ((new_sp > old_sp) + && ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return NULL; + } + if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL; + return new_sp; +} + +// This ensures that GetStackTrace stes up the Link Register properly. +void StacktracePowerPCDummyFunction() __attribute__((noinline)); +void StacktracePowerPCDummyFunction() { __asm__ volatile(""); } +#endif // BASE_STACKTRACE_POWERPC_INL_H_ + +// Note: this part of the file is included several times. +// Do not put globals below. + +// The following 4 functions are generated from the code below: +// GetStack{Trace,Frames}() +// GetStack{Trace,Frames}WithContext() +// +// These functions take the following args: +// void** result: the stack-trace, as an array +// int* sizes: the size of each stack frame, as an array +// (GetStackFrames* only) +// int max_depth: the size of the result (and sizes) array(s) +// int skip_count: how many stack pointers to skip before storing in result +// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) +int GET_STACK_TRACE_OR_FRAMES { + void **sp; + // Apple OS X uses an old version of gnu as -- both Darwin 7.9.0 (Panther) + // and Darwin 8.8.1 (Tiger) use as 1.38. This means we have to use a + // different asm syntax. I don't know quite the best way to discriminate + // systems using the old as from the new one; I've gone with __APPLE__. + // TODO(csilvers): use autoconf instead, to look for 'as --version' == 1 or 2 + __asm__ volatile ("mr %0,r1" : "=r" (sp)); + + // On PowerPC, the "Link Register" or "Link Record" (LR), is a stack + // entry that holds the return address of the subroutine call (what + // instruction we run after our function finishes). This is the + // same as the stack-pointer of our parent routine, which is what we + // want here. While the compiler will always(?) set up LR for + // subroutine calls, it may not for leaf functions (such as this one). + // This routine forces the compiler (at least gcc) to push it anyway. + StacktracePowerPCDummyFunction(); + +#if IS_STACK_FRAMES + // Note we do *not* increment skip_count here for the SYSV ABI. If + // we did, the list of stack frames wouldn't properly match up with + // the list of return addresses. Note this means the top pc entry + // is probably bogus for linux/ppc (and other SYSV-ABI systems). +#else + // The LR save area is used by the callee, so the top entry is bogus. + skip_count++; +#endif + + int n = 0; + while (sp && n < max_depth) { + // The GetStackFrames routine is called when we are in some + // informational context (the failure signal handler for example). + // Use the non-strict unwinding rules to produce a stack trace + // that is as complete as possible (even if it contains a few + // bogus entries in some rare cases). + void **next_sp = NextStackFrame(sp); + + if (skip_count > 0) { + skip_count--; + } else { + // PowerPC has 3 main ABIs, which say where in the stack the + // Link Register is. For DARWIN and AIX (used by apple and + // linux ppc64), it's in sp[2]. For SYSV (used by linux ppc), + // it's in sp[1]. +#if defined(__PPC64__) + // This check is in case the compiler doesn't define _CALL_AIX/etc. + result[n] = *(sp+2); +#elif defined(__linux) + // This check is in case the compiler doesn't define _CALL_SYSV. + result[n] = *(sp+1); +#endif + +#if IS_STACK_FRAMES + if (next_sp > sp) { + sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp; + } else { + // A frame-size of 0 is used to indicate unknown frame size. + sizes[n] = 0; + } +#endif + n++; + } + sp = next_sp; + } + return n; +} diff -Nru google-perftools-2.1/src/stacktrace_powerpc-inl.h google-perftools-2.2.1/src/stacktrace_powerpc-inl.h --- google-perftools-2.1/src/stacktrace_powerpc-inl.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/stacktrace_powerpc-inl.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2007, Google Inc. // All rights reserved. // @@ -125,7 +126,7 @@ // int max_depth: the size of the result (and sizes) array(s) // int skip_count: how many stack pointers to skip before storing in result // void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) -int GET_STACK_TRACE_OR_FRAMES { +static int GET_STACK_TRACE_OR_FRAMES { layout_ppc *current; int n; @@ -138,8 +139,9 @@ StacktracePowerPCDummyFunction(); n = 0; + skip_count++; // skip parent's frame due to indirection in + // stacktrace.cc while (current && n < max_depth) { - result[n] = current->return_addr; // The GetStackFrames routine is called when we are in some // informational context (the failure signal handler for example). @@ -147,16 +149,21 @@ // that is as complete as possible (even if it contains a few // bogus entries in some rare cases). layout_ppc *next = NextStackFrame(current); -#if IS_STACK_FRAMES - if (next > current) { - sizes[n] = (uintptr_t)next - (uintptr_t)current; + if (skip_count > 0) { + skip_count--; } else { - // A frame-size of 0 is used to indicate unknown frame size. - sizes[n] = 0; - } + result[n] = current->return_addr; +#if IS_STACK_FRAMES + if (next > current) { + sizes[n] = (uintptr_t)next - (uintptr_t)current; + } else { + // A frame-size of 0 is used to indicate unknown frame size. + sizes[n] = 0; + } #endif + n++; + } current = next; - n++; } // It's possible the second-last stack frame can't return diff -Nru google-perftools-2.1/src/stacktrace_powerpc-linux-inl.h google-perftools-2.2.1/src/stacktrace_powerpc-linux-inl.h --- google-perftools-2.1/src/stacktrace_powerpc-linux-inl.h 1970-01-01 01:00:00.000000000 +0100 +++ google-perftools-2.2.1/src/stacktrace_powerpc-linux-inl.h 2014-04-13 03:35:40.000000000 +0200 @@ -0,0 +1,231 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// --- +// Author: Craig Silverstein +// +// Produce stack trace. ABI documentation reference can be found at: +// * PowerPC32 ABI: https://www.power.org/documentation/ +// power-architecture-32-bit-abi-supplement-1-0-embeddedlinuxunified/ +// * PowerPC64 ABI: +// http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK + +#ifndef BASE_STACKTRACE_POWERPC_INL_H_ +#define BASE_STACKTRACE_POWERPC_INL_H_ +// Note: this file is included into stacktrace.cc more than once. +// Anything that should only be defined once should be here: + +#include // for uintptr_t +#include // for NULL +#include +#include + +#if defined(HAVE_SYS_UCONTEXT_H) +#include +#elif defined(HAVE_UCONTEXT_H) +#include // for ucontext_t +#endif +typedef ucontext ucontext_t; + +// PowerPC64 Little Endian follows BE wrt. backchain, condition register, +// and LR save area, so no need to adjust the reading struct. +struct layout_ppc { + struct layout_ppc *next; +#ifdef __PPC64__ + long condition_register; +#endif + void *return_addr; +}; + +// Signal callbacks are handled by the vDSO symbol: +// +// * PowerPC64 Linux (arch/powerpc/kernel/vdso64/sigtramp.S): +// __kernel_sigtramp_rt64 +// * PowerPC32 Linux (arch/powerpc/kernel/vdso32/sigtramp.S): +// __kernel_sigtramp32 +// __kernel_sigtramp_rt32 +// +// So a backtrace may need to specially handling if the symbol readed is +// the signal trampoline. + +// Given a pointer to a stack frame, locate and return the calling +// stackframe, or return NULL if no stackframe can be found. Perform sanity +// checks (the strictness of which is controlled by the boolean parameter +// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned. +template +static layout_ppc *NextStackFrame(layout_ppc *current) { + uintptr_t old_sp = (uintptr_t)(current); + uintptr_t new_sp = (uintptr_t)(current->next); + + // Check that the transition from frame pointer old_sp to frame + // pointer new_sp isn't clearly bogus + if (STRICT_UNWINDING) { + // With the stack growing downwards, older stack frame must be + // at a greater address that the current one. + if (new_sp <= old_sp) + return NULL; + // Assume stack frames larger than 100,000 bytes are bogus. + if (new_sp - old_sp > 100000) + return NULL; + } else { + // In the non-strict mode, allow discontiguous stack frames. + // (alternate-signal-stacks for example). + if (new_sp == old_sp) + return NULL; + // And allow frames upto about 1MB. + if ((new_sp > old_sp) && (new_sp - old_sp > 1000000)) + return NULL; + } + if (new_sp & (sizeof(void *) - 1)) + return NULL; + return current->next; +} + +// This ensures that GetStackTrace stes up the Link Register properly. +void StacktracePowerPCDummyFunction() __attribute__((noinline)); +void StacktracePowerPCDummyFunction() { __asm__ volatile(""); } +#endif // BASE_STACKTRACE_POWERPC_INL_H_ + +// Note: this part of the file is included several times. +// Do not put globals below. + +// Load instruction used on top-of-stack get. +#if defined(__PPC64__) || defined(__LP64__) +# define LOAD "ld" +#else +# define LOAD "lwz" +#endif + +// The following 4 functions are generated from the code below: +// GetStack{Trace,Frames}() +// GetStack{Trace,Frames}WithContext() +// +// These functions take the following args: +// void** result: the stack-trace, as an array +// int* sizes: the size of each stack frame, as an array +// (GetStackFrames* only) +// int max_depth: the size of the result (and sizes) array(s) +// int skip_count: how many stack pointers to skip before storing in result +// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) +static int GET_STACK_TRACE_OR_FRAMES { + layout_ppc *current; + int n; + + // Get the address on top-of-stack + current = reinterpret_cast (__builtin_frame_address (0)); + // And ignore the current symbol + current = current->next; + + StacktracePowerPCDummyFunction(); + + n = 0; + skip_count++; // skip parent's frame due to indirection in + // stacktrace.cc + + base::VDSOSupport vdso; + base::ElfMemImage::SymbolInfo rt_sigreturn_symbol_info; +#ifdef __PPC64__ + const void *sigtramp64_vdso = 0; + if (vdso.LookupSymbol("__kernel_sigtramp_rt64", "LINUX_2.6.15", STT_NOTYPE, + &rt_sigreturn_symbol_info)) + sigtramp64_vdso = rt_sigreturn_symbol_info.address; +#else + const void *sigtramp32_vdso = 0; + if (vdso.LookupSymbol("__kernel_sigtramp32", "LINUX_2.6.15", STT_NOTYPE, + &rt_sigreturn_symbol_info)) + sigtramp32_vdso = rt_sigreturn_symbol_info.address; + const void *sigtramp32_rt_vdso = 0; + if (vdso.LookupSymbol("__kernel_sigtramp_rt32", "LINUX_2.6.15", STT_NOTYPE, + &rt_sigreturn_symbol_info)) + sigtramp32_rt_vdso = rt_sigreturn_symbol_info.address; +#endif + + while (current && n < max_depth) { + + // The GetStackFrames routine is called when we are in some + // informational context (the failure signal handler for example). + // Use the non-strict unwinding rules to produce a stack trace + // that is as complete as possible (even if it contains a few + // bogus entries in some rare cases). + layout_ppc *next = NextStackFrame(current); + if (skip_count > 0) { + skip_count--; + } else { + result[n] = current->return_addr; +#ifdef __PPC64__ + if (sigtramp64_vdso && (sigtramp64_vdso == current->return_addr)) { + struct signal_frame_64 { + char dummy[128]; + ucontext_t uc; + // We don't care about the rest, since the IP value is at 'uc' field. + } *sigframe = reinterpret_cast(current); + result[n] = (void*) sigframe->uc.uc_mcontext.gp_regs[PT_NIP]; + } +#else + if (sigtramp32_vdso && (sigtramp32_vdso == current->return_addr)) { + struct signal_frame_32 { + char dummy[64]; + struct sigcontext sctx; + mcontext_t mctx; + // We don't care about the rest, since IP value is at 'mctx' field. + } *sigframe = reinterpret_cast(current); + result[n] = (void*) sigframe->mctx.gregs[PT_NIP]; + } else if (sigtramp32_rt_vdso && (sigtramp32_rt_vdso == current->return_addr)) { + struct rt_signal_frame_32 { + char dummy[64 + 16]; + siginfo_t info; + struct ucontext uc; + // We don't care about the rest, since IP value is at 'uc' field.A + } *sigframe = reinterpret_cast(current); + result[n] = (void*) sigframe->uc.uc_mcontext.uc_regs->gregs[PT_NIP]; + } +#endif + +#if IS_STACK_FRAMES + if (next > current) { + sizes[n] = (uintptr_t)next - (uintptr_t)current; + } else { + // A frame-size of 0 is used to indicate unknown frame size. + sizes[n] = 0; + } +#endif + n++; + } + current = next; + } + + // It's possible the second-last stack frame can't return + // (that is, it's __libc_start_main), in which case + // the CRT startup code will have set its LR to 'NULL'. + if (n > 0 && result[n-1] == NULL) + n--; + + return n; +} diff -Nru google-perftools-2.1/src/stack_trace_table.cc google-perftools-2.2.1/src/stack_trace_table.cc --- google-perftools-2.1/src/stack_trace_table.cc 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/stack_trace_table.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2009, Google Inc. // All rights reserved. // @@ -135,7 +136,7 @@ b = b->next; } } - out[idx++] = static_cast(0); + out[idx++] = NULL; ASSERT(idx == out_len); // Clear state diff -Nru google-perftools-2.1/src/stack_trace_table.h google-perftools-2.2.1/src/stack_trace_table.h --- google-perftools-2.1/src/stack_trace_table.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/stack_trace_table.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2009, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/stacktrace_win32-inl.h google-perftools-2.2.1/src/stacktrace_win32-inl.h --- google-perftools-2.1/src/stacktrace_win32-inl.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/stacktrace_win32-inl.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // @@ -70,22 +71,37 @@ (RtlCaptureStackBackTrace_Function*) GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace"); -PERFTOOLS_DLL_DECL int GetStackTrace(void** result, int max_depth, - int skip_count) { +static int GetStackTrace_win32(void** result, int max_depth, + int skip_count) { if (!RtlCaptureStackBackTrace_fn) { // TODO(csilvers): should we log an error here? return 0; // can't find a stacktrace with no function to call } - return (int)RtlCaptureStackBackTrace_fn(skip_count + 2, max_depth, + return (int)RtlCaptureStackBackTrace_fn(skip_count + 3, max_depth, result, 0); } -PERFTOOLS_DLL_DECL int GetStackFrames(void** /* pcs */, - int* /* sizes */, - int /* max_depth */, - int /* skip_count */) { +static int not_implemented(void) { assert(0 == "Not yet implemented"); return 0; } +static int GetStackFrames_win32(void** /* pcs */, + int* /* sizes */, + int /* max_depth */, + int /* skip_count */) { + return not_implemented(); +} + +static int GetStackFramesWithContext_win32(void** result, int* sizes, int max_depth, + int skip_count, const void *uc) { + return not_implemented(); +} + +static int GetStackTraceWithContext_win32(void** result, int max_depth, + int skip_count, const void *uc) { + return not_implemented(); +} + + #endif // BASE_STACKTRACE_WIN32_INL_H_ diff -Nru google-perftools-2.1/src/stacktrace_x86-inl.h google-perftools-2.2.1/src/stacktrace_x86-inl.h --- google-perftools-2.1/src/stacktrace_x86-inl.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/stacktrace_x86-inl.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -287,7 +288,7 @@ // int skip_count: how many stack pointers to skip before storing in result // void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) -int GET_STACK_TRACE_OR_FRAMES { +static int GET_STACK_TRACE_OR_FRAMES { void **sp; #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) || __llvm__ // __builtin_frame_address(0) can return the wrong address on gcc-4.1.0-k8. @@ -320,6 +321,8 @@ # error Using stacktrace_x86-inl.h on a non x86 architecture! #endif + skip_count++; // skip parent's frame due to indirection in stacktrace.cc + int n = 0; while (sp && n < max_depth) { if (*(sp+1) == reinterpret_cast(0)) { diff -Nru google-perftools-2.1/src/static_vars.cc google-perftools-2.2.1/src/static_vars.cc --- google-perftools-2.1/src/static_vars.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/static_vars.cc 2014-06-22 00:34:32.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // @@ -30,9 +31,13 @@ // --- // Author: Ken Ashcraft +#include #include "static_vars.h" #include // for NULL #include // for operator new +#ifdef HAVE_PTHREAD +#include // for pthread_atfork +#endif #include "internal_logging.h" // for CHECK_CONDITION #include "common.h" #include "sampler.h" // for Sampler @@ -62,17 +67,6 @@ } #endif -static inline -void SetupAtForkLocksHandler() -{ -#if defined(HAVE_FORK) && defined(HAVE_PTHREAD) - pthread_atfork(CentralCacheLockAll, // parent calls before fork - CentralCacheUnlockAll, // parent calls after fork - CentralCacheUnlockAll); // child calls after fork -#endif -} - - SpinLock Static::pageheap_lock_(SpinLock::LINKER_INITIALIZED); SizeMap Static::sizemap_; CentralFreeListPadded Static::central_cache_[kNumClasses]; @@ -102,10 +96,23 @@ // in is caches as pointers that are sources of heap object liveness, // which leads to it missing some memory leaks. pageheap_ = new (MetaDataAlloc(sizeof(PageHeap))) PageHeap; + pageheap_->SetAggressiveDecommit(EnvToBool("TCMALLOC_AGGRESSIVE_DECOMMIT", false)); DLL_Init(&sampled_objects_); Sampler::InitStatics(); } + +#if defined(HAVE_FORK) && defined(HAVE_PTHREAD) + +static inline +void SetupAtForkLocksHandler() +{ + pthread_atfork(CentralCacheLockAll, // parent calls before fork + CentralCacheUnlockAll, // parent calls after fork + CentralCacheUnlockAll); // child calls after fork +} REGISTER_MODULE_INITIALIZER(tcmalloc_fork_handler, SetupAtForkLocksHandler()); +#endif + } // namespace tcmalloc diff -Nru google-perftools-2.1/src/static_vars.h google-perftools-2.2.1/src/static_vars.h --- google-perftools-2.1/src/static_vars.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/static_vars.h 2014-06-22 00:34:32.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/symbolize.cc google-perftools-2.2.1/src/symbolize.cc --- google-perftools-2.1/src/symbolize.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/symbolize.cc 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2009, Google Inc. // All rights reserved. // @@ -75,9 +76,13 @@ // Returns NULL if we're on an OS where we can't get the invocation name. // Using a static var is ok because we're not called from a thread. -static char* GetProgramInvocationName() { +static const char* GetProgramInvocationName() { #if defined(HAVE_PROGRAM_INVOCATION_NAME) +#ifdef __UCLIBC__ + extern const char* program_invocation_name; // uclibc provides this +#else extern char* program_invocation_name; // gcc provides this +#endif return program_invocation_name; #elif defined(__MACH__) // We don't want to allocate memory for this since we may be diff -Nru google-perftools-2.1/src/symbolize.h google-perftools-2.2.1/src/symbolize.h --- google-perftools-2.1/src/symbolize.h 2013-07-29 05:20:40.000000000 +0200 +++ google-perftools-2.2.1/src/symbolize.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2009, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/system-alloc.cc google-perftools-2.2.1/src/system-alloc.cc --- google-perftools-2.1/src/system-alloc.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/system-alloc.cc 2014-03-01 21:40:51.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -201,8 +202,7 @@ void* SbrkSysAllocator::Alloc(size_t size, size_t *actual_size, size_t alignment) { -#ifndef HAVE_SBRK - failed_ = true; +#if !defined(HAVE_SBRK) || defined(__UCLIBC__) return NULL; #else // Check if we should use sbrk allocation. @@ -274,7 +274,6 @@ void* MmapSysAllocator::Alloc(size_t size, size_t *actual_size, size_t alignment) { #ifndef HAVE_MMAP - failed_ = true; return NULL; #else // Check if we should use mmap allocation. @@ -343,7 +342,6 @@ void* DevMemSysAllocator::Alloc(size_t size, size_t *actual_size, size_t alignment) { #ifndef HAVE_MMAP - failed_ = true; return NULL; #else static bool initialized = false; @@ -494,17 +492,17 @@ // Enforce minimum alignment if (alignment < sizeof(MemoryAligner)) alignment = sizeof(MemoryAligner); + size_t actual_size_storage; + if (actual_size == NULL) { + actual_size = &actual_size_storage; + } + void* result = sys_alloc->Alloc(size, actual_size, alignment); if (result != NULL) { - if (actual_size) { - CheckAddressBits( - reinterpret_cast(result) + *actual_size - 1); - TCMalloc_SystemTaken += *actual_size; - } else { + CHECK_CONDITION( CheckAddressBits( - reinterpret_cast(result) + size - 1); - TCMalloc_SystemTaken += size; - } + reinterpret_cast(result) + *actual_size - 1)); + TCMalloc_SystemTaken += *actual_size; } return result; } @@ -546,3 +544,9 @@ #endif return false; } + +void TCMalloc_SystemCommit(void* start, size_t length) { + // Nothing to do here. TCMalloc_SystemRelease does not alter pages + // such that they need to be re-committed before they can be used by the + // application. +} diff -Nru google-perftools-2.1/src/system-alloc.h google-perftools-2.2.1/src/system-alloc.h --- google-perftools-2.1/src/system-alloc.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/system-alloc.h 2014-03-01 21:40:51.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -75,6 +76,13 @@ extern PERFTOOLS_DLL_DECL bool TCMalloc_SystemRelease(void* start, size_t length); +// Called to ressurect memory which has been previously released +// to the system via TCMalloc_SystemRelease. An attempt to +// commit a page that is already committed does not cause this +// function to fail. +extern PERFTOOLS_DLL_DECL +void TCMalloc_SystemCommit(void* start, size_t length); + // The current system allocator. extern PERFTOOLS_DLL_DECL SysAllocator* sys_alloc; diff -Nru google-perftools-2.1/src/tcmalloc.cc google-perftools-2.2.1/src/tcmalloc.cc --- google-perftools-2.1/src/tcmalloc.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/tcmalloc.cc 2014-06-21 21:12:02.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -699,6 +700,11 @@ return true; } + if (strcmp(name, "tcmalloc.aggressive_memory_decommit") == 0) { + *value = size_t(Static::pageheap()->GetAggressiveDecommit()); + return true; + } + return false; } @@ -711,6 +717,11 @@ return true; } + if (strcmp(name, "tcmalloc.aggressive_memory_decommit") == 0) { + Static::pageheap()->SetAggressiveDecommit(value != 0); + return true; + } + return false; } @@ -926,7 +937,11 @@ TCMallocGuard::~TCMallocGuard() { if (--tcmallocguard_refcount == 0) { - const char* env = getenv("MALLOCSTATS"); + const char* env = NULL; + if (!RunningOnValgrind()) { + // Valgrind uses it's own malloc so we cannot do MALLOCSTATS + env = getenv("MALLOCSTATS"); + } if (env != NULL) { int level = atoi(env); if (level < 1) level = 1; @@ -1720,4 +1735,10 @@ return MallocExtension::instance()->GetAllocatedSize(ptr); } +extern "C" PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) __THROW { + void* result = do_malloc(size); + MallocHook::InvokeNewHook(result, size); + return result; +} + #endif // TCMALLOC_USING_DEBUGALLOCATION diff -Nru google-perftools-2.1/src/tcmalloc_guard.h google-perftools-2.2.1/src/tcmalloc_guard.h --- google-perftools-2.1/src/tcmalloc_guard.h 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tcmalloc_guard.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tcmalloc.h google-perftools-2.2.1/src/tcmalloc.h --- google-perftools-2.1/src/tcmalloc.h 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tcmalloc.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2007, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/addressmap_unittest.cc google-perftools-2.2.1/src/tests/addressmap_unittest.cc --- google-perftools-2.1/src/tests/addressmap_unittest.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/addressmap_unittest.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/atomicops_unittest.cc google-perftools-2.2.1/src/tests/atomicops_unittest.cc --- google-perftools-2.1/src/tests/atomicops_unittest.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/tests/atomicops_unittest.cc 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2006, Google Inc. * All rights reserved. * @@ -37,76 +38,6 @@ #define GG_ULONGLONG(x) static_cast(x) -template -static void TestAtomicIncrement(AtomicType (*atomic_increment_func) - (volatile AtomicType*, AtomicType)) { - // For now, we just test single threaded execution - - // use a guard value to make sure the atomic_increment_func doesn't go - // outside the expected address bounds. This is in particular to - // test that some future change to the asm code doesn't cause the - // 32-bit atomic_increment_func doesn't do the wrong thing on 64-bit - // machines. - struct { - AtomicType prev_word; - AtomicType count; - AtomicType next_word; - } s; - - AtomicType prev_word_value, next_word_value; - memset(&prev_word_value, 0xFF, sizeof(AtomicType)); - memset(&next_word_value, 0xEE, sizeof(AtomicType)); - - s.prev_word = prev_word_value; - s.count = 0; - s.next_word = next_word_value; - - ASSERT_EQ(1, (*atomic_increment_func)(&s.count, 1)); - ASSERT_EQ(1, s.count); - ASSERT_EQ(prev_word_value, s.prev_word); - ASSERT_EQ(next_word_value, s.next_word); - - ASSERT_EQ(3, (*atomic_increment_func)(&s.count, 2)); - ASSERT_EQ(3, s.count); - ASSERT_EQ(prev_word_value, s.prev_word); - ASSERT_EQ(next_word_value, s.next_word); - - ASSERT_EQ(6, (*atomic_increment_func)(&s.count, 3)); - ASSERT_EQ(6, s.count); - ASSERT_EQ(prev_word_value, s.prev_word); - ASSERT_EQ(next_word_value, s.next_word); - - ASSERT_EQ(3, (*atomic_increment_func)(&s.count, -3)); - ASSERT_EQ(3, s.count); - ASSERT_EQ(prev_word_value, s.prev_word); - ASSERT_EQ(next_word_value, s.next_word); - - ASSERT_EQ(1, (*atomic_increment_func)(&s.count, -2)); - ASSERT_EQ(1, s.count); - ASSERT_EQ(prev_word_value, s.prev_word); - ASSERT_EQ(next_word_value, s.next_word); - - ASSERT_EQ(0, (*atomic_increment_func)(&s.count, -1)); - ASSERT_EQ(0, s.count); - ASSERT_EQ(prev_word_value, s.prev_word); - ASSERT_EQ(next_word_value, s.next_word); - - ASSERT_EQ(-1, (*atomic_increment_func)(&s.count, -1)); - ASSERT_EQ(-1, s.count); - ASSERT_EQ(prev_word_value, s.prev_word); - ASSERT_EQ(next_word_value, s.next_word); - - ASSERT_EQ(-5, (*atomic_increment_func)(&s.count, -4)); - ASSERT_EQ(-5, s.count); - ASSERT_EQ(prev_word_value, s.prev_word); - ASSERT_EQ(next_word_value, s.next_word); - - ASSERT_EQ(0, (*atomic_increment_func)(&s.count, 5)); - ASSERT_EQ(0, s.count); - ASSERT_EQ(prev_word_value, s.prev_word); - ASSERT_EQ(next_word_value, s.next_word); -} - #define NUM_BITS(T) (sizeof(T) * 8) @@ -159,21 +90,6 @@ } -template -static void TestAtomicIncrementBounds(AtomicType (*atomic_increment_func) - (volatile AtomicType*, AtomicType)) { - // Test increment at the half-width boundary of the atomic type. - // It is primarily for testing at the 32-bit boundary for 64-bit atomic type. - AtomicType test_val = GG_ULONGLONG(1) << (NUM_BITS(AtomicType) / 2); - AtomicType value = test_val - 1; - AtomicType new_value = (*atomic_increment_func)(&value, 1); - ASSERT_EQ(test_val, value); - ASSERT_EQ(value, new_value); - - (*atomic_increment_func)(&value, -1); - ASSERT_EQ(test_val - 1, value); -} - // This is a simple sanity check that values are correct. Not testing // atomicity template @@ -234,42 +150,13 @@ TestAtomicExchange(base::subtle::Acquire_AtomicExchange); TestAtomicExchange(base::subtle::Release_AtomicExchange); - TestAtomicIncrementBounds( - base::subtle::NoBarrier_AtomicIncrement); - TestAtomicIncrementBounds( - base::subtle::Barrier_AtomicIncrement); - TestStore(); TestLoad(); } int main(int argc, char** argv) { - TestAtomicIncrement(base::subtle::NoBarrier_AtomicIncrement); - TestAtomicIncrement(base::subtle::Barrier_AtomicIncrement); - TestAtomicIncrement(base::subtle::NoBarrier_AtomicIncrement); - TestAtomicIncrement(base::subtle::Barrier_AtomicIncrement); - TestAtomicOps(); TestAtomicOps(); - - // I've commented the Atomic64 tests out for now, because Atomic64 - // doesn't work on x86 systems that are not compiled to support mmx - // registers. Since I want this project to be as portable as - // possible -- that is, not to assume we've compiled for mmx or even - // that the processor supports it -- and we don't actually use - // Atomic64 anywhere, I've commented it out of the test for now. - // (Luckily, if we ever do use Atomic64 by accident, we'll get told - // via a compiler error rather than some obscure runtime failure, so - // this course of action is safe.) - // If we ever *do* want to enable this, try adding -msse (or -mmmx?) - // to the CXXFLAGS in Makefile.am. -#if 0 and defined(BASE_HAS_ATOMIC64) - TestAtomicIncrement( - base::subtle::NoBarrier_AtomicIncrement); - TestAtomicIncrement( - base::subtle::Barrier_AtomicIncrement); -#endif - printf("PASS\n"); return 0; } diff -Nru google-perftools-2.1/src/tests/current_allocated_bytes_test.cc google-perftools-2.2.1/src/tests/current_allocated_bytes_test.cc --- google-perftools-2.1/src/tests/current_allocated_bytes_test.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/current_allocated_bytes_test.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2011, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/debugallocation_test.cc google-perftools-2.2.1/src/tests/debugallocation_test.cc --- google-perftools-2.1/src/tests/debugallocation_test.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/debugallocation_test.cc 2014-04-13 03:35:40.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2007, Google Inc. // All rights reserved. // @@ -32,8 +33,10 @@ #include #include +#include // for memcmp #include #include "gperftools/malloc_extension.h" +#include "gperftools/tcmalloc.h" #include "base/logging.h" using std::vector; @@ -295,6 +298,22 @@ #endif } +// based on test program contributed by mikesart@gmail.com aka +// mikesart@valvesoftware.com. See issue-464. +TEST(DebugAllocationTest, ReallocAfterMemalign) { + char stuff[50]; + memset(stuff, 0x11, sizeof(stuff)); + void *p = tc_memalign(16, sizeof(stuff)); + EXPECT_NE(p, NULL); + memcpy(stuff, p, sizeof(stuff)); + + p = realloc(p, sizeof(stuff) + 10); + EXPECT_NE(p, NULL); + + int rv = memcmp(stuff, p, sizeof(stuff)); + EXPECT_EQ(rv, 0); +} + int main(int argc, char** argv) { // If you run without args, we run the non-death parts of the test. // Otherwise, argv[1] should be a number saying which death-test diff -Nru google-perftools-2.1/src/tests/frag_unittest.cc google-perftools-2.2.1/src/tests/frag_unittest.cc --- google-perftools-2.1/src/tests/frag_unittest.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/frag_unittest.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2003, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/getpc_test.cc google-perftools-2.2.1/src/tests/getpc_test.cc --- google-perftools-2.1/src/tests/getpc_test.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/tests/getpc_test.cc 2014-03-29 21:35:36.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -99,14 +100,16 @@ char* expected = (char*)&RoutineCallingTheSignal; char* actual = (char*)getpc_retval; - // For ia64, ppc64, and parisc64, the function pointer is actually + // For ia64, ppc64v1, and parisc64, the function pointer is actually // a struct. For instance, ia64's dl-fptr.h: // struct fdesc { /* An FDESC is a function descriptor. */ // ElfW(Addr) ip; /* code entry point */ // ElfW(Addr) gp; /* global pointer */ // }; // We want the code entry point. -#if defined(__ia64) || defined(__powerpc64__) // NOTE: ppc64 is UNTESTED + // NOTE: ppc64 ELFv2 (Little Endian) does not have function pointers +#if defined(__ia64) || \ + (defined(__powerpc64__) && _CALL_ELF != 2) expected = ((char**)expected)[0]; // this is "ip" #endif diff -Nru google-perftools-2.1/src/tests/heap-checker-death_unittest.sh google-perftools-2.2.1/src/tests/heap-checker-death_unittest.sh --- google-perftools-2.1/src/tests/heap-checker-death_unittest.sh 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/heap-checker-death_unittest.sh 2013-12-06 21:16:47.000000000 +0100 @@ -44,7 +44,7 @@ exit 1 fi -EXE="${1:-$BINDIR}/heap-checker_unittest" +EXE="${1:-$BINDIR/heap-checker_unittest}" TMPDIR="/tmp/heap_check_death_info" ALARM() { diff -Nru google-perftools-2.1/src/tests/heap-checker_unittest.cc google-perftools-2.2.1/src/tests/heap-checker_unittest.cc --- google-perftools-2.1/src/tests/heap-checker_unittest.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/tests/heap-checker_unittest.cc 2014-04-13 03:35:40.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -1266,7 +1267,7 @@ // On PPC64 the stacktrace returned by GetStatcTrace contains the function // address from .text segment while function pointers points to ODP entries. // The following code decodes the ODP to get the actual symbol address. -#if defined(__linux) && defined(__PPC64__) +#if defined(__linux) && defined(__PPC64__) && (_CALL_ELF != 2) static inline uintptr_t GetFunctionAddress (void* (*func)(uintptr_t*)) { struct odp_entry_t { diff -Nru google-perftools-2.1/src/tests/heap-checker_unittest.sh google-perftools-2.2.1/src/tests/heap-checker_unittest.sh --- google-perftools-2.1/src/tests/heap-checker_unittest.sh 2012-02-10 03:45:37.000000000 +0100 +++ google-perftools-2.2.1/src/tests/heap-checker_unittest.sh 2013-12-06 21:16:47.000000000 +0100 @@ -48,7 +48,7 @@ exit 1 fi -HEAP_CHECKER="${1:-$BINDIR}/heap-checker_unittest" +HEAP_CHECKER="${1:-$BINDIR/heap-checker_unittest}" PPROF_PATH="${2:-$PPROF_PATH}" TMPDIR=/tmp/heap_check_info diff -Nru google-perftools-2.1/src/tests/heap-profiler_unittest.cc google-perftools-2.2.1/src/tests/heap-profiler_unittest.cc --- google-perftools-2.1/src/tests/heap-profiler_unittest.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/heap-profiler_unittest.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/heap-profiler_unittest.sh google-perftools-2.2.1/src/tests/heap-profiler_unittest.sh --- google-perftools-2.1/src/tests/heap-profiler_unittest.sh 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/heap-profiler_unittest.sh 2013-12-06 21:16:47.000000000 +0100 @@ -52,7 +52,7 @@ exit 1 fi -HEAP_PROFILER="${1:-$BINDIR}/heap-profiler_unittest" +HEAP_PROFILER="${1:-$BINDIR/heap-profiler_unittest}" PPROF="${2:-$PPROF_PATH}" TEST_TMPDIR=/tmp/heap_profile_info diff -Nru google-perftools-2.1/src/tests/low_level_alloc_unittest.cc google-perftools-2.2.1/src/tests/low_level_alloc_unittest.cc --- google-perftools-2.1/src/tests/low_level_alloc_unittest.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/low_level_alloc_unittest.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2006, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/tests/malloc_extension_c_test.c google-perftools-2.2.1/src/tests/malloc_extension_c_test.c --- google-perftools-2.1/src/tests/malloc_extension_c_test.c 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/tests/malloc_extension_c_test.c 2013-12-06 21:16:47.000000000 +0100 @@ -1,3 +1,4 @@ +/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* Copyright (c) 2009, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/tests/malloc_extension_test.cc google-perftools-2.2.1/src/tests/malloc_extension_test.cc --- google-perftools-2.1/src/tests/malloc_extension_test.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/malloc_extension_test.cc 2014-03-01 20:24:54.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // @@ -39,8 +40,6 @@ #include #include -using STL_NAMESPACE::vector; - int main(int argc, char** argv) { void* a = malloc(1000); diff -Nru google-perftools-2.1/src/tests/malloc_hook_test.cc google-perftools-2.2.1/src/tests/malloc_hook_test.cc --- google-perftools-2.1/src/tests/malloc_hook_test.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/tests/malloc_hook_test.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2011, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/markidle_unittest.cc google-perftools-2.2.1/src/tests/markidle_unittest.cc --- google-perftools-2.1/src/tests/markidle_unittest.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/tests/markidle_unittest.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2003, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/memalign_unittest.cc google-perftools-2.2.1/src/tests/memalign_unittest.cc --- google-perftools-2.1/src/tests/memalign_unittest.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/memalign_unittest.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2004, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/packed-cache_test.cc google-perftools-2.2.1/src/tests/packed-cache_test.cc --- google-perftools-2.1/src/tests/packed-cache_test.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/packed-cache_test.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2007, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/page_heap_test.cc google-perftools-2.2.1/src/tests/page_heap_test.cc --- google-perftools-2.1/src/tests/page_heap_test.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/tests/page_heap_test.cc 2013-12-06 21:16:47.000000000 +0100 @@ -1,5 +1,9 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright 2009 Google Inc. All Rights Reserved. // Author: fikes@google.com (Andrew Fikes) +// +// Use of this source code is governed by a BSD-style license that can +// be found in the LICENSE file. #include "config_for_unittests.h" #include "page_heap.h" diff -Nru google-perftools-2.1/src/tests/pagemap_unittest.cc google-perftools-2.2.1/src/tests/pagemap_unittest.cc --- google-perftools-2.1/src/tests/pagemap_unittest.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/pagemap_unittest.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2003, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/profiledata_unittest.cc google-perftools-2.2.1/src/tests/profiledata_unittest.cc --- google-perftools-2.1/src/tests/profiledata_unittest.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/profiledata_unittest.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2007, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/profile-handler_unittest.cc google-perftools-2.2.1/src/tests/profile-handler_unittest.cc --- google-perftools-2.1/src/tests/profile-handler_unittest.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/profile-handler_unittest.cc 2013-12-06 21:16:47.000000000 +0100 @@ -1,7 +1,12 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright 2009 Google Inc. All Rights Reserved. // Author: Nabeel Mian (nabeelmian@google.com) // Chris Demetriou (cgd@google.com) // +// Use of this source code is governed by a BSD-style license that can +// be found in the LICENSE file. +// +// // This file contains the unit tests for profile-handler.h interface. // // It is linked into three separate unit tests: diff -Nru google-perftools-2.1/src/tests/profiler_unittest.cc google-perftools-2.2.1/src/tests/profiler_unittest.cc --- google-perftools-2.1/src/tests/profiler_unittest.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/profiler_unittest.cc 2013-12-06 21:16:47.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -110,27 +111,31 @@ ProfilerFlush(); // just because we can // The other threads, if any, will run only half as long as the main thread - RunManyThreads(test_other_thread, num_threads); - + if(num_threads > 0) { + RunManyThreads(test_other_thread, num_threads); + } else { // Or maybe they asked to fork. The fork test is only interesting // when we use CPUPROFILE to name, so check for that #ifdef HAVE_UNISTD_H - for (; num_threads < 0; ++num_threads) { // - to fork - if (filename) { - printf("FORK test only makes sense when no filename is specified.\n"); - return 2; - } - switch (fork()) { - case -1: - printf("FORK failed!\n"); - return 1; - case 0: // child - return execl(argv[0], argv[0], argv[1], NULL); - default: - wait(NULL); // we'll let the kids run one at a time + for (; num_threads < 0; ++num_threads) { // - to fork + if (filename) { + printf("FORK test only makes sense when no filename is specified.\n"); + return 2; + } + switch (fork()) { + case -1: + printf("FORK failed!\n"); + return 1; + case 0: // child + return execl(argv[0], argv[0], argv[1], NULL); + default: + wait(NULL); // we'll let the kids run one at a time + } } - } +#else + fprintf(stderr, "%s was compiled without support for fork() and exec()\n", argv[0]); #endif + } test_main_thread(); diff -Nru google-perftools-2.1/src/tests/raw_printer_test.cc google-perftools-2.2.1/src/tests/raw_printer_test.cc --- google-perftools-2.1/src/tests/raw_printer_test.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/raw_printer_test.cc 2013-12-06 21:16:47.000000000 +0100 @@ -1,5 +1,9 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright 2009 Google Inc. All Rights Reserved. // Author: sanjay@google.com (Sanjay Ghemawat) +// +// Use of this source code is governed by a BSD-style license that can +// be found in the LICENSE file. #include "raw_printer.h" #include diff -Nru google-perftools-2.1/src/tests/realloc_unittest.cc google-perftools-2.2.1/src/tests/realloc_unittest.cc --- google-perftools-2.1/src/tests/realloc_unittest.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/realloc_unittest.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2004, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/sampler_test.cc google-perftools-2.2.1/src/tests/sampler_test.cc --- google-perftools-2.1/src/tests/sampler_test.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/sampler_test.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/sampling_test.cc google-perftools-2.2.1/src/tests/sampling_test.cc --- google-perftools-2.1/src/tests/sampling_test.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/sampling_test.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/simple_compat_test.cc google-perftools-2.2.1/src/tests/simple_compat_test.cc --- google-perftools-2.1/src/tests/simple_compat_test.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/simple_compat_test.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2012, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/stack_trace_table_test.cc google-perftools-2.2.1/src/tests/stack_trace_table_test.cc --- google-perftools-2.1/src/tests/stack_trace_table_test.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/stack_trace_table_test.cc 2013-12-06 21:16:47.000000000 +0100 @@ -1,5 +1,10 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright 2009 Google Inc. All Rights Reserved. // Author: fikes@google.com (Andrew Fikes) +// +// Use of this source code is governed by a BSD-style license that can +// be found in the LICENSE file. + #include "config_for_unittests.h" #include // for puts() diff -Nru google-perftools-2.1/src/tests/system-alloc_unittest.cc google-perftools-2.2.1/src/tests/system-alloc_unittest.cc --- google-perftools-2.1/src/tests/system-alloc_unittest.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/system-alloc_unittest.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2007, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/tcmalloc_large_unittest.cc google-perftools-2.2.1/src/tests/tcmalloc_large_unittest.cc --- google-perftools-2.1/src/tests/tcmalloc_large_unittest.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/tcmalloc_large_unittest.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/tcmalloc_unittest.cc google-perftools-2.2.1/src/tests/tcmalloc_unittest.cc --- google-perftools-2.1/src/tests/tcmalloc_unittest.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/tests/tcmalloc_unittest.cc 2014-04-13 03:35:40.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2005, Google Inc. // All rights reserved. // @@ -868,6 +869,23 @@ } #endif +class AggressiveDecommitChanger { + size_t old_value_; +public: + AggressiveDecommitChanger(size_t new_value) { + MallocExtension *inst = MallocExtension::instance(); + bool rv = inst->GetNumericProperty("tcmalloc.aggressive_memory_decommit", &old_value_); + CHECK_CONDITION(rv); + rv = inst->SetNumericProperty("tcmalloc.aggressive_memory_decommit", new_value); + CHECK_CONDITION(rv); + } + ~AggressiveDecommitChanger() { + MallocExtension *inst = MallocExtension::instance(); + bool rv = inst->SetNumericProperty("tcmalloc.aggressive_memory_decommit", old_value_); + CHECK_CONDITION(rv); + } +}; + static void TestReleaseToSystem() { // Debug allocation mode adds overhead to each allocation which // messes up all the equality tests here. I just disable the @@ -879,6 +897,8 @@ const double old_tcmalloc_release_rate = FLAGS_tcmalloc_release_rate; FLAGS_tcmalloc_release_rate = 0; + AggressiveDecommitChanger disabler(0); + static const int MB = 1048576; void* a = malloc(MB); void* b = malloc(MB); @@ -929,6 +949,51 @@ #endif // #ifndef DEBUGALLOCATION } +static void TestAggressiveDecommit() { + // Debug allocation mode adds overhead to each allocation which + // messes up all the equality tests here. I just disable the + // teset in this mode. +#ifndef DEBUGALLOCATION + + if(!HaveSystemRelease) return; + + fprintf(LOGSTREAM, "Testing aggressive de-commit\n"); + + AggressiveDecommitChanger enabler(1); + + static const int MB = 1048576; + void* a = malloc(MB); + void* b = malloc(MB); + + size_t starting_bytes = GetUnmappedBytes(); + + // ReleaseToSystem shouldn't do anything either. + MallocExtension::instance()->ReleaseToSystem(MB); + EXPECT_EQ(starting_bytes, GetUnmappedBytes()); + + free(a); + + // The span to release should be 1MB. + EXPECT_EQ(starting_bytes + MB, GetUnmappedBytes()); + + free(b); + + EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); + + // Nothing else to release. + MallocExtension::instance()->ReleaseFreeMemory(); + EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); + + a = malloc(MB); + free(a); + + EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); + + fprintf(LOGSTREAM, "Done testing aggressive de-commit\n"); + +#endif // #ifndef DEBUGALLOCATION +} + // On MSVC10, in release mode, the optimizer convinces itself // g_no_memory is never changed (I guess it doesn't realize OnNoMemory // might be called). Work around this by setting the var volatile. @@ -1067,6 +1132,11 @@ free(p1); VerifyDeleteHookWasCalled(); + p1 = tc_malloc_skip_new_handler(10); + CHECK(p1 != NULL); + VerifyNewHookWasCalled(); + free(p1); + VerifyDeleteHookWasCalled(); p1 = calloc(10, 2); CHECK(p1 != NULL); @@ -1307,6 +1377,7 @@ TestHugeThreadCache(); TestRanges(); TestReleaseToSystem(); + TestAggressiveDecommit(); TestSetNewMode(); return 0; diff -Nru google-perftools-2.1/src/tests/tcmalloc_unittest.sh google-perftools-2.2.1/src/tests/tcmalloc_unittest.sh --- google-perftools-2.1/src/tests/tcmalloc_unittest.sh 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/tests/tcmalloc_unittest.sh 2014-04-13 03:28:02.000000000 +0200 @@ -38,17 +38,13 @@ # behavior, just performance. BINDIR="${BINDIR:-.}" -TCMALLOC_UNITTEST="${1:-$BINDIR}/tcmalloc_unittest" +TCMALLOC_UNITTEST="${1:-$BINDIR/tcmalloc_unittest}" TMPDIR=/tmp/tcmalloc_unittest rm -rf $TMPDIR || exit 2 mkdir $TMPDIR || exit 3 -# $1: value of tcmalloc_unittest env. var. -run_check_transfer_num_obj() { - [ -n "$1" ] && export TCMALLOC_TRANSFER_NUM_OBJ="$1" - - echo -n "Testing $TCMALLOC_UNITTEST with TCMALLOC_TRANSFER_NUM_OBJ=$1 ... " +run_unittest() { if $TCMALLOC_UNITTEST > $TMPDIR/output 2>&1; then echo "OK" else @@ -61,8 +57,20 @@ fi } +# $1: value of tcmalloc_unittest env. var. +run_check_transfer_num_obj() { + [ -n "$1" ] && export TCMALLOC_TRANSFER_NUM_OBJ="$1" + + echo -n "Testing $TCMALLOC_UNITTEST with TCMALLOC_TRANSFER_NUM_OBJ=$1 ... " + run_unittest +} + run_check_transfer_num_obj "" run_check_transfer_num_obj "40" run_check_transfer_num_obj "4096" +echo -n "Testing $TCMALLOC_UNITTEST with TCMALLOC_AGGRESSIVE_DECOMMIT=t ... " + +TCMALLOC_AGGRESSIVE_DECOMMIT=t run_unittest + echo "PASS" diff -Nru google-perftools-2.1/src/tests/testutil.cc google-perftools-2.2.1/src/tests/testutil.cc --- google-perftools-2.1/src/tests/testutil.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/testutil.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2007, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/testutil.h google-perftools-2.2.1/src/tests/testutil.h --- google-perftools-2.1/src/tests/testutil.h 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/testutil.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2007, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/tests/thread_dealloc_unittest.cc google-perftools-2.2.1/src/tests/thread_dealloc_unittest.cc --- google-perftools-2.1/src/tests/thread_dealloc_unittest.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/tests/thread_dealloc_unittest.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2004, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/thread_cache.cc google-perftools-2.2.1/src/thread_cache.cc --- google-perftools-2.1/src/thread_cache.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/thread_cache.cc 2014-06-21 21:12:02.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // @@ -37,19 +38,24 @@ #include // for max, min #include "base/commandlineflags.h" // for SpinLockHolder #include "base/spinlock.h" // for SpinLockHolder +#include "getenv_safe.h" // for TCMallocGetenvSafe #include "central_freelist.h" // for CentralFreeListPadded #include "maybe_threads.h" using std::min; using std::max; -DEFINE_int64(tcmalloc_max_total_thread_cache_bytes, - EnvToInt64("TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES", - kDefaultOverallThreadCacheSize), - "Bound on the total amount of bytes allocated to " - "thread caches. This bound is not strict, so it is possible " - "for the cache to go over this bound in certain circumstances. " - "Maximum value of this flag is capped to 1 GB."); +// Note: this is initialized manually in InitModule to ensure that +// it's configured at right time +// +// DEFINE_int64(tcmalloc_max_total_thread_cache_bytes, +// EnvToInt64("TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES", +// kDefaultOverallThreadCacheSize), +// "Bound on the total amount of bytes allocated to " +// "thread caches. This bound is not strict, so it is possible " +// "for the cache to go over this bound in certain circumstances. " +// "Maximum value of this flag is capped to 1 GB."); + namespace tcmalloc { @@ -308,6 +314,10 @@ void ThreadCache::InitModule() { SpinLockHolder h(Static::pageheap_lock()); if (!phinited) { + const char *tcb = TCMallocGetenvSafe("TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES"); + if (tcb) { + set_overall_thread_cache_size(strtoll(tcb, NULL, 10)); + } Static::InitStaticVars(); threadcache_allocator.Init(); phinited = 1; diff -Nru google-perftools-2.1/src/thread_cache.h google-perftools-2.2.1/src/thread_cache.h --- google-perftools-2.1/src/thread_cache.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/thread_cache.h 2014-06-21 21:12:02.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/windows/auto_testing_hook.h google-perftools-2.2.1/src/windows/auto_testing_hook.h --- google-perftools-2.1/src/windows/auto_testing_hook.h 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/windows/auto_testing_hook.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2010 The Chromium Authors. All rights reserved. // // Redistribution and use in source and binary forms, with or without diff -Nru google-perftools-2.1/src/windows/config.h google-perftools-2.2.1/src/windows/config.h --- google-perftools-2.1/src/windows/config.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/windows/config.h 2014-06-22 00:52:34.000000000 +0200 @@ -1,4 +1,8 @@ -/* A manual version of config.h fit for windows machines. */ +/* A manual version of config.h fit for windows machines. + * + * Use of this source code is governed by a BSD-style license that can + * be found in the LICENSE file. + */ /* Sometimes we accidentally #include this config.h instead of the one in .. -- this is particularly true for msys/mingw, which uses the @@ -222,7 +226,7 @@ #define PACKAGE_NAME "gperftools" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "gperftools 2.1" +#define PACKAGE_STRING "gperftools 2.2.1" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "gperftools" @@ -231,7 +235,7 @@ #undef PACKAGE_URL /* Define to the version of this package. */ -#define PACKAGE_VERSION "2.1" +#define PACKAGE_VERSION "2.2.1" /* How to access the PC from a struct ucontext */ #undef PC_FROM_UCONTEXT diff -Nru google-perftools-2.1/src/windows/get_mangled_names.cc google-perftools-2.2.1/src/windows/get_mangled_names.cc --- google-perftools-2.1/src/windows/get_mangled_names.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/windows/get_mangled_names.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2008, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/windows/gperftools/tcmalloc.h google-perftools-2.2.1/src/windows/gperftools/tcmalloc.h --- google-perftools-2.1/src/windows/gperftools/tcmalloc.h 2013-07-30 11:12:44.000000000 +0200 +++ google-perftools-2.2.1/src/windows/gperftools/tcmalloc.h 2014-06-22 00:53:07.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2003, Google Inc. * All rights reserved. * @@ -49,9 +50,9 @@ // Define the version number so folks can check against it #define TC_VERSION_MAJOR 2 -#define TC_VERSION_MINOR 1 -#define TC_VERSION_PATCH "" -#define TC_VERSION_STRING "gperftools 2.1" +#define TC_VERSION_MINOR 2 +#define TC_VERSION_PATCH ".1" +#define TC_VERSION_STRING "gperftools 2.2.1" #include // for struct mallinfo, if it's defined @@ -78,6 +79,7 @@ const char** patch) __THROW; PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW; + PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) __THROW; PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW; PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW; PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) __THROW; diff -Nru google-perftools-2.1/src/windows/gperftools/tcmalloc.h.in google-perftools-2.2.1/src/windows/gperftools/tcmalloc.h.in --- google-perftools-2.1/src/windows/gperftools/tcmalloc.h.in 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/windows/gperftools/tcmalloc.h.in 2014-04-13 03:35:40.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2003, Google Inc. * All rights reserved. * @@ -78,6 +79,7 @@ const char** patch) __THROW; PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW; + PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) __THROW; PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW; PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW; PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) __THROW; diff -Nru google-perftools-2.1/src/windows/mingw.h google-perftools-2.2.1/src/windows/mingw.h --- google-perftools-2.1/src/windows/mingw.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/windows/mingw.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* Copyright (c) 2007, Google Inc. * All rights reserved. * @@ -58,7 +59,9 @@ // Some mingw distributions have a pthreads wrapper, but it doesn't // work as well as native windows spinlocks (at least for us). So // pretend the pthreads wrapper doesn't exist, even when it does. +#ifndef HAVE_PTHREAD_DESPITE_ASKING_FOR #undef HAVE_PTHREAD +#endif #define HAVE_PID_T diff -Nru google-perftools-2.1/src/windows/mini_disassembler.cc google-perftools-2.2.1/src/windows/mini_disassembler.cc --- google-perftools-2.1/src/windows/mini_disassembler.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/windows/mini_disassembler.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2007, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/windows/mini_disassembler.h google-perftools-2.2.1/src/windows/mini_disassembler.h --- google-perftools-2.1/src/windows/mini_disassembler.h 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/windows/mini_disassembler.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2007, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/windows/mini_disassembler_types.h google-perftools-2.2.1/src/windows/mini_disassembler_types.h --- google-perftools-2.1/src/windows/mini_disassembler_types.h 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/windows/mini_disassembler_types.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2007, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/windows/override_functions.cc google-perftools-2.2.1/src/windows/override_functions.cc --- google-perftools-2.1/src/windows/override_functions.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/windows/override_functions.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- // Copyright (c) 2007, Google Inc. // All rights reserved. // diff -Nru google-perftools-2.1/src/windows/patch_functions.cc google-perftools-2.2.1/src/windows/patch_functions.cc --- google-perftools-2.1/src/windows/patch_functions.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/windows/patch_functions.cc 2014-06-07 22:54:00.000000000 +0200 @@ -548,13 +548,10 @@ if (windows_fn_[i] && windows_fn_[i] != perftools_fn_[i]) { // if origstub_fn_ is not NULL, it's left around from a previous // patch. We need to set it to NULL for the new Patch call. - // Since we've patched Unpatch() not to delete origstub_fn_ (it - // causes problems in some contexts, though obviously not this - // one), we should delete it now, before setting it to NULL. - // NOTE: casting from a function to a pointer is contra the C++ - // spec. It's not safe on IA64, but is on i386. We use - // a C-style cast here to emphasize this is not legal C++. - delete[] (char*)(origstub_fn_[i]); + // + // Note that origstub_fn_ was logically freed by + // PreamblePatcher::Unpatch, so we don't have to do anything + // about it. origstub_fn_[i] = NULL; // Patch() will fill this in CHECK_EQ(sidestep::SIDESTEP_SUCCESS, PreamblePatcher::Patch(windows_fn_[i], perftools_fn_[i], diff -Nru google-perftools-2.1/src/windows/port.cc google-perftools-2.2.1/src/windows/port.cc --- google-perftools-2.1/src/windows/port.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/windows/port.cc 2014-06-21 21:12:02.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2007, Google Inc. * All rights reserved. * @@ -40,12 +41,12 @@ #include // for strlen(), memset(), memcmp() #include #include // for va_list, va_start, va_end +#include // for std:{min,max} #include #include "port.h" #include "base/logging.h" #include "base/spinlock.h" #include "internal_logging.h" -#include "system-alloc.h" // ----------------------------------------------------------------------- // Basic libraries @@ -216,68 +217,6 @@ } -// ----------------------------------------------------------------------- -// These functions replace system-alloc.cc - -// The current system allocator declaration (unused here) -SysAllocator* sys_alloc = NULL; -// Number of bytes taken from system. -size_t TCMalloc_SystemTaken = 0; - -// This is mostly like MmapSysAllocator::Alloc, except it does these weird -// munmap's in the middle of the page, which is forbidden in windows. -extern PERFTOOLS_DLL_DECL -void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, - size_t alignment) { - // Align on the pagesize boundary - const int pagesize = getpagesize(); - if (alignment < pagesize) alignment = pagesize; - size = ((size + alignment - 1) / alignment) * alignment; - - // Safest is to make actual_size same as input-size. - if (actual_size) { - *actual_size = size; - } - - // Ask for extra memory if alignment > pagesize - size_t extra = 0; - if (alignment > pagesize) { - extra = alignment - pagesize; - } - - void* result = VirtualAlloc(0, size + extra, - MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); - if (result == NULL) - return NULL; - - TCMalloc_SystemTaken += size + extra; - - // Adjust the return memory so it is aligned - uintptr_t ptr = reinterpret_cast(result); - size_t adjust = 0; - if ((ptr & (alignment - 1)) != 0) { - adjust = alignment - (ptr & (alignment - 1)); - } - - ptr += adjust; - return reinterpret_cast(ptr); -} - -extern PERFTOOLS_DLL_DECL -bool TCMalloc_SystemRelease(void* start, size_t length) { - // TODO(csilvers): should I be calling VirtualFree here? - return false; -} - -bool RegisterSystemAllocator(SysAllocator *allocator, int priority) { - return false; // we don't allow registration on windows, right now -} - -void DumpSystemAllocatorStats(TCMalloc_Printer* printer) { - // We don't dump stats on windows, right now -} - - // ----------------------------------------------------------------------- // These functions rework existing functions of the same name in the // Google codebase. diff -Nru google-perftools-2.1/src/windows/port.h google-perftools-2.2.1/src/windows/port.h --- google-perftools-2.1/src/windows/port.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/windows/port.h 2014-02-22 21:25:25.000000000 +0100 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2007, Google Inc. * All rights reserved. * @@ -132,7 +133,14 @@ return left == right; } +/* + * windows/port.h defines compatibility APIs for several .h files, which + * we therefore shouldn't be #including directly. This hack keeps us from + * doing so. TODO(csilvers): do something more principled. + */ +#define GOOGLE_MAYBE_THREADS_H_ 1 /* This replaces maybe_threads.{h,cc} */ + EXTERN_C pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)); /* port.cc */ inline int perftools_pthread_key_create(pthread_key_t *pkey, @@ -164,12 +172,13 @@ void (*init_routine)(void)); #endif /* __cplusplus */ -#endif /* HAVE_PTHREAD */ inline void sched_yield(void) { Sleep(0); } +#endif /* HAVE_PTHREAD */ + /* * __declspec(thread) isn't usable in a dll opened via LoadLibrary(). * But it doesn't work to LoadLibrary() us anyway, because of all the @@ -447,6 +456,7 @@ #endif #ifndef __MINGW32__ +#if _MSC_VER < 1800 inline long long int strtoll(const char *nptr, char **endptr, int base) { return _strtoi64(nptr, endptr, base); } @@ -457,6 +467,7 @@ inline long long int strtoq(const char *nptr, char **endptr, int base) { return _strtoi64(nptr, endptr, base); } +#endif inline unsigned long long int strtouq(const char *nptr, char **endptr, int base) { return _strtoui64(nptr, endptr, base); @@ -473,16 +484,6 @@ /* tcmalloc.cc calls this so we can patch VirtualAlloc() et al. */ extern void PatchWindowsFunctions(); -// ----------------------------------- BUILD-SPECIFIC - -/* - * windows/port.h defines compatibility APIs for several .h files, which - * we therefore shouldn't be #including directly. This hack keeps us from - * doing so. TODO(csilvers): do something more principled. - */ -#define GOOGLE_MAYBE_THREADS_H_ 1 - - #endif /* _WIN32 */ #undef inline diff -Nru google-perftools-2.1/src/windows/preamble_patcher.cc google-perftools-2.2.1/src/windows/preamble_patcher.cc --- google-perftools-2.1/src/windows/preamble_patcher.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/windows/preamble_patcher.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2007, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/windows/preamble_patcher.h google-perftools-2.2.1/src/windows/preamble_patcher.h --- google-perftools-2.1/src/windows/preamble_patcher.h 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/windows/preamble_patcher.h 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2007, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/windows/preamble_patcher_test.cc google-perftools-2.2.1/src/windows/preamble_patcher_test.cc --- google-perftools-2.1/src/windows/preamble_patcher_test.cc 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/src/windows/preamble_patcher_test.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2011, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/windows/preamble_patcher_with_stub.cc google-perftools-2.2.1/src/windows/preamble_patcher_with_stub.cc --- google-perftools-2.1/src/windows/preamble_patcher_with_stub.cc 2013-07-30 11:12:11.000000000 +0200 +++ google-perftools-2.2.1/src/windows/preamble_patcher_with_stub.cc 2013-09-22 04:03:49.000000000 +0200 @@ -1,3 +1,4 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- /* Copyright (c) 2007, Google Inc. * All rights reserved. * diff -Nru google-perftools-2.1/src/windows/system-alloc.cc google-perftools-2.2.1/src/windows/system-alloc.cc --- google-perftools-2.1/src/windows/system-alloc.cc 1970-01-01 01:00:00.000000000 +0100 +++ google-perftools-2.2.1/src/windows/system-alloc.cc 2014-03-29 21:24:54.000000000 +0100 @@ -0,0 +1,204 @@ +// Copyright (c) 2013, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// --- +// Author: Petr Hosek + +#ifndef _WIN32 +# error You should only be including windows/system-alloc.cc in a windows environment! +#endif + +#include +#include +#include // std::min +#include +#include "base/logging.h" +#include "base/spinlock.h" +#include "internal_logging.h" +#include "system-alloc.h" + +static SpinLock spinlock(SpinLock::LINKER_INITIALIZED); + +// The current system allocator declaration +SysAllocator* sys_alloc = NULL; +// Number of bytes taken from system. +size_t TCMalloc_SystemTaken = 0; + +class VirtualSysAllocator : public SysAllocator { +public: + VirtualSysAllocator() : SysAllocator() { + } + void* Alloc(size_t size, size_t *actual_size, size_t alignment); +}; +static char virtual_space[sizeof(VirtualSysAllocator)]; + +// This is mostly like MmapSysAllocator::Alloc, except it does these weird +// munmap's in the middle of the page, which is forbidden in windows. +void* VirtualSysAllocator::Alloc(size_t size, size_t *actual_size, + size_t alignment) { + // Align on the pagesize boundary + const int pagesize = getpagesize(); + if (alignment < pagesize) alignment = pagesize; + size = ((size + alignment - 1) / alignment) * alignment; + + // Report the total number of bytes the OS actually delivered. This might be + // greater than |size| because of alignment concerns. The full size is + // necessary so that adjacent spans can be coalesced. + // TODO(antonm): proper processing of alignments + // in actual_size and decommitting. + if (actual_size) { + *actual_size = size; + } + + // We currently do not support alignments larger than the pagesize or + // alignments that are not multiples of the pagesize after being floored. + // If this ability is needed it can be done by the caller (assuming it knows + // the page size). + assert(alignment <= pagesize); + + void* result = VirtualAlloc(0, size, + MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); + if (result == NULL) + return NULL; + + // If the result is not aligned memory fragmentation will result which can + // lead to pathological memory use. + assert((reinterpret_cast(result) & (alignment - 1)) == 0); + + return result; +} + +#ifdef _MSC_VER + +extern "C" SysAllocator* tc_get_sysalloc_override(SysAllocator *def); +extern "C" SysAllocator* tc_get_sysalloc_default(SysAllocator *def) +{ + return def; +} + +#if defined(_M_IX86) +#pragma comment(linker, "/alternatename:_tc_get_sysalloc_override=_tc_get_sysalloc_default") +#elif defined(_M_X64) +#pragma comment(linker, "/alternatename:tc_get_sysalloc_override=tc_get_sysalloc_default") +#endif + +#else // !_MSC_VER + +extern "C" ATTRIBUTE_NOINLINE +SysAllocator* tc_get_sysalloc_override(SysAllocator *def) +{ + return def; +} + +#endif + +static bool system_alloc_inited = false; +void InitSystemAllocators(void) { + VirtualSysAllocator *alloc = new (virtual_space) VirtualSysAllocator(); + sys_alloc = tc_get_sysalloc_override(alloc); +} + +extern PERFTOOLS_DLL_DECL +void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, + size_t alignment) { + SpinLockHolder lock_holder(&spinlock); + + if (!system_alloc_inited) { + InitSystemAllocators(); + system_alloc_inited = true; + } + + void* result = sys_alloc->Alloc(size, actual_size, alignment); + if (result != NULL) { + if (actual_size) { + TCMalloc_SystemTaken += *actual_size; + } else { + TCMalloc_SystemTaken += size; + } + } + return result; +} + +extern PERFTOOLS_DLL_DECL +bool TCMalloc_SystemRelease(void* start, size_t length) { + if (VirtualFree(start, length, MEM_DECOMMIT)) + return true; + + // The decommit may fail if the memory region consists of allocations + // from more than one call to VirtualAlloc. In this case, fall back to + // using VirtualQuery to retrieve the allocation boundaries and decommit + // them each individually. + + char* ptr = static_cast(start); + char* end = ptr + length; + MEMORY_BASIC_INFORMATION info; + while (ptr < end) { + size_t resultSize = VirtualQuery(ptr, &info, sizeof(info)); + assert(resultSize == sizeof(info)); + size_t decommitSize = std::min(info.RegionSize, end - ptr); + BOOL success = VirtualFree(ptr, decommitSize, MEM_DECOMMIT); + assert(success == TRUE); + ptr += decommitSize; + } + + return true; +} + +extern PERFTOOLS_DLL_DECL +void TCMalloc_SystemCommit(void* start, size_t length) { + if (VirtualAlloc(start, length, MEM_COMMIT, PAGE_READWRITE) == start) + return; + + // The commit may fail if the memory region consists of allocations + // from more than one call to VirtualAlloc. In this case, fall back to + // using VirtualQuery to retrieve the allocation boundaries and commit them + // each individually. + + char* ptr = static_cast(start); + char* end = ptr + length; + MEMORY_BASIC_INFORMATION info; + while (ptr < end) { + size_t resultSize = VirtualQuery(ptr, &info, sizeof(info)); + assert(resultSize == sizeof(info)); + + size_t commitSize = std::min(info.RegionSize, end - ptr); + void* newAddress = VirtualAlloc(ptr, commitSize, MEM_COMMIT, + PAGE_READWRITE); + assert(newAddress == ptr); + ptr += commitSize; + } +} + +bool RegisterSystemAllocator(SysAllocator *allocator, int priority) { + return false; // we don't allow registration on windows, right now +} + +void DumpSystemAllocatorStats(TCMalloc_Printer* printer) { + // We don't dump stats on windows, right now +} diff -Nru google-perftools-2.1/src/windows/TODO google-perftools-2.2.1/src/windows/TODO --- google-perftools-2.1/src/windows/TODO 1970-01-01 01:00:00.000000000 +0100 +++ google-perftools-2.2.1/src/windows/TODO 2013-05-25 23:42:55.000000000 +0200 @@ -0,0 +1,86 @@ +* Get heap-profile-table.cc using DeleteMatchingFiles +* Get heap-profile-table.cc using FillProcSelfMaps, DumpProcSelfMaps +* Play around with ExperimentalGetStackTrace +* Support the windows-level memory-allocation functions? See + /home/build/googleclient/earth/client/tools/memorytracking/client/memorytrace/src/memorytrace.cpp + /home/build/googleclient/total_recall/common/sitestep/* + http://www.internals.com/articles/apispy/apispy.htm + http://www.wheaty.net/APISPY32.zip +* Verify /proc/xxx/maps: + http://www.geocities.com/wah_java_dotnet/procmap/index.html +* Figure out how to edit the executable IAT so tcmalloc.dll is loaded first +* Use QueryPerformanceCounter instead of GetTickCount() (also for sparsehash) + +---- +More info on windows-level memory-allocation functions: + C runtime malloc + LocalAlloc + GlobalAlloc + HeapAlloc + VirtualAlloc + mmap stuff + +malloc, LocalAlloc and GlobalAlloc call HeapAlloc, which calls +VirtualAlloc when needed, which calls VirtualAllocEx (the __sbrk equiv?) + +siggi sez: If you want to do a generic job, you probably need to +preserve the semantics of all of these Win32 calls: + Heap32First + Heap32ListFirst + Heap32ListNext + Heap32Next + HeapAlloc + HeapCompact + HeapCreate + HeapCreateTagsW + HeapDestroy + HeapExtend + HeapFree + HeapLock + HeapQueryInformation + HeapQueryTagW + HeapReAlloc + HeapSetInformation + HeapSize + HeapSummary + HeapUnlock + HeapUsage + HeapValidate + HeapWalk + +kernel32.dll export functions and nt.dll export functions: + http://www.shorthike.com/svn/trunk/tools_win32/dm/lib/kernel32.def + http://undocumented.ntinternals.net/ + +You can edit the executable IAT to have the patching DLL be the +first one loaded. + +Most complete way to intercept system calls is patch the functions +(not the IAT). + +Microsoft has somee built-in routines for heap-checking: + http://support.microsoft.com/kb/268343 + +---- +Itimer replacement: + http://msdn2.microsoft.com/en-us/library/ms712713.aspx + +---- +Changes I've had to make to the project file: + +0) When creating the project file, click on "no autogenerated files" + +--- For each project: +1) Alt-F7 -> General -> [pulldown "all configurations" ] -> Output Directory -> $(SolutionDir)$(ConfigurationName) +2) Alt-F7 -> General -> [pulldown "all configurations" ] -> Intermediate Directory -> $(ConfigurationName) + +--- For each .cc file: +1) Alt-F7 -> C/C++ -> General -> [pulldown "all configurations"] -> Additional Include Directives --> src/windows + src/ +2) Alt-F7 -> C/C++ -> Code Generation -> Runtime Library -> Multi-threaded, debug/release, DLL or not + +--- For DLL: +3) Alt-F7 -> Linker -> Input -> [pulldown "all configurations" ] -> Module Definition File -> src\windows\vc7and8.def +--- For binaries depending on a DLL: +3) Right-click on project -> Project Dependencies -> [add dll] +--- For static binaries (not depending on a DLL) +3) Alt-F7 -> C/C++ -> Command Line -> [pulldown "all configurations"] -> /D PERFTOOLS_DLL_DECL= diff -Nru google-perftools-2.1/test-driver google-perftools-2.2.1/test-driver --- google-perftools-2.1/test-driver 2013-07-30 11:12:29.000000000 +0200 +++ google-perftools-2.2.1/test-driver 2014-06-22 00:52:50.000000000 +0200 @@ -1,7 +1,7 @@ #! /bin/sh # test-driver - basic testsuite driver script. -scriptversion=2012-06-27.10; # UTC +scriptversion=2013-07-13.22; # UTC # Copyright (C) 2011-2013 Free Software Foundation, Inc. # @@ -44,13 +44,12 @@ Usage: test-driver --test-name=NAME --log-file=PATH --trs-file=PATH [--expect-failure={yes|no}] [--color-tests={yes|no}] - [--enable-hard-errors={yes|no}] [--] TEST-SCRIPT + [--enable-hard-errors={yes|no}] [--] + TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS] The '--test-name', '--log-file' and '--trs-file' options are mandatory. END } -# TODO: better error handling in option parsing (in particular, ensure -# TODO: $log_file, $trs_file and $test_name are defined). test_name= # Used for reporting. log_file= # Where to save the output of the test script. trs_file= # Where to save the metadata of the test run. @@ -69,10 +68,23 @@ --enable-hard-errors) enable_hard_errors=$2; shift;; --) shift; break;; -*) usage_error "invalid option: '$1'";; + *) break;; esac shift done +missing_opts= +test x"$test_name" = x && missing_opts="$missing_opts --test-name" +test x"$log_file" = x && missing_opts="$missing_opts --log-file" +test x"$trs_file" = x && missing_opts="$missing_opts --trs-file" +if test x"$missing_opts" != x; then + usage_error "the following mandatory options are missing:$missing_opts" +fi + +if test $# -eq 0; then + usage_error "missing argument" +fi + if test $color_tests = yes; then # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'. red='' # Red. diff -Nru google-perftools-2.1/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj google-perftools-2.2.1/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj --- google-perftools-2.1/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj 2013-09-22 03:14:21.000000000 +0200 @@ -453,6 +453,23 @@ + + + + + + + + diff -Nru google-perftools-2.1/vsprojects/system-alloc_unittest/system-alloc_unittest.vcproj google-perftools-2.2.1/vsprojects/system-alloc_unittest/system-alloc_unittest.vcproj --- google-perftools-2.1/vsprojects/system-alloc_unittest/system-alloc_unittest.vcproj 1970-01-01 01:00:00.000000000 +0100 +++ google-perftools-2.2.1/vsprojects/system-alloc_unittest/system-alloc_unittest.vcproj 2013-09-22 03:14:21.000000000 +0200 @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru google-perftools-2.1/vsprojects/tmu-static/tmu-static.vcproj google-perftools-2.2.1/vsprojects/tmu-static/tmu-static.vcproj --- google-perftools-2.1/vsprojects/tmu-static/tmu-static.vcproj 2013-07-29 05:20:41.000000000 +0200 +++ google-perftools-2.2.1/vsprojects/tmu-static/tmu-static.vcproj 2013-09-22 03:14:21.000000000 +0200 @@ -489,6 +489,25 @@ + + + + + + + +