* Suppress all large allocs when report threshold==0

* Clarified meaning of various malloc stats
	* Change from ATTRIBUTED_DEPRECATED to comments
	* Make array-size a var to compile under clang
	* Reduce page map key size under x86_64 by 4.4MB
	* Added full qualification to MemoryBarrier
	* Support systems that capitalize /proc weirdly
	* Avoid gcc warning: exporting type in unnamed ns
	* Add some dynamic annotations for gcc attributes
	* Add support for census profiler in pprof
	* Speed up pprof's ExtractSymbols
	* Speed up GoogleOnce
	* Add pkg-config (.pc) files
	* Detect when __environ exists but is NULL
	* Improve spinlock contention performance
	* Add GetFreeListSizes
	* Improve sampling_test, eg by adding no-inline
	* Relax malloc_extension test-check for big pages
	* Add proper library version number information
	* Update from autoconf 2.64 to 2.65
	* Better document how to write a server that works with pprof
	* Change FillProcSelfMaps to better handle out-of-space
	* No longer hook _aligned_malloc/free in windows
	* Handle function-forwarding in DLLs when patching (in windows)
	* Update .vcproj files that had wrong .cc files in them (!)
	* get rid of unnecessary 'size < 0'
	* fix comments a bit in sysinfo.cc
	* another go at improving malloc-stats output
	* fix comment typo in profiler.cc
	* Add a few more thread annotations
	* Try to read TSC frequency from 'tsc_freq_khz'
	* Fix annotalysis/TSAN incompatibility
	* Add pprof --evince to go along with --gv
	* Document need for sampling to use GetHeapSample
	* Fix flakiness in malloc_extension_test
	* Separate out synchronization profiling routines


git-svn-id: http://gperftools.googlecode.com/svn/trunk@99 6b5cf1ce-ec42-a296-1ba9-69fdba395a50
This commit is contained in:
csilvers 2010-11-18 01:07:25 +00:00
parent 682ff7da12
commit 3014cf142e
63 changed files with 21259 additions and 20636 deletions

View File

@ -194,6 +194,7 @@ libwindows_la_SOURCES = $(WINDOWS_INCLUDES) \
libwindows_la_LIBADD = -lPsapi
SPINLOCK_INCLUDES = src/base/spinlock.h \
src/base/spinlock_internal.h \
src/base/spinlock_win32-inl.h \
src/base/spinlock_linux-inl.h \
src/base/spinlock_posix-inl.h \
@ -203,6 +204,7 @@ SPINLOCK_INCLUDES = src/base/spinlock.h \
src/base/atomicops-internals-x86.h
noinst_LTLIBRARIES += libspinlock.la
libspinlock_la_SOURCES = src/base/spinlock.cc \
src/base/spinlock_internal.cc \
$(SPINLOCK_INCLUDES)
LIBSPINLOCK = libwindows.la libspinlock.la libsysinfo.la liblogging.la
@ -219,6 +221,7 @@ SYSTEM_ALLOC_CC =
else !MINGW
# spinlock is the only code that uses atomicops.
SPINLOCK_INCLUDES = src/base/spinlock.h \
src/base/spinlock_internal.h \
src/base/atomicops.h \
src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
@ -227,6 +230,7 @@ SPINLOCK_INCLUDES = src/base/spinlock.h \
noinst_LTLIBRARIES += libspinlock.la
libspinlock_la_SOURCES = src/base/spinlock.cc \
src/base/spinlock_internal.cc \
src/base/atomicops-internals-x86.cc \
$(SPINLOCK_INCLUDES)
libspinlock_la_LIBADD = $(NANOSLEEP_LIBS)
@ -407,7 +411,8 @@ WINDOWS_PROJECTS += vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
libtcmalloc_minimal_la_SOURCES = $(TCMALLOC_CC) $(TCMALLOC_MINIMAL_INCLUDES)
libtcmalloc_minimal_la_CXXFLAGS = -DNO_TCMALLOC_SAMPLES \
$(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS)
libtcmalloc_minimal_la_LDFLAGS = $(PTHREAD_CFLAGS)
# -version-info gets passed to libtool
libtcmalloc_minimal_la_LDFLAGS = $(PTHREAD_CFLAGS) -version-info @TCMALLOC_SO_VERSION@
libtcmalloc_minimal_la_LIBADD = libtcmalloc_minimal_internal.la $(PTHREAD_LIBS)
# For windows, we're playing around with trying to do some stacktrace
@ -675,7 +680,9 @@ libtcmalloc_minimal_debug_la_SOURCES = src/debugallocation.cc \
$(TCMALLOC_MINIMAL_INCLUDES)
libtcmalloc_minimal_debug_la_CXXFLAGS = $(libtcmalloc_minimal_la_CXXFLAGS) \
-DTCMALLOC_FOR_DEBUGALLOCATION
libtcmalloc_minimal_debug_la_LDFLAGS = $(libtcmalloc_minimal_la_LDFLAGS)
# version_info gets passed to libtool
libtcmalloc_minimal_debug_la_LDFLAGS = $(libtcmalloc_minimal_la_LDFLAGS) \
-version-info @TCMALLOC_SO_VERSION@
libtcmalloc_minimal_debug_la_LIBADD = $(libtcmalloc_minimal_la_LIBADD)
LIBS_TO_WEAKEN += libtcmalloc_minimal_debug.la
@ -770,7 +777,7 @@ libtcmalloc_internal_la_LIBADD = libstacktrace.la $(PTHREAD_LIBS)
lib_LTLIBRARIES += libtcmalloc.la
libtcmalloc_la_SOURCES = $(TCMALLOC_CC) $(TCMALLOC_INCLUDES)
libtcmalloc_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS)
libtcmalloc_la_LDFLAGS = $(PTHREAD_CFLAGS)
libtcmalloc_la_LDFLAGS = $(PTHREAD_CFLAGS) -version-info @TCMALLOC_SO_VERSION@
libtcmalloc_la_LIBADD = libtcmalloc_internal.la $(PTHREAD_LIBS)
if WITH_HEAP_CHECKER
@ -973,7 +980,8 @@ libtcmalloc_debug_la_SOURCES = src/debugallocation.cc $(HEAP_CHECKER_SOURCES) \
$(TCMALLOC_INCLUDES)
libtcmalloc_debug_la_CXXFLAGS = $(libtcmalloc_la_CXXFLAGS) \
-DTCMALLOC_FOR_DEBUGALLOCATION
libtcmalloc_debug_la_LDFLAGS = $(libtcmalloc_la_LDFLAGS)
libtcmalloc_debug_la_LDFLAGS = $(libtcmalloc_la_LDFLAGS) \
-version-info @TCMALLOC_SO_VERSION@
libtcmalloc_debug_la_LIBADD = $(libtcmalloc_la_LIBADD)
LIBS_TO_WEAKEN += libtcmalloc_debug.la
@ -1083,7 +1091,8 @@ libprofiler_la_SOURCES = src/profiler.cc \
libprofiler_la_LIBADD = libstacktrace.la
# We have to include ProfileData for profiledata_unittest
CPU_PROFILER_SYMBOLS = '(ProfilerStart|ProfilerStartWithOptions|ProfilerStop|ProfilerFlush|ProfilerEnable|ProfilerDisable|ProfilingIsEnabledForAllThreads|ProfilerRegisterThread|ProfilerGetCurrentState|ProfilerState|ProfileData|ProfileHandler)'
libprofiler_la_LDFLAGS = -export-symbols-regex $(CPU_PROFILER_SYMBOLS)
libprofiler_la_LDFLAGS = -export-symbols-regex $(CPU_PROFILER_SYMBOLS) \
-version-info @PROFILER_SO_VERSION@
# See discussion above (under LIBTCMALLOC_MINIMAL) for why we do this.
# Basically it's to work around systems where --rpath doesn't work right.
@ -1172,8 +1181,11 @@ if WITH_CPU_PROFILER
lib_LTLIBRARIES += libtcmalloc_and_profiler.la
libtcmalloc_and_profiler_la_SOURCES = $(libtcmalloc_la_SOURCES) $(libprofiler_la_SOURCES)
libtcmalloc_and_profiler_la_CXXFLAGS = $(libtcmalloc_la_CXXFLAGS) $(libprofiler_la_CXXFLAGS)
# Since this library is meant to be used as a .a, I don't worry as much
# about .so versioning. I just give the libtcmalloc version number.
# TODO(csilvers): use -export-symbols-regex?
libtcmalloc_and_profiler_la_LDFLAGS = $(PTHREAD_CFLAGS)
libtcmalloc_and_profiler_la_LDFLAGS = $(PTHREAD_CFLAGS) \
-version-info @TCMALLOC_SO_VERSION@
# We don't include libprofiler_la_LIBADD here because all it adds is
# libstacktrace.la, which we already get via libtcmalloc. Trying to
# specify it twice causes link-time duplicate-definition errors. :-(
@ -1210,6 +1222,45 @@ rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec
deb: dist-gzip packages/deb.sh packages/deb/*
@cd packages && ./deb.sh ${PACKAGE} ${VERSION}
# http://linux.die.net/man/1/pkg-config, http://pkg-config.freedesktop.org/wiki
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libtcmalloc.pc libtcmalloc_minimal.pc \
libtcmalloc_debug.pc libtcmalloc_minimal_debug.pc \
libprofiler.pc
CLEANFILES = $(pkgconfig_DATA)
# I get the description and URL lines from the rpm spec. I use sed to
# try to rewrite exec_prefix, libdir, and includedir in terms of
# prefix, if possible.
libtcmalloc.pc: Makefile packages/rpm/rpm.spec
echo 'prefix=$(prefix)' > "$@".tmp
echo 'exec_prefix='`echo '$(exec_prefix)' | sed 's@^$(prefix)@$${prefix}@'` >> "$@".tmp
echo 'libdir='`echo '$(libdir)' | sed 's@^$(exec_prefix)@$${exec_prefix}@'` >> "$@".tmp
echo 'includedir='`echo '$(includedir)' | sed 's@^$(prefix)@$${prefix}@'` >> "$@".tmp
echo '' >> "$@".tmp
echo 'Name: $(PACKAGE)' >> "$@".tmp
echo 'Version: $(VERSION)' >> "$@".tmp
-grep '^Summary:' packages/rpm/rpm.spec | sed s/^Summary:/Description:/ | head -n1 >> "$@".tmp
-grep '^URL: ' packages/rpm/rpm.spec >> "$@".tmp
echo 'Requires:' >> "$@".tmp
echo 'Libs: -L$${libdir} -ltcmalloc' >> "$@".tmp
echo 'Libs.private: $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)' >> "$@".tmp
echo 'Cflags: -I$${includedir}' >> "$@".tmp
mv -f "$@".tmp "$@"
# The other versions are mostly the same.
libtcmalloc_minimal.pc: libtcmalloc.pc
cat libtcmalloc.pc | sed s/-ltcmalloc/-ltcmalloc_minimal/ > "$@"
libtcmalloc_debug.pc: libtcmalloc.pc
cat libtcmalloc.pc | sed s/-ltcmalloc/-ltcmalloc_debug/ > "$@"
libtcmalloc_minimal_debug.pc: libtcmalloc.pc
cat libtcmalloc.pc | sed s/-ltcmalloc/-ltcmalloc_minimal_debug/ > "$@"
libprofiler.pc: libtcmalloc.pc
cat libtcmalloc.pc | sed s/-ltcmalloc/-lprofiler/ > "$@"
libtool: $(LIBTOOL_DEPS)
$(SHELL) ./config.status --recheck

View File

@ -264,7 +264,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_have_attribute.m4 \
$(top_srcdir)/m4/acx_nanosleep.m4 \
$(top_srcdir)/m4/acx_pthread.m4 \
$(top_srcdir)/m4/compiler_characteristics.m4 \
$(top_srcdir)/m4/install_prefix.m4 \
$(top_srcdir)/m4/install_prefix.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/namespaces.m4 \
$(top_srcdir)/m4/pc_from_ucontext.m4 \
$(top_srcdir)/m4/program_invocation_name.m4 \
@ -284,7 +286,8 @@ am__vpath_adj = case $$p in \
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
"$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \
"$(DESTDIR)$(docdir)" "$(DESTDIR)$(googleincludedir)" \
"$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgconfigdir)" \
"$(DESTDIR)$(googleincludedir)" \
"$(DESTDIR)$(googleincludedir)"
libLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
@ -300,8 +303,8 @@ am__libprofiler_la_SOURCES_DIST = src/profiler.cc \
src/profile-handler.h src/getpc.h src/base/basictypes.h \
src/base/commandlineflags.h src/base/googleinit.h \
src/base/logging.h src/base/simple_mutex.h src/base/sysinfo.h \
src/base/spinlock.h src/base/atomicops.h \
src/base/atomicops-internals-macosx.h \
src/base/spinlock.h src/base/spinlock_internal.h \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
src/base/atomicops-internals-x86.h \
@ -321,16 +324,20 @@ libprofiler_la_OBJECTS = $(am_libprofiler_la_OBJECTS)
am__DEPENDENCIES_1 =
@MINGW_FALSE@libspinlock_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__libspinlock_la_SOURCES_DIST = src/base/spinlock.cc \
src/base/spinlock_internal.cc \
src/base/atomicops-internals-x86.cc src/base/spinlock.h \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/spinlock_internal.h src/base/atomicops.h \
src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
src/base/atomicops-internals-x86.h \
src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \
src/base/spinlock_posix-inl.h
@MINGW_FALSE@am_libspinlock_la_OBJECTS = spinlock.lo \
@MINGW_FALSE@ atomicops-internals-x86.lo $(am__objects_1)
@MINGW_TRUE@am_libspinlock_la_OBJECTS = spinlock.lo $(am__objects_1)
@MINGW_FALSE@ spinlock_internal.lo atomicops-internals-x86.lo \
@MINGW_FALSE@ $(am__objects_1)
@MINGW_TRUE@am_libspinlock_la_OBJECTS = spinlock.lo \
@MINGW_TRUE@ spinlock_internal.lo $(am__objects_1)
libspinlock_la_OBJECTS = $(am_libspinlock_la_OBJECTS)
@MINGW_FALSE@am_libspinlock_la_rpath =
@MINGW_TRUE@am_libspinlock_la_rpath =
@ -363,7 +370,8 @@ libsysinfo_la_OBJECTS = $(am_libsysinfo_la_OBJECTS)
am__libtcmalloc_la_SOURCES_DIST = src/tcmalloc.cc src/common.h \
src/internal_logging.h src/system-alloc.h \
src/packed-cache-inl.h src/base/spinlock.h \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/spinlock_internal.h src/base/atomicops.h \
src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
src/base/atomicops-internals-x86.h \
@ -413,7 +421,8 @@ libtcmalloc_la_OBJECTS = $(am_libtcmalloc_la_OBJECTS)
am__libtcmalloc_and_profiler_la_SOURCES_DIST = src/tcmalloc.cc \
src/common.h src/internal_logging.h src/system-alloc.h \
src/packed-cache-inl.h src/base/spinlock.h \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/spinlock_internal.h src/base/atomicops.h \
src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
src/base/atomicops-internals-x86.h \
@ -466,7 +475,8 @@ am__libtcmalloc_debug_la_SOURCES_DIST = src/debugallocation.cc \
src/heap-checker.cc src/heap-checker-bcad.cc src/common.h \
src/internal_logging.h src/system-alloc.h \
src/packed-cache-inl.h src/base/spinlock.h \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/spinlock_internal.h src/base/atomicops.h \
src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
src/base/atomicops-internals-x86.h \
@ -509,7 +519,8 @@ am__libtcmalloc_internal_la_SOURCES_DIST = src/common.cc \
src/malloc_hook.cc src/malloc_extension.cc \
src/maybe_threads.cc src/common.h src/internal_logging.h \
src/system-alloc.h src/packed-cache-inl.h src/base/spinlock.h \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/spinlock_internal.h src/base/atomicops.h \
src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
src/base/atomicops-internals-x86.h \
@ -568,7 +579,8 @@ libtcmalloc_minimal_la_DEPENDENCIES = libtcmalloc_minimal_internal.la \
am__libtcmalloc_minimal_la_SOURCES_DIST = src/tcmalloc.cc src/common.h \
src/internal_logging.h src/system-alloc.h \
src/packed-cache-inl.h src/base/spinlock.h \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/spinlock_internal.h src/base/atomicops.h \
src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
src/base/atomicops-internals-x86.h \
@ -594,7 +606,8 @@ am__DEPENDENCIES_4 = libtcmalloc_minimal_internal.la \
am__libtcmalloc_minimal_debug_la_SOURCES_DIST = \
src/debugallocation.cc src/common.h src/internal_logging.h \
src/system-alloc.h src/packed-cache-inl.h src/base/spinlock.h \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/spinlock_internal.h src/base/atomicops.h \
src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
src/base/atomicops-internals-x86.h \
@ -625,7 +638,8 @@ am__libtcmalloc_minimal_internal_la_SOURCES_DIST = src/common.cc \
src/malloc_hook.cc src/malloc_extension.cc \
src/maybe_threads.cc src/common.h src/internal_logging.h \
src/system-alloc.h src/packed-cache-inl.h src/base/spinlock.h \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/spinlock_internal.h src/base/atomicops.h \
src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
src/base/atomicops-internals-x86.h \
@ -860,7 +874,8 @@ am__low_level_alloc_unittest_SOURCES_DIST = \
src/tests/low_level_alloc_unittest.cc \
src/base/low_level_alloc.h src/base/basictypes.h \
src/google/malloc_hook.h src/google/malloc_hook_c.h \
src/malloc_hook-inl.h src/base/spinlock.h src/base/atomicops.h \
src/malloc_hook-inl.h src/base/spinlock.h \
src/base/spinlock_internal.h src/base/atomicops.h \
src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
@ -1374,7 +1389,8 @@ am__dist_doc_DATA_DIST = AUTHORS COPYING ChangeLog INSTALL NEWS README \
doc/pprof-test.gif doc/pprof-vsnprintf-big.gif \
doc/pprof-vsnprintf.gif
dist_docDATA_INSTALL = $(INSTALL_DATA)
DATA = $(dist_doc_DATA)
pkgconfigDATA_INSTALL = $(INSTALL_DATA)
DATA = $(dist_doc_DATA) $(pkgconfig_DATA)
am__googleinclude_HEADERS_DIST = src/google/stacktrace.h \
src/google/malloc_hook.h src/google/malloc_hook_c.h \
src/google/malloc_extension.h src/google/malloc_extension_c.h \
@ -1419,7 +1435,7 @@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DSYMUTIL = @DSYMUTIL@
ECHO = @ECHO@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
@ -1429,8 +1445,7 @@ ENABLE_FRAME_POINTERS_TRUE = @ENABLE_FRAME_POINTERS_TRUE@
ENABLE_STATIC_FALSE = @ENABLE_STATIC_FALSE@
ENABLE_STATIC_TRUE = @ENABLE_STATIC_TRUE@
EXEEXT = @EXEEXT@
F77 = @F77@
FFLAGS = @FFLAGS@
FGREP = @FGREP@
GCC_FALSE = @GCC_FALSE@
GCC_TRUE = @GCC_TRUE@
GREP = @GREP@
@ -1440,21 +1455,27 @@ INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBSTDCXX_LA_LINKER_FLAG = @LIBSTDCXX_LA_LINKER_FLAG@
LIBTOOL = @LIBTOOL@
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MINGW_FALSE = @MINGW_FALSE@
MINGW_TRUE = @MINGW_TRUE@
NANOSLEEP_LIBS = @NANOSLEEP_LIBS@
NM = @NM@
NMEDIT = @NMEDIT@
OBJCOPY = @OBJCOPY@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@ -1463,6 +1484,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PROFILER_SO_VERSION = @PROFILER_SO_VERSION@
PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_LIBS = @PTHREAD_LIBS@
@ -1471,6 +1493,7 @@ SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
TCMALLOC_SO_VERSION = @TCMALLOC_SO_VERSION@
TC_VERSION_MAJOR = @TC_VERSION_MAJOR@
TC_VERSION_MINOR = @TC_VERSION_MINOR@
TC_VERSION_PATCH = @TC_VERSION_PATCH@
@ -1494,7 +1517,7 @@ X86_64_AND_NO_FP_BY_DEFAULT_FALSE = @X86_64_AND_NO_FP_BY_DEFAULT_FALSE@
X86_64_AND_NO_FP_BY_DEFAULT_TRUE = @X86_64_AND_NO_FP_BY_DEFAULT_TRUE@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
ac_cv_have_struct_mallinfo = @ac_cv_have_struct_mallinfo@
acx_pthread_config = @acx_pthread_config@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
@ -1530,6 +1553,7 @@ libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
@ -1761,6 +1785,7 @@ libsysinfo_la_LIBADD = $(NANOSLEEP_LIBS) $(am__append_7)
@MINGW_TRUE@libwindows_la_LIBADD = -lPsapi
# spinlock is the only code that uses atomicops.
@MINGW_FALSE@SPINLOCK_INCLUDES = src/base/spinlock.h \
@MINGW_FALSE@ src/base/spinlock_internal.h \
@MINGW_FALSE@ src/base/atomicops.h \
@MINGW_FALSE@ src/base/atomicops-internals-macosx.h \
@MINGW_FALSE@ src/base/atomicops-internals-linuxppc.h \
@ -1768,6 +1793,7 @@ libsysinfo_la_LIBADD = $(NANOSLEEP_LIBS) $(am__append_7)
@MINGW_FALSE@ src/base/atomicops-internals-x86.h
@MINGW_TRUE@SPINLOCK_INCLUDES = src/base/spinlock.h \
@MINGW_TRUE@ src/base/spinlock_internal.h \
@MINGW_TRUE@ src/base/spinlock_win32-inl.h \
@MINGW_TRUE@ src/base/spinlock_linux-inl.h \
@MINGW_TRUE@ src/base/spinlock_posix-inl.h \
@ -1777,10 +1803,12 @@ libsysinfo_la_LIBADD = $(NANOSLEEP_LIBS) $(am__append_7)
@MINGW_TRUE@ src/base/atomicops-internals-x86.h
@MINGW_FALSE@libspinlock_la_SOURCES = src/base/spinlock.cc \
@MINGW_FALSE@ src/base/spinlock_internal.cc \
@MINGW_FALSE@ src/base/atomicops-internals-x86.cc \
@MINGW_FALSE@ $(SPINLOCK_INCLUDES)
@MINGW_TRUE@libspinlock_la_SOURCES = src/base/spinlock.cc \
@MINGW_TRUE@ src/base/spinlock_internal.cc \
@MINGW_TRUE@ $(SPINLOCK_INCLUDES)
# spinlock also needs NumCPUs, from libsysinfo, which in turn needs liblogging
@ -1928,7 +1956,8 @@ libtcmalloc_minimal_la_SOURCES = $(TCMALLOC_CC) $(TCMALLOC_MINIMAL_INCLUDES)
libtcmalloc_minimal_la_CXXFLAGS = -DNO_TCMALLOC_SAMPLES \
$(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS)
libtcmalloc_minimal_la_LDFLAGS = $(PTHREAD_CFLAGS)
# -version-info gets passed to libtool
libtcmalloc_minimal_la_LDFLAGS = $(PTHREAD_CFLAGS) -version-info @TCMALLOC_SO_VERSION@
libtcmalloc_minimal_la_LIBADD = libtcmalloc_minimal_internal.la $(PTHREAD_LIBS)
@MINGW_FALSE@LIBTCMALLOC_MINIMAL = libtcmalloc_minimal.la
@ -2057,7 +2086,10 @@ thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_CXXFLAGS = $(libtcmalloc_minimal_la_CXXFLAGS) \
@WITH_DEBUGALLOC_TRUE@ -DTCMALLOC_FOR_DEBUGALLOCATION
@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_LDFLAGS = $(libtcmalloc_minimal_la_LDFLAGS)
# version_info gets passed to libtool
@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_LDFLAGS = $(libtcmalloc_minimal_la_LDFLAGS) \
@WITH_DEBUGALLOC_TRUE@ -version-info @TCMALLOC_SO_VERSION@
@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_LIBADD = $(libtcmalloc_minimal_la_LIBADD)
@WITH_DEBUGALLOC_TRUE@tcmalloc_minimal_debug_unittest_SOURCES = $(tcmalloc_minimal_unittest_SOURCES)
@WITH_DEBUGALLOC_TRUE@tcmalloc_minimal_debug_unittest_CXXFLAGS = $(tcmalloc_minimal_unittest_CXXFLAGS) \
@ -2127,7 +2159,7 @@ thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
@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_32)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_LDFLAGS = $(PTHREAD_CFLAGS)
@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 =
@ -2241,7 +2273,9 @@ thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_debug_la_CXXFLAGS = $(libtcmalloc_la_CXXFLAGS) \
@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ -DTCMALLOC_FOR_DEBUGALLOCATION
@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_debug_la_LDFLAGS = $(libtcmalloc_la_LDFLAGS)
@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_debug_la_LDFLAGS = $(libtcmalloc_la_LDFLAGS) \
@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ -version-info @TCMALLOC_SO_VERSION@
@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_debug_la_LIBADD = $(libtcmalloc_la_LIBADD)
@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_debug_unittest_SOURCES = $(tcmalloc_unittest_SOURCES)
@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_debug_unittest_CXXFLAGS = $(tcmalloc_unittest_CXXFLAGS) \
@ -2302,7 +2336,9 @@ thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
@WITH_CPU_PROFILER_TRUE@libprofiler_la_LIBADD = libstacktrace.la
# We have to include ProfileData for profiledata_unittest
@WITH_CPU_PROFILER_TRUE@CPU_PROFILER_SYMBOLS = '(ProfilerStart|ProfilerStartWithOptions|ProfilerStop|ProfilerFlush|ProfilerEnable|ProfilerDisable|ProfilingIsEnabledForAllThreads|ProfilerRegisterThread|ProfilerGetCurrentState|ProfilerState|ProfileData|ProfileHandler)'
@WITH_CPU_PROFILER_TRUE@libprofiler_la_LDFLAGS = -export-symbols-regex $(CPU_PROFILER_SYMBOLS)
@WITH_CPU_PROFILER_TRUE@libprofiler_la_LDFLAGS = -export-symbols-regex $(CPU_PROFILER_SYMBOLS) \
@WITH_CPU_PROFILER_TRUE@ -version-info @PROFILER_SO_VERSION@
# See discussion above (under LIBTCMALLOC_MINIMAL) for why we do this.
# Basically it's to work around systems where --rpath doesn't work right.
@ -2351,8 +2387,12 @@ thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
@WITH_CPU_PROFILER_TRUE@profiler4_unittest_DEPENDENCIES = $(LIBPROFILER)
@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_and_profiler_la_SOURCES = $(libtcmalloc_la_SOURCES) $(libprofiler_la_SOURCES)
@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_and_profiler_la_CXXFLAGS = $(libtcmalloc_la_CXXFLAGS) $(libprofiler_la_CXXFLAGS)
# Since this library is meant to be used as a .a, I don't worry as much
# about .so versioning. I just give the libtcmalloc version number.
# TODO(csilvers): use -export-symbols-regex?
@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_and_profiler_la_LDFLAGS = $(PTHREAD_CFLAGS)
@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_and_profiler_la_LDFLAGS = $(PTHREAD_CFLAGS) \
@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ -version-info @TCMALLOC_SO_VERSION@
# We don't include libprofiler_la_LIBADD here because all it adds is
# libstacktrace.la, which we already get via libtcmalloc. Trying to
# specify it twice causes link-time duplicate-definition errors. :-(
@ -2361,6 +2401,14 @@ thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_CXXFLAGS = $(tcmalloc_both_unittest_CXXFLAGS)
@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_LDFLAGS = $(tcmalloc_both_unittest_LDFLAGS)
@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_LDADD = libtcmalloc_and_profiler.la
# http://linux.die.net/man/1/pkg-config, http://pkg-config.freedesktop.org/wiki
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libtcmalloc.pc libtcmalloc_minimal.pc \
libtcmalloc_debug.pc libtcmalloc_minimal_debug.pc \
libprofiler.pc
CLEANFILES = $(pkgconfig_DATA)
EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \
$(SCRIPTS) libtool \
src/windows/get_mangled_names.cc src/windows/override_functions.cc \
@ -2829,6 +2877,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sampling_debug_test-sampling_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sampling_test-sampling_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spinlock.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spinlock_internal.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stacktrace.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stacktrace_unittest.Po@am__quote@
@ -2958,6 +3007,13 @@ spinlock.lo: src/base/spinlock.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o spinlock.lo `test -f 'src/base/spinlock.cc' || echo '$(srcdir)/'`src/base/spinlock.cc
spinlock_internal.lo: src/base/spinlock_internal.cc
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT spinlock_internal.lo -MD -MP -MF "$(DEPDIR)/spinlock_internal.Tpo" -c -o spinlock_internal.lo `test -f 'src/base/spinlock_internal.cc' || echo '$(srcdir)/'`src/base/spinlock_internal.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/spinlock_internal.Tpo" "$(DEPDIR)/spinlock_internal.Plo"; else rm -f "$(DEPDIR)/spinlock_internal.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/spinlock_internal.cc' object='spinlock_internal.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o spinlock_internal.lo `test -f 'src/base/spinlock_internal.cc' || echo '$(srcdir)/'`src/base/spinlock_internal.cc
atomicops-internals-x86.lo: src/base/atomicops-internals-x86.cc
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT atomicops-internals-x86.lo -MD -MP -MF "$(DEPDIR)/atomicops-internals-x86.Tpo" -c -o atomicops-internals-x86.lo `test -f 'src/base/atomicops-internals-x86.cc' || echo '$(srcdir)/'`src/base/atomicops-internals-x86.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/atomicops-internals-x86.Tpo" "$(DEPDIR)/atomicops-internals-x86.Plo"; else rm -f "$(DEPDIR)/atomicops-internals-x86.Tpo"; exit 1; fi
@ -4310,6 +4366,23 @@ uninstall-dist_docDATA:
echo " rm -f '$(DESTDIR)$(docdir)/$$f'"; \
rm -f "$(DESTDIR)$(docdir)/$$f"; \
done
install-pkgconfigDATA: $(pkgconfig_DATA)
@$(NORMAL_INSTALL)
test -z "$(pkgconfigdir)" || $(mkdir_p) "$(DESTDIR)$(pkgconfigdir)"
@list='$(pkgconfig_DATA)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f=$(am__strip_dir) \
echo " $(pkgconfigDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
$(pkgconfigDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgconfigdir)/$$f"; \
done
uninstall-pkgconfigDATA:
@$(NORMAL_UNINSTALL)
@list='$(pkgconfig_DATA)'; for p in $$list; do \
f=$(am__strip_dir) \
echo " rm -f '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
rm -f "$(DESTDIR)$(pkgconfigdir)/$$f"; \
done
install-googleincludeHEADERS: $(googleinclude_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(googleincludedir)" || $(mkdir_p) "$(DESTDIR)$(googleincludedir)"
@ -4606,7 +4679,7 @@ all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(MANS) $(DATA) \
install-binPROGRAMS: install-libLTLIBRARIES
installdirs:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(googleincludedir)" "$(DESTDIR)$(googleincludedir)"; do \
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(googleincludedir)" "$(DESTDIR)$(googleincludedir)"; do \
test -z "$$dir" || $(mkdir_p) "$$dir"; \
done
install: install-am
@ -4626,6 +4699,7 @@ install-strip:
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@ -4657,7 +4731,8 @@ info: info-am
info-am:
install-data-am: install-dist_docDATA install-googleincludeHEADERS \
install-man install-nodist_googleincludeHEADERS
install-man install-nodist_googleincludeHEADERS \
install-pkgconfigDATA
install-exec-am: install-binPROGRAMS install-binSCRIPTS \
install-exec-local install-libLTLIBRARIES
@ -4691,7 +4766,7 @@ ps-am:
uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \
uninstall-dist_docDATA uninstall-googleincludeHEADERS \
uninstall-info-am uninstall-libLTLIBRARIES uninstall-man \
uninstall-nodist_googleincludeHEADERS
uninstall-nodist_googleincludeHEADERS uninstall-pkgconfigDATA
uninstall-man: uninstall-man1
@ -4708,15 +4783,16 @@ uninstall-man: uninstall-man1
install-exec-am install-exec-local \
install-googleincludeHEADERS install-info install-info-am \
install-libLTLIBRARIES install-man install-man1 \
install-nodist_googleincludeHEADERS install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags uninstall uninstall-am uninstall-binPROGRAMS \
uninstall-binSCRIPTS uninstall-dist_docDATA \
uninstall-googleincludeHEADERS uninstall-info-am \
uninstall-libLTLIBRARIES uninstall-man uninstall-man1 \
uninstall-nodist_googleincludeHEADERS
install-nodist_googleincludeHEADERS install-pkgconfigDATA \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
pdf pdf-am ps ps-am tags uninstall uninstall-am \
uninstall-binPROGRAMS uninstall-binSCRIPTS \
uninstall-dist_docDATA uninstall-googleincludeHEADERS \
uninstall-info-am uninstall-libLTLIBRARIES uninstall-man \
uninstall-man1 uninstall-nodist_googleincludeHEADERS \
uninstall-pkgconfigDATA
@ENABLE_FRAME_POINTERS_FALSE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@ # TODO(csilvers): check if -fomit-frame-pointer might be in $(CXXFLAGS),
@ENABLE_FRAME_POINTERS_FALSE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@ # before setting this.
@ -4778,6 +4854,38 @@ rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec
deb: dist-gzip packages/deb.sh packages/deb/*
@cd packages && ./deb.sh ${PACKAGE} ${VERSION}
# I get the description and URL lines from the rpm spec. I use sed to
# try to rewrite exec_prefix, libdir, and includedir in terms of
# prefix, if possible.
libtcmalloc.pc: Makefile packages/rpm/rpm.spec
echo 'prefix=$(prefix)' > "$@".tmp
echo 'exec_prefix='`echo '$(exec_prefix)' | sed 's@^$(prefix)@$${prefix}@'` >> "$@".tmp
echo 'libdir='`echo '$(libdir)' | sed 's@^$(exec_prefix)@$${exec_prefix}@'` >> "$@".tmp
echo 'includedir='`echo '$(includedir)' | sed 's@^$(prefix)@$${prefix}@'` >> "$@".tmp
echo '' >> "$@".tmp
echo 'Name: $(PACKAGE)' >> "$@".tmp
echo 'Version: $(VERSION)' >> "$@".tmp
-grep '^Summary:' packages/rpm/rpm.spec | sed s/^Summary:/Description:/ | head -n1 >> "$@".tmp
-grep '^URL: ' packages/rpm/rpm.spec >> "$@".tmp
echo 'Requires:' >> "$@".tmp
echo 'Libs: -L$${libdir} -ltcmalloc' >> "$@".tmp
echo 'Libs.private: $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)' >> "$@".tmp
echo 'Cflags: -I$${includedir}' >> "$@".tmp
mv -f "$@".tmp "$@"
# The other versions are mostly the same.
libtcmalloc_minimal.pc: libtcmalloc.pc
cat libtcmalloc.pc | sed s/-ltcmalloc/-ltcmalloc_minimal/ > "$@"
libtcmalloc_debug.pc: libtcmalloc.pc
cat libtcmalloc.pc | sed s/-ltcmalloc/-ltcmalloc_debug/ > "$@"
libtcmalloc_minimal_debug.pc: libtcmalloc.pc
cat libtcmalloc.pc | sed s/-ltcmalloc/-ltcmalloc_minimal_debug/ > "$@"
libprofiler.pc: libtcmalloc.pc
cat libtcmalloc.pc | sed s/-ltcmalloc/-lprofiler/ > "$@"
libtool: $(LIBTOOL_DEPS)
$(SHELL) ./config.status --recheck

6
NEWS
View File

@ -8,9 +8,9 @@ support for `malloc_usable_size()` as a glibc-compatible alias to
experimental support for tcmalloc large pages, which may speed up
tcmalloc at the cost of greater memory use. To use tcmalloc large
pages, see the
[http://google-perftools.googlecode.com/svn/tags/perftools-1.5/INSTALL
[http://google-perftools.googlecode.com/svn/tags/perftools-1.6/INSTALL
INSTALL file]; for all changes, see the
[http://google-perftools.googlecode.com/svn/tags/perftools-1.5/ChangeLog
[http://google-perftools.googlecode.com/svn/tags/perftools-1.6/ChangeLog
ChangeLog].
OS X NOTE: improvements in the profiler unittest have turned up an OS
@ -22,7 +22,7 @@ setitimer) in threaded programs, and has insight into this problem,
please send mail to google-perftools@googlegroups.com.
To see if you're affected by this, look for profiling time that pprof
attributes to ___semwait_signal. This is work being done in other
attributes to `___semwait_signal`. This is work being done in other
threads, that is being attributed to sleeping-time in the main thread.

2
README
View File

@ -37,7 +37,7 @@ As a quick-start, do the following after installing this package:
1) Link your executable with -ltcmalloc
2) Run your executable with the HEAPPROFILE environment var set:
$ HEAPROFILE=/tmp/heapprof <path/to/binary> [binary args]
$ HEAPPROFILE=/tmp/heapprof <path/to/binary> [binary args]
3) Run pprof to analyze the heap usage
$ pprof <path/to/binary> /tmp/heapprof.0045.heap # run 'ls' to see options
$ pprof --gv <path/to/binary> /tmp/heapprof.0045.heap

6657
aclocal.m4 vendored

File diff suppressed because it is too large Load Diff

16624
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -5,9 +5,16 @@
AC_PREREQ(2.57)
AC_INIT(google-perftools, 1.6, opensource@google.com)
TCMALLOC_SO_VERSION=0:1:0
PROFILER_SO_VERSION=0:1:0
AC_SUBST(TCMALLOC_SO_VERSION)
AC_SUBST(PROFILER_SO_VERSION)
# The argument here is just something that should be in the current directory
# (for sanity checking)
AC_CONFIG_SRCDIR(README)
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_HOST
AM_INIT_AUTOMAKE([dist-zip])
AM_CONFIG_HEADER(src/config.h)

View File

@ -58,13 +58,28 @@ get heap information. The actual url is controlled via the variable
<code>HEAP_PAGE</code> in the <code>pprof</code> script, so you
can change it if you'd like.</p>
<p>The server should respond by calling</p>
<p>There are two ways to get this data. The first is to call</p>
<pre>
MallocExtension::instance()->GetHeapSample(&output);
</pre>
<p>and sending <code>output</code> back as an HTTP response to
<code>pprof</code>. <code>MallocExtension</code> is defined in the
header file <code>google/malloc_extension.h</code>.</p>
<p>and have the server send <code>output</code> back as an HTTP
response to <code>pprof</code>. <code>MallocExtension</code> is
defined in the header file <code>google/malloc_extension.h</code>.</p>
<p>Note this will only only work if the binary is being run with
sampling turned on (which is not the default). To do this, set the
environment variable <code>TCMALLOC_SAMPLE_PARAMETER</code> to a
positive value, such as 524288, before running.</p>
<p>The other way is to call <code>HeapProfileStart(filename)</code>
(from <code>heap-profiler.h</code>), continue to do work, and then,
some number of seconds later, call <code>GetHeapProfile()</code>
(followed by <code>HeapProfilerStop()</code>). The server can send
the output of <code>GetHeapProfile</code> back as the HTTP response to
pprof. (Note you must <code>free()</code> this data after using it.)
This is similar to how <A HREF="#profile">profile requests</A> are
handled, below. This technique does not require the application to
run with sampling turned on.</p>
<p>Here's an example of what the output should look like:</p>
<pre>
@ -84,7 +99,8 @@ heap profile: 14933: 791700132 [ 14933: 791700132] @ heap
2942: 388629374 [ 2942: 388629374] @ 0xa4b142 0x4006a0 0x400bed 0x5f0cfa 0x5f1744 0x607cee 0x5f4a5e 0x40080f 0x2aaaabad7afa
[...]
</pre>
<p> pprof accepts both old and new heap profiles and automatically detects which one you are using.</p>
<p>pprof accepts both old and new heap profiles and automatically
detects which one you are using.</p>
<h2> <code><b>/pprof/growth</b></code> </h2>
@ -111,7 +127,7 @@ heap profile: 741: 812122112 [ 741: 812122112] @ growth
</pre>
<h2> <code><b>/pprof/profile</b></code> </h2>
<h2> <A NAME="profile"><code><b>/pprof/profile</b></code></A> </h2>
<p><code>pprof</code> asks for the url
<code>/pprof/profile?seconds=XX</code> to get cpu-profiling
@ -194,10 +210,21 @@ map from hex addresses to variable names. The actual url is
controlled via the variable <code>SYMBOL_PAGE</code> in the
<code>pprof</code> script, so you can change it if you'd like.</p>
<p>This is perhaps the hardest request to write code for, because
it must accept POST requests. This means that after the HTTP headers,
pprof will pass in a list of hex addresses connected by
<code>+</code>, like so:</p>
<p>When the server receives a GET request for
<code>/pprof/symbol</code>, it should return a line formatted like
so:</p>
<pre>
num_symbols: ###
</pre>
<p>where <code>###</code> is the number of symbols found in the
binary. (For now, the only important distinction is whether the value
is 0, which it is for executables that lack debug information, or
not-0).</p>
<p>This is perhaps the hardest request to write code for, because in
addition to the GET request for this url, the server must accept POST
requests. This means that after the HTTP headers, pprof will pass in
a list of hex addresses connected by <code>+</code>, like so:</p>
<pre>
curl -d '0x0824d061+0x0824d1cf' http://remote_host:80/pprof/symbol
</pre>
@ -216,10 +243,11 @@ stream, like so:</p>
<p>The other reason this is the most difficult request to implement,
is that the application will have to figure out for itself how to map
from address to function name. One possibility is to run <code>nm -C
-n &lt;program name&gt;</code> to get the mappings, either statically
(say at program-compile time), or dynamically, by having the
application call out to <code>nm</code> for every
<code>pprof/symbol</code> call (presumably with some caching!).</p>
-n &lt;program name&gt;</code> to get the mappings at
program-compile-time. Another, at least on Linux, is to call out to
addr2line for every <code>pprof/symbol</code> call, for instance
<code>addr2line -Cfse /proc/<getpid>/exe 0x12345678 0x876543210</code>
(presumably with some caching!)</p>
<p><code>pprof</code> itself does just this for local profiles (not
ones that talk to remote servers); look at the subroutine

8503
ltmain.sh

File diff suppressed because it is too large Load Diff

7377
m4/libtool.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

368
m4/ltoptions.m4 vendored Normal file
View File

@ -0,0 +1,368 @@
# Helper functions for option handling. -*- Autoconf -*-
#
# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 6 ltoptions.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
# ------------------------------------------
m4_define([_LT_MANGLE_OPTION],
[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
# ---------------------------------------
# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
# matching handler defined, dispatch to it. Other OPTION-NAMEs are
# saved as a flag.
m4_define([_LT_SET_OPTION],
[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
_LT_MANGLE_DEFUN([$1], [$2]),
[m4_warning([Unknown $1 option `$2'])])[]dnl
])
# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
# ------------------------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
m4_define([_LT_IF_OPTION],
[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
# -------------------------------------------------------
# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
# are set.
m4_define([_LT_UNLESS_OPTIONS],
[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
[m4_define([$0_found])])])[]dnl
m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
])[]dnl
])
# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
# ----------------------------------------
# OPTION-LIST is a space-separated list of Libtool options associated
# with MACRO-NAME. If any OPTION has a matching handler declared with
# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
# the unknown option and exit.
m4_defun([_LT_SET_OPTIONS],
[# Set options
m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[_LT_SET_OPTION([$1], _LT_Option)])
m4_if([$1],[LT_INIT],[
dnl
dnl Simply set some default values (i.e off) if boolean options were not
dnl specified:
_LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
])
_LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
])
dnl
dnl If no reference was made to various pairs of opposing options, then
dnl we run the default mode handler for the pair. For example, if neither
dnl `shared' nor `disable-shared' was passed, we enable building of shared
dnl archives by default:
_LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
_LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
_LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
_LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
[_LT_ENABLE_FAST_INSTALL])
])
])# _LT_SET_OPTIONS
## --------------------------------- ##
## Macros to handle LT_INIT options. ##
## --------------------------------- ##
# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
# -----------------------------------------
m4_define([_LT_MANGLE_DEFUN],
[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
# -----------------------------------------------
m4_define([LT_OPTION_DEFINE],
[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
])# LT_OPTION_DEFINE
# dlopen
# ------
LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
])
AU_DEFUN([AC_LIBTOOL_DLOPEN],
[_LT_SET_OPTION([LT_INIT], [dlopen])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `dlopen' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
# win32-dll
# ---------
# Declare package support for building win32 dll's.
LT_OPTION_DEFINE([LT_INIT], [win32-dll],
[enable_win32_dll=yes
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*)
AC_CHECK_TOOL(AS, as, false)
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
AC_CHECK_TOOL(OBJDUMP, objdump, false)
;;
esac
test -z "$AS" && AS=as
_LT_DECL([], [AS], [0], [Assembler program])dnl
test -z "$DLLTOOL" && DLLTOOL=dlltool
_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl
test -z "$OBJDUMP" && OBJDUMP=objdump
_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl
])# win32-dll
AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
_LT_SET_OPTION([LT_INIT], [win32-dll])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `win32-dll' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
# _LT_ENABLE_SHARED([DEFAULT])
# ----------------------------
# implement the --enable-shared flag, and supports the `shared' and
# `disable-shared' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_SHARED],
[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([shared],
[AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_shared=yes ;;
no) enable_shared=no ;;
*)
enable_shared=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_shared=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
_LT_DECL([build_libtool_libs], [enable_shared], [0],
[Whether or not to build shared libraries])
])# _LT_ENABLE_SHARED
LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
# Old names:
AC_DEFUN([AC_ENABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
])
AC_DEFUN([AC_DISABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], [disable-shared])
])
AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_SHARED], [])
dnl AC_DEFUN([AM_DISABLE_SHARED], [])
# _LT_ENABLE_STATIC([DEFAULT])
# ----------------------------
# implement the --enable-static flag, and support the `static' and
# `disable-static' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_STATIC],
[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([static],
[AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_static=yes ;;
no) enable_static=no ;;
*)
enable_static=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_static=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_static=]_LT_ENABLE_STATIC_DEFAULT)
_LT_DECL([build_old_libs], [enable_static], [0],
[Whether or not to build static libraries])
])# _LT_ENABLE_STATIC
LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
# Old names:
AC_DEFUN([AC_ENABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
])
AC_DEFUN([AC_DISABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], [disable-static])
])
AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_STATIC], [])
dnl AC_DEFUN([AM_DISABLE_STATIC], [])
# _LT_ENABLE_FAST_INSTALL([DEFAULT])
# ----------------------------------
# implement the --enable-fast-install flag, and support the `fast-install'
# and `disable-fast-install' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_FAST_INSTALL],
[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([fast-install],
[AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
[optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_fast_install=yes ;;
no) enable_fast_install=no ;;
*)
enable_fast_install=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_fast_install=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
_LT_DECL([fast_install], [enable_fast_install], [0],
[Whether or not to optimize for fast installation])dnl
])# _LT_ENABLE_FAST_INSTALL
LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
# Old names:
AU_DEFUN([AC_ENABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the `fast-install' option into LT_INIT's first parameter.])
])
AU_DEFUN([AC_DISABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the `disable-fast-install' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
# _LT_WITH_PIC([MODE])
# --------------------
# implement the --with-pic flag, and support the `pic-only' and `no-pic'
# LT_INIT options.
# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
m4_define([_LT_WITH_PIC],
[AC_ARG_WITH([pic],
[AS_HELP_STRING([--with-pic],
[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
[pic_mode="$withval"],
[pic_mode=default])
test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
])# _LT_WITH_PIC
LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
# Old name:
AU_DEFUN([AC_LIBTOOL_PICMODE],
[_LT_SET_OPTION([LT_INIT], [pic-only])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `pic-only' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
## ----------------- ##
## LTDL_INIT Options ##
## ----------------- ##
m4_define([_LTDL_MODE], [])
LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
[m4_define([_LTDL_MODE], [nonrecursive])])
LT_OPTION_DEFINE([LTDL_INIT], [recursive],
[m4_define([_LTDL_MODE], [recursive])])
LT_OPTION_DEFINE([LTDL_INIT], [subproject],
[m4_define([_LTDL_MODE], [subproject])])
m4_define([_LTDL_TYPE], [])
LT_OPTION_DEFINE([LTDL_INIT], [installable],
[m4_define([_LTDL_TYPE], [installable])])
LT_OPTION_DEFINE([LTDL_INIT], [convenience],
[m4_define([_LTDL_TYPE], [convenience])])

123
m4/ltsugar.m4 vendored Normal file
View File

@ -0,0 +1,123 @@
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 6 ltsugar.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
# lt_join(SEP, ARG1, [ARG2...])
# -----------------------------
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
# associated separator.
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
# versions in m4sugar had bugs.
m4_define([lt_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
m4_define([_lt_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
# lt_car(LIST)
# lt_cdr(LIST)
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59 which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
[$#], 1, [],
[m4_dquote(m4_shift($@))])])
m4_define([lt_unquote], $1)
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
# than defined and empty).
#
# This macro is needed until we can rely on Autoconf 2.62, since earlier
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
m4_define([lt_append],
[m4_define([$1],
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
# ----------------------------------------------------------
# Produce a SEP delimited list of all paired combinations of elements of
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
# has the form PREFIXmINFIXSUFFIXn.
# Needed until we can rely on m4_combine added in Autoconf 2.62.
m4_define([lt_combine],
[m4_if(m4_eval([$# > 3]), [1],
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
[[m4_foreach([_Lt_prefix], [$2],
[m4_foreach([_Lt_suffix],
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
# -----------------------------------------------------------------------
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
m4_define([lt_if_append_uniq],
[m4_ifdef([$1],
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
[lt_append([$1], [$2], [$3])$4],
[$5])],
[lt_append([$1], [$2], [$3])$4])])
# lt_dict_add(DICT, KEY, VALUE)
# -----------------------------
m4_define([lt_dict_add],
[m4_define([$1($2)], [$3])])
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
# --------------------------------------------
m4_define([lt_dict_add_subkey],
[m4_define([$1($2:$3)], [$4])])
# lt_dict_fetch(DICT, KEY, [SUBKEY])
# ----------------------------------
m4_define([lt_dict_fetch],
[m4_ifval([$3],
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------------------
m4_define([lt_if_dict_fetch],
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
[$5],
[$6])])
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
# --------------------------------------------------------------
m4_define([lt_dict_filter],
[m4_if([$5], [], [],
[lt_join(m4_quote(m4_default([$4], [[, ]])),
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
])

23
m4/ltversion.m4 vendored Normal file
View File

@ -0,0 +1,23 @@
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004
#
# 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.
# Generated from ltversion.in.
# serial 3017 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.2.6b])
m4_define([LT_PACKAGE_REVISION], [1.3017])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.2.6b'
macro_revision='1.3017'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])

92
m4/lt~obsolete.m4 vendored Normal file
View File

@ -0,0 +1,92 @@
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 4 lt~obsolete.m4
# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
# using a macro with the same name in our local m4/libtool.m4 it'll
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
# and doesn't know about Autoconf macros at all.)
#
# So we provide this file, which has a silly filename so it's always
# included after everything else. This provides aclocal with the
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
# because those macros already exist, or will be overwritten later.
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
#
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
# Yes, that means every name once taken will need to remain here until
# we give up compatibility with versions before 1.7, at which point
# we need to keep only those names which we still refer to.
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])])
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])

View File

@ -1,3 +1,4 @@
usr/lib
usr/lib/pkgconfig
usr/include
usr/include/google

View File

@ -2,7 +2,9 @@ usr/include/google/*
usr/lib/lib*.so
usr/lib/lib*.a
usr/lib/*.la
usr/lib/pkgconfig/*.pc
debian/tmp/usr/include/google/*
debian/tmp/usr/lib/lib*.so
debian/tmp/usr/lib/lib*.a
debian/tmp/usr/lib/*.la
debian/tmp/usr/lib/pkgconfig/*.pc

View File

@ -73,3 +73,4 @@ rm -rf $RPM_BUILD_ROOT
%{_libdir}/*.a
%{_libdir}/*.la
%{_libdir}/*.so
%{_libdir}/pkgconfig/*.pc

View File

@ -0,0 +1,234 @@
/* Copyright (c) 2010, 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: Lei Zhang, Sasha Levitskiy
*/
// This file is an internal atomic implementation, use base/atomicops.h instead.
//
// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears.
#ifndef BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
#define BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
#include <stdio.h>
#include "base/basictypes.h" // For COMPILE_ASSERT
typedef int32_t Atomic32;
namespace base {
namespace subtle {
typedef int64_t Atomic64;
// 0xffff0fc0 is the hard coded address of a function provided by
// the kernel which implements an atomic compare-exchange. On older
// ARM architecture revisions (pre-v6) this may be implemented using
// a syscall. This address is stable, and in active use (hard coded)
// by at least glibc-2.7 and the Android C library.
// pLinuxKernelCmpxchg has both acquire and release barrier sematincs.
typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value,
Atomic32 new_value,
volatile Atomic32* ptr);
LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak)) =
(LinuxKernelCmpxchgFunc) 0xffff0fc0;
typedef void (*LinuxKernelMemoryBarrierFunc)(void);
LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) =
(LinuxKernelMemoryBarrierFunc) 0xffff0fa0;
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 prev_value = *ptr;
do {
if (!pLinuxKernelCmpxchg(old_value, new_value,
const_cast<Atomic32*>(ptr))) {
return old_value;
}
prev_value = *ptr;
} while (prev_value == old_value);
return prev_value;
}
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
Atomic32 new_value) {
Atomic32 old_value;
do {
old_value = *ptr;
} while (pLinuxKernelCmpxchg(old_value, new_value,
const_cast<Atomic32*>(ptr)));
return old_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<Atomic32*>(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) {
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
*ptr = value;
}
inline void MemoryBarrier() {
pLinuxKernelMemoryBarrier();
}
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 are not implemented yet.
inline void NotImplementedFatalError(const char *function_name) {
fprintf(stderr, "64-bit %s() not implemented on this platform\n",
function_name);
abort();
}
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
NotImplementedFatalError("NoBarrier_CompareAndSwap");
return 0;
}
inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
Atomic64 new_value) {
NotImplementedFatalError("NoBarrier_AtomicExchange");
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");
}
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
NoBarrier_AtomicExchange(ptr, value);
// acts as a barrier in this implementation
}
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
NotImplementedFatalError("Release_Store");
}
inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
NotImplementedFatalError("NoBarrier_Load");
return 0;
}
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
Atomic64 value = NoBarrier_Load(ptr);
return value;
}
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
MemoryBarrier();
return NoBarrier_Load(ptr);
}
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}
inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}
} // namespace base::subtle
} // namespace base
#endif // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_

View File

@ -109,7 +109,7 @@ const int64 kint64min = ( ((( int64) kint32min) << 32) | 0 );
// Also allow for printing of a pthread_t.
#define GPRIuPTHREAD "lu"
#define GPRIxPTHREAD "lx"
#if defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__APPLE__)
#if defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__APPLE__) || defined(__FreeBSD__)
#define PRINTABLE_PTHREAD(pthreadt) reinterpret_cast<uintptr_t>(pthreadt)
#else
#define PRINTABLE_PTHREAD(pthreadt) pthreadt

View File

@ -370,6 +370,41 @@
#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
/* Macro definitions for GCC attributes that allow static thread safety
analysis to recognize and use some of the dynamic annotations as
escape hatches.
TODO(lcwu): remove the check for __SUPPORT_DYN_ANNOTATION__ once the
default crosstool/GCC supports these GCC attributes. */
#define ANNOTALYSIS_STATIC_INLINE
#define ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY ;
#if defined(__GNUC__) && defined(__SUPPORT_TS_ANNOTATION__) \
&& (!defined(SWIG)) && defined(__SUPPORT_DYN_ANNOTATION__)
#if DYNAMIC_ANNOTATIONS_ENABLED == 0
#define ANNOTALYSIS_ONLY 1
#undef ANNOTALYSIS_STATIC_INLINE
#define ANNOTALYSIS_STATIC_INLINE static inline
#undef ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
#define ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY {}
#endif
#define ANNOTALYSIS_IGNORE_READS_BEGIN __attribute__ ((ignore_reads_begin))
#define ANNOTALYSIS_IGNORE_READS_END __attribute__ ((ignore_reads_end))
#define ANNOTALYSIS_IGNORE_WRITES_BEGIN __attribute__ ((ignore_writes_begin))
#define ANNOTALYSIS_IGNORE_WRITES_END __attribute__ ((ignore_writes_end))
#define ANNOTALYSIS_UNPROTECTED_READ __attribute__ ((unprotected_read))
#else
#define ANNOTALYSIS_IGNORE_READS_BEGIN
#define ANNOTALYSIS_IGNORE_READS_END
#define ANNOTALYSIS_IGNORE_WRITES_BEGIN
#define ANNOTALYSIS_IGNORE_WRITES_END
#define ANNOTALYSIS_UNPROTECTED_READ
#endif
/* Use the macros above rather than using these functions directly. */
#ifdef __cplusplus
extern "C" {
@ -431,10 +466,18 @@ void AnnotateTraceMemory(const char *file, int line,
const volatile void *arg);
void AnnotateThreadName(const char *file, int line,
const char *name);
void AnnotateIgnoreReadsBegin(const char *file, int line);
void AnnotateIgnoreReadsEnd(const char *file, int line);
void AnnotateIgnoreWritesBegin(const char *file, int line);
void AnnotateIgnoreWritesEnd(const char *file, int line);
ANNOTALYSIS_STATIC_INLINE
void AnnotateIgnoreReadsBegin(const char *file, int line)
ANNOTALYSIS_IGNORE_READS_BEGIN ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
ANNOTALYSIS_STATIC_INLINE
void AnnotateIgnoreReadsEnd(const char *file, int line)
ANNOTALYSIS_IGNORE_READS_END ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
ANNOTALYSIS_STATIC_INLINE
void AnnotateIgnoreWritesBegin(const char *file, int line)
ANNOTALYSIS_IGNORE_WRITES_BEGIN ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
ANNOTALYSIS_STATIC_INLINE
void AnnotateIgnoreWritesEnd(const char *file, int line)
ANNOTALYSIS_IGNORE_WRITES_END ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
void AnnotateEnableRaceDetection(const char *file, int line, int enable);
void AnnotateNoOp(const char *file, int line,
const volatile void *arg);
@ -485,7 +528,8 @@ double ValgrindSlowdown(void);
one can use
... = ANNOTATE_UNPROTECTED_READ(x); */
template <class T>
inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x) {
inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x)
ANNOTALYSIS_UNPROTECTED_READ {
ANNOTATE_IGNORE_READS_BEGIN();
T res = x;
ANNOTATE_IGNORE_READS_END();
@ -511,4 +555,67 @@ double ValgrindSlowdown(void);
#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
/* Annotalysis, a GCC based static analyzer, is able to understand and use
some of the dynamic annotations defined in this file. However, dynamic
annotations are usually disabled in the opt mode (to avoid additional
runtime overheads) while Annotalysis only works in the opt mode.
In order for Annotalysis to use these dynamic annotations when they
are disabled, we re-define these annotations here. Note that unlike the
original macro definitions above, these macros are expanded to calls to
static inline functions so that the compiler will be able to remove the
calls after the analysis. */
#ifdef ANNOTALYSIS_ONLY
#undef ANNOTALYSIS_ONLY
/* Undefine and re-define the macros that the static analyzer understands. */
#undef ANNOTATE_IGNORE_READS_BEGIN
#define ANNOTATE_IGNORE_READS_BEGIN() \
AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
#undef ANNOTATE_IGNORE_READS_END
#define ANNOTATE_IGNORE_READS_END() \
AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
#undef ANNOTATE_IGNORE_WRITES_BEGIN
#define ANNOTATE_IGNORE_WRITES_BEGIN() \
AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
#undef ANNOTATE_IGNORE_WRITES_END
#define ANNOTATE_IGNORE_WRITES_END() \
AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
#undef ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
do { \
ANNOTATE_IGNORE_READS_BEGIN(); \
ANNOTATE_IGNORE_WRITES_BEGIN(); \
}while(0) \
#undef ANNOTATE_IGNORE_READS_AND_WRITES_END
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
do { \
ANNOTATE_IGNORE_WRITES_END(); \
ANNOTATE_IGNORE_READS_END(); \
}while(0) \
#if defined(__cplusplus)
#undef ANNOTATE_UNPROTECTED_READ
template <class T>
inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x)
__attribute__ ((unprotected_read)) {
ANNOTATE_IGNORE_READS_BEGIN();
T res = x;
ANNOTATE_IGNORE_READS_END();
return res;
}
#endif /* __cplusplus */
#endif /* ANNOTALYSIS_ONLY */
/* Undefine the macros intended only in this file. */
#undef ANNOTALYSIS_STATIC_INLINE
#undef ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
#endif /* BASE_DYNAMIC_ANNOTATIONS_H_ */

View File

@ -49,10 +49,13 @@
// On some systems (like freebsd), we can't call write() at all in a
// global constructor, perhaps because errno hasn't been set up.
// (In windows, we can't call it because it might call malloc.)
// Calling the write syscall is safer (it doesn't set errno), so we
// prefer that. Note we don't care about errno for logging: we just
// do logging on a best-effort basis.
#ifdef HAVE_SYS_SYSCALL_H
#if defined(_MSC_VER)
#define WRITE_TO_STDERR(buf, len) WriteToStderr(buf, len); // in port.cc
#elif defined(HAVE_SYS_SYSCALL_H)
#include <sys/syscall.h>
#define WRITE_TO_STDERR(buf, len) syscall(SYS_write, STDERR_FILENO, buf, len)
#else

View File

@ -59,7 +59,9 @@
// ---------------------------------------------------------------------------
static const int kMaxLevel = 30;
namespace {
// We put this class-only struct in a namespace to avoid polluting the
// global namespace with this struct name (thus risking an ODR violation).
namespace low_level_alloc_internal {
// This struct describes one allocated block, or one free block.
struct AllocList {
struct Header {
@ -79,6 +81,8 @@ namespace {
// LLA_SkiplistLevels()
};
}
using low_level_alloc_internal::AllocList;
// ---------------------------------------------------------------------------
// A trivial skiplist implementation. This is used to keep the freelist

View File

@ -32,47 +32,28 @@
*/
#include <config.h>
#include <time.h> /* For nanosleep() */
#ifdef HAVE_SCHED_H
#include <sched.h> /* For sched_yield() */
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* For read() */
#endif
#include <fcntl.h> /* for open(), O_RDONLY */
#include <string.h> /* for strncmp */
#include <errno.h>
#include "base/spinlock.h"
#include "base/synchronization_profiling.h"
#include "base/spinlock_internal.h"
#include "base/cycleclock.h"
#include "base/sysinfo.h" /* for NumCPUs() */
// We can do contention-profiling of SpinLocks, but the code is in
// mutex.cc, which is not always linked in with spinlock. Hence we
// provide this weak definition, which is used if mutex.cc isn't linked in.
ATTRIBUTE_WEAK extern void SubmitSpinLockProfileData(const void *, int64);
void SubmitSpinLockProfileData(const void *, int64) {}
// NOTE on the Lock-state values:
//
// kSpinLockFree represents the unlocked state
// kSpinLockHeld represents the locked state with no waiters
//
// Values greater than kSpinLockHeld represent the locked state with waiters,
// where the value is the time the current lock holder had to
// wait before obtaining the lock. The kSpinLockSleeper state is a special
// "locked with waiters" state that indicates that a sleeper needs to
// be woken, but the thread that just released the lock didn't wait.
static int adaptive_spin_count = 0;
const base::LinkerInitialized SpinLock::LINKER_INITIALIZED =
base::LINKER_INITIALIZED;
// The OS-specific header included below must provide two calls:
// Wait until *w becomes zero, atomically set it to 1 and return.
// static void SpinLockWait(volatile Atomic32 *w);
//
// Hint that a thread waiting in SpinLockWait() could now make progress. May
// do nothing. This call may not read or write *w; it must use only the
// address.
// static void SpinLockWake(volatile Atomic32 *w);
#if defined(_WIN32)
#include "base/spinlock_win32-inl.h"
#elif defined(__linux__)
#include "base/spinlock_linux-inl.h"
#else
#include "base/spinlock_posix-inl.h"
#endif
namespace {
struct SpinLock_InitHelper {
SpinLock_InitHelper() {
@ -91,36 +72,111 @@ static SpinLock_InitHelper init_helper;
} // unnamed namespace
// Monitor the lock to see if its value changes within some time period
// (adaptive_spin_count loop iterations). A timestamp indicating
// when the thread initially started waiting for the lock is passed in via
// the initial_wait_timestamp value. The total wait time in cycles for the
// lock is returned in the wait_cycles parameter. The last value read
// from the lock is returned from the method.
Atomic32 SpinLock::SpinLoop(int64 initial_wait_timestamp,
Atomic32* wait_cycles) {
int c = adaptive_spin_count;
while (base::subtle::NoBarrier_Load(&lockword_) != kSpinLockFree && --c > 0) {
}
Atomic32 spin_loop_wait_cycles = CalculateWaitCycles(initial_wait_timestamp);
Atomic32 lock_value =
base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree,
spin_loop_wait_cycles);
*wait_cycles = spin_loop_wait_cycles;
return lock_value;
}
void SpinLock::SlowLock() {
int c = adaptive_spin_count;
// The lock was not obtained initially, so this thread needs to wait for
// it. Record the current timestamp in the local variable wait_start_time
// so the total wait time can be stored in the lockword once this thread
// obtains the lock.
int64 wait_start_time = CycleClock::Now();
Atomic32 wait_cycles;
Atomic32 lock_value = SpinLoop(wait_start_time, &wait_cycles);
// Spin a few times in the hope that the lock holder releases the lock
while ((c > 0) && (lockword_ != 0)) {
c--;
int lock_wait_call_count = 0;
while (lock_value != kSpinLockFree) {
// If the lock is currently held, but not marked as having a sleeper, mark
// it as having a sleeper.
if (lock_value == kSpinLockHeld) {
// Here, just "mark" that the thread is going to sleep. Don't store the
// lock wait time in the lock as that will cause the current lock
// owner to think it experienced contention.
lock_value = base::subtle::Acquire_CompareAndSwap(&lockword_,
kSpinLockHeld,
kSpinLockSleeper);
if (lock_value == kSpinLockHeld) {
// Successfully transitioned to kSpinLockSleeper. Pass
// kSpinLockSleeper to the SpinLockWait routine to properly indicate
// the last lock_value observed.
lock_value = kSpinLockSleeper;
} else if (lock_value == kSpinLockFree) {
// Lock is free again, so try and aquire it before sleeping. The
// new lock state will be the number of cycles this thread waited if
// this thread obtains the lock.
lock_value = base::subtle::Acquire_CompareAndSwap(&lockword_,
kSpinLockFree,
wait_cycles);
continue; // skip the delay at the end of the loop
}
}
// Wait for an OS specific delay.
base::internal::SpinLockDelay(&lockword_, lock_value,
++lock_wait_call_count);
// Spin again after returning from the wait routine to give this thread
// some chance of obtaining the lock.
lock_value = SpinLoop(wait_start_time, &wait_cycles);
}
if (lockword_ == 1) {
int32 now = (CycleClock::Now() >> PROFILE_TIMESTAMP_SHIFT);
// Don't loose the lock: make absolutely sure "now" is not zero
now |= 1;
// Atomically replace the value of lockword_ with "now" if
// lockword_ is 1, thereby remembering the first timestamp to
// be recorded.
base::subtle::NoBarrier_CompareAndSwap(&lockword_, 1, now);
// base::subtle::NoBarrier_CompareAndSwap() returns:
// 0: the lock is/was available; nothing stored
// 1: our timestamp was stored
// > 1: an older timestamp is already in lockword_; nothing stored
}
SpinLockWait(&lockword_); // wait until lock acquired; OS specific
}
void SpinLock::SlowUnlock(int64 wait_timestamp) {
SpinLockWake(&lockword_); // wake waiter if necessary; OS specific
// The wait time for contentionz lock profiling must fit into 32 bits.
// However, the lower 32-bits of the cycle counter wrap around too quickly
// with high frequency processors, so a right-shift by 7 is performed to
// quickly divide the cycles by 128. Using these 32 bits, reduces the
// granularity of time measurement to 128 cycles, and loses track
// of wait time for waits greater than 109 seconds on a 5 GHz machine
// [(2^32 cycles/5 Ghz)*128 = 109.95 seconds]. Waits this long should be
// very rare and the reduced granularity should not be an issue given
// processors in the Google fleet operate at a minimum of one billion
// cycles/sec.
enum { PROFILE_TIMESTAMP_SHIFT = 7 };
// Collect contentionz profile info. Subtract one from wait_timestamp as
// antidote to "now |= 1;" in SlowLock().
SubmitSpinLockProfileData(this, wait_timestamp - 1);
void SpinLock::SlowUnlock(uint64 wait_cycles) {
base::internal::SpinLockWake(&lockword_, false); // wake waiter if necessary
// Collect contentionz profile info, expanding the wait_cycles back out to
// the full value. If wait_cycles is <= kSpinLockSleeper, then no wait
// was actually performed, so don't record the wait time. Note, that the
// CalculateWaitCycles method adds in kSpinLockSleeper cycles
// unconditionally to guarantee the wait time is not kSpinLockFree or
// kSpinLockHeld. The adding in of these small number of cycles may
// overestimate the contention by a slight amount 50% of the time. However,
// if this code tried to correct for that addition by subtracting out the
// kSpinLockSleeper amount that would underestimate the contention slightly
// 50% of the time. Both ways get the wrong answer, so the code
// overestimates to be more conservative. Overestimating also makes the code
// a little simpler.
//
if (wait_cycles > kSpinLockSleeper) {
base::SubmitSpinLockProfileData(this,
wait_cycles << PROFILE_TIMESTAMP_SHIFT);
}
}
inline int32 SpinLock::CalculateWaitCycles(int64 wait_start_time) {
int32 wait_cycles = ((CycleClock::Now() - wait_start_time) >>
PROFILE_TIMESTAMP_SHIFT);
// The number of cycles waiting for the lock is used as both the
// wait_cycles and lock value, so it can't be kSpinLockFree or
// kSpinLockHeld. Make sure the value returned is at least
// kSpinLockSleeper.
wait_cycles |= kSpinLockSleeper;
return wait_cycles;
}

View File

@ -44,14 +44,14 @@
#define BASE_SPINLOCK_H_
#include <config.h>
#include "base/basictypes.h"
#include "base/atomicops.h"
#include "base/basictypes.h"
#include "base/dynamic_annotations.h"
#include "base/thread_annotations.h"
class LOCKABLE SpinLock {
public:
SpinLock() : lockword_(0) { }
SpinLock() : lockword_(kSpinLockFree) { }
// Special constructor for use with static SpinLock objects. E.g.,
//
@ -70,18 +70,21 @@ class LOCKABLE SpinLock {
// TODO(csilvers): uncomment the annotation when we figure out how to
// support this macro with 0 args (see thread_annotations.h)
inline void Lock() /*EXCLUSIVE_LOCK_FUNCTION()*/ {
if (Acquire_CompareAndSwap(&lockword_, 0, 1) != 0) {
if (base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree,
kSpinLockHeld) != kSpinLockFree) {
SlowLock();
}
ANNOTATE_RWLOCK_ACQUIRED(this, 1);
}
// Acquire this SpinLock and return true if the acquisition can be
// done without blocking, else return false. If this SpinLock is
// free at the time of the call, TryLock will return true with high
// probability.
// Try to acquire this SpinLock without blocking and return true if the
// acquisition was successful. If the lock was not acquired, false is
// returned. If this SpinLock is free at the time of the call, TryLock
// will return true with high probability.
inline bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true) {
bool res = (Acquire_CompareAndSwap(&lockword_, 0, 1) == 0);
bool res =
(base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree,
kSpinLockHeld) == kSpinLockFree);
if (res) {
ANNOTATE_RWLOCK_ACQUIRED(this, 1);
}
@ -92,47 +95,37 @@ class LOCKABLE SpinLock {
// TODO(csilvers): uncomment the annotation when we figure out how to
// support this macro with 0 args (see thread_annotations.h)
inline void Unlock() /*UNLOCK_FUNCTION()*/ {
// This is defined in mutex.cc.
extern void SubmitSpinLockProfileData(const void *, int64);
int64 wait_timestamp = static_cast<uint32>(lockword_);
uint64 wait_cycles =
static_cast<uint64>(base::subtle::NoBarrier_Load(&lockword_));
ANNOTATE_RWLOCK_RELEASED(this, 1);
Release_Store(&lockword_, 0);
if (wait_timestamp != 1) {
base::subtle::Release_Store(&lockword_, kSpinLockFree);
if (wait_cycles != kSpinLockHeld) {
// Collect contentionz profile info, and speed the wakeup of any waiter.
// The lockword_ value indicates when the waiter started waiting.
SlowUnlock(wait_timestamp);
// The wait_cycles value indicates how long this thread spent waiting
// for the lock.
SlowUnlock(wait_cycles);
}
}
// Report if we think the lock can be held by this thread.
// When the lock is truly held by the invoking thread
// we will always return true.
// Indended to be used as CHECK(lock.IsHeld());
// Determine if the lock is held. When the lock is held by the invoking
// thread, true will always be returned. Intended to be used as
// CHECK(lock.IsHeld()).
inline bool IsHeld() const {
return lockword_ != 0;
return base::subtle::NoBarrier_Load(&lockword_) != kSpinLockFree;
}
// The timestamp for contention lock profiling must fit into 31 bits.
// as lockword_ is 32 bits and we loose an additional low-order bit due
// to the statement "now |= 1" in SlowLock().
// To select 31 bits from the 64-bit cycle counter, we shift right by
// PROFILE_TIMESTAMP_SHIFT = 7.
// Using these 31 bits, we reduce granularity of time measurement to
// 256 cycles, and will loose track of wait time for waits greater than
// 109 seconds on a 5 GHz machine, longer for faster clock cycles.
// Waits this long should be very rare.
enum { PROFILE_TIMESTAMP_SHIFT = 7 };
static const base::LinkerInitialized LINKER_INITIALIZED; // backwards compat
private:
// Lock-state: 0 means unlocked; 1 means locked with no waiters; values
// greater than 1 indicate locked with waiters, where the value is the time
// the first waiter started waiting and is used for contention profiling.
enum { kSpinLockFree = 0 };
enum { kSpinLockHeld = 1 };
enum { kSpinLockSleeper = 2 };
volatile Atomic32 lockword_;
void SlowLock();
void SlowUnlock(int64 wait_timestamp);
void SlowUnlock(uint64 wait_cycles);
Atomic32 SpinLoop(int64 initial_wait_timestamp, Atomic32* wait_cycles);
inline int32 CalculateWaitCycles(int64 wait_start_time);
DISALLOW_COPY_AND_ASSIGN(SpinLock);
};

View File

@ -0,0 +1,77 @@
/* Copyright (c) 2010, 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.
*/
// The OS-specific header included below must provide two calls:
// base::internal::SpinLockDelay() and base::internal::SpinLockWake().
// See spinlock_internal.h for the spec of SpinLockWake().
// void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop)
// SpinLockDelay() generates an apprproate spin delay on iteration "loop" of a
// spin loop on location *w, whose previously observed value was "value".
// SpinLockDelay() may do nothing, may yield the CPU, may sleep a clock tick,
// or may wait for a delay that can be truncated by a call to SpinlockWake(w).
// In all cases, it must return in bounded time even if SpinlockWake() is not
// called.
#include "base/spinlock_internal.h"
#if defined(_WIN32)
#include "base/spinlock_win32-inl.h"
#elif defined(__linux__)
#include "base/spinlock_linux-inl.h"
#else
#include "base/spinlock_posix-inl.h"
#endif
namespace base {
namespace internal {
// See spinlock_internal.h for spec.
int32 SpinLockWait(volatile Atomic32 *w, int n,
const SpinLockWaitTransition trans[]) {
int32 v;
bool done = false;
for (int loop = 0; !done; loop++) {
v = base::subtle::Acquire_Load(w);
int i;
for (i = 0; i != n && v != trans[i].from; i++) {
}
if (i == n) {
SpinLockDelay(w, v, loop); // no matching transition
} else if (trans[i].to == v || // null transition
base::subtle::Acquire_CompareAndSwap(w, v, trans[i].to) == v) {
done = trans[i].done;
}
}
return v;
}
} // namespace internal
} // namespace base

View File

@ -0,0 +1,64 @@
/* Copyright (c) 2010, 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 is an internal part spinlock.cc and once.cc
* It may not be used directly by code outside of //base.
*/
#ifndef BASE_SPINLOCK_INTERNAL_H_
#define BASE_SPINLOCK_INTERNAL_H_
#include <config.h>
#include "base/basictypes.h"
#include "base/atomicops.h"
namespace base {
namespace internal {
// SpinLockWait() waits until it can perform one of several transitions from
// "from" to "to". It returns when it performs a transition where done==true.
struct SpinLockWaitTransition {
int32 from;
int32 to;
bool done;
};
// Wait until *w can transition from trans[i].from to trans[i].to for some i
// satisfying 0<=i<n && trans[i].done, atomically make the transition,
// then return the old value of *w. Make any other atomic tranistions
// where !trans[i].done, but continue waiting.
int32 SpinLockWait(volatile Atomic32 *w, int n,
const SpinLockWaitTransition trans[]);
void SpinLockWake(volatile Atomic32 *w, bool all);
void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop);
} // namespace internal
} // namespace base
#endif

View File

@ -28,11 +28,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ---
* This file is a Linux-specific part of spinlock.cc
* This file is a Linux-specific part of spinlock_internal.cc
*/
#include <sched.h>
#include <time.h>
#include <limits.h>
#include "base/linux_syscall_support.h"
#define FUTEX_WAIT 0
@ -48,7 +49,7 @@ static struct InitModule {
int x = 0;
// futexes are ints, so we can use them only when
// that's the same size as the lockword_ in SpinLock.
have_futex = (sizeof (Atomic32) == sizeof (int) &&
have_futex = (sizeof (Atomic32) == sizeof (int) &&
sys_futex(&x, FUTEX_WAKE, 1, 0) >= 0);
if (have_futex &&
sys_futex(&x, FUTEX_WAKE | futex_private_flag, 1, 0) < 0) {
@ -56,36 +57,41 @@ static struct InitModule {
}
}
} init_module;
} // anonymous namespace
static void SpinLockWait(volatile Atomic32 *w) {
int save_errno = errno;
struct timespec tm;
tm.tv_sec = 0;
if (have_futex) {
int value;
tm.tv_nsec = 1000000; // 1ms; really we're trying to sleep for one kernel
// clock tick
while ((value = base::subtle::Acquire_CompareAndSwap(w, 0, 1)) != 0) {
namespace base {
namespace internal {
void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop) {
if (loop != 0) {
int save_errno = errno;
struct timespec tm;
tm.tv_sec = 0;
if (have_futex) {
tm.tv_nsec = 1000000; // 1ms; really we're trying to sleep for one
// kernel clock tick
} else {
tm.tv_nsec = 2000001; // above 2ms so linux 2.4 doesn't spin
}
if (have_futex) {
sys_futex(reinterpret_cast<int *>(const_cast<Atomic32 *>(w)),
FUTEX_WAIT | futex_private_flag,
value, reinterpret_cast<struct kernel_timespec *>(&tm));
}
} else {
tm.tv_nsec = 2000001; // above 2ms so linux 2.4 doesn't spin
if (base::subtle::NoBarrier_Load(w) != 0) {
sched_yield();
}
while (base::subtle::Acquire_CompareAndSwap(w, 0, 1) != 0) {
FUTEX_WAIT | futex_private_flag,
value, reinterpret_cast<struct kernel_timespec *>(&tm));
} else {
nanosleep(&tm, NULL);
}
errno = save_errno;
}
errno = save_errno;
}
static void SpinLockWake(volatile Atomic32 *w) {
void SpinLockWake(volatile Atomic32 *w, bool all) {
if (have_futex) {
sys_futex(reinterpret_cast<int *>(const_cast<Atomic32 *>(w)),
FUTEX_WAKE | futex_private_flag, 1, 0);
FUTEX_WAKE | futex_private_flag, all? INT_MAX : 1, 0);
}
}
} // namespace internal
} // namespace base

View File

@ -28,25 +28,35 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ---
* This file is a Posix-specific part of spinlock.cc
* This file is a Posix-specific part of spinlock_internal.cc
*/
#include <sched.h>
#include <time.h>
#include <config.h>
#include <errno.h>
#ifdef HAVE_SCHED_H
#include <sched.h> /* For sched_yield() */
#endif
#include <time.h> /* For nanosleep() */
static void SpinLockWait(volatile Atomic32 *w) {
namespace base {
namespace internal {
void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop) {
int save_errno = errno;
struct timespec tm;
tm.tv_sec = 0;
tm.tv_nsec = 1000000;
if (base::subtle::NoBarrier_Load(w) != 0) {
if (loop == 0) {
} else if (loop == 1) {
sched_yield();
}
while (base::subtle::Acquire_CompareAndSwap(w, 0, 1) != 0) {
} else {
struct timespec tm;
tm.tv_sec = 0;
tm.tv_nsec = 1000000;
nanosleep(&tm, NULL);
}
errno = save_errno;
}
static void SpinLockWake(volatile Atomic32 *w) {
void SpinLockWake(volatile Atomic32 *w, bool all) {
}
} // namespace internal
} // namespace base

View File

@ -28,20 +28,26 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ---
* This file is a Win32-specific part of spinlock.cc
* This file is a Win32-specific part of spinlock_internal.cc
*/
#include <windows.h>
static void SpinLockWait(volatile Atomic32 *w) {
if (base::subtle::NoBarrier_Load(w) != 0) {
namespace base {
namespace internal {
void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop) {
if (loop == 0) {
} else if (loop == 1) {
Sleep(0);
}
while (base::subtle::Acquire_CompareAndSwap(w, 0, 1) != 0) {
} else {
Sleep(1);
}
}
static void SpinLockWake(volatile Atomic32 *w) {
void SpinLockWake(volatile Atomic32 *w, bool all) {
}
} // namespace internal
} // namespace base

View File

@ -0,0 +1,50 @@
/* Copyright (c) 2010, 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: Chris Ruemmler
*/
#ifndef BASE_AUXILIARY_SYNCHRONIZATION_PROFILING_H_
#define BASE_AUXILIARY_SYNCHRONIZATION_PROFILING_H_
#include "base/basictypes.h"
namespace base {
// We can do contention-profiling of SpinLocks, but the code is in
// mutex.cc, which is not always linked in with spinlock. Hence we
// provide a weak definition, which are used if mutex.cc isn't linked in.
// Submit the number of cycles the spinlock spent contending.
ATTRIBUTE_WEAK extern void SubmitSpinLockProfileData(const void *, int64);
extern void SubmitSpinLockProfileData(const void *contendedlock,
int64 wait_cycles) {}
}
#endif // BASE_AUXILIARY_SYNCHRONIZATION_PROFILING_H_

View File

@ -111,20 +111,23 @@
// 8K), so it's not an ideal solution.
const char* GetenvBeforeMain(const char* name) {
#if defined(HAVE___ENVIRON) // if we have it, it's declared in unistd.h
const int namelen = strlen(name);
for (char** p = __environ; *p; p++) {
if (!memcmp(*p, name, namelen) && (*p)[namelen] == '=') // it's a match
return *p + namelen+1; // point after =
if (__environ) { // can exist but be NULL, if statically linked
const int namelen = strlen(name);
for (char** p = __environ; *p; p++) {
if (!memcmp(*p, name, namelen) && (*p)[namelen] == '=') // it's a match
return *p + namelen+1; // point after =
}
return NULL;
}
return NULL;
#elif defined(PLATFORM_WINDOWS)
#endif
#if defined(PLATFORM_WINDOWS)
// TODO(mbelshe) - repeated calls to this function will overwrite the
// contents of the static buffer.
static char envbuf[1024]; // enough to hold any envvar we care about
if (!GetEnvironmentVariableA(name, envbuf, sizeof(envbuf)-1))
static char envvar_buf[1024]; // enough to hold any envvar we care about
if (!GetEnvironmentVariableA(name, envvar_buf, sizeof(envvar_buf)-1))
return NULL;
return envbuf;
#else
return envvar_buf;
#endif
// static is ok because this function should only be called before
// main(), when we're single-threaded.
static char envbuf[16<<10];
@ -152,7 +155,6 @@ const char* GetenvBeforeMain(const char* name) {
p = endp + 1;
}
return NULL; // env var never found
#endif
}
// This takes as an argument an environment-variable name (like
@ -229,6 +231,26 @@ static int64 EstimateCyclesPerSecond(const int estimate_time_ms) {
return guess;
}
// Helper function for reading an int from a file. Returns true if successful
// and the memory location pointed to by value is set to the value read.
static bool ReadIntFromFile(const char *file, int *value) {
bool ret = false;
int fd = open(file, O_RDONLY);
if (fd != -1) {
char line[1024];
char* err;
memset(line, '\0', sizeof(line));
read(fd, line, sizeof(line) - 1);
const int temp_value = strtol(line, &err, 10);
if (line[0] != '\0' && (*err == '\n' || *err == '\0')) {
*value = temp_value;
ret = true;
}
close(fd);
}
return ret;
}
// WARNING: logging calls back to InitializeSystemInfo() so it must
// not invoke any logging code. Also, InitializeSystemInfo() can be
// called before main() -- in fact it *must* be since already_called
@ -254,26 +276,31 @@ static void InitializeSystemInfo() {
#if defined(__linux__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
char line[1024];
char* err;
int freq;
// If the kernel is exporting the tsc frequency use that. There are issues
// where cpuinfo_max_freq cannot be relied on because the BIOS may be
// exporintg an invalid p-state (on x86) or p-states may be used to put the
// processor in a new mode (turbo mode). Essentially, those frequencies
// cannot always be relied upon. The same reasons apply to /proc/cpuinfo as
// well.
if (!saw_mhz &&
ReadIntFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)) {
// The value is in kHz (as the file name suggests). For example, on a
// 2GHz warpstation, the file contains the value "2000000".
cpuinfo_cycles_per_second = freq * 1000.0;
saw_mhz = true;
}
// If CPU scaling is in effect, we want to use the *maximum* frequency,
// not whatever CPU speed some random processor happens to be using now.
if (!saw_mhz) {
const char* pname0 =
"/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
int fd0 = open(pname0, O_RDONLY);
if (fd0 != -1) {
memset(line, '\0', sizeof(line));
read(fd0, line, sizeof(line));
const int max_freq = strtol(line, &err, 10);
if (line[0] != '\0' && (*err == '\n' || *err == '\0')) {
// The value is in kHz. For example, on a 2GHz machine, the file
// contains the value "2000000". Historically this file contained no
// newline, but at some point the kernel started appending a newline.
cpuinfo_cycles_per_second = max_freq * 1000.0;
saw_mhz = true;
}
close(fd0);
}
if (!saw_mhz &&
ReadIntFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
&freq)) {
// The value is in kHz. For example, on a 2GHz machine, the file
// contains the value "2000000".
cpuinfo_cycles_per_second = freq * 1000.0;
saw_mhz = true;
}
// Read /proc/cpuinfo for other values, and if there is no cpuinfo_max_freq.
@ -311,20 +338,20 @@ static void InitializeSystemInfo() {
if (newline != NULL)
*newline = '\0';
if (!saw_mhz && strncmp(line, "cpu MHz", sizeof("cpu MHz")-1) == 0) {
if (!saw_mhz && strncasecmp(line, "cpu MHz", sizeof("cpu MHz")-1) == 0) {
const char* freqstr = strchr(line, ':');
if (freqstr) {
cpuinfo_cycles_per_second = strtod(freqstr+1, &err) * 1000000.0;
if (freqstr[1] != '\0' && *err == '\0')
saw_mhz = true;
}
} else if (strncmp(line, "bogomips", sizeof("bogomips")-1) == 0) {
} else if (strncasecmp(line, "bogomips", sizeof("bogomips")-1) == 0) {
const char* freqstr = strchr(line, ':');
if (freqstr)
bogo_clock = strtod(freqstr+1, &err) * 1000000.0;
if (freqstr == NULL || freqstr[1] == '\0' || *err != '\0')
bogo_clock = 1.0;
} else if (strncmp(line, "processor", sizeof("processor")-1) == 0) {
} else if (strncasecmp(line, "processor", sizeof("processor")-1) == 0) {
num_cpus++; // count up every time we see an "processor :" entry
}
} while (chars_read > 0);
@ -888,9 +915,10 @@ namespace tcmalloc {
// Helper to add the list of mapped shared libraries to a profile.
// Fill formatted "/proc/self/maps" contents into buffer 'buf' of size 'size'
// and return the actual size occupied in 'buf'.
// and return the actual size occupied in 'buf'. We fill wrote_all to true
// if we successfully wrote all proc lines to buf, false else.
// We do not provision for 0-terminating 'buf'.
int FillProcSelfMaps(char buf[], int size) {
int FillProcSelfMaps(char buf[], int size, bool* wrote_all) {
ProcMapsIterator::Buffer iterbuf;
ProcMapsIterator it(0, &iterbuf); // 0 means "current pid"
@ -898,10 +926,17 @@ int FillProcSelfMaps(char buf[], int size) {
int64 inode;
char *flags, *filename;
int bytes_written = 0;
*wrote_all = true;
while (it.Next(&start, &end, &flags, &offset, &inode, &filename)) {
bytes_written += it.FormatLine(buf + bytes_written, size - bytes_written,
start, end, flags, offset, inode, filename,
0);
const int line_length = it.FormatLine(buf + bytes_written,
size - bytes_written,
start, end, flags, offset,
inode, filename, 0);
if (line_length == 0)
*wrote_all = false; // failed to write this line out
else
bytes_written += line_length;
}
return bytes_written;
}

View File

@ -226,7 +226,7 @@ class ProcMapsIterator {
// Helper routines
namespace tcmalloc {
int FillProcSelfMaps(char buf[], int size);
int FillProcSelfMaps(char buf[], int size, bool* wrote_all);
void DumpProcSelfMaps(RawFD fd);
}

View File

@ -46,7 +46,9 @@
#define BASE_THREAD_ANNOTATIONS_H_
#if defined(__GNUC__) && defined(__SUPPORT_TS_ANNOTATION__) && (!defined(SWIG))
#if defined(__GNUC__) \
&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) \
&& defined(__SUPPORT_TS_ANNOTATION__) && (!defined(SWIG))
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op

View File

@ -395,7 +395,7 @@ const void *VDSOSupport::Init() {
}
// Subtle: this code runs outside of any locks; prevent compiler
// from assigning to getcpu_fn_ more than once.
MemoryBarrier();
base::subtle::MemoryBarrier();
getcpu_fn_ = fn;
return vdso_base_;
}

View File

@ -77,6 +77,8 @@ static const size_t kPageSize = 1 << kPageShift;
static const size_t kMaxSize = 8u * kPageSize;
static const size_t kAlignment = 8;
static const size_t kLargeSizeClass = 0;
// For all span-lengths < kMaxPages we keep an exact-size list.
static const size_t kMaxPages = 1 << (20 - kPageShift);
// Default bound on the total amount of thread caches.
static const size_t kDefaultOverallThreadCacheSize = 8u * kMaxThreadCacheSize;
@ -102,6 +104,17 @@ static const int kMaxDynamicFreeListLength = 8192;
static const Length kMaxValidPages = (~static_cast<Length>(0)) >> kPageShift;
#ifdef __x86_64__
// All current and planned x86_64 processors only look at the lower 48 bits
// in virtual to physical address translation. The top 16 are thus unused.
// TODO(rus): Under what operating systems can we increase it safely to 17?
// This lets us use smaller page maps. On first allocation, a 36-bit page map
// uses only 96 KB instead of the 4.5 MB used by a 52-bit page map.
static const int kAddressBits = 48;
#else
static const int kAddressBits = 8 * sizeof(void*);
#endif
namespace tcmalloc {
// Convert byte size into pages. This won't overflow, but may return

View File

@ -119,6 +119,9 @@
/* Define to 1 if the system has the type `struct mallinfo'. */
#undef HAVE_STRUCT_MALLINFO
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/prctl.h> header file. */
#undef HAVE_SYS_PRCTL_H
@ -173,6 +176,10 @@
/* Define to 1 if int32_t is equivalent to intptr_t */
#undef INT32_EQUALS_INTPTR
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
#undef NO_MINUS_C_MINUS_O

View File

@ -497,7 +497,7 @@ class MallocBlock {
// practical effect is that allocations are limited to 4Gb or so, even if
// the address space could take more.
static size_t max_size_t = ~0;
if (size < 0 || size > max_size_t - sizeof(MallocBlock)) {
if (size > max_size_t - sizeof(MallocBlock)) {
RAW_LOG(ERROR, "Massive size passed to malloc: %"PRIuS"", size);
return NULL;
}
@ -1356,6 +1356,20 @@ class DebugMallocImplementation : public ParentImplementation {
virtual size_t GetEstimatedAllocatedSize(size_t size) {
return size;
}
virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* v) {
static const char* kDebugFreeQueue = "debug.free_queue";
ParentImplementation::GetFreeListSizes(v);
MallocExtension::FreeListInfo i;
i.type = kDebugFreeQueue;
i.min_object_size = 0;
i.max_object_size = numeric_limits<size_t>::max();
i.total_bytes_free = MallocBlock::FreeQueueSize();
v->push_back(i);
}
};
static DebugMallocImplementation debug_malloc_implementation;

View File

@ -136,7 +136,7 @@ class PERFTOOLS_DLL_DECL HeapLeakChecker {
bool NoLeaks() { return DoNoLeaks(DO_NOT_SYMBOLIZE); }
// These forms are obsolete; use NoLeaks() instead.
// TODO(csilvers): mark with ATTRIBUTE_DEPRECATED.
// TODO(csilvers): mark as DEPRECATED.
bool QuickNoLeaks() { return NoLeaks(); }
bool BriefNoLeaks() { return NoLeaks(); }
bool SameHeap() { return NoLeaks(); }

View File

@ -50,6 +50,7 @@
#include <stdint.h>
#endif
#include <string>
#include <vector>
// Annoying stuff for windows -- makes sure clients can import these functions
#ifndef PERFTOOLS_DLL_DECL
@ -102,12 +103,17 @@ class PERFTOOLS_DLL_DECL MallocExtension {
// that allocated these objects. The format of the returned output
// is equivalent to the output of the heap profiler and can
// therefore be passed to "pprof".
// NOTE: by default, tcmalloc does not do any heap sampling, and this
// function will always return an empty sample. To get useful
// data from GetHeapSample, you must also set the environment
// variable TCMALLOC_SAMPLE_PARAMETER to a value such as 524288.
virtual void GetHeapSample(MallocExtensionWriter* writer);
// Outputs to "writer" the stack traces that caused growth in the
// address space size. The format of the returned output is
// equivalent to the output of the heap profiler and can therefore
// be passed to "pprof".
// be passed to "pprof". (This does not depend on, or require,
// TCMALLOC_SAMPLE_PARAMETER.)
virtual void GetHeapGrowthStacks(MallocExtensionWriter* writer);
// Invokes func(arg, range) for every controlled memory
@ -244,6 +250,45 @@ class PERFTOOLS_DLL_DECL MallocExtension {
// malloc implementation during initialization.
static void Register(MallocExtension* implementation);
// Returns detailed information about malloc's freelists. For each list,
// return a FreeListInfo:
struct FreeListInfo {
size_t min_object_size;
size_t max_object_size;
size_t total_bytes_free;
const char* type;
};
// Each item in the vector refers to a different freelist. The lists
// are identified by the range of allocations that objects in the
// list can satisfy ([min_object_size, max_object_size]) and the
// type of freelist (see below). The current size of the list is
// returned in total_bytes_free (which count against a processes
// resident and virtual size).
//
// Currently supported types are:
//
// "tcmalloc.page{_unmapped}" - tcmalloc's page heap. An entry for each size
// class in the page heap is returned. Bytes in "page_unmapped"
// are no longer backed by physical memory and do not count against
// the resident size of a process.
//
// "tcmalloc.large{_unmapped}" - tcmalloc's list of objects larger
// than the largest page heap size class. Only one "large"
// entry is returned. There is no upper-bound on the size
// of objects in the large free list; this call returns
// kint64max for max_object_size. Bytes in
// "large_unmapped" are no longer backed by physical memory
// and do not count against the resident size of a process.
//
// "tcmalloc.central" - tcmalloc's central free-list. One entry per
// size-class is returned. Never unmapped.
//
// "debug.free_queue" - free objects queued by the debug allocator
// and not returned to tcmalloc.
//
// "tcmalloc.thread" - tcmalloc's per-thread caches. Never unmapped.
virtual void GetFreeListSizes(std::vector<FreeListInfo>* v);
protected:
// Get a list of stack traces of sampled allocation points. Returns
// a pointer to a "new[]-ed" result array, and stores the sample

View File

@ -342,7 +342,8 @@ int HeapProfileTable::FillOrderedProfile(char buf[], int size) const {
// any gaps. Whew!
int map_length = snprintf(buf, size, "%s", kProcSelfMapsHeader);
if (map_length < 0 || map_length >= size) return 0;
map_length += FillProcSelfMaps(buf + map_length, size - map_length);
bool dummy; // "wrote_all" -- did /proc/self/maps fit in its entirety?
map_length += FillProcSelfMaps(buf + map_length, size - map_length, &dummy);
RAW_DCHECK(map_length <= size, "");
char* const map_start = buf + size - map_length; // move to end
memmove(map_start, buf, map_length);

View File

@ -52,6 +52,7 @@
#include "maybe_threads.h"
using STL_NAMESPACE::string;
using STL_NAMESPACE::vector;
static void DumpAddressMap(string* result) {
*result += "\nMAPPED_LIBRARIES:\n";
@ -59,9 +60,11 @@ static void DumpAddressMap(string* result) {
const size_t old_resultlen = result->size();
for (int amap_size = 10240; amap_size < 10000000; amap_size *= 2) {
result->resize(old_resultlen + amap_size);
bool wrote_all = false;
const int bytes_written =
tcmalloc::FillProcSelfMaps(&((*result)[old_resultlen]), amap_size);
if (bytes_written < amap_size - 1) { // we fit!
tcmalloc::FillProcSelfMaps(&((*result)[old_resultlen]), amap_size,
&wrote_all);
if (wrote_all) { // we fit!
(*result)[old_resultlen + bytes_written] = '\0';
result->resize(old_resultlen + bytes_written);
return;
@ -167,6 +170,11 @@ size_t MallocExtension::GetAllocatedSize(void* p) {
return 0;
}
void MallocExtension::GetFreeListSizes(
vector<MallocExtension::FreeListInfo>* v) {
v->clear();
}
// The current malloc extension object.
static pthread_once_t module_init = PTHREAD_ONCE_INIT;

View File

@ -117,7 +117,6 @@
#include "memory_region_map.h"
#include "base/linux_syscall_support.h"
#include "base/logging.h"
#include "base/low_level_alloc.h"
#include "malloc_hook-inl.h"

View File

@ -338,6 +338,35 @@ static double PagesToMB(uint64_t pages) {
return (pages << kPageShift) / 1048576.0;
}
void PageHeap::GetClassSizes(int64 class_sizes_normal[kMaxPages],
int64 class_sizes_returned[kMaxPages],
int64* normal_pages_in_spans,
int64* returned_pages_in_spans) {
for (int s = 0; s < kMaxPages; s++) {
if (class_sizes_normal != NULL) {
class_sizes_normal[s] = DLL_Length(&free_[s].normal);
}
if (class_sizes_returned != NULL) {
class_sizes_returned[s] = DLL_Length(&free_[s].returned);
}
}
if (normal_pages_in_spans != NULL) {
*normal_pages_in_spans = 0;
for (Span* s = large_.normal.next; s != &large_.normal; s = s->next) {
*normal_pages_in_spans += s->length;;
}
}
if (returned_pages_in_spans != NULL) {
*returned_pages_in_spans = 0;
for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) {
*returned_pages_in_spans += s->length;
}
}
}
void PageHeap::Dump(TCMalloc_Printer* out) {
int nonempty_sizes = 0;
for (int s = 0; s < kMaxPages; s++) {

View File

@ -140,6 +140,10 @@ class PERFTOOLS_DLL_DECL PageHeap {
uint64_t unmapped_bytes; // Total bytes on returned freelists
};
inline Stats stats() const { return stats_; }
void GetClassSizes(int64 class_sizes_normal[kMaxPages],
int64 class_sizes_returned[kMaxPages],
int64* normal_pages_in_spans,
int64* returned_pages_in_spans);
bool Check();
// Like Check() but does some more comprehensive checking.
@ -176,11 +180,8 @@ class PERFTOOLS_DLL_DECL PageHeap {
// should keep this value big because various incarnations of Linux
// have small limits on the number of mmap() regions per
// address-space.
static const int kMinSystemAlloc = 1 << (20 - kPageShift);
// For all span-lengths < kMaxPages we keep an exact-size list.
// REQUIRED: kMaxPages >= kMinSystemAlloc;
static const size_t kMaxPages = kMinSystemAlloc;
// REQUIRED: kMinSystemAlloc <= kMaxPages;
static const int kMinSystemAlloc = kMaxPages;
// Never delay scavenging for more than the following number of
// deallocated pages. With 4K pages, this comes to 4GB of
@ -192,8 +193,8 @@ class PERFTOOLS_DLL_DECL PageHeap {
static const int kDefaultReleaseDelay = 1 << 18;
// Pick the appropriate map and cache types based on pointer size
typedef MapSelector<8*sizeof(uintptr_t)>::Type PageMap;
typedef MapSelector<8*sizeof(uintptr_t)>::CacheType PageMapCache;
typedef MapSelector<kAddressBits>::Type PageMap;
typedef MapSelector<kAddressBits>::CacheType PageMapCache;
PageMap pagemap_;
mutable PageMapCache pagemap_cache_;

View File

@ -89,6 +89,7 @@ my %obj_tool_map = (
);
my $DOT = "dot"; # leave non-absolute, since it may be in /usr/local
my $GV = "gv";
my $EVINCE = "evince"; # could also be xpdf or perhaps acroread
my $KCACHEGRIND = "kcachegrind";
my $PS2PDF = "ps2pdf";
# These are used for dynamic profiles
@ -103,6 +104,7 @@ my $GROWTH_PAGE = "/pprof/growth";
my $CONTENTION_PAGE = "/pprof/contention";
my $WALL_PAGE = "/pprof/wall(?:\\?.*)?"; # accepts options like namefilter
my $FILTEREDPROFILE_PAGE = "/pprof/filteredprofile(?:\\?.*)?";
my $CENSUSPROFILE_PAGE = "/pprof/censusprofile"; # must support "?seconds=#"
my $SYMBOL_PAGE = "/pprof/symbol"; # must support symbol lookup via POST
my $PROGRAM_NAME_PAGE = "/pprof/cmdline";
@ -110,7 +112,7 @@ my $PROGRAM_NAME_PAGE = "/pprof/cmdline";
# All the alternatives must begin with /.
my $PROFILES = "($HEAP_PAGE|$PROFILE_PAGE|$PMUPROFILE_PAGE|" .
"$GROWTH_PAGE|$CONTENTION_PAGE|$WALL_PAGE|" .
"$FILTEREDPROFILE_PAGE)";
"$FILTEREDPROFILE_PAGE|$CENSUSPROFILE_PAGE)";
# default binary name
my $UNKNOWN_BINARY = "(unknown)";
@ -148,7 +150,7 @@ pprof [options] <profile>
The /<service> can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile,
$GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall,
or /pprof/filteredprofile.
$CENSUSPROFILE_PAGE, or /pprof/filteredprofile.
For instance: "pprof http://myserver.com:80$HEAP_PAGE".
If /<service> is omitted, the service defaults to $PROFILE_PAGE (cpu profiling).
pprof --symbols <program>
@ -180,6 +182,7 @@ Output type:
--text Generate text report
--callgrind Generate callgrind format to stdout
--gv Generate Postscript and display
--evince Generate PDF and display
--web Generate SVG and display
--list=<regexp> Generate source listing of matching routines
--disasm=<regexp> Generate disassembly of matching routines
@ -304,6 +307,7 @@ sub Init() {
$main::opt_disasm = "";
$main::opt_symbols = 0;
$main::opt_gv = 0;
$main::opt_evince = 0;
$main::opt_web = 0;
$main::opt_dot = 0;
$main::opt_ps = 0;
@ -372,6 +376,7 @@ sub Init() {
"disasm=s" => \$main::opt_disasm,
"symbols!" => \$main::opt_symbols,
"gv!" => \$main::opt_gv,
"evince!" => \$main::opt_evince,
"web!" => \$main::opt_web,
"dot!" => \$main::opt_dot,
"ps!" => \$main::opt_ps,
@ -452,6 +457,7 @@ sub Init() {
($main::opt_disasm eq '' ? 0 : 1) +
($main::opt_symbols == 0 ? 0 : 1) +
$main::opt_gv +
$main::opt_evince +
$main::opt_web +
$main::opt_dot +
$main::opt_ps +
@ -646,6 +652,8 @@ sub Main() {
if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {
if ($main::opt_gv) {
RunGV(TempName($main::next_tmpfile, "ps"), "");
} elsif ($main::opt_evince) {
RunEvince(TempName($main::next_tmpfile, "pdf"), "");
} elsif ($main::opt_web) {
my $tmp = TempName($main::next_tmpfile, "svg");
RunWeb($tmp);
@ -708,6 +716,12 @@ sub RunGV {
}
}
sub RunEvince {
my $fname = shift;
my $bg = shift; # "" or " &" if we should run in background
system("$EVINCE " . $fname . $bg);
}
sub RunWeb {
my $fname = shift;
print STDERR "Loading web page file:///$fname\n";
@ -805,6 +819,7 @@ sub InteractiveCommand {
$main::opt_disasm = 0;
$main::opt_list = 0;
$main::opt_gv = 0;
$main::opt_evince = 0;
$main::opt_cum = 0;
if (m/^\s*(text|top)(\d*)\s*(.*)/) {
@ -878,11 +893,14 @@ sub InteractiveCommand {
PrintDisassembly($libs, $flat, $cumulative, $routine, $total);
return 1;
}
if (m/^\s*(gv|web)\s*(.*)/) {
if (m/^\s*(gv|web|evince)\s*(.*)/) {
$main::opt_gv = 0;
$main::opt_evince = 0;
$main::opt_web = 0;
if ($1 eq "gv") {
$main::opt_gv = 1;
} elsif ($1 eq "evince") {
$main::opt_evince = 1;
} elsif ($1 eq "web") {
$main::opt_web = 1;
}
@ -902,6 +920,8 @@ sub InteractiveCommand {
if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {
if ($main::opt_gv) {
RunGV(TempName($main::next_tmpfile, "ps"), " &");
} elsif ($main::opt_evince) {
RunEvince(TempName($main::next_tmpfile, "pdf"), " &");
} elsif ($main::opt_web) {
RunWeb(TempName($main::next_tmpfile, "svg"));
}
@ -1685,6 +1705,8 @@ sub PrintDot {
my $output;
if ($main::opt_gv) {
$output = "| $DOT -Tps2 >" . TempName($main::next_tmpfile, "ps");
} elsif ($main::opt_evince) {
$output = "| $DOT -Tps2 | $PS2PDF - " . TempName($main::next_tmpfile, "pdf");
} elsif ($main::opt_ps) {
$output = "| $DOT -Tps2";
} elsif ($main::opt_pdf) {
@ -2955,7 +2977,7 @@ sub FetchDynamicProfile {
my $fetcher = AddFetchTimeout($URL_FETCHER, $fetch_timeout);
my $cmd = "$fetcher '$url' > '$tmp_profile'";
if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE/){
if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE|$CENSUSPROFILE_PAGE/){
print STDERR "Gathering CPU profile from $url for $main::opt_seconds seconds to\n ${real_profile}\n";
if ($encourage_patience) {
print STDERR "Be patient...\n";
@ -3531,16 +3553,18 @@ sub ReadHeapProfile {
# The sampling frequency is the rate of a Poisson process.
# This means that the probability of sampling an allocation of
# size X with sampling rate Y is 1 - exp(-X/Y)
my $ratio;
$ratio = (($s1*1.0)/$n1)/($sample_adjustment);
my $scale_factor;
$scale_factor = 1/(1 - exp(-$ratio));
$n1 *= $scale_factor;
$s1 *= $scale_factor;
$ratio = (($s2*1.0)/$n2)/($sample_adjustment);
$scale_factor = 1/(1 - exp(-$ratio));
$n2 *= $scale_factor;
$s2 *= $scale_factor;
if ($n1 != 0) {
my $ratio = (($s1*1.0)/$n1)/($sample_adjustment);
my $scale_factor = 1/(1 - exp(-$ratio));
$n1 *= $scale_factor;
$s1 *= $scale_factor;
}
if ($n2 != 0) {
my $ratio = (($s2*1.0)/$n2)/($sample_adjustment);
my $scale_factor = 1/(1 - exp(-$ratio));
$n2 *= $scale_factor;
$s2 *= $scale_factor;
}
} else {
# Remote-heap version 1
my $ratio;
@ -4091,9 +4115,15 @@ sub ExtractSymbols {
my $symbols = {};
# Map each PC value to the containing library
my %seen = ();
foreach my $lib (@{$libs}) {
# Map each PC value to the containing library. To make this faster,
# we sort libraries by their starting pc value (highest first), and
# advance through the libraries as we advance the pc. Sometimes the
# addresses of libraries may overlap with the addresses of the main
# binary, so to make sure the libraries 'win', we iterate over the
# libraries in reverse order (which assumes the binary doesn't start
# in the middle of a library, which seems a fair assumption).
my @pcs = (sort { $a cmp $b } keys(%{$pcset})); # pcset is 0-extended strings
foreach my $lib (sort {$b->[1] cmp $a->[1]} @{$libs}) {
my $libname = $lib->[0];
my $start = $lib->[1];
my $finish = $lib->[2];
@ -4101,12 +4131,21 @@ sub ExtractSymbols {
# Get list of pcs that belong in this library.
my $contained = [];
foreach my $pc (keys(%{$pcset})) {
if (!$seen{$pc} && ($pc ge $start) && ($pc le $finish)) {
$seen{$pc} = 1;
push(@{$contained}, $pc);
}
my ($start_pc_index, $finish_pc_index);
# Find smallest finish_pc_index such that $finish < $pc[$finish_pc_index].
for ($finish_pc_index = $#pcs + 1; $finish_pc_index > 0;
$finish_pc_index--) {
last if $pcs[$finish_pc_index - 1] le $finish;
}
# Find smallest start_pc_index such that $start <= $pc[$start_pc_index].
for ($start_pc_index = $finish_pc_index; $start_pc_index > 0;
$start_pc_index--) {
last if $pcs[$start_pc_index - 1] lt $start;
}
# This keeps PC values higher than $pc[$finish_pc_index] in @pcs,
# in case there are overlaps in libraries and the main binary.
@{$contained} = splice(@pcs, $start_pc_index,
$finish_pc_index - $start_pc_index);
# Map to symbols
MapToSymbols($libname, AddressSub($start, $offset), $contained, $symbols);
}

View File

@ -111,7 +111,7 @@ class CpuProfiler {
int (*filter_)(void*);
void* filter_arg_;
// Opague token returned by the profile handler. To be used when calling
// Opaque token returned by the profile handler. To be used when calling
// ProfileHandlerUnregisterCallback.
ProfileHandlerToken* prof_handler_token_;

View File

@ -46,6 +46,7 @@
#include <sys/mman.h>
#endif
#include <errno.h>
#include "common.h"
#include "system-alloc.h"
#include "internal_logging.h"
#include "base/logging.h"
@ -73,6 +74,24 @@ static const bool kDebugMode = false;
static const bool kDebugMode = true;
#endif
// Anonymous namespace to avoid name conflicts on "CheckAddressBits".
namespace {
// Check that no bit is set at position ADDRESS_BITS or higher.
template <int ADDRESS_BITS> bool CheckAddressBits(uintptr_t ptr) {
return (ptr >> ADDRESS_BITS) == 0;
}
// Specialize for the bit width of a pointer to avoid undefined shift.
template <> bool CheckAddressBits<8 * sizeof(void*)>(uintptr_t ptr) {
return true;
}
} // Anonymous namespace to avoid name conflicts on "CheckAddressBits".
COMPILE_ASSERT(kAddressBits <= 8 * sizeof(void*),
address_bits_larger_than_pointer_size);
// Structure for discovering alignment
union MemoryAligner {
void* p;
@ -443,7 +462,16 @@ void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size,
if (a == NULL) continue;
if (a->usable_ && !a->failed_) {
void* result = a->Alloc(size, actual_size, alignment);
if (result != NULL) return result;
if (result != NULL) {
if (actual_size) {
CheckAddressBits<kAddressBits>(
reinterpret_cast<uintptr_t>(result) + *actual_size - 1);
} else {
CheckAddressBits<kAddressBits>(
reinterpret_cast<uintptr_t>(result) + size - 1);
}
return result;
}
}
}

View File

@ -110,6 +110,7 @@
#include <errno.h>
#include <stdarg.h>
#include <algorithm>
#include <limits>
#include <google/tcmalloc.h>
#include "base/commandlineflags.h"
#include "base/basictypes.h" // gets us PRIu64
@ -136,7 +137,9 @@
# define WIN32_DO_PATCHING 1
#endif
using std::max;
using STL_NAMESPACE::max;
using STL_NAMESPACE::numeric_limits;
using STL_NAMESPACE::vector;
using tcmalloc::AlignmentForSize;
using tcmalloc::PageHeap;
using tcmalloc::PageHeapAllocator;
@ -439,6 +442,52 @@ static void DumpStats(TCMalloc_Printer* out, int level) {
static const double MB = 1048576.0;
const uint64_t virtual_memory_used = (stats.pageheap.system_bytes
+ stats.metadata_bytes);
const uint64_t physical_memory_used = (virtual_memory_used
- stats.pageheap.unmapped_bytes);
const uint64_t bytes_in_use_by_app = (physical_memory_used
- stats.metadata_bytes
- stats.pageheap.free_bytes
- stats.central_bytes
- stats.transfer_bytes
- stats.thread_bytes);
out->printf(
"------------------------------------------------\n"
"MALLOC: %12" PRIu64 " (%7.1f MB) Bytes in use by application\n"
"MALLOC: + %12" PRIu64 " (%7.1f MB) Bytes in page heap freelist\n"
"MALLOC: + %12" PRIu64 " (%7.1f MB) Bytes in central cache freelist\n"
"MALLOC: + %12" PRIu64 " (%7.1f MB) Bytes in transfer cache freelist\n"
"MALLOC: + %12" PRIu64 " (%7.1f MB) Bytes in thread cache freelists\n"
"MALLOC: + %12" PRIu64 " (%7.1f MB) Bytes in malloc metadata\n"
"MALLOC: ------------\n"
"MALLOC: = %12" PRIu64 " (%7.1f MB) Actual memory used (physical + swap)\n"
"MALLOC: + %12" PRIu64 " (%7.1f MB) Bytes released to OS (aka unmapped)\n"
"MALLOC: ------------\n"
"MALLOC: = %12" PRIu64 " (%7.1f MB) Virtual address space used\n"
"MALLOC:\n"
"MALLOC: %12" PRIu64 " Spans in use\n"
"MALLOC: %12" PRIu64 " Thread heaps in use\n"
"MALLOC: %12" PRIu64 " Tcmalloc page size\n"
"------------------------------------------------\n"
"Call ReleaseFreeMemory() to release freelist memory to the OS"
" (via madvise()).\n"
"Bytes released to the OS take up virtual address space"
" but no physical memory.\n",
bytes_in_use_by_app, bytes_in_use_by_app / MB,
stats.pageheap.free_bytes, stats.pageheap.free_bytes / MB,
stats.central_bytes, stats.central_bytes / MB,
stats.transfer_bytes, stats.transfer_bytes / MB,
stats.thread_bytes, stats.thread_bytes / MB,
stats.metadata_bytes, stats.metadata_bytes / MB,
physical_memory_used, physical_memory_used / MB,
stats.pageheap.unmapped_bytes, stats.pageheap.unmapped_bytes / MB,
virtual_memory_used, virtual_memory_used / MB,
uint64_t(Static::span_allocator()->inuse()),
uint64_t(ThreadCache::HeapsInUse()),
uint64_t(kPageSize));
if (level >= 2) {
out->printf("------------------------------------------------\n");
out->printf("Size class breakdown\n");
@ -464,38 +513,6 @@ static void DumpStats(TCMalloc_Printer* out, int level) {
out->printf("------------------------------------------------\n");
DumpSystemAllocatorStats(out);
}
const uint64_t bytes_in_use = stats.pageheap.system_bytes
- stats.pageheap.free_bytes
- stats.pageheap.unmapped_bytes
- stats.central_bytes
- stats.transfer_bytes
- stats.thread_bytes;
out->printf("------------------------------------------------\n"
"MALLOC: %12" PRIu64 " (%7.1f MB) Heap size\n"
"MALLOC: %12" PRIu64 " (%7.1f MB) Bytes in use by application\n"
"MALLOC: %12" PRIu64 " (%7.1f MB) Bytes free in page heap\n"
"MALLOC: %12" PRIu64 " (%7.1f MB) Bytes unmapped in page heap\n"
"MALLOC: %12" PRIu64 " (%7.1f MB) Bytes free in central cache\n"
"MALLOC: %12" PRIu64 " (%7.1f MB) Bytes free in transfer cache\n"
"MALLOC: %12" PRIu64 " (%7.1f MB) Bytes free in thread caches\n"
"MALLOC: %12" PRIu64 " Spans in use\n"
"MALLOC: %12" PRIu64 " Thread heaps in use\n"
"MALLOC: %12" PRIu64 " (%7.1f MB) Metadata allocated\n"
"MALLOC: %12" PRIu64 " Tcmalloc page size\n"
"------------------------------------------------\n",
stats.pageheap.system_bytes, stats.pageheap.system_bytes / MB,
bytes_in_use, bytes_in_use / MB,
stats.pageheap.free_bytes, stats.pageheap.free_bytes / MB,
stats.pageheap.unmapped_bytes, stats.pageheap.unmapped_bytes / MB,
stats.central_bytes, stats.central_bytes / MB,
stats.transfer_bytes, stats.transfer_bytes / MB,
stats.thread_bytes, stats.thread_bytes / MB,
uint64_t(Static::span_allocator()->inuse()),
uint64_t(ThreadCache::HeapsInUse()),
stats.metadata_bytes, stats.metadata_bytes / MB,
uint64_t(kPageSize));
}
static void PrintStats(int level) {
@ -609,6 +626,20 @@ class TCMallocImplementation : public MallocExtension {
}
}
// We may print an extra, tcmalloc-specific warning message here.
virtual void GetHeapSample(MallocExtensionWriter* writer) {
if (FLAGS_tcmalloc_sample_parameter == 0) {
const char* const kWarningMsg =
"#\n# WARNING: This heap profile does not have any data in it,\n"
"# because the application was run with heap sampling turned off.\n"
"# To get useful data from from GetHeapSample(), you must first\n"
"# set the environment variable TCMALLOC_SAMPLE_PARAMETER to a\n"
"# positive sampling period, such as 524288.\n#\n";
writer->append(kWarningMsg, strlen(kWarningMsg));
}
MallocExtension::GetHeapSample(writer);
}
virtual void** ReadStackTraces(int* sample_period) {
tcmalloc::StackTraceTable table;
{
@ -753,6 +784,99 @@ class TCMallocImplementation : public MallocExtension {
// unnamed namespace, we need to move the definition below it in the
// file.
virtual size_t GetAllocatedSize(void* ptr);
virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* v) {
static const char* kCentralCacheType = "tcmalloc.central";
static const char* kTransferCacheType = "tcmalloc.transfer";
static const char* kThreadCacheType = "tcmalloc.thread";
static const char* kPageHeapType = "tcmalloc.page";
static const char* kPageHeapUnmappedType = "tcmalloc.page_unmapped";
static const char* kLargeSpanType = "tcmalloc.large";
static const char* kLargeUnmappedSpanType = "tcmalloc.large_unmapped";
v->clear();
// central class information
int64 prev_class_size = 0;
for (int cl = 1; cl < kNumClasses; ++cl) {
size_t class_size = Static::sizemap()->ByteSizeForClass(cl);
MallocExtension::FreeListInfo i;
i.min_object_size = prev_class_size + 1;
i.max_object_size = class_size;
i.total_bytes_free =
Static::central_cache()[cl].length() * class_size;
i.type = kCentralCacheType;
v->push_back(i);
// transfer cache
i.total_bytes_free =
Static::central_cache()[cl].tc_length() * class_size;
i.type = kTransferCacheType;
v->push_back(i);
prev_class_size = Static::sizemap()->ByteSizeForClass(cl);
}
// Add stats from per-thread heaps
uint64_t class_count[kNumClasses];
memset(class_count, 0, sizeof(class_count));
{
SpinLockHolder h(Static::pageheap_lock());
uint64_t thread_bytes = 0;
ThreadCache::GetThreadStats(&thread_bytes, class_count);
}
prev_class_size = 0;
for (int cl = 1; cl < kNumClasses; ++cl) {
MallocExtension::FreeListInfo i;
i.min_object_size = prev_class_size + 1;
i.max_object_size = Static::sizemap()->ByteSizeForClass(cl);
i.total_bytes_free =
class_count[cl] * Static::sizemap()->ByteSizeForClass(cl);
i.type = kThreadCacheType;
v->push_back(i);
}
// append page heap info
int64 page_count_normal[kMaxPages];
int64 page_count_returned[kMaxPages];
int64 span_count_normal;
int64 span_count_returned;
{
SpinLockHolder h(Static::pageheap_lock());
Static::pageheap()->GetClassSizes(page_count_normal,
page_count_returned,
&span_count_normal,
&span_count_returned);
}
// spans: mapped
MallocExtension::FreeListInfo span_info;
span_info.type = kLargeSpanType;
span_info.max_object_size = (numeric_limits<size_t>::max)();
span_info.min_object_size = kMaxPages << kPageShift;
span_info.total_bytes_free = span_count_normal << kPageShift;
v->push_back(span_info);
// spans: unmapped
span_info.type = kLargeUnmappedSpanType;
span_info.total_bytes_free = span_count_returned << kPageShift;
v->push_back(span_info);
for (int s = 1; s < kMaxPages; s++) {
MallocExtension::FreeListInfo i;
i.max_object_size = (s << kPageShift);
i.min_object_size = ((s - 1) << kPageShift);
i.type = kPageHeapType;
i.total_bytes_free = (s << kPageShift) * page_count_normal[s];
v->push_back(i);
i.type = kPageHeapUnmappedType;
i.total_bytes_free = (s << kPageShift) * page_count_returned[s];
v->push_back(i);
}
}
};
// The constructor allocates an object to ensure that initialization

View File

@ -259,7 +259,10 @@ TEST(DebugAllocationTest, GetAllocatedSizeTest) {
}
TEST(DebugAllocationTest, HugeAlloc) {
const size_t kTooBig = ~static_cast<size_t>(0);
// This must not be a const variable so it doesn't form an
// integral-constant-expression which can be *statically* rejected by the
// compiler as too large for the allocation.
size_t kTooBig = ~static_cast<size_t>(0);
void* a = NULL;
char* b = NULL;
@ -273,8 +276,9 @@ TEST(DebugAllocationTest, HugeAlloc) {
EXPECT_EQ(NULL, b);
// kAlsoTooBig is small enough not to get caught by debugallocation's check,
// but will still fall through to tcmalloc's check.
const size_t kAlsoTooBig = kTooBig - 1024;
// but will still fall through to tcmalloc's check. This must also be
// a non-const variable. See kTooBig for more details.
size_t kAlsoTooBig = kTooBig - 1024;
a = malloc(kAlsoTooBig);
EXPECT_EQ(NULL, a);

View File

@ -39,6 +39,8 @@
#include <google/malloc_extension.h>
#include <google/malloc_extension_c.h>
using STL_NAMESPACE::vector;
int main(int argc, char** argv) {
void* a = malloc(1000);
@ -70,6 +72,30 @@ int main(int argc, char** argv) {
ASSERT_LE(MallocExtension_GetAllocatedSize(a), 5000);
ASSERT_GE(MallocExtension_GetEstimatedAllocatedSize(1000), 1000);
// test invariant: size of freelist = heap_size - allocated_bytes
free(malloc(32000));
size_t heap_size = 0;
size_t allocated = 0;
ASSERT_TRUE(MallocExtension::instance()->GetNumericProperty(
"generic.current_allocated_bytes", &allocated));
ASSERT_TRUE(MallocExtension::instance()->GetNumericProperty(
"generic.heap_size", &heap_size));
vector<MallocExtension::FreeListInfo> info;
MallocExtension::instance()->GetFreeListSizes(&info);
ASSERT_GE(info.size(), 0);
int64 free_bytes = 0;
for (vector<MallocExtension::FreeListInfo>::const_iterator it = info.begin();
it != info.end();
++it) {
free_bytes += it->total_bytes_free;
}
// don't expect an exact equality since the calls to query the heap
// themselves free and allocate memory
size_t error = abs((heap_size - allocated) - free_bytes);
ASSERT_LT(error, 0.15 * heap_size);
free(a);
printf("DONE\n");

View File

@ -45,6 +45,8 @@
using std::string;
extern "C" void* AllocateAllocate() ATTRIBUTE_NOINLINE;
extern "C" void* AllocateAllocate() {
// The VLOG's are mostly to discourage inlining
VLOG(1, "Allocating some more");

View File

@ -81,13 +81,13 @@ mkdir "$OUTDIR" || die "Unable to create $OUTDIR"
echo "Testing heap output..."
"$PPROF" --text "$SAMPLING_TEST_BINARY" "$OUTDIR/out.heap" \
| grep '^ *[5-9][0-9]\.[0-9][ 0-9.%]*_*AllocateAllocate' >/dev/null \
| grep '[5-9][0-9]\.[0-9][ 0-9.%]*_*AllocateAllocate' >/dev/null \
|| die "$PPROF" --text "$SAMPLING_TEST_BINARY" "$OUTDIR/out.heap"
echo "OK"
echo "Testing growth output..."
"$PPROF" --text "$SAMPLING_TEST_BINARY" "$OUTDIR/out.growth" \
| grep '^ *[5-9][0-9]\.[0-9][ 0-9.%]*_*AllocateAllocate' >/dev/null \
| grep '[5-9][0-9]\.[0-9][ 0-9.%]*_*AllocateAllocate' >/dev/null \
|| die "$PPROF" --text "$SAMPLING_TEST_BINARY" "$OUTDIR/out.growth"
echo "OK"

View File

@ -38,7 +38,9 @@
#include <inttypes.h> // another place uintptr_t might be defined
#endif
#include <sys/types.h>
#include <algorithm>
#include "base/logging.h"
#include "common.h"
#include "system-alloc.h"
class ArraySysAllocator : public SysAllocator {
@ -98,6 +100,18 @@ static void TestBasicInvoked() {
CHECK(a.invoked_);
}
#if 0 // could port this to various OSs, but won't bother for now
TEST(AddressBits, CpuVirtualBits) {
// Check that kAddressBits is as least as large as either the number of bits
// in a pointer or as the number of virtual bits handled by the processor.
// To be effective this test must be run on each processor model.
const int kPointerBits = 8 * sizeof(void*);
const int kImplementedVirtualBits = NumImplementedVirtualBits();
CHECK_GE(kAddressBits, min(kImplementedVirtualBits, kPointerBits));
}
#endif
int main(int argc, char** argv) {
TestBasicInvoked();

View File

@ -100,17 +100,12 @@
# define cfree free // don't bother to try to test these obsolete fns
# define valloc malloc
# define pvalloc malloc
# ifdef PERFTOOLS_NO_ALIGNED_MALLOC
# define _aligned_malloc(size, alignment) malloc(size)
# else
# include <malloc.h> // for _aligned_malloc
# endif
# define memalign(alignment, size) _aligned_malloc(size, alignment)
// Assume if we fail, it's because of out-of-memory.
// Note, this isn't a perfect analogue: we don't enforce constraints on "align"
// I'd like to map posix_memalign to _aligned_malloc, but _aligned_malloc
// must be paired with _aligned_free (not normal free), which is too
// invasive a change to how we allocate memory here. So just bail
# include <errno.h>
# define posix_memalign(pptr, align, size) \
((*(pptr)=_aligned_malloc(size, align)) ? 0 : ENOMEM)
# define memalign(alignment, size) malloc(size)
# define posix_memalign(pptr, align, size) ((*(pptr)=malloc(size)) ? 0 : ENOMEM)
#endif
// On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old
@ -1033,6 +1028,14 @@ static int RunAllTests(int argc, char** argv) {
free(p1);
VerifyDeleteHookWasCalled();
// Windows has _aligned_malloc. Let's test that that's captured too.
#if (defined(_MSC_VER) || defined(__MINGW32__)) && !defined(PERFTOOLS_NO_ALIGNED_MALLOC)
p1 = _aligned_malloc(sizeof(p1) * 2, 64);
VerifyNewHookWasCalled();
_aligned_free(p1);
VerifyDeleteHookWasCalled();
#endif
p1 = valloc(60);
VerifyNewHookWasCalled();
free(p1);

View File

@ -92,7 +92,7 @@
#undef HAVE_LINUX_PTRACE_H
/* Define to 1 if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H
#define HAVE_MALLOC_H 1
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H

View File

@ -175,7 +175,7 @@ class LibcInfo {
kNew, kNewArray, kDelete, kDeleteArray,
kNewNothrow, kNewArrayNothrow, kDeleteNothrow, kDeleteArrayNothrow,
// These are windows-only functions from malloc.h
k_Msize, k_Expand, k_Aligned_malloc, k_Aligned_free,
k_Msize, k_Expand,
kNumFunctions
};
@ -274,12 +274,12 @@ template<int> class LibcInfoWithPatchFunctions : public LibcInfo {
const std::nothrow_t&) __THROW;
static size_t Perftools__msize(void *ptr) __THROW;
static void* Perftools__expand(void *ptr, size_t size) __THROW;
static void* Perftools__aligned_malloc(size_t size, size_t alignment) __THROW;
static void Perftools__aligned_free(void *ptr) __THROW;
// malloc.h also defines these functions:
// _aligned_malloc, _aligned_free,
// _recalloc, _aligned_offset_malloc, _aligned_realloc, _aligned_recalloc
// _aligned_offset_realloc, _aligned_offset_recalloc, _malloca, _freea
// But they seem pretty obscure, and I'm fine not overriding them for now.
// It may be they all call into malloc/free anyway.
};
// This is a subset of MODDULEENTRY32, that we need for patching.
@ -300,10 +300,19 @@ struct ModuleEntryCopy {
ModuleEntryCopy(const MODULEINFO& mi) {
this->modBaseAddr = mi.lpBaseOfDll;
this->modBaseSize = mi.SizeOfImage;
for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++)
rgProcAddresses[i] = (GenericFnPtr)::GetProcAddress(
LPVOID modEndAddr = (char*)mi.lpBaseOfDll + mi.SizeOfImage;
for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++) {
FARPROC target = ::GetProcAddress(
reinterpret_cast<const HMODULE>(mi.lpBaseOfDll),
LibcInfo::function_name(i));
// Sometimes a DLL forwards a function to a function in another
// DLL. We don't want to patch those forwarded functions --
// they'll get patched when the other DLL is processed.
if (target >= modBaseAddr && target < modEndAddr)
rgProcAddresses[i] = (GenericFnPtr)target;
else
rgProcAddresses[i] = (GenericFnPtr)NULL;
}
}
};
@ -390,7 +399,7 @@ const char* const LibcInfo::function_name_[] = {
NULL, // kMangledNewArrayNothrow,
NULL, // kMangledDeleteNothrow,
NULL, // kMangledDeleteArrayNothrow,
"_msize", "_expand", "_aligned_malloc", "_aligned_free",
"_msize", "_expand",
};
// For mingw, I can't patch the new/delete here, because the
@ -421,14 +430,6 @@ const GenericFnPtr LibcInfo::static_fn_[] = {
#endif
(GenericFnPtr)&::_msize,
(GenericFnPtr)&::_expand,
#ifdef PERFTOOLS_NO_ALIGNED_MALLOC // for older versions of mingw
// _aligned_malloc isn't always available in mingw, so don't try to patch.
(GenericFnPtr)NULL,
(GenericFnPtr)NULL,
#else
(GenericFnPtr)&::_aligned_malloc,
(GenericFnPtr)&::_aligned_free,
#endif
};
template<int T> GenericFnPtr LibcInfoWithPatchFunctions<T>::origstub_fn_[] = {
@ -451,8 +452,6 @@ const GenericFnPtr LibcInfoWithPatchFunctions<T>::perftools_fn_[] = {
(GenericFnPtr)&Perftools_deletearray_nothrow,
(GenericFnPtr)&Perftools__msize,
(GenericFnPtr)&Perftools__expand,
(GenericFnPtr)&Perftools__aligned_malloc,
(GenericFnPtr)&Perftools__aligned_free,
};
/*static*/ WindowsInfo::FunctionInfo WindowsInfo::function_info_[] = {
@ -908,21 +907,6 @@ void* LibcInfoWithPatchFunctions<T>::Perftools__expand(void *ptr,
return NULL;
}
template<int T>
void* LibcInfoWithPatchFunctions<T>::Perftools__aligned_malloc(size_t size,
size_t alignment)
__THROW {
void* result = do_memalign_or_cpp_memalign(alignment, size);
MallocHook::InvokeNewHook(result, size);
return result;
}
template<int T>
void LibcInfoWithPatchFunctions<T>::Perftools__aligned_free(void *ptr) __THROW {
MallocHook::InvokeDeleteHook(ptr);
do_free_with_callback(ptr, (void (*)(void*))origstub_fn_[k_Aligned_free]);
}
LPVOID WINAPI WindowsInfo::Perftools_HeapAlloc(HANDLE hHeap, DWORD dwFlags,
DWORD_PTR dwBytes) {
LPVOID result = ((LPVOID (WINAPI *)(HANDLE, DWORD, DWORD_PTR))

View File

@ -83,6 +83,18 @@ extern "C" PERFTOOLS_DLL_DECL void* __sbrk(ptrdiff_t increment) {
return NULL;
}
// We need to write to 'stderr' without having windows allocate memory.
// The safest way is via a low-level call like WriteConsoleA(). But
// even then we need to be sure to print in small bursts so as to not
// require memory allocation.
extern "C" PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len) {
// Looks like windows allocates for writes of >80 bytes
for (int i = 0; i < len; i += 80) {
write(STDERR_FILENO, buf + i, std::min(80, len - i));
}
}
// -----------------------------------------------------------------------
// Threads code

View File

@ -277,6 +277,8 @@ enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
#define O_RDONLY _O_RDONLY
#endif
extern "C" PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len);
// ----------------------------------- SYSTEM/PROCESS
typedef int pid_t;
#define getpid _getpid

View File

@ -195,6 +195,23 @@
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\spinlock_internal.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\windows\port.cc">
<FileConfiguration
@ -236,13 +253,37 @@
RelativePath="..\..\src\base\logging.h">
</File>
<File
RelativePath="..\..\src\base\spinlock.h">
RelativePath="..\..\src\base\atomicops-internals-arm-gcc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-linuxppc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-macosx.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86.h">
</File>
<File
RelativePath="..\..\src\base\atomicops.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
RelativePath="..\..\src\base\spinlock.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_internal.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_linux-inl.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_posix-inl.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_win32-inl.h">
</File>
<File
RelativePath="..\..\src\base\cycleclock.h">

View File

@ -554,6 +554,23 @@
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\spinlock_internal.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\sysinfo.cc">
<FileConfiguration
@ -639,13 +656,37 @@
RelativePath="..\..\src\base\low_level_alloc.h">
</File>
<File
RelativePath="..\..\src\base\spinlock.h">
RelativePath="..\..\src\base\atomicops-internals-arm-gcc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-linuxppc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-macosx.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86.h">
</File>
<File
RelativePath="..\..\src\base\atomicops.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
RelativePath="..\..\src\base\spinlock.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_internal.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_linux-inl.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_posix-inl.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_win32-inl.h">
</File>
<File
RelativePath="..\..\src\google\malloc_extension.h">

View File

@ -195,6 +195,23 @@
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\spinlock_internal.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\tests\low_level_alloc_unittest.cc">
<FileConfiguration
@ -275,13 +292,37 @@
RelativePath="..\..\src\base\commandlineflags.h">
</File>
<File
RelativePath="..\..\src\base\spinlock.h">
RelativePath="..\..\src\base\atomicops-internals-arm-gcc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-linuxppc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-macosx.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86.h">
</File>
<File
RelativePath="..\..\src\base\atomicops.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
RelativePath="..\..\src\base\spinlock.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_internal.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_linux-inl.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_posix-inl.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_win32-inl.h">
</File>
<File
RelativePath="..\..\src\windows\config.h">

View File

@ -144,13 +144,37 @@
RelativePath="..\..\src\base\logging.h">
</File>
<File
RelativePath="..\..\src\base\spinlock.h">
RelativePath="..\..\src\base\atomicops-internals-arm-gcc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-linuxppc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-macosx.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86.h">
</File>
<File
RelativePath="..\..\src\base\atomicops.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
RelativePath="..\..\src\base\spinlock.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_internal.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_linux-inl.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_posix-inl.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_win32-inl.h">
</File>
<File
RelativePath="..\..\src\base\cycleclock.h">

View File

@ -598,6 +598,25 @@
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\spinlock_internal.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D PERFTOOLS_DLL_DECL="
AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D PERFTOOLS_DLL_DECL="
AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\sysinfo.cc">
<FileConfiguration
@ -728,13 +747,37 @@
RelativePath="..\..\src\base\low_level_alloc.h">
</File>
<File
RelativePath="..\..\src\base\spinlock.h">
RelativePath="..\..\src\base\atomicops-internals-arm-gcc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-linuxppc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-macosx.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86.h">
</File>
<File
RelativePath="..\..\src\base\atomicops.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
RelativePath="..\..\src\base\spinlock.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_internal.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_linux-inl.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_posix-inl.h">
</File>
<File
RelativePath="..\..\src\base\spinlock_win32-inl.h">
</File>
<File
RelativePath="..\..\src\google\malloc_extension.h">