summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcsilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50>2008-06-14 02:30:53 +0000
committercsilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50>2008-06-14 02:30:53 +0000
commit100e657c5092bc274424286a728db5116a4bbc54 (patch)
tree3a688677e9366e218b25651d0a75567e8ecacf4f
parent7ec719093b1c9fda979ba0d07eed288e2a7c3c9b (diff)
downloadgperftools-100e657c5092bc274424286a728db5116a4bbc54.tar.gz
Mon Jun 9 16:47:03 2008 Google Inc. <opensource@google.com>
* google-perftools: version 0.98 release * Add ProfilerStartWithOptions() (cgd) * Change tcmalloc_minimal to not do any stack-tracing at all (csilvers) * Prefer mmap to sbrk for 64-buit debug mode (sanjay) * Fix accounting for some tcmalloc stats (sanjay) * Use setrlimit() to keep unittests from killing the machine (odo) * Fix a bug when sbrk-ing near address 4G (csilvers) * Make MallocHook thread-safe (jyasskin) * Fix windows build for MemoryBarrier (jyasskin) * Fix CPU-profiler docs to mention correct libs (csilvers) * Fix for GetHeapProfile() when heap-profiling is off (maxim) * Avoid realloc resizing ping-pongs using hysteresis (csilvers) * Add --callgrind output support to pprof (klimek) * Fix profiler.h and heap-profiler.h to be C-compatible (csilvers) * Break malloc_hook.h into two parts to reduce dependencies (csilvers) * Better handle systems that don't implement mmap (csilvers) * PORTING: disable system_alloc_unittest for msvc (csilvers) * PORTING: Makefile tweaks to build better on cygwin (csilvers) git-svn-id: http://gperftools.googlecode.com/svn/trunk@52 6b5cf1ce-ec42-a296-1ba9-69fdba395a50
-rw-r--r--ChangeLog21
-rw-r--r--Makefile.am33
-rw-r--r--Makefile.in433
-rw-r--r--README.windows3
-rwxr-xr-xconfigure1049
-rw-r--r--configure.ac21
-rw-r--r--doc/cpuprofile.html25
-rwxr-xr-xgoogle-perftools.sln9
-rw-r--r--m4/acx_pthread.m4218
-rw-r--r--packages/deb/changelog6
-rw-r--r--src/addressmap-inl.h6
-rw-r--r--src/base/atomicops-internals-linuxppc.h6
-rw-r--r--src/base/atomicops-internals-macosx.h6
-rw-r--r--src/base/atomicops-internals-x86-msvc.h58
-rw-r--r--src/base/atomicops-internals-x86.cc4
-rw-r--r--src/base/atomicops-internals-x86.h6
-rw-r--r--src/base/atomicops.h14
-rw-r--r--src/base/commandlineflags.h6
-rw-r--r--src/base/cycleclock.h6
-rw-r--r--src/base/dynamic_annotations.cc59
-rw-r--r--src/base/dynamic_annotations.h125
-rw-r--r--src/base/linux_syscall_support.h199
-rw-r--r--src/base/low_level_alloc.cc2
-rw-r--r--src/base/low_level_alloc.h8
-rw-r--r--src/base/simple_mutex.h11
-rw-r--r--src/base/spinlock.h6
-rw-r--r--src/base/stl_allocator.h10
-rw-r--r--src/base/sysinfo.h4
-rw-r--r--src/config.h.in3
-rw-r--r--src/getpc.h6
-rw-r--r--src/google/heap-checker.h11
-rw-r--r--src/google/heap-profiler.h148
-rw-r--r--src/google/malloc_extension.h8
-rw-r--r--src/google/malloc_hook.h114
-rw-r--r--src/google/profiler.h272
-rw-r--r--src/google/stacktrace.h9
-rw-r--r--src/heap-checker.cc38
-rw-r--r--src/heap-profile-table.h8
-rw-r--r--src/heap-profiler.cc23
-rw-r--r--src/internal_logging.h6
-rw-r--r--src/malloc_hook-inl.h161
-rw-r--r--src/malloc_hook.cc82
-rw-r--r--src/maybe_threads.cc8
-rw-r--r--src/maybe_threads.h6
-rw-r--r--src/memory_region_map.cc3
-rw-r--r--src/memory_region_map.h17
-rw-r--r--src/packed-cache-inl.h6
-rw-r--r--src/pagemap.h23
-rwxr-xr-xsrc/pprof76
-rw-r--r--src/profiledata.h6
-rw-r--r--src/profiler.cc31
-rw-r--r--src/stacktrace_generic-inl.h2
-rw-r--r--src/system-alloc.cc52
-rw-r--r--src/system-alloc.h6
-rw-r--r--src/tcmalloc.cc135
-rwxr-xr-xsrc/tests/maybe_threads_unittest.sh8
-rw-r--r--src/tests/memalign_unittest.cc9
-rw-r--r--src/tests/tcmalloc_unittest.cc41
-rw-r--r--src/tests/testutil.cc39
-rw-r--r--src/tests/testutil.h12
-rw-r--r--src/windows/config.h11
-rw-r--r--src/windows/mingw.h6
-rw-r--r--src/windows/mini_disassembler.h6
-rw-r--r--src/windows/mini_disassembler_types.h6
-rw-r--r--src/windows/patch_functions.cc1
-rw-r--r--src/windows/port.h16
-rw-r--r--src/windows/preamble_patcher.h6
-rwxr-xr-xvsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj9
-rwxr-xr-xvsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj9
-rwxr-xr-xvsprojects/memalign_unittest/memalign_unittest.vcproj20
-rwxr-xr-xvsprojects/system_alloc_unittest/system_alloc_unittest.vcproj150
-rwxr-xr-xvsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj9
72 files changed, 2536 insertions, 1436 deletions
diff --git a/ChangeLog b/ChangeLog
index 37bafc8..fa49279 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+Mon Jun 9 16:47:03 2008 Google Inc. <opensource@google.com>
+
+ * google-perftools: version 0.98 release
+ * Add ProfilerStartWithOptions() (cgd)
+ * Change tcmalloc_minimal to not do any stack-tracing at all (csilvers)
+ * Prefer mmap to sbrk for 64-buit debug mode (sanjay)
+ * Fix accounting for some tcmalloc stats (sanjay)
+ * Use setrlimit() to keep unittests from killing the machine (odo)
+ * Fix a bug when sbrk-ing near address 4G (csilvers)
+ * Make MallocHook thread-safe (jyasskin)
+ * Fix windows build for MemoryBarrier (jyasskin)
+ * Fix CPU-profiler docs to mention correct libs (csilvers)
+ * Fix for GetHeapProfile() when heap-profiling is off (maxim)
+ * Avoid realloc resizing ping-pongs using hysteresis (csilvers)
+ * Add --callgrind output support to pprof (klimek)
+ * Fix profiler.h and heap-profiler.h to be C-compatible (csilvers)
+ * Break malloc_hook.h into two parts to reduce dependencies (csilvers)
+ * Better handle systems that don't implement mmap (csilvers)
+ * PORTING: disable system_alloc_unittest for msvc (csilvers)
+ * PORTING: Makefile tweaks to build better on cygwin (csilvers)
+
Mon Apr 21 15:20:52 2008 Google Inc. <opensource@google.com>
* google-perftools: version 0.97 release
diff --git a/Makefile.am b/Makefile.am
index e13086f..65399cb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -149,6 +149,7 @@ WINDOWS_PROJECTS += vsprojects/low_level_alloc_unittest/low_level_alloc_unittest
LOW_LEVEL_ALLOC_UNITTEST_INCLUDES = src/base/low_level_alloc.h \
src/base/basictypes.h \
src/google/malloc_hook.h \
+ src/malloc_hook-inl.h \
$(SPINLOCK_INCLUDES) \
$(LOGGING_INCLUDES)
low_level_alloc_unittest_SOURCES = src/base/low_level_alloc.cc \
@@ -236,6 +237,7 @@ S_TCMALLOC_MINIMAL_INCLUDES = src/internal_logging.h \
src/base/commandlineflags.h \
src/base/basictypes.h \
src/pagemap.h \
+ src/malloc_hook-inl.h \
src/maybe_threads.h
SG_TCMALLOC_MINIMAL_INCLUDES = src/google/malloc_hook.h \
src/google/malloc_extension.h \
@@ -254,10 +256,11 @@ libtcmalloc_minimal_la_SOURCES = src/internal_logging.cc \
src/malloc_extension.cc \
$(MAYBE_THREADS_CC) \
$(TCMALLOC_MINIMAL_INCLUDES)
-libtcmalloc_minimal_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS)
+# We #define NO_TCMALLOC_SAMPLES, since sampling is turned off for _minimal.
+libtcmalloc_minimal_la_CXXFLAGS = -DNO_TCMALLOC_SAMPLES \
+ $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS)
libtcmalloc_minimal_la_LDFLAGS = $(PTHREAD_CFLAGS)
-libtcmalloc_minimal_la_LIBADD = $(PTHREAD_LIBS) \
- libstacktrace.la
+libtcmalloc_minimal_la_LIBADD = $(PTHREAD_LIBS) $(LIBSPINLOCK)
LIBTCMALLOC_MINIMAL = libtcmalloc_minimal.la
@@ -268,6 +271,7 @@ LIBTCMALLOC_MINIMAL = libtcmalloc_minimal.la
## TESTS += malloc_unittest
## MALLOC_UNITEST_INCLUDES = src/google/malloc_extension.h \
## src/google/malloc_hook.h \
+## src/malloc_hook-inl.h \
## src/base/basictypes.h \
## src/maybe_threads.h
## malloc_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \
@@ -322,7 +326,6 @@ addressmap_unittest_LDADD = liblogging.la
if !MINGW
TESTS += system_alloc_unittest
-WINDOWS_PROJECTS += vsprojects/system_alloc_unittest/system_alloc_unittest.vcproj
system_alloc_unittest_SOURCES = src/config_for_unittests.h \
src/tests/system-alloc_unittest.cc
system_alloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
@@ -356,7 +359,8 @@ TESTS += memalign_unittest
WINDOWS_PROJECTS += vsprojects/memalign_unittest/memalign_unittest.vcproj
memalign_unittest_SOURCES = src/tests/memalign_unittest.cc \
src/config_for_unittests.h \
- src/tcmalloc.h
+ src/tcmalloc.h \
+ src/tests/testutil.h src/tests/testutil.cc
memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
memalign_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
memalign_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
@@ -441,6 +445,7 @@ S_TCMALLOC_INCLUDES = src/internal_logging.h \
src/system-alloc.h \
src/pagemap.h \
src/addressmap-inl.h \
+ src/malloc_hook-inl.h \
src/packed-cache-inl.h \
src/heap-profile-table.h \
src/base/basictypes.h \
@@ -503,17 +508,24 @@ tcmalloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
tcmalloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
tcmalloc_unittest_LDADD = $(LIBTCMALLOC) liblogging.la $(PTHREAD_LIBS)
-# This makes sure it's safe to link in both tcmalloc and tcmalloc_minimal.
-# (One would never do this on purpose, but perhaps by accident...)
-# We also link in libprofiler to make sure that works too
+# This makes sure it's safe to link in both tcmalloc and
+# tcmalloc_minimal. (One would never do this on purpose, but perhaps
+# by accident...) When we can compile libprofiler, we also link it in
+# to make sure that works too.
+
TESTS += tcmalloc_both_unittest
tcmalloc_both_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \
src/tests/testutil.h src/tests/testutil.cc \
$(TCMALLOC_UNITTEST_INCLUDES)
tcmalloc_both_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
tcmalloc_both_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
+if HAS_PC
tcmalloc_both_unittest_LDADD = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \
libprofiler.la liblogging.la $(PTHREAD_LIBS)
+else
+tcmalloc_both_unittest_LDADD = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \
+ liblogging.la $(PTHREAD_LIBS)
+endif !HAS_PC
TESTS += tcmalloc_large_unittest
tcmalloc_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc
@@ -583,8 +595,10 @@ endif !MINGW
### ------- CPU profiler
-# The CPU profiler doesn't work on windows yet
+# The CPU profiler doesn't work on windows yet. It also doesn't work
+# if there's no way to get the PC.
if !MINGW
+if HAS_PC
### The header files we use. We divide into categories based on directory
S_CPU_PROFILER_INCLUDES = src/profiledata.h \
@@ -675,6 +689,7 @@ dist_doc_DATA += doc/cpuprofile.html \
doc/pprof-vsnprintf-big.gif \
doc/pprof-vsnprintf.gif
+endif HAS_PC
endif !MINGW
## ^^^^ END OF RULES TO MAKE YOUR LIBRARIES, BINARIES, AND UNITTESTS
diff --git a/Makefile.in b/Makefile.in
index 888586b..f34f0e4 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -52,7 +52,7 @@ target_triplet = @target@
# These are x86-specific, having to do with frame-pointers
@ENABLE_FRAME_POINTERS_TRUE@@X86_64_TRUE@am__append_2 = -fno-omit-frame-pointer
@ENABLE_FRAME_POINTERS_FALSE@@X86_64_TRUE@am__append_3 = -DNO_FRAME_POINTER
-noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_5)
+noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_7)
@MINGW_TRUE@am__append_4 = libwindows.la
@MINGW_FALSE@am__append_5 = libspinlock.la
@MINGW_FALSE@am__append_6 = atomicops_unittest
@@ -63,55 +63,64 @@ noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_5)
@MINGW_FALSE@am__append_7 = PPROF_PATH=$(top_srcdir)/src/pprof \
@MINGW_FALSE@ BINDIR=. TMPDIR=/tmp/perftools
@MINGW_FALSE@am__append_8 = system_alloc_unittest
-@MINGW_FALSE@am__append_9 = vsprojects/system_alloc_unittest/system_alloc_unittest.vcproj
EXTRA_PROGRAMS = ptmalloc_unittest1$(EXEEXT) \
ptmalloc_unittest2$(EXEEXT)
-@MINGW_FALSE@am__append_10 = $(SG_TCMALLOC_INCLUDES) \
-@MINGW_FALSE@ $(SG_CPU_PROFILER_INCLUDES)
+@MINGW_FALSE@am__append_9 = $(SG_TCMALLOC_INCLUDES)
### Making the library
-
-### Making the library
-@MINGW_FALSE@am__append_11 = libtcmalloc.la libprofiler.la
+@MINGW_FALSE@am__append_10 = libtcmalloc.la
### Unittests
-# This makes sure it's safe to link in both tcmalloc and tcmalloc_minimal.
-# (One would never do this on purpose, but perhaps by accident...)
-# We also link in libprofiler to make sure that works too
-
-### Unittests
-@MINGW_FALSE@am__append_12 = tcmalloc_unittest tcmalloc_both_unittest \
+# This makes sure it's safe to link in both tcmalloc and
+# tcmalloc_minimal. (One would never do this on purpose, but perhaps
+# by accident...) When we can compile libprofiler, we also link it in
+# to make sure that works too.
+@MINGW_FALSE@am__append_11 = tcmalloc_unittest tcmalloc_both_unittest \
@MINGW_FALSE@ tcmalloc_large_unittest heap-profiler_unittest.sh \
@MINGW_FALSE@ heap-checker_unittest.sh \
-@MINGW_FALSE@ heap-checker-death_unittest.sh getpc_test \
-@MINGW_FALSE@ profiledata_unittest profiler_unittest.sh
-@MINGW_FALSE@am__append_13 = $(heap_profiler_unittest_sh_SOURCES) \
+@MINGW_FALSE@ heap-checker-death_unittest.sh
+@MINGW_FALSE@am__append_12 = $(heap_profiler_unittest_sh_SOURCES) \
@MINGW_FALSE@ $(heap_checker_unittest_sh_SOURCES) \
-@MINGW_FALSE@ $(top_srcdir)/$(heap_checker_death_unittest_sh_SOURCES) \
-@MINGW_FALSE@ $(profiler_unittest_sh_SOURCES)
+@MINGW_FALSE@ $(top_srcdir)/$(heap_checker_death_unittest_sh_SOURCES)
# These are sub-programs used by heap-profiler_unittest.sh
# These are sub-programs used by heap-checker_unittest.sh
+@MINGW_FALSE@am__append_13 = heap-profiler_unittest \
+@MINGW_FALSE@ heap-checker_unittest
+
+### Documentation (above and beyond tcmalloc_minimal documentation)
+@MINGW_FALSE@am__append_14 = doc/heapprofile.html \
+@MINGW_FALSE@ doc/heap-example1.png \
+@MINGW_FALSE@ doc/heap_checker.html
+
+@HAS_PC_TRUE@@MINGW_FALSE@am__append_15 = $(SG_CPU_PROFILER_INCLUDES)
+
+### Making the library
+@HAS_PC_TRUE@@MINGW_FALSE@am__append_16 = libprofiler.la
+
+### Unittests
+@HAS_PC_TRUE@@MINGW_FALSE@am__append_17 = getpc_test \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiledata_unittest \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiler_unittest.sh
+@HAS_PC_TRUE@@MINGW_FALSE@am__append_18 = $(profiler_unittest_sh_SOURCES)
# These are sub-programs used by profiler_unittest.sh
-@MINGW_FALSE@am__append_14 = heap-profiler_unittest \
-@MINGW_FALSE@ heap-checker_unittest profiler1_unittest \
-@MINGW_FALSE@ profiler2_unittest profiler3_unittest \
-@MINGW_FALSE@ profiler4_unittest
+@HAS_PC_TRUE@@MINGW_FALSE@am__append_19 = profiler1_unittest profiler2_unittest profiler3_unittest \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiler4_unittest
-### Documentation (above and beyond tcmalloc_minimal documentation)
+@HAS_PC_FALSE@profiler2_unittest_DEPENDENCIES =
+@MINGW_TRUE@profiler2_unittest_DEPENDENCIES =
### Documentation
-@MINGW_FALSE@am__append_15 = doc/heapprofile.html \
-@MINGW_FALSE@ doc/heap-example1.png doc/heap_checker.html \
-@MINGW_FALSE@ doc/cpuprofile.html \
-@MINGW_FALSE@ doc/cpuprofile-fileformat.html \
-@MINGW_FALSE@ doc/pprof-test-big.gif doc/pprof-test.gif \
-@MINGW_FALSE@ doc/pprof-vsnprintf-big.gif \
-@MINGW_FALSE@ doc/pprof-vsnprintf.gif
-@MINGW_TRUE@profiler2_unittest_DEPENDENCIES =
+@HAS_PC_TRUE@@MINGW_FALSE@am__append_20 = doc/cpuprofile.html \
+@HAS_PC_TRUE@@MINGW_FALSE@ doc/cpuprofile-fileformat.html \
+@HAS_PC_TRUE@@MINGW_FALSE@ doc/pprof-test-big.gif \
+@HAS_PC_TRUE@@MINGW_FALSE@ doc/pprof-test.gif \
+@HAS_PC_TRUE@@MINGW_FALSE@ doc/pprof-vsnprintf-big.gif \
+@HAS_PC_TRUE@@MINGW_FALSE@ doc/pprof-vsnprintf.gif
+
DIST_COMMON = README $(am__configure_deps) $(am__dist_doc_DATA_DIST) \
$(am__googleinclude_HEADERS_DIST) $(dist_man_MANS) \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
@@ -151,7 +160,8 @@ am__objects_1 =
am_liblogging_la_OBJECTS = logging.lo dynamic_annotations.lo \
$(am__objects_1)
liblogging_la_OBJECTS = $(am_liblogging_la_OBJECTS)
-@MINGW_FALSE@libprofiler_la_DEPENDENCIES = libstacktrace.la
+@HAS_PC_TRUE@@MINGW_FALSE@libprofiler_la_DEPENDENCIES = \
+@HAS_PC_TRUE@@MINGW_FALSE@ libstacktrace.la
am__libprofiler_la_SOURCES_DIST = src/profiler.cc src/profiledata.cc \
src/profiledata.h src/getpc.h src/base/basictypes.h \
src/base/commandlineflags.h src/base/googleinit.h \
@@ -163,12 +173,14 @@ am__libprofiler_la_SOURCES_DIST = src/profiler.cc src/profiledata.cc \
src/base/atomicops-internals-x86.h \
src/base/dynamic_annotations.h src/google/profiler.h \
src/google/stacktrace.h
-@MINGW_FALSE@am__objects_2 = $(am__objects_1) $(am__objects_1)
-@MINGW_FALSE@am__objects_3 = $(am__objects_2) $(am__objects_1)
-@MINGW_FALSE@am_libprofiler_la_OBJECTS = profiler.lo profiledata.lo \
-@MINGW_FALSE@ $(am__objects_3)
+@HAS_PC_TRUE@@MINGW_FALSE@am__objects_2 = $(am__objects_1) \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__objects_1)
+@HAS_PC_TRUE@@MINGW_FALSE@am__objects_3 = $(am__objects_2) \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__objects_1)
+@HAS_PC_TRUE@@MINGW_FALSE@am_libprofiler_la_OBJECTS = profiler.lo \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiledata.lo $(am__objects_3)
libprofiler_la_OBJECTS = $(am_libprofiler_la_OBJECTS)
-@MINGW_FALSE@am_libprofiler_la_rpath = -rpath $(libdir)
+@HAS_PC_TRUE@@MINGW_FALSE@am_libprofiler_la_rpath = -rpath $(libdir)
libspinlock_la_LIBADD =
am__libspinlock_la_SOURCES_DIST = src/base/spinlock.cc \
src/base/atomicops-internals-x86.cc src/base/spinlock.h \
@@ -203,13 +215,14 @@ am__libtcmalloc_la_SOURCES_DIST = src/internal_logging.cc \
src/heap-checker.cc src/base/linuxthreads.c \
src/base/thread_lister.c src/base/low_level_alloc.cc \
src/internal_logging.h src/system-alloc.h src/pagemap.h \
- src/addressmap-inl.h src/packed-cache-inl.h \
- src/heap-profile-table.h src/base/basictypes.h \
- src/base/commandlineflags.h src/base/googleinit.h \
- src/base/elfcore.h src/base/linux_syscall_support.h \
- src/base/linuxthreads.h src/base/thread_lister.h \
- src/base/sysinfo.h src/base/stl_allocator.h \
- src/maybe_threads.h src/base/spinlock.h src/base/atomicops.h \
+ src/addressmap-inl.h src/malloc_hook-inl.h \
+ src/packed-cache-inl.h src/heap-profile-table.h \
+ src/base/basictypes.h src/base/commandlineflags.h \
+ src/base/googleinit.h src/base/elfcore.h \
+ src/base/linux_syscall_support.h src/base/linuxthreads.h \
+ src/base/thread_lister.h src/base/sysinfo.h \
+ src/base/stl_allocator.h src/maybe_threads.h \
+ src/base/spinlock.h src/base/atomicops.h \
src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
@@ -220,6 +233,8 @@ am__libtcmalloc_la_SOURCES_DIST = src/internal_logging.cc \
src/heap-checker-bcad.cc
@MINGW_FALSE@am__objects_5 = libtcmalloc_la-system-alloc.lo
@MINGW_FALSE@am__objects_6 = libtcmalloc_la-maybe_threads.lo
+@MINGW_FALSE@am__objects_7 = $(am__objects_1) $(am__objects_1)
+@MINGW_FALSE@am__objects_8 = $(am__objects_7) $(am__objects_1)
@MINGW_FALSE@am_libtcmalloc_la_OBJECTS = \
@MINGW_FALSE@ libtcmalloc_la-internal_logging.lo \
@MINGW_FALSE@ $(am__objects_5) libtcmalloc_la-memfs_malloc.lo \
@@ -233,12 +248,12 @@ am__libtcmalloc_la_SOURCES_DIST = src/internal_logging.cc \
@MINGW_FALSE@ libtcmalloc_la-heap-checker.lo linuxthreads.lo \
@MINGW_FALSE@ thread_lister.lo \
@MINGW_FALSE@ libtcmalloc_la-low_level_alloc.lo \
-@MINGW_FALSE@ $(am__objects_3) \
+@MINGW_FALSE@ $(am__objects_8) \
@MINGW_FALSE@ libtcmalloc_la-heap-checker-bcad.lo
libtcmalloc_la_OBJECTS = $(am_libtcmalloc_la_OBJECTS)
@MINGW_FALSE@am_libtcmalloc_la_rpath = -rpath $(libdir)
libtcmalloc_minimal_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
- libstacktrace.la
+ $(am__DEPENDENCIES_2)
am__libtcmalloc_minimal_la_SOURCES_DIST = src/internal_logging.cc \
src/system-alloc.cc src/memfs_malloc.cc src/tcmalloc.cc \
src/malloc_hook.cc src/malloc_extension.cc \
@@ -248,20 +263,20 @@ am__libtcmalloc_minimal_la_SOURCES_DIST = src/internal_logging.cc \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
src/base/atomicops-internals-x86.h src/base/commandlineflags.h \
- src/base/basictypes.h src/pagemap.h src/maybe_threads.h \
- src/google/malloc_hook.h src/google/malloc_extension.h \
- src/google/stacktrace.h
-@MINGW_FALSE@am__objects_7 = libtcmalloc_minimal_la-system-alloc.lo
-@MINGW_FALSE@am__objects_8 = libtcmalloc_minimal_la-maybe_threads.lo
-am__objects_9 = $(am__objects_1)
-am__objects_10 = $(am__objects_9) $(am__objects_1)
+ src/base/basictypes.h src/pagemap.h src/malloc_hook-inl.h \
+ src/maybe_threads.h src/google/malloc_hook.h \
+ src/google/malloc_extension.h src/google/stacktrace.h
+@MINGW_FALSE@am__objects_9 = libtcmalloc_minimal_la-system-alloc.lo
+@MINGW_FALSE@am__objects_10 = libtcmalloc_minimal_la-maybe_threads.lo
+am__objects_11 = $(am__objects_1)
+am__objects_12 = $(am__objects_11) $(am__objects_1)
am_libtcmalloc_minimal_la_OBJECTS = \
- libtcmalloc_minimal_la-internal_logging.lo $(am__objects_7) \
+ libtcmalloc_minimal_la-internal_logging.lo $(am__objects_9) \
libtcmalloc_minimal_la-memfs_malloc.lo \
libtcmalloc_minimal_la-tcmalloc.lo \
libtcmalloc_minimal_la-malloc_hook.lo \
- libtcmalloc_minimal_la-malloc_extension.lo $(am__objects_8) \
- $(am__objects_10)
+ libtcmalloc_minimal_la-malloc_extension.lo $(am__objects_10) \
+ $(am__objects_12)
libtcmalloc_minimal_la_OBJECTS = $(am_libtcmalloc_minimal_la_OBJECTS)
libwindows_la_LIBADD =
am__libwindows_la_SOURCES_DIST = src/windows/port.h \
@@ -279,34 +294,36 @@ am__libwindows_la_SOURCES_DIST = src/windows/port.h \
libwindows_la_OBJECTS = $(am_libwindows_la_OBJECTS)
@MINGW_TRUE@am_libwindows_la_rpath =
@MINGW_FALSE@am__EXEEXT_1 = heap-profiler_unittest$(EXEEXT) \
-@MINGW_FALSE@ heap-checker_unittest$(EXEEXT) \
-@MINGW_FALSE@ profiler1_unittest$(EXEEXT) \
-@MINGW_FALSE@ profiler2_unittest$(EXEEXT) \
-@MINGW_FALSE@ profiler3_unittest$(EXEEXT) \
-@MINGW_FALSE@ profiler4_unittest$(EXEEXT)
-@MINGW_FALSE@am__EXEEXT_2 = atomicops_unittest$(EXEEXT)
-@MINGW_FALSE@am__EXEEXT_3 = system_alloc_unittest$(EXEEXT)
-@MINGW_FALSE@am__EXEEXT_4 = tcmalloc_unittest$(EXEEXT) \
+@MINGW_FALSE@ heap-checker_unittest$(EXEEXT)
+@HAS_PC_TRUE@@MINGW_FALSE@am__EXEEXT_2 = profiler1_unittest$(EXEEXT) \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiler2_unittest$(EXEEXT) \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiler3_unittest$(EXEEXT) \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiler4_unittest$(EXEEXT)
+@MINGW_FALSE@am__EXEEXT_3 = atomicops_unittest$(EXEEXT)
+@MINGW_FALSE@am__EXEEXT_4 = system_alloc_unittest$(EXEEXT)
+@MINGW_FALSE@am__EXEEXT_5 = tcmalloc_unittest$(EXEEXT) \
@MINGW_FALSE@ tcmalloc_both_unittest$(EXEEXT) \
@MINGW_FALSE@ tcmalloc_large_unittest$(EXEEXT) \
@MINGW_FALSE@ heap-profiler_unittest.sh$(EXEEXT) \
@MINGW_FALSE@ heap-checker_unittest.sh$(EXEEXT) \
-@MINGW_FALSE@ heap-checker-death_unittest.sh$(EXEEXT) \
-@MINGW_FALSE@ getpc_test$(EXEEXT) profiledata_unittest$(EXEEXT) \
-@MINGW_FALSE@ profiler_unittest.sh$(EXEEXT)
-am__EXEEXT_5 = low_level_alloc_unittest$(EXEEXT) $(am__EXEEXT_2) \
+@MINGW_FALSE@ heap-checker-death_unittest.sh$(EXEEXT)
+@HAS_PC_TRUE@@MINGW_FALSE@am__EXEEXT_6 = getpc_test$(EXEEXT) \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiledata_unittest$(EXEEXT) \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiler_unittest.sh$(EXEEXT)
+am__EXEEXT_7 = low_level_alloc_unittest$(EXEEXT) $(am__EXEEXT_3) \
stacktrace_unittest$(EXEEXT) \
tcmalloc_minimal_unittest$(EXEEXT) \
tcmalloc_minimal_large_unittest$(EXEEXT) \
maybe_threads_unittest.sh$(EXEEXT) \
- addressmap_unittest$(EXEEXT) $(am__EXEEXT_3) \
+ addressmap_unittest$(EXEEXT) $(am__EXEEXT_4) \
packed_cache_test$(EXEEXT) frag_unittest$(EXEEXT) \
markidle_unittest$(EXEEXT) memalign_unittest$(EXEEXT) \
- thread_dealloc_unittest$(EXEEXT) $(am__EXEEXT_4)
+ thread_dealloc_unittest$(EXEEXT) $(am__EXEEXT_5) \
+ $(am__EXEEXT_6)
PROGRAMS = $(noinst_PROGRAMS)
am_addressmap_unittest_OBJECTS = \
addressmap_unittest-addressmap_unittest.$(OBJEXT) \
- $(am__objects_9)
+ $(am__objects_11)
addressmap_unittest_OBJECTS = $(am_addressmap_unittest_OBJECTS)
addressmap_unittest_DEPENDENCIES = liblogging.la
am__atomicops_unittest_SOURCES_DIST = src/tests/atomicops_unittest.cc \
@@ -315,9 +332,9 @@ am__atomicops_unittest_SOURCES_DIST = src/tests/atomicops_unittest.cc \
src/base/atomicops-internals-x86.h src/base/logging.h \
src/base/commandlineflags.h src/base/basictypes.h \
src/base/dynamic_annotations.h
-@MINGW_FALSE@am__objects_11 = $(am__objects_1)
+@MINGW_FALSE@am__objects_13 = $(am__objects_1)
@MINGW_FALSE@am_atomicops_unittest_OBJECTS = \
-@MINGW_FALSE@ atomicops_unittest.$(OBJEXT) $(am__objects_11)
+@MINGW_FALSE@ atomicops_unittest.$(OBJEXT) $(am__objects_13)
atomicops_unittest_OBJECTS = $(am_atomicops_unittest_OBJECTS)
@MINGW_FALSE@atomicops_unittest_DEPENDENCIES = $(am__DEPENDENCIES_2)
am_frag_unittest_OBJECTS = frag_unittest-frag_unittest.$(OBJEXT)
@@ -326,7 +343,8 @@ am__DEPENDENCIES_3 = libtcmalloc_minimal.la
frag_unittest_DEPENDENCIES = $(am__DEPENDENCIES_3) \
$(am__DEPENDENCIES_1)
am__getpc_test_SOURCES_DIST = src/tests/getpc_test.cc src/getpc.h
-@MINGW_FALSE@am_getpc_test_OBJECTS = getpc_test.$(OBJEXT)
+@HAS_PC_TRUE@@MINGW_FALSE@am_getpc_test_OBJECTS = \
+@HAS_PC_TRUE@@MINGW_FALSE@ getpc_test.$(OBJEXT)
getpc_test_OBJECTS = $(am_getpc_test_OBJECTS)
getpc_test_LDADD = $(LDADD)
am__heap_checker_death_unittest_sh_SOURCES_DIST = \
@@ -342,7 +360,7 @@ am__heap_checker_unittest_SOURCES_DIST = \
src/base/logging.h src/base/basictypes.h \
src/base/dynamic_annotations.h
@MINGW_FALSE@am_heap_checker_unittest_OBJECTS = heap_checker_unittest-heap-checker_unittest.$(OBJEXT) \
-@MINGW_FALSE@ $(am__objects_11)
+@MINGW_FALSE@ $(am__objects_13)
heap_checker_unittest_OBJECTS = $(am_heap_checker_unittest_OBJECTS)
@MINGW_FALSE@am__DEPENDENCIES_4 = libtcmalloc.la
@MINGW_FALSE@heap_checker_unittest_DEPENDENCIES = \
@@ -372,8 +390,9 @@ am__low_level_alloc_unittest_SOURCES_DIST = \
src/base/low_level_alloc.cc src/malloc_hook.cc \
src/tests/low_level_alloc_unittest.cc \
src/base/low_level_alloc.h src/base/basictypes.h \
- src/google/malloc_hook.h src/base/spinlock.h \
- src/base/atomicops.h src/base/atomicops-internals-macosx.h \
+ src/google/malloc_hook.h src/malloc_hook-inl.h \
+ src/base/spinlock.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/logging.h \
@@ -395,7 +414,8 @@ maybe_threads_unittest_sh_OBJECTS = \
$(am_maybe_threads_unittest_sh_OBJECTS)
maybe_threads_unittest_sh_LDADD = $(LDADD)
am_memalign_unittest_OBJECTS = \
- memalign_unittest-memalign_unittest.$(OBJEXT)
+ memalign_unittest-memalign_unittest.$(OBJEXT) \
+ memalign_unittest-testutil.$(OBJEXT)
memalign_unittest_OBJECTS = $(am_memalign_unittest_OBJECTS)
memalign_unittest_DEPENDENCIES = $(am__DEPENDENCIES_3) \
$(am__DEPENDENCIES_1)
@@ -406,50 +426,53 @@ am__profiledata_unittest_SOURCES_DIST = \
src/tests/profiledata_unittest.cc src/profiledata.h \
src/base/commandlineflags.h src/base/logging.h \
src/base/basictypes.h
-@MINGW_FALSE@am_profiledata_unittest_OBJECTS = \
-@MINGW_FALSE@ profiledata_unittest.$(OBJEXT)
+@HAS_PC_TRUE@@MINGW_FALSE@am_profiledata_unittest_OBJECTS = \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiledata_unittest.$(OBJEXT)
profiledata_unittest_OBJECTS = $(am_profiledata_unittest_OBJECTS)
-@MINGW_FALSE@am__DEPENDENCIES_5 = libstacktrace.la libprofiler.la
-@MINGW_FALSE@profiledata_unittest_DEPENDENCIES = \
-@MINGW_FALSE@ $(am__DEPENDENCIES_5)
+@HAS_PC_TRUE@@MINGW_FALSE@am__DEPENDENCIES_5 = libstacktrace.la \
+@HAS_PC_TRUE@@MINGW_FALSE@ libprofiler.la
+@HAS_PC_TRUE@@MINGW_FALSE@profiledata_unittest_DEPENDENCIES = \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__DEPENDENCIES_5)
am__profiler1_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \
src/tests/testutil.h src/tests/testutil.cc \
src/config_for_unittests.h src/google/profiler.h
-@MINGW_FALSE@am__objects_12 = \
-@MINGW_FALSE@ profiler1_unittest-profiler_unittest.$(OBJEXT) \
-@MINGW_FALSE@ profiler1_unittest-testutil.$(OBJEXT) \
-@MINGW_FALSE@ $(am__objects_1)
-@MINGW_FALSE@am_profiler1_unittest_OBJECTS = $(am__objects_12)
+@HAS_PC_TRUE@@MINGW_FALSE@am__objects_14 = profiler1_unittest-profiler_unittest.$(OBJEXT) \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiler1_unittest-testutil.$(OBJEXT) \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__objects_1)
+@HAS_PC_TRUE@@MINGW_FALSE@am_profiler1_unittest_OBJECTS = \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__objects_14)
profiler1_unittest_OBJECTS = $(am_profiler1_unittest_OBJECTS)
-@MINGW_FALSE@profiler1_unittest_DEPENDENCIES = $(am__DEPENDENCIES_5)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler1_unittest_DEPENDENCIES = \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__DEPENDENCIES_5)
am__profiler2_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \
src/tests/testutil.h src/tests/testutil.cc \
src/config_for_unittests.h src/google/profiler.h
-@MINGW_FALSE@am__objects_13 = \
-@MINGW_FALSE@ profiler2_unittest-profiler_unittest.$(OBJEXT) \
-@MINGW_FALSE@ profiler2_unittest-testutil.$(OBJEXT) \
-@MINGW_FALSE@ $(am__objects_1)
-@MINGW_FALSE@am_profiler2_unittest_OBJECTS = $(am__objects_13)
+@HAS_PC_TRUE@@MINGW_FALSE@am__objects_15 = profiler2_unittest-profiler_unittest.$(OBJEXT) \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiler2_unittest-testutil.$(OBJEXT) \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__objects_1)
+@HAS_PC_TRUE@@MINGW_FALSE@am_profiler2_unittest_OBJECTS = \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__objects_15)
profiler2_unittest_OBJECTS = $(am_profiler2_unittest_OBJECTS)
am__profiler3_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \
src/tests/testutil.h src/tests/testutil.cc \
src/config_for_unittests.h src/google/profiler.h
-@MINGW_FALSE@am__objects_14 = \
-@MINGW_FALSE@ profiler3_unittest-profiler_unittest.$(OBJEXT) \
-@MINGW_FALSE@ profiler3_unittest-testutil.$(OBJEXT) \
-@MINGW_FALSE@ $(am__objects_1)
-@MINGW_FALSE@am_profiler3_unittest_OBJECTS = $(am__objects_14)
+@HAS_PC_TRUE@@MINGW_FALSE@am__objects_16 = profiler3_unittest-profiler_unittest.$(OBJEXT) \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiler3_unittest-testutil.$(OBJEXT) \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__objects_1)
+@HAS_PC_TRUE@@MINGW_FALSE@am_profiler3_unittest_OBJECTS = \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__objects_16)
profiler3_unittest_OBJECTS = $(am_profiler3_unittest_OBJECTS)
-@MINGW_FALSE@profiler3_unittest_DEPENDENCIES = $(am__DEPENDENCIES_5) \
-@MINGW_FALSE@ $(am__DEPENDENCIES_1)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler3_unittest_DEPENDENCIES = \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__DEPENDENCIES_5) \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__DEPENDENCIES_1)
am__profiler4_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \
src/tests/testutil.h src/tests/testutil.cc \
src/config_for_unittests.h src/google/profiler.h
-@MINGW_FALSE@am__objects_15 = \
-@MINGW_FALSE@ profiler4_unittest-profiler_unittest.$(OBJEXT) \
-@MINGW_FALSE@ profiler4_unittest-testutil.$(OBJEXT) \
-@MINGW_FALSE@ $(am__objects_1)
-@MINGW_FALSE@am_profiler4_unittest_OBJECTS = $(am__objects_15)
+@HAS_PC_TRUE@@MINGW_FALSE@am__objects_17 = profiler4_unittest-profiler_unittest.$(OBJEXT) \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiler4_unittest-testutil.$(OBJEXT) \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__objects_1)
+@HAS_PC_TRUE@@MINGW_FALSE@am_profiler4_unittest_OBJECTS = \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__objects_17)
profiler4_unittest_OBJECTS = $(am_profiler4_unittest_OBJECTS)
am__profiler_unittest_sh_SOURCES_DIST = \
src/tests/profiler_unittest.sh
@@ -464,9 +487,9 @@ am_ptmalloc_unittest2_OBJECTS = ptmalloc_unittest2-t-test2.$(OBJEXT) \
$(am__objects_1)
ptmalloc_unittest2_OBJECTS = $(am_ptmalloc_unittest2_OBJECTS)
ptmalloc_unittest2_DEPENDENCIES = $(am__DEPENDENCIES_1)
-am__objects_16 = $(am__objects_4) $(am__objects_1)
+am__objects_18 = $(am__objects_4) $(am__objects_1)
am_stacktrace_unittest_OBJECTS = stacktrace_unittest.$(OBJEXT) \
- $(am__objects_16)
+ $(am__objects_18)
stacktrace_unittest_OBJECTS = $(am_stacktrace_unittest_OBJECTS)
stacktrace_unittest_DEPENDENCIES = libstacktrace.la liblogging.la
am__system_alloc_unittest_SOURCES_DIST = src/config_for_unittests.h \
@@ -483,10 +506,14 @@ am__tcmalloc_both_unittest_SOURCES_DIST = \
@MINGW_FALSE@ tcmalloc_both_unittest-testutil.$(OBJEXT) \
@MINGW_FALSE@ $(am__objects_1)
tcmalloc_both_unittest_OBJECTS = $(am_tcmalloc_both_unittest_OBJECTS)
-@MINGW_FALSE@tcmalloc_both_unittest_DEPENDENCIES = \
-@MINGW_FALSE@ $(am__DEPENDENCIES_4) $(am__DEPENDENCIES_3) \
-@MINGW_FALSE@ libprofiler.la liblogging.la \
-@MINGW_FALSE@ $(am__DEPENDENCIES_1)
+@HAS_PC_FALSE@@MINGW_FALSE@tcmalloc_both_unittest_DEPENDENCIES = \
+@HAS_PC_FALSE@@MINGW_FALSE@ $(am__DEPENDENCIES_4) \
+@HAS_PC_FALSE@@MINGW_FALSE@ $(am__DEPENDENCIES_3) liblogging.la \
+@HAS_PC_FALSE@@MINGW_FALSE@ $(am__DEPENDENCIES_1)
+@HAS_PC_TRUE@@MINGW_FALSE@tcmalloc_both_unittest_DEPENDENCIES = \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__DEPENDENCIES_4) \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(am__DEPENDENCIES_3) libprofiler.la \
+@HAS_PC_TRUE@@MINGW_FALSE@ liblogging.la $(am__DEPENDENCIES_1)
am__tcmalloc_large_unittest_SOURCES_DIST = \
src/tests/tcmalloc_large_unittest.cc
@MINGW_FALSE@am_tcmalloc_large_unittest_OBJECTS = tcmalloc_large_unittest-tcmalloc_large_unittest.$(OBJEXT)
@@ -697,6 +724,8 @@ F77 = @F77@
FFLAGS = @FFLAGS@
GCC_FALSE = @GCC_FALSE@
GCC_TRUE = @GCC_TRUE@
+HAS_PC_FALSE = @HAS_PC_FALSE@
+HAS_PC_TRUE = @HAS_PC_TRUE@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -792,7 +821,8 @@ googleincludedir = $(includedir)/google
# who install this package can include in their own applications.)
# We'll add to this later, on a library-by-library basis
googleinclude_HEADERS = $(SG_STACKTRACE_INCLUDES) \
- $(SG_TCMALLOC_MINIMAL_INCLUDES) $(am__append_10)
+ $(SG_TCMALLOC_MINIMAL_INCLUDES) $(am__append_9) \
+ $(am__append_15)
docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION)
# This is for HTML and other documentation you want to install.
# Add your documentation files (in doc/) in addition to these
@@ -835,13 +865,14 @@ dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \
doc/tcmalloc-opspersec.vs.size.5.threads.png \
doc/tcmalloc-opspersec.vs.size.8.threads.png doc/overview.dot \
doc/pageheap.dot doc/spanmap.dot doc/threadheap.dot \
- $(am__append_15)
+ $(am__append_14) $(am__append_20)
# The libraries (.so's) you want to install
# We'll add to this later, on a library-by-library basis
### Making the library
-lib_LTLIBRARIES = libtcmalloc_minimal.la $(am__append_11)
+lib_LTLIBRARIES = libtcmalloc_minimal.la $(am__append_10) \
+ $(am__append_16)
# This is for 'convenience libraries' -- basically just a container for sources
### Making the library
@@ -854,7 +885,6 @@ WINDOWS_PROJECTS = google-perftools.sln \
vsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj \
vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj \
vsprojects/addressmap_unittest/addressmap_unittest.vcproj \
- $(am__append_9) \
vsprojects/packed-cache_test/packed-cache_test.vcproj \
vsprojects/frag_unittest/frag_unittest.vcproj \
vsprojects/markidle_unittest/markidle_unittest.vcproj \
@@ -887,13 +917,15 @@ TESTS = low_level_alloc_unittest $(am__append_6) stacktrace_unittest \
tcmalloc_minimal_unittest tcmalloc_minimal_large_unittest \
maybe_threads_unittest.sh addressmap_unittest $(am__append_8) \
packed_cache_test frag_unittest markidle_unittest \
- memalign_unittest thread_dealloc_unittest $(am__append_12)
+ memalign_unittest thread_dealloc_unittest $(am__append_11) \
+ $(am__append_17)
# TESTS_ENVIRONMENT sets environment variables for when you run unittest.
# We always get "srcdir" set for free.
# We'll add to this later, on a library-by-library basis.
TESTS_ENVIRONMENT = $(am__append_7)
# All script tests should be added here
-noinst_SCRIPTS = $(maybe_threads_unittest_sh_SOURCES) $(am__append_13)
+noinst_SCRIPTS = $(maybe_threads_unittest_sh_SOURCES) $(am__append_12) \
+ $(am__append_18)
### ------- library routines, in src/base
@@ -961,6 +993,7 @@ libsysinfo_la_SOURCES = src/base/sysinfo.cc \
LOW_LEVEL_ALLOC_UNITTEST_INCLUDES = src/base/low_level_alloc.h \
src/base/basictypes.h \
src/google/malloc_hook.h \
+ src/malloc_hook-inl.h \
$(SPINLOCK_INCLUDES) \
$(LOGGING_INCLUDES)
@@ -1027,6 +1060,7 @@ S_TCMALLOC_MINIMAL_INCLUDES = src/internal_logging.h \
src/base/commandlineflags.h \
src/base/basictypes.h \
src/pagemap.h \
+ src/malloc_hook-inl.h \
src/maybe_threads.h
SG_TCMALLOC_MINIMAL_INCLUDES = src/google/malloc_hook.h \
@@ -1043,11 +1077,12 @@ libtcmalloc_minimal_la_SOURCES = src/internal_logging.cc \
$(MAYBE_THREADS_CC) \
$(TCMALLOC_MINIMAL_INCLUDES)
-libtcmalloc_minimal_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS)
-libtcmalloc_minimal_la_LDFLAGS = $(PTHREAD_CFLAGS)
-libtcmalloc_minimal_la_LIBADD = $(PTHREAD_LIBS) \
- libstacktrace.la
+# We #define NO_TCMALLOC_SAMPLES, since sampling is turned off for _minimal.
+libtcmalloc_minimal_la_CXXFLAGS = -DNO_TCMALLOC_SAMPLES \
+ $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS)
+libtcmalloc_minimal_la_LDFLAGS = $(PTHREAD_CFLAGS)
+libtcmalloc_minimal_la_LIBADD = $(PTHREAD_LIBS) $(LIBSPINLOCK)
LIBTCMALLOC_MINIMAL = libtcmalloc_minimal.la
tcmalloc_minimal_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \
src/tests/testutil.h src/tests/testutil.cc \
@@ -1095,7 +1130,8 @@ markidle_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
markidle_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
memalign_unittest_SOURCES = src/tests/memalign_unittest.cc \
src/config_for_unittests.h \
- src/tcmalloc.h
+ src/tcmalloc.h \
+ src/tests/testutil.h src/tests/testutil.cc
memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
memalign_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
@@ -1135,6 +1171,7 @@ ptmalloc_unittest2_LDADD = $(PTHREAD_LIBS)
@MINGW_FALSE@ src/system-alloc.h \
@MINGW_FALSE@ src/pagemap.h \
@MINGW_FALSE@ src/addressmap-inl.h \
+@MINGW_FALSE@ src/malloc_hook-inl.h \
@MINGW_FALSE@ src/packed-cache-inl.h \
@MINGW_FALSE@ src/heap-profile-table.h \
@MINGW_FALSE@ src/base/basictypes.h \
@@ -1198,8 +1235,11 @@ ptmalloc_unittest2_LDADD = $(PTHREAD_LIBS)
@MINGW_FALSE@tcmalloc_both_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
@MINGW_FALSE@tcmalloc_both_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-@MINGW_FALSE@tcmalloc_both_unittest_LDADD = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \
-@MINGW_FALSE@ libprofiler.la liblogging.la $(PTHREAD_LIBS)
+@HAS_PC_FALSE@@MINGW_FALSE@tcmalloc_both_unittest_LDADD = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \
+@HAS_PC_FALSE@@MINGW_FALSE@ liblogging.la $(PTHREAD_LIBS)
+
+@HAS_PC_TRUE@@MINGW_FALSE@tcmalloc_both_unittest_LDADD = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \
+@HAS_PC_TRUE@@MINGW_FALSE@ libprofiler.la liblogging.la $(PTHREAD_LIBS)
@MINGW_FALSE@tcmalloc_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc
@MINGW_FALSE@tcmalloc_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
@@ -1234,72 +1274,73 @@ ptmalloc_unittest2_LDADD = $(PTHREAD_LIBS)
### ------- CPU profiler
-# The CPU profiler doesn't work on windows yet
+# The CPU profiler doesn't work on windows yet. It also doesn't work
+# if there's no way to get the PC.
### The header files we use. We divide into categories based on directory
-@MINGW_FALSE@S_CPU_PROFILER_INCLUDES = src/profiledata.h \
-@MINGW_FALSE@ src/getpc.h \
-@MINGW_FALSE@ src/base/basictypes.h \
-@MINGW_FALSE@ src/base/commandlineflags.h \
-@MINGW_FALSE@ src/base/googleinit.h \
-@MINGW_FALSE@ src/base/logging.h \
-@MINGW_FALSE@ src/base/simple_mutex.h \
-@MINGW_FALSE@ src/base/sysinfo.h \
-@MINGW_FALSE@ $(SPINLOCK_INCLUDES) \
-@MINGW_FALSE@ $(LOGGING_INCLUDES)
-
-@MINGW_FALSE@SG_CPU_PROFILER_INCLUDES = src/google/profiler.h \
-@MINGW_FALSE@ src/google/stacktrace.h
-
-@MINGW_FALSE@CPU_PROFILER_INCLUDES = $(S_CPU_PROFILER_INCLUDES) $(SG_CPU_PROFILER_INCLUDES)
-@MINGW_FALSE@libprofiler_la_SOURCES = src/profiler.cc \
-@MINGW_FALSE@ src/profiledata.cc \
-@MINGW_FALSE@ $(CPU_PROFILER_INCLUDES)
-
-@MINGW_FALSE@libprofiler_la_LIBADD = libstacktrace.la
+@HAS_PC_TRUE@@MINGW_FALSE@S_CPU_PROFILER_INCLUDES = src/profiledata.h \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/getpc.h \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/base/basictypes.h \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/base/commandlineflags.h \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/base/googleinit.h \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/base/logging.h \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/base/simple_mutex.h \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/base/sysinfo.h \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(SPINLOCK_INCLUDES) \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(LOGGING_INCLUDES)
+
+@HAS_PC_TRUE@@MINGW_FALSE@SG_CPU_PROFILER_INCLUDES = src/google/profiler.h \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/google/stacktrace.h
+
+@HAS_PC_TRUE@@MINGW_FALSE@CPU_PROFILER_INCLUDES = $(S_CPU_PROFILER_INCLUDES) $(SG_CPU_PROFILER_INCLUDES)
+@HAS_PC_TRUE@@MINGW_FALSE@libprofiler_la_SOURCES = src/profiler.cc \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/profiledata.cc \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(CPU_PROFILER_INCLUDES)
+
+@HAS_PC_TRUE@@MINGW_FALSE@libprofiler_la_LIBADD = libstacktrace.la
# We have to include ProfileData for profiledata_unittest
-@MINGW_FALSE@CPU_PROFILER_SYMBOLS = '(ProfilerStart|ProfilerStop|ProfilerEnable|ProfilerDisable|ProfilerFlush|ProfilerRegisterThread|ProfileData)'
-@MINGW_FALSE@libprofiler_la_LDFLAGS = -export-symbols-regex $(CPU_PROFILER_SYMBOLS)
+@HAS_PC_TRUE@@MINGW_FALSE@CPU_PROFILER_SYMBOLS = '(ProfilerStart|ProfilerStop|ProfilerEnable|ProfilerDisable|ProfilerFlush|ProfilerRegisterThread|ProfileData)'
+@HAS_PC_TRUE@@MINGW_FALSE@libprofiler_la_LDFLAGS = -export-symbols-regex $(CPU_PROFILER_SYMBOLS)
# See discussion above (under LIBTCMALLOC_MINIMAL) for why we do this.
# Basically it's to work around systems where --rpath doesn't work right.
-@MINGW_FALSE@LIBPROFILER = libstacktrace.la libprofiler.la
+@HAS_PC_TRUE@@MINGW_FALSE@LIBPROFILER = libstacktrace.la libprofiler.la
#WINDOWS_PROJECTS += vsprojects/getpc_test/getpc_test.vcproj
-@MINGW_FALSE@getpc_test_SOURCES = src/tests/getpc_test.cc src/getpc.h
+@HAS_PC_TRUE@@MINGW_FALSE@getpc_test_SOURCES = src/tests/getpc_test.cc src/getpc.h
#WINDOWS_PROJECTS += vsprojects/profiledata_unittest/profiledata_unittest.vcproj
-@MINGW_FALSE@profiledata_unittest_SOURCES = src/tests/profiledata_unittest.cc \
-@MINGW_FALSE@ src/profiledata.h \
-@MINGW_FALSE@ src/base/commandlineflags.h \
-@MINGW_FALSE@ src/base/logging.h \
-@MINGW_FALSE@ src/base/basictypes.h
-
-@MINGW_FALSE@profiledata_unittest_LDADD = $(LIBPROFILER)
-@MINGW_FALSE@profiler_unittest_sh_SOURCES = src/tests/profiler_unittest.sh
-@MINGW_FALSE@PROFILER_UNITTEST_INCLUDES = src/config_for_unittests.h \
-@MINGW_FALSE@ src/google/profiler.h
-
-@MINGW_FALSE@PROFILER_UNITTEST_SRCS = src/tests/profiler_unittest.cc \
-@MINGW_FALSE@ src/tests/testutil.h src/tests/testutil.cc \
-@MINGW_FALSE@ $(PROFILER_UNITTEST_INCLUDES)
-
-@MINGW_FALSE@profiler1_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
-@MINGW_FALSE@profiler1_unittest_CXXFLAGS = -g -DNO_THREADS $(AM_CXXFLAGS)
-@MINGW_FALSE@profiler1_unittest_LDADD = $(LIBPROFILER)
-@MINGW_FALSE@profiler2_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
-@MINGW_FALSE@profiler2_unittest_CXXFLAGS = -g -DNO_THREADS $(AM_CXXFLAGS)
-@MINGW_FALSE@profiler2_unittest_LDADD = -lstacktrace -lprofiler
+@HAS_PC_TRUE@@MINGW_FALSE@profiledata_unittest_SOURCES = src/tests/profiledata_unittest.cc \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/profiledata.h \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/base/commandlineflags.h \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/base/logging.h \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/base/basictypes.h
+
+@HAS_PC_TRUE@@MINGW_FALSE@profiledata_unittest_LDADD = $(LIBPROFILER)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler_unittest_sh_SOURCES = src/tests/profiler_unittest.sh
+@HAS_PC_TRUE@@MINGW_FALSE@PROFILER_UNITTEST_INCLUDES = src/config_for_unittests.h \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/google/profiler.h
+
+@HAS_PC_TRUE@@MINGW_FALSE@PROFILER_UNITTEST_SRCS = src/tests/profiler_unittest.cc \
+@HAS_PC_TRUE@@MINGW_FALSE@ src/tests/testutil.h src/tests/testutil.cc \
+@HAS_PC_TRUE@@MINGW_FALSE@ $(PROFILER_UNITTEST_INCLUDES)
+
+@HAS_PC_TRUE@@MINGW_FALSE@profiler1_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler1_unittest_CXXFLAGS = -g -DNO_THREADS $(AM_CXXFLAGS)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler1_unittest_LDADD = $(LIBPROFILER)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler2_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler2_unittest_CXXFLAGS = -g -DNO_THREADS $(AM_CXXFLAGS)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler2_unittest_LDADD = -lstacktrace -lprofiler
# We depend on -lprofiler but haven't yet said how to build it. Do so now.
-@MINGW_FALSE@profiler2_unittest_DEPENDENCIES = $(LIBPROFILER)
-@MINGW_FALSE@profiler3_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
-@MINGW_FALSE@profiler3_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
-@MINGW_FALSE@profiler3_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-@MINGW_FALSE@profiler3_unittest_LDADD = $(LIBPROFILER) $(PTHREAD_LIBS)
-@MINGW_FALSE@profiler4_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
-@MINGW_FALSE@profiler4_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
-@MINGW_FALSE@profiler4_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-@MINGW_FALSE@profiler4_unittest_LDADD = -lstacktrace -lprofiler $(PTHREAD_LIBS)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler2_unittest_DEPENDENCIES = $(LIBPROFILER)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler3_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler3_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler3_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler3_unittest_LDADD = $(LIBPROFILER) $(PTHREAD_LIBS)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler4_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler4_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler4_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler4_unittest_LDADD = -lstacktrace -lprofiler $(PTHREAD_LIBS)
# We depend on -lprofiler but haven't yet said how to build it. Do so now.
-@MINGW_FALSE@profiler4_unittest_DEPENDENCIES = $(LIBPROFILER)
+@HAS_PC_TRUE@@MINGW_FALSE@profiler4_unittest_DEPENDENCIES = $(LIBPROFILER)
EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \
$(SCRIPTS) libtool \
src/windows/config.h src/windows/vc7and8.def $(WINDOWS_PROJECTS) \
@@ -1472,6 +1513,9 @@ profiler3_unittest$(EXEEXT): $(profiler3_unittest_OBJECTS) $(profiler3_unittest_
profiler4_unittest$(EXEEXT): $(profiler4_unittest_OBJECTS) $(profiler4_unittest_DEPENDENCIES)
@rm -f profiler4_unittest$(EXEEXT)
$(CXXLINK) $(profiler4_unittest_LDFLAGS) $(profiler4_unittest_OBJECTS) $(profiler4_unittest_LDADD) $(LIBS)
+@HAS_PC_FALSE@profiler_unittest.sh$(EXEEXT): $(profiler_unittest_sh_OBJECTS) $(profiler_unittest_sh_DEPENDENCIES)
+@HAS_PC_FALSE@ @rm -f profiler_unittest.sh$(EXEEXT)
+@HAS_PC_FALSE@ $(LINK) $(profiler_unittest_sh_LDFLAGS) $(profiler_unittest_sh_OBJECTS) $(profiler_unittest_sh_LDADD) $(LIBS)
@MINGW_TRUE@profiler_unittest.sh$(EXEEXT): $(profiler_unittest_sh_OBJECTS) $(profiler_unittest_sh_DEPENDENCIES)
@MINGW_TRUE@ @rm -f profiler_unittest.sh$(EXEEXT)
@MINGW_TRUE@ $(LINK) $(profiler_unittest_sh_LDFLAGS) $(profiler_unittest_sh_OBJECTS) $(profiler_unittest_sh_LDADD) $(LIBS)
@@ -1569,6 +1613,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/markidle_unittest-markidle_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/markidle_unittest-testutil.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memalign_unittest-memalign_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memalign_unittest-testutil.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mini_disassembler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packed-cache_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/patch_functions.Plo@am__quote@
@@ -2102,6 +2147,20 @@ memalign_unittest-memalign_unittest.obj: src/tests/memalign_unittest.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -c -o memalign_unittest-memalign_unittest.obj `if test -f 'src/tests/memalign_unittest.cc'; then $(CYGPATH_W) 'src/tests/memalign_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/memalign_unittest.cc'; fi`
+memalign_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_unittest-testutil.o -MD -MP -MF "$(DEPDIR)/memalign_unittest-testutil.Tpo" -c -o memalign_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/memalign_unittest-testutil.Tpo" "$(DEPDIR)/memalign_unittest-testutil.Po"; else rm -f "$(DEPDIR)/memalign_unittest-testutil.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='memalign_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -c -o memalign_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+memalign_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_unittest-testutil.obj -MD -MP -MF "$(DEPDIR)/memalign_unittest-testutil.Tpo" -c -o memalign_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/memalign_unittest-testutil.Tpo" "$(DEPDIR)/memalign_unittest-testutil.Po"; else rm -f "$(DEPDIR)/memalign_unittest-testutil.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='memalign_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -c -o memalign_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi`
+
packed-cache_test.o: src/tests/packed-cache_test.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT packed-cache_test.o -MD -MP -MF "$(DEPDIR)/packed-cache_test.Tpo" -c -o packed-cache_test.o `test -f 'src/tests/packed-cache_test.cc' || echo '$(srcdir)/'`src/tests/packed-cache_test.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/packed-cache_test.Tpo" "$(DEPDIR)/packed-cache_test.Po"; else rm -f "$(DEPDIR)/packed-cache_test.Tpo"; exit 1; fi
@@ -2623,7 +2682,7 @@ check-TESTS: $(TESTS)
distdir: $(DISTFILES)
$(am__remove_distdir)
mkdir $(distdir)
- $(mkdir_p) $(distdir)/$(top_srcdir) $(distdir)/doc $(distdir)/m4 $(distdir)/packages $(distdir)/packages/rpm $(distdir)/src $(distdir)/src/google $(distdir)/src/solaris $(distdir)/src/tests $(distdir)/src/windows $(distdir)/vsprojects/addressmap_unittest $(distdir)/vsprojects/frag_unittest $(distdir)/vsprojects/libtcmalloc_minimal $(distdir)/vsprojects/low_level_alloc_unittest $(distdir)/vsprojects/markidle_unittest $(distdir)/vsprojects/memalign_unittest $(distdir)/vsprojects/packed-cache_test $(distdir)/vsprojects/system_alloc_unittest $(distdir)/vsprojects/tcmalloc_minimal_large $(distdir)/vsprojects/tcmalloc_minimal_unittest $(distdir)/vsprojects/tcmalloc_minimal_unittest-static $(distdir)/vsprojects/thread_dealloc_unittest
+ $(mkdir_p) $(distdir)/$(top_srcdir) $(distdir)/doc $(distdir)/m4 $(distdir)/packages $(distdir)/packages/rpm $(distdir)/src $(distdir)/src/google $(distdir)/src/solaris $(distdir)/src/tests $(distdir)/src/windows $(distdir)/vsprojects/addressmap_unittest $(distdir)/vsprojects/frag_unittest $(distdir)/vsprojects/libtcmalloc_minimal $(distdir)/vsprojects/low_level_alloc_unittest $(distdir)/vsprojects/markidle_unittest $(distdir)/vsprojects/memalign_unittest $(distdir)/vsprojects/packed-cache_test $(distdir)/vsprojects/tcmalloc_minimal_large $(distdir)/vsprojects/tcmalloc_minimal_unittest $(distdir)/vsprojects/tcmalloc_minimal_unittest-static $(distdir)/vsprojects/thread_dealloc_unittest
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
@@ -2886,11 +2945,11 @@ maybe_threads_unittest.sh$(EXEEXT): $(top_srcdir)/$(maybe_threads_unittest_sh_SO
@MINGW_FALSE@ heap-checker_unittest
@MINGW_FALSE@ rm -f $@
@MINGW_FALSE@ cp -p $(top_srcdir)/$(heap_checker_death_unittest_sh_SOURCES) $@
-@MINGW_FALSE@profiler_unittest.sh$(EXEEXT): $(top_srcdir)/$(profiler_unittest_sh_SOURCES) \
-@MINGW_FALSE@ profiler1_unittest profiler2_unittest \
-@MINGW_FALSE@ profiler3_unittest profiler4_unittest
-@MINGW_FALSE@ rm -f $@
-@MINGW_FALSE@ cp -p $(top_srcdir)/$(profiler_unittest_sh_SOURCES) $@
+@HAS_PC_TRUE@@MINGW_FALSE@profiler_unittest.sh$(EXEEXT): $(top_srcdir)/$(profiler_unittest_sh_SOURCES) \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiler1_unittest profiler2_unittest \
+@HAS_PC_TRUE@@MINGW_FALSE@ profiler3_unittest profiler4_unittest
+@HAS_PC_TRUE@@MINGW_FALSE@ rm -f $@
+@HAS_PC_TRUE@@MINGW_FALSE@ cp -p $(top_srcdir)/$(profiler_unittest_sh_SOURCES) $@
rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec
@cd packages && ./rpm.sh ${PACKAGE} ${VERSION}
diff --git a/README.windows b/README.windows
index fd80d20..dd6aed1 100644
--- a/README.windows
+++ b/README.windows
@@ -32,6 +32,9 @@ understand yet, you still need to use the "DLL" CRT library even when
statically linking. Again, you can look at the
tcmalloc_minimal_unittest-static project, which does this.
+Note that the other features of perftools, such as the cpu-profiler,
+heap-profiler, and leak-checker, have not yet been ported to Windows.
+
I have little experience with Windows programming, so there may be
better ways to set this up than I've done! If you run across any
problems, please post to the google-perftools Google Group, or report
diff --git a/configure b/configure
index ca956aa..cdfc363 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for google-perftools 0.97.
+# Generated by GNU Autoconf 2.59 for google-perftools 0.98.
#
# Report bugs to <opensource@google.com>.
#
@@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='google-perftools'
PACKAGE_TARNAME='google-perftools'
-PACKAGE_VERSION='0.97'
-PACKAGE_STRING='google-perftools 0.97'
+PACKAGE_VERSION='0.98'
+PACKAGE_STRING='google-perftools 0.98'
PACKAGE_BUGREPORT='opensource@google.com'
ac_unique_file="README"
@@ -465,7 +465,7 @@ ac_includes_default="\
# include <unistd.h>
#endif"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CPP CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE GCC_TRUE GCC_FALSE EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL LIBTOOL_DEPS UNWIND_LIBS ENABLE_FRAME_POINTERS_TRUE ENABLE_FRAME_POINTERS_FALSE X86_64_TRUE X86_64_FALSE acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS MINGW_TRUE MINGW_FALSE LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CPP CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE GCC_TRUE GCC_FALSE EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL LIBTOOL_DEPS HAS_PC_TRUE HAS_PC_FALSE UNWIND_LIBS ENABLE_FRAME_POINTERS_TRUE ENABLE_FRAME_POINTERS_FALSE X86_64_TRUE X86_64_FALSE acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS MINGW_TRUE MINGW_FALSE LIBOBJS LTLIBOBJS'
ac_subst_files=''
# Initialize some variables set by options.
@@ -954,7 +954,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures google-perftools 0.97 to adapt to many kinds of systems.
+\`configure' configures google-perftools 0.98 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1021,7 +1021,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of google-perftools 0.97:";;
+ short | recursive ) echo "Configuration of google-perftools 0.98:";;
esac
cat <<\_ACEOF
@@ -1162,7 +1162,7 @@ fi
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
-google-perftools configure 0.97
+google-perftools configure 0.98
generated by GNU Autoconf 2.59
Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1176,7 +1176,7 @@ cat >&5 <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by google-perftools $as_me 0.97, which was
+It was created by google-perftools $as_me 0.98, which was
generated by GNU Autoconf 2.59. Invocation command line was
$ $0 $@
@@ -1904,7 +1904,7 @@ fi
# Define the identity of the package.
PACKAGE='google-perftools'
- VERSION='0.97'
+ VERSION='0.98'
cat >>confdefs.h <<_ACEOF
@@ -19249,8 +19249,7 @@ fi
done
# for turning off services when run as root
-
-for ac_header in stdlib.h unistd.h
+for ac_header in malloc.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -19397,285 +19396,9 @@ _ACEOF
fi
done
+ # some systems define stuff there, others not
-
-for ac_func in getpagesize
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
-if eval "test \"\${$as_ac_var+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-char (*f) () = $ac_func;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != $ac_func;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-eval "$as_ac_var=no"
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-echo "$as_me:$LINENO: checking for working mmap" >&5
-echo $ECHO_N "checking for working mmap... $ECHO_C" >&6
-if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test "$cross_compiling" = yes; then
- ac_cv_func_mmap_fixed_mapped=no
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-/* malloc might have been renamed as rpl_malloc. */
-#undef malloc
-
-/* Thanks to Mike Haertel and Jim Avera for this test.
- Here is a matrix of mmap possibilities:
- mmap private not fixed
- mmap private fixed at somewhere currently unmapped
- mmap private fixed at somewhere already mapped
- mmap shared not fixed
- mmap shared fixed at somewhere currently unmapped
- mmap shared fixed at somewhere already mapped
- For private mappings, we should verify that changes cannot be read()
- back from the file, nor mmap's back from the file at a different
- address. (There have been systems where private was not correctly
- implemented like the infamous i386 svr4.0, and systems where the
- VM page cache was not coherent with the file system buffer cache
- like early versions of FreeBSD and possibly contemporary NetBSD.)
- For shared mappings, we should conversely verify that changes get
- propagated back to all the places they're supposed to be.
-
- Grep wants private fixed already mapped.
- The main things grep needs to know about mmap are:
- * does it exist and is it safe to write into the mmap'd area
- * how to use it (BSD variants) */
-
-#include <fcntl.h>
-#include <sys/mman.h>
-
-#if !STDC_HEADERS && !HAVE_STDLIB_H
-char *malloc ();
-#endif
-
-/* This mess was copied from the GNU getpagesize.h. */
-#if !HAVE_GETPAGESIZE
-/* Assume that all systems that can run configure have sys/param.h. */
-# if !HAVE_SYS_PARAM_H
-# define HAVE_SYS_PARAM_H 1
-# endif
-
-# ifdef _SC_PAGESIZE
-# define getpagesize() sysconf(_SC_PAGESIZE)
-# else /* no _SC_PAGESIZE */
-# if HAVE_SYS_PARAM_H
-# include <sys/param.h>
-# ifdef EXEC_PAGESIZE
-# define getpagesize() EXEC_PAGESIZE
-# else /* no EXEC_PAGESIZE */
-# ifdef NBPG
-# define getpagesize() NBPG * CLSIZE
-# ifndef CLSIZE
-# define CLSIZE 1
-# endif /* no CLSIZE */
-# else /* no NBPG */
-# ifdef NBPC
-# define getpagesize() NBPC
-# else /* no NBPC */
-# ifdef PAGESIZE
-# define getpagesize() PAGESIZE
-# endif /* PAGESIZE */
-# endif /* no NBPC */
-# endif /* no NBPG */
-# endif /* no EXEC_PAGESIZE */
-# else /* no HAVE_SYS_PARAM_H */
-# define getpagesize() 8192 /* punt totally */
-# endif /* no HAVE_SYS_PARAM_H */
-# endif /* no _SC_PAGESIZE */
-
-#endif /* no HAVE_GETPAGESIZE */
-
-int
-main ()
-{
- char *data, *data2, *data3;
- int i, pagesize;
- int fd;
-
- pagesize = getpagesize ();
-
- /* First, make a file with some known garbage in it. */
- data = (char *) malloc (pagesize);
- if (!data)
- exit (1);
- for (i = 0; i < pagesize; ++i)
- *(data + i) = rand ();
- umask (0);
- fd = creat ("conftest.mmap", 0600);
- if (fd < 0)
- exit (1);
- if (write (fd, data, pagesize) != pagesize)
- exit (1);
- close (fd);
-
- /* Next, try to mmap the file at a fixed address which already has
- something else allocated at it. If we can, also make sure that
- we see the same garbage. */
- fd = open ("conftest.mmap", O_RDWR);
- if (fd < 0)
- exit (1);
- data2 = (char *) malloc (2 * pagesize);
- if (!data2)
- exit (1);
- data2 += (pagesize - ((long) data2 & (pagesize - 1))) & (pagesize - 1);
- if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_FIXED, fd, 0L))
- exit (1);
- for (i = 0; i < pagesize; ++i)
- if (*(data + i) != *(data2 + i))
- exit (1);
-
- /* Finally, make sure that changes to the mapped area do not
- percolate back to the file as seen by read(). (This is a bug on
- some variants of i386 svr4.0.) */
- for (i = 0; i < pagesize; ++i)
- *(data2 + i) = *(data2 + i) + 1;
- data3 = (char *) malloc (pagesize);
- if (!data3)
- exit (1);
- if (read (fd, data3, pagesize) != pagesize)
- exit (1);
- for (i = 0; i < pagesize; ++i)
- if (*(data + i) != *(data3 + i))
- exit (1);
- close (fd);
- exit (0);
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_func_mmap_fixed_mapped=yes
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_func_mmap_fixed_mapped=no
-fi
-rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-fi
-echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5
-echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6
-if test $ac_cv_func_mmap_fixed_mapped = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_MMAP 1
-_ACEOF
-
-fi
-rm -f conftest.mmap
-
-
-for ac_header in malloc.h
+for ac_header in glob.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -19822,9 +19545,9 @@ _ACEOF
fi
done
- # some systems define stuff there, others not
+ # for heap-profile-table (cleaning up profiles)
-for ac_header in glob.h
+for ac_header in execinfo.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -19971,9 +19694,9 @@ _ACEOF
fi
done
- # for heap-profile-table (cleaning up profiles)
+ # for stacktrace? and heapchecker_unittest
-for ac_header in execinfo.h
+for ac_header in libunwind.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -20120,9 +19843,9 @@ _ACEOF
fi
done
- # for stacktrace? and heapchecker_unittest
+ # for stacktrace
-for ac_header in libunwind.h
+for ac_header in unwind.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -20269,9 +19992,9 @@ _ACEOF
fi
done
- # for stacktrace
+ # for stacktrace
-for ac_header in unwind.h
+for ac_header in ucontext.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -20418,9 +20141,9 @@ _ACEOF
fi
done
- # for stacktrace
+ # for profiler.cc (cpu profiler)
-for ac_header in ucontext.h
+for ac_header in conflict-signal.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -20567,9 +20290,9 @@ _ACEOF
fi
done
- # for profiler.cc (cpu profiler)
+ # defined on some windows platforms
-for ac_header in conflict-signal.h
+for ac_header in sys/prctl.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -20716,9 +20439,9 @@ _ACEOF
fi
done
- # defined on some windows platforms
+ # for thread_lister (needed by leak-checker)
-for ac_header in sys/prctl.h
+for ac_header in linux/ptrace.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -20865,9 +20588,9 @@ _ACEOF
fi
done
- # for thread_lister (needed by leak-checker)
+# also needed by leak-checker
-for ac_header in linux/ptrace.h
+for ac_header in sys/syscall.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -21014,9 +20737,9 @@ _ACEOF
fi
done
-# also needed by leak-checker
-for ac_header in sys/syscall.h
+
+for ac_header in fcntl.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -21163,9 +20886,9 @@ _ACEOF
fi
done
+ # for tcmalloc_unittest
-
-for ac_header in fcntl.h
+for ac_header in grp.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -21312,9 +21035,9 @@ _ACEOF
fi
done
- # for tcmalloc_unittest
+ # for heapchecker_unittest
-for ac_header in grp.h
+for ac_header in pwd.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -21463,7 +21186,7 @@ fi
done
# for heapchecker_unittest
-for ac_header in pwd.h
+for ac_header in sys/resource.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -21610,7 +21333,7 @@ _ACEOF
fi
done
- # for heapchecker_unittest
+ # for memalign_unittest.cc
# We override a lot of memory allocation routines, not all of which are
# standard. For those the system doesn't declare, we'll declare ourselves.
echo "$as_me:$LINENO: checking whether cfree is declared" >&5
@@ -21976,6 +21699,448 @@ fi
+# We need to check for mmap. cygwin supports mmap, but the autoconf
+# test doesn't work on cygwin:
+# http://www.cygwin.com/ml/cygwin/2002-04/msg00412.html
+# This workaround comes from
+# http://cygwin.com/ml/cygwin/2004-11/msg00138.html
+case "$host" in
+ *-*-cygwin*) ac_cv_func_mmap_fixed_mapped=yes
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MMAP 1
+_ACEOF
+
+ ;;
+ *)
+
+for ac_header in stdlib.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to opensource@google.com ##
+## ------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in getpagesize
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+echo "$as_me:$LINENO: checking for working mmap" >&5
+echo $ECHO_N "checking for working mmap... $ECHO_C" >&6
+if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_mmap_fixed_mapped=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+/* malloc might have been renamed as rpl_malloc. */
+#undef malloc
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+ Here is a matrix of mmap possibilities:
+ mmap private not fixed
+ mmap private fixed at somewhere currently unmapped
+ mmap private fixed at somewhere already mapped
+ mmap shared not fixed
+ mmap shared fixed at somewhere currently unmapped
+ mmap shared fixed at somewhere already mapped
+ For private mappings, we should verify that changes cannot be read()
+ back from the file, nor mmap's back from the file at a different
+ address. (There have been systems where private was not correctly
+ implemented like the infamous i386 svr4.0, and systems where the
+ VM page cache was not coherent with the file system buffer cache
+ like early versions of FreeBSD and possibly contemporary NetBSD.)
+ For shared mappings, we should conversely verify that changes get
+ propagated back to all the places they're supposed to be.
+
+ Grep wants private fixed already mapped.
+ The main things grep needs to know about mmap are:
+ * does it exist and is it safe to write into the mmap'd area
+ * how to use it (BSD variants) */
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#if !STDC_HEADERS && !HAVE_STDLIB_H
+char *malloc ();
+#endif
+
+/* This mess was copied from the GNU getpagesize.h. */
+#if !HAVE_GETPAGESIZE
+/* Assume that all systems that can run configure have sys/param.h. */
+# if !HAVE_SYS_PARAM_H
+# define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+# define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+# if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else /* no EXEC_PAGESIZE */
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif /* no CLSIZE */
+# else /* no NBPG */
+# ifdef NBPC
+# define getpagesize() NBPC
+# else /* no NBPC */
+# ifdef PAGESIZE
+# define getpagesize() PAGESIZE
+# endif /* PAGESIZE */
+# endif /* no NBPC */
+# endif /* no NBPG */
+# endif /* no EXEC_PAGESIZE */
+# else /* no HAVE_SYS_PARAM_H */
+# define getpagesize() 8192 /* punt totally */
+# endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+int
+main ()
+{
+ char *data, *data2, *data3;
+ int i, pagesize;
+ int fd;
+
+ pagesize = getpagesize ();
+
+ /* First, make a file with some known garbage in it. */
+ data = (char *) malloc (pagesize);
+ if (!data)
+ exit (1);
+ for (i = 0; i < pagesize; ++i)
+ *(data + i) = rand ();
+ umask (0);
+ fd = creat ("conftest.mmap", 0600);
+ if (fd < 0)
+ exit (1);
+ if (write (fd, data, pagesize) != pagesize)
+ exit (1);
+ close (fd);
+
+ /* Next, try to mmap the file at a fixed address which already has
+ something else allocated at it. If we can, also make sure that
+ we see the same garbage. */
+ fd = open ("conftest.mmap", O_RDWR);
+ if (fd < 0)
+ exit (1);
+ data2 = (char *) malloc (2 * pagesize);
+ if (!data2)
+ exit (1);
+ data2 += (pagesize - ((long) data2 & (pagesize - 1))) & (pagesize - 1);
+ if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED, fd, 0L))
+ exit (1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data2 + i))
+ exit (1);
+
+ /* Finally, make sure that changes to the mapped area do not
+ percolate back to the file as seen by read(). (This is a bug on
+ some variants of i386 svr4.0.) */
+ for (i = 0; i < pagesize; ++i)
+ *(data2 + i) = *(data2 + i) + 1;
+ data3 = (char *) malloc (pagesize);
+ if (!data3)
+ exit (1);
+ if (read (fd, data3, pagesize) != pagesize)
+ exit (1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data3 + i))
+ exit (1);
+ close (fd);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_mmap_fixed_mapped=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5
+echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MMAP 1
+_ACEOF
+
+fi
+rm -f conftest.mmap
+
+ ;;
+esac
+
# If AtomicWord != Atomic32, we need to define two versions of all the
# atomicops functions. If they're the same, we want to define only one.
echo "$as_me:$LINENO: checking if int32_t is the same type as intptr_t" >&5
@@ -22108,10 +22273,20 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
done
if ! $pc_field_found; then
- { echo "$as_me:$LINENO: WARNING: Could not find the PC. libprofiler will probably not compile!" >&5
-echo "$as_me: WARNING: Could not find the PC. libprofiler will probably not compile!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: Could not find the PC. Will not try to compile libprofiler..." >&5
+echo "$as_me: WARNING: Could not find the PC. Will not try to compile libprofiler..." >&2;}
fi
+
+if test "$pc_field_found" = true; then
+ HAS_PC_TRUE=
+ HAS_PC_FALSE='#'
+else
+ HAS_PC_TRUE='#'
+ HAS_PC_FALSE=
+fi
+
+
# We want to link in libunwind if it exists
echo "$as_me:$LINENO: checking for backtrace in -lunwind" >&5
echo $ECHO_N "checking for backtrace in -lunwind... $ECHO_C" >&6
@@ -23011,50 +23186,99 @@ test -n "$PTHREAD_CC" || PTHREAD_CC="${CC}"
PTHREAD_CC=$CC
fi
- # The next part tries to detect GCC inconsistency with -shared on some
- # architectures and systems. The problem is that in certain
- # configurations, when -shared is specified, GCC "forgets" to
- # internally use various flags which are still necessary.
+ # The next part tries to detect GCC inconsistency with -shared on some
+ # architectures and systems. The problem is that in certain
+ # configurations, when -shared is specified, GCC "forgets" to
+ # internally use various flags which are still necessary.
- echo "$as_me:$LINENO: checking whether to check for GCC pthread/shared inconsistencies" >&5
+ #
+ # Prepare the flags
+ #
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+ save_CC="$CC"
+
+ # Try with the flags determined by the earlier checks.
+ #
+ # -Wl,-z,defs forces link-time symbol resolution, so that the
+ # linking checks with -shared actually have any value
+ #
+ # FIXME: -fPIC is required for -shared on many architectures,
+ # so we specify it here, but the right way would probably be to
+ # properly detect whether it is actually required.
+ CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CC="$PTHREAD_CC"
+
+ # In order not to create several levels of indentation, we test
+ # the value of "$done" until we find the cure or run out of ideas.
+ done="no"
+
+ # First, make sure the CFLAGS we added are actually accepted by our
+ # compiler. If not (and OS X's ld, for instance, does not accept -z),
+ # then we can't do this test.
+ if test x"$done" = xno; then
+ echo "$as_me:$LINENO: checking whether to check for GCC pthread/shared inconsistencies" >&5
echo $ECHO_N "checking whether to check for GCC pthread/shared inconsistencies... $ECHO_C" >&6
- check_inconsistencies=yes
- case "${host_cpu}-${host_os}" in
- *-darwin*) check_inconsistencies=no ;;
- esac
- if test x"$GCC" != xyes -o "x$check_inconsistencies" != xyes ; then
- echo "$as_me:$LINENO: result: no" >&5
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+done=yes
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+ if test "x$done" = xyes ; then
+ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
- else
- echo "$as_me:$LINENO: result: yes" >&5
+ else
+ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
+ fi
+ fi
- # In order not to create several levels of indentation, we test
- # the value of "$ok" until we find out the cure or run out of
- # ideas.
- ok="no"
-
- #
- # Prepare the flags
- #
- save_CFLAGS="$CFLAGS"
- save_LIBS="$LIBS"
- save_CC="$CC"
- # Try with the flags determined by the earlier checks.
- #
- # -Wl,-z,defs forces link-time symbol resolution, so that the
- # linking checks with -shared actually have any value
- #
- # FIXME: -fPIC is required for -shared on many architectures,
- # so we specify it here, but the right way would probably be to
- # properly detect whether it is actually required.
- CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS"
- LIBS="$PTHREAD_LIBS $LIBS"
- CC="$PTHREAD_CC"
-
- echo "$as_me:$LINENO: checking whether -pthread is sufficient with -shared" >&5
+ if test x"$done" = xno; then
+ echo "$as_me:$LINENO: checking whether -pthread is sufficient with -shared" >&5
echo $ECHO_N "checking whether -pthread is sufficient with -shared... $ECHO_C" >&6
- cat >conftest.$ac_ext <<_ACEOF
+ cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
@@ -23065,8 +23289,8 @@ int
main ()
{
pthread_t th; pthread_join(th, 0);
- pthread_attr_init(0); pthread_cleanup_push(0, 0);
- pthread_create(0,0,0,0); pthread_cleanup_pop(0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0);
;
return 0;
}
@@ -23092,7 +23316,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ok=yes
+ done=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
@@ -23101,23 +23325,24 @@ fi
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
- if test "x$ok" = xyes; then
- echo "$as_me:$LINENO: result: yes" >&5
+ if test "x$done" = xyes; then
+ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
- else
- echo "$as_me:$LINENO: result: no" >&5
+ else
+ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
- fi
+ fi
+ fi
- #
- # Linux gcc on some architectures such as mips/mipsel forgets
- # about -lpthread
- #
- if test x"$ok" = xno; then
- echo "$as_me:$LINENO: checking whether -lpthread fixes that" >&5
+ #
+ # Linux gcc on some architectures such as mips/mipsel forgets
+ # about -lpthread
+ #
+ if test x"$done" = xno; then
+ echo "$as_me:$LINENO: checking whether -lpthread fixes that" >&5
echo $ECHO_N "checking whether -lpthread fixes that... $ECHO_C" >&6
- LIBS="-lpthread $PTHREAD_LIBS $save_LIBS"
- cat >conftest.$ac_ext <<_ACEOF
+ LIBS="-lpthread $PTHREAD_LIBS $save_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
@@ -23128,8 +23353,8 @@ int
main ()
{
pthread_t th; pthread_join(th, 0);
- pthread_attr_init(0); pthread_cleanup_push(0, 0);
- pthread_create(0,0,0,0); pthread_cleanup_pop(0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0);
;
return 0;
}
@@ -23155,7 +23380,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ok=yes
+ done=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
@@ -23164,23 +23389,23 @@ fi
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
- if test "x$ok" = xyes; then
- echo "$as_me:$LINENO: result: yes" >&5
+ if test "x$done" = xyes; then
+ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
- PTHREAD_LIBS="-lpthread $PTHREAD_LIBS"
- else
- echo "$as_me:$LINENO: result: no" >&5
+ PTHREAD_LIBS="-lpthread $PTHREAD_LIBS"
+ else
+ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
- fi
- fi
- #
- # FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc
- #
- if test x"$ok" = xno; then
- echo "$as_me:$LINENO: checking whether -lc_r fixes that" >&5
+ fi
+ fi
+ #
+ # FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc
+ #
+ if test x"$done" = xno; then
+ echo "$as_me:$LINENO: checking whether -lc_r fixes that" >&5
echo $ECHO_N "checking whether -lc_r fixes that... $ECHO_C" >&6
- LIBS="-lc_r $PTHREAD_LIBS $save_LIBS"
- cat >conftest.$ac_ext <<_ACEOF
+ LIBS="-lc_r $PTHREAD_LIBS $save_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
@@ -23191,8 +23416,8 @@ int
main ()
{
pthread_t th; pthread_join(th, 0);
- pthread_attr_init(0); pthread_cleanup_push(0, 0);
- pthread_create(0,0,0,0); pthread_cleanup_pop(0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0);
;
return 0;
}
@@ -23218,7 +23443,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ok=yes
+ done=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
@@ -23227,28 +23452,27 @@ fi
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
- if test "x$ok" = xyes; then
- echo "$as_me:$LINENO: result: yes" >&5
+ if test "x$done" = xyes; then
+ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
- PTHREAD_LIBS="-lc_r $PTHREAD_LIBS"
- else
- echo "$as_me:$LINENO: result: no" >&5
+ PTHREAD_LIBS="-lc_r $PTHREAD_LIBS"
+ else
+ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
- fi
- fi
- if test x"$ok" = xno; then
- # OK, we have run out of ideas
- { echo "$as_me:$LINENO: WARNING: Impossible to determine how to use pthreads with shared libraries" >&5
+ fi
+ fi
+ if test x"$done" = xno; then
+ # OK, we have run out of ideas
+ { echo "$as_me:$LINENO: WARNING: Impossible to determine how to use pthreads with shared libraries" >&5
echo "$as_me: WARNING: Impossible to determine how to use pthreads with shared libraries" >&2;}
- # so it's not safe to assume that we may use pthreads
- acx_pthread_ok=no
- fi
+ # so it's not safe to assume that we may use pthreads
+ acx_pthread_ok=no
+ fi
- CFLAGS="$save_CFLAGS"
- LIBS="$save_LIBS"
- CC="$save_CC"
- fi
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+ CC="$save_CC"
else
PTHREAD_CC="$CC"
fi
@@ -23800,6 +24024,13 @@ echo "$as_me: error: conditional \"GCC\" was never defined.
Usually this means the macro was only invoked conditionally." >&2;}
{ (exit 1); exit 1; }; }
fi
+if test -z "${HAS_PC_TRUE}" && test -z "${HAS_PC_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"HAS_PC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"HAS_PC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
if test -z "${ENABLE_FRAME_POINTERS_TRUE}" && test -z "${ENABLE_FRAME_POINTERS_FALSE}"; then
{ { echo "$as_me:$LINENO: error: conditional \"ENABLE_FRAME_POINTERS\" was never defined.
Usually this means the macro was only invoked conditionally." >&5
@@ -24092,7 +24323,7 @@ _ASBOX
} >&5
cat >&5 <<_CSEOF
-This file was extended by google-perftools $as_me 0.97, which was
+This file was extended by google-perftools $as_me 0.98, which was
generated by GNU Autoconf 2.59. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -24155,7 +24386,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-google-perftools config.status 0.97
+google-perftools config.status 0.98
configured by $0, generated by GNU Autoconf 2.59,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
@@ -24425,6 +24656,8 @@ s,@FFLAGS@,$FFLAGS,;t t
s,@ac_ct_F77@,$ac_ct_F77,;t t
s,@LIBTOOL@,$LIBTOOL,;t t
s,@LIBTOOL_DEPS@,$LIBTOOL_DEPS,;t t
+s,@HAS_PC_TRUE@,$HAS_PC_TRUE,;t t
+s,@HAS_PC_FALSE@,$HAS_PC_FALSE,;t t
s,@UNWIND_LIBS@,$UNWIND_LIBS,;t t
s,@ENABLE_FRAME_POINTERS_TRUE@,$ENABLE_FRAME_POINTERS_TRUE,;t t
s,@ENABLE_FRAME_POINTERS_FALSE@,$ENABLE_FRAME_POINTERS_FALSE,;t t
diff --git a/configure.ac b/configure.ac
index e8abd24..72361d1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@
# make sure we're interpreted by some minimal autoconf
AC_PREREQ(2.57)
-AC_INIT(google-perftools, 0.97, opensource@google.com)
+AC_INIT(google-perftools, 0.98, opensource@google.com)
# The argument here is just something that should be in the current directory
# (for sanity checking)
AC_CONFIG_SRCDIR(README)
@@ -31,7 +31,6 @@ AC_CHECK_TYPES([__int64]) # defined in some windows platforms
AC_CHECK_TYPES([struct mallinfo],,, [#include <malloc.h>])
AC_CHECK_FUNCS(sbrk) # for tcmalloc to get memory
AC_CHECK_FUNCS(geteuid) # for turning off services when run as root
-AC_FUNC_MMAP
AC_CHECK_HEADERS(malloc.h) # some systems define stuff there, others not
AC_CHECK_HEADERS(glob.h) # for heap-profile-table (cleaning up profiles)
AC_CHECK_HEADERS(execinfo.h) # for stacktrace? and heapchecker_unittest
@@ -45,6 +44,7 @@ AC_CHECK_HEADERS(sys/syscall.h)
AC_CHECK_HEADERS(fcntl.h) # for tcmalloc_unittest
AC_CHECK_HEADERS(grp.h) # for heapchecker_unittest
AC_CHECK_HEADERS(pwd.h) # for heapchecker_unittest
+AC_CHECK_HEADERS(sys/resource.h) # for memalign_unittest.cc
# We override a lot of memory allocation routines, not all of which are
# standard. For those the system doesn't declare, we'll declare ourselves.
AC_CHECK_DECLS([cfree,
@@ -56,6 +56,20 @@ AC_CHECK_DECLS([cfree,
#include <stdlib.h>
#include <malloc.h>])
+# We need to check for mmap. cygwin supports mmap, but the autoconf
+# test doesn't work on cygwin:
+# http://www.cygwin.com/ml/cygwin/2002-04/msg00412.html
+# This workaround comes from
+# http://cygwin.com/ml/cygwin/2004-11/msg00138.html
+case "$host" in
+ *-*-cygwin*) ac_cv_func_mmap_fixed_mapped=yes
+ AC_DEFINE(HAVE_MMAP, 1,
+ [Define to 1 if you have a working `mmap' system call.])
+ ;;
+ *) AC_FUNC_MMAP
+ ;;
+esac
+
# If AtomicWord != Atomic32, we need to define two versions of all the
# atomicops functions. If they're the same, we want to define only one.
AC_MSG_CHECKING([if int32_t is the same type as intptr_t])
@@ -97,8 +111,9 @@ for pc_field in $pc_fields; do
fi
done
if ! $pc_field_found; then
- AC_MSG_WARN(Could not find the PC. libprofiler will probably not compile!)
+ AC_MSG_WARN(Could not find the PC. Will not try to compile libprofiler...)
fi
+AM_CONDITIONAL(HAS_PC, test "$pc_field_found" = true)
# We want to link in libunwind if it exists
AC_CHECK_LIB(unwind, backtrace, UNWIND_LIBS=-lunwind, UNWIND_LIBS=)
diff --git a/doc/cpuprofile.html b/doc/cpuprofile.html
index c3ba2de..4f71c02 100644
--- a/doc/cpuprofile.html
+++ b/doc/cpuprofile.html
@@ -51,8 +51,8 @@ for a given run of an executable:</p>
<ol>
<li> <p>Define the environment variable CPUPROFILE to the filename
to dump the profile to. For instance, to profile
- <code>/usr/local/bin/my_binary_compiled_with_tcmalloc</code>:</p>
- <pre>% env CPUPROFILE=/tmp/mybin.prof /usr/local/bin/my_binary_compiled_with_tcmalloc</pre>
+ <code>/usr/local/bin/my_binary_compiled_with_libprofiler_so</code>:</p>
+ <pre>% env CPUPROFILE=/tmp/mybin.prof /usr/local/bin/my_binary_compiled_with_libprofiler_so</pre>
<li> <p>In your code, bracket the code you want profiled in calls to
<code>ProfilerStart()</code> and <code>ProfilerStop()</code>.
@@ -122,6 +122,8 @@ detail below.</p>
(Per-PC) annotated disassembly for getdir()
% pprof --text localhost:1234
Outputs one line per procedure for localhost:1234
+% pprof --callgrind /bin/ls ls.prof
+ Outputs the call information in callgrind format
</pre>
@@ -142,6 +144,23 @@ detail below.</p>
<li> Function name
</ol>
+<h3>Analyzing Callgrind Output</h3>
+
+<p>Use <a href="http://kcachegrind.sourceforge.net">kcachegrind</a> to
+analyze your callgrind output:</p>
+<pre>
+% pprof --callgrind /bin/ls ls.prof > ls.callgrind
+% kcachegrind ls.callgrind
+</pre>
+
+<p>The cost is specified in 'hits', i.e. how many times a function
+appears in the recorded call stack information. The 'calls' from
+function a to b record how many times function b was found in the
+stack traces directly below function a.</p>
+
+<p>Tip: if you use a debug build the output will include file and line
+number information and kcachegrind will show an annotated source
+code view.</p>
<h3>Node Information</h3>
@@ -477,7 +496,7 @@ add up to only 40.</p>
<address>Sanjay Ghemawat<br>
<!-- Created: Tue Dec 19 10:43:14 PST 2000 -->
<!-- hhmts start -->
-Last modified: Sat Feb 24 13:11:38 PST 2007 (csilvers)
+Last modified: Fri May 9 14:41:29 PDT 2008
<!-- hhmts end -->
</address>
</BODY>
diff --git a/google-perftools.sln b/google-perftools.sln
index 5b5b495..8dc36b6 100755
--- a/google-perftools.sln
+++ b/google-perftools.sln
@@ -40,11 +40,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "packed-cache_test", "vsproj
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "system_alloc_unittest", "vsprojects\system_alloc_unittest\system_alloc_unittest.vcproj", "{8249D44B-4CF5-4BDC-9183-C5D6F12413E7}"
- ProjectSection(ProjectDependencies) = postProject
- {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F} = {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}
- EndProjectSection
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "thread_dealloc_unittest", "vsprojects\thread_dealloc_unittest\thread_dealloc_unittest.vcproj", "{6CFFBD0F-09E3-4282-A711-0564451FDF74}"
ProjectSection(ProjectDependencies) = postProject
{55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F} = {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}
@@ -98,10 +93,6 @@ Global
{605D3CED-B530-424E-B7D2-2A31F14FD570}.Debug.Build.0 = Debug|Win32
{605D3CED-B530-424E-B7D2-2A31F14FD570}.Release.ActiveCfg = Release|Win32
{605D3CED-B530-424E-B7D2-2A31F14FD570}.Release.Build.0 = Release|Win32
- {8249D44B-4CF5-4BDC-9183-C5D6F12413E7}.Debug.ActiveCfg = Debug|Win32
- {8249D44B-4CF5-4BDC-9183-C5D6F12413E7}.Debug.Build.0 = Debug|Win32
- {8249D44B-4CF5-4BDC-9183-C5D6F12413E7}.Release.ActiveCfg = Release|Win32
- {8249D44B-4CF5-4BDC-9183-C5D6F12413E7}.Release.Build.0 = Release|Win32
{6CFFBD0F-09E3-4282-A711-0564451FDF74}.Debug.ActiveCfg = Debug|Win32
{6CFFBD0F-09E3-4282-A711-0564451FDF74}.Debug.Build.0 = Debug|Win32
{6CFFBD0F-09E3-4282-A711-0564451FDF74}.Release.ActiveCfg = Release|Win32
diff --git a/m4/acx_pthread.m4 b/m4/acx_pthread.m4
index f5db4f0..2cf20de 100644
--- a/m4/acx_pthread.m4
+++ b/m4/acx_pthread.m4
@@ -1,7 +1,12 @@
# This was retrieved from
-# http://0pointer.de/cgi-bin/viewcvs.cgi/trunk/common/acx_pthread.m4?rev=1227
+# http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?revision=1277&root=avahi
# See also (perhaps for new versions?)
-# http://0pointer.de/cgi-bin/viewcvs.cgi/trunk/common/acx_pthread.m4
+# http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?root=avahi
+#
+# We've rewritten the inconsistency check code (from avahi), to work
+# more broadly. In particular, it no longer assumes ld accepts -zdefs.
+# This caused a restructing of the code, but the functionality has only
+# changed a little.
dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
dnl
@@ -231,108 +236,113 @@ if test "x$acx_pthread_ok" = xyes; then
PTHREAD_CC=$CC
fi
- # The next part tries to detect GCC inconsistency with -shared on some
- # architectures and systems. The problem is that in certain
- # configurations, when -shared is specified, GCC "forgets" to
- # internally use various flags which are still necessary.
-
- AC_MSG_CHECKING([whether to check for GCC pthread/shared inconsistencies])
- check_inconsistencies=yes
- case "${host_cpu}-${host_os}" in
- *-darwin*) check_inconsistencies=no ;;
- esac
- if test x"$GCC" != xyes -o "x$check_inconsistencies" != xyes ; then
- AC_MSG_RESULT([no])
- else
- AC_MSG_RESULT([yes])
-
- # In order not to create several levels of indentation, we test
- # the value of "$ok" until we find out the cure or run out of
- # ideas.
- ok="no"
-
- #
- # Prepare the flags
- #
- save_CFLAGS="$CFLAGS"
- save_LIBS="$LIBS"
- save_CC="$CC"
- # Try with the flags determined by the earlier checks.
- #
- # -Wl,-z,defs forces link-time symbol resolution, so that the
- # linking checks with -shared actually have any value
- #
- # FIXME: -fPIC is required for -shared on many architectures,
- # so we specify it here, but the right way would probably be to
- # properly detect whether it is actually required.
- CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS"
- LIBS="$PTHREAD_LIBS $LIBS"
- CC="$PTHREAD_CC"
-
- AC_MSG_CHECKING([whether -pthread is sufficient with -shared])
- AC_TRY_LINK([#include <pthread.h>],
- [pthread_t th; pthread_join(th, 0);
- pthread_attr_init(0); pthread_cleanup_push(0, 0);
- pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
- [ok=yes])
-
- if test "x$ok" = xyes; then
- AC_MSG_RESULT([yes])
- else
- AC_MSG_RESULT([no])
- fi
-
- #
- # Linux gcc on some architectures such as mips/mipsel forgets
- # about -lpthread
- #
- if test x"$ok" = xno; then
- AC_MSG_CHECKING([whether -lpthread fixes that])
- LIBS="-lpthread $PTHREAD_LIBS $save_LIBS"
- AC_TRY_LINK([#include <pthread.h>],
- [pthread_t th; pthread_join(th, 0);
- pthread_attr_init(0); pthread_cleanup_push(0, 0);
- pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
- [ok=yes])
-
- if test "x$ok" = xyes; then
- AC_MSG_RESULT([yes])
- PTHREAD_LIBS="-lpthread $PTHREAD_LIBS"
- else
- AC_MSG_RESULT([no])
- fi
- fi
- #
- # FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc
- #
- if test x"$ok" = xno; then
- AC_MSG_CHECKING([whether -lc_r fixes that])
- LIBS="-lc_r $PTHREAD_LIBS $save_LIBS"
- AC_TRY_LINK([#include <pthread.h>],
- [pthread_t th; pthread_join(th, 0);
- pthread_attr_init(0); pthread_cleanup_push(0, 0);
- pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
- [ok=yes])
-
- if test "x$ok" = xyes; then
- AC_MSG_RESULT([yes])
- PTHREAD_LIBS="-lc_r $PTHREAD_LIBS"
- else
- AC_MSG_RESULT([no])
- fi
- fi
- if test x"$ok" = xno; then
- # OK, we have run out of ideas
- AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries])
-
- # so it's not safe to assume that we may use pthreads
- acx_pthread_ok=no
- fi
-
- CFLAGS="$save_CFLAGS"
- LIBS="$save_LIBS"
- CC="$save_CC"
- fi
+ # The next part tries to detect GCC inconsistency with -shared on some
+ # architectures and systems. The problem is that in certain
+ # configurations, when -shared is specified, GCC "forgets" to
+ # internally use various flags which are still necessary.
+
+ #
+ # Prepare the flags
+ #
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+ save_CC="$CC"
+
+ # Try with the flags determined by the earlier checks.
+ #
+ # -Wl,-z,defs forces link-time symbol resolution, so that the
+ # linking checks with -shared actually have any value
+ #
+ # FIXME: -fPIC is required for -shared on many architectures,
+ # so we specify it here, but the right way would probably be to
+ # properly detect whether it is actually required.
+ CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CC="$PTHREAD_CC"
+
+ # In order not to create several levels of indentation, we test
+ # the value of "$done" until we find the cure or run out of ideas.
+ done="no"
+
+ # First, make sure the CFLAGS we added are actually accepted by our
+ # compiler. If not (and OS X's ld, for instance, does not accept -z),
+ # then we can't do this test.
+ if test x"$done" = xno; then
+ AC_MSG_CHECKING([whether to check for GCC pthread/shared inconsistencies])
+ AC_TRY_LINK(,, , [done=yes])
+
+ if test "x$done" = xyes ; then
+ AC_MSG_RESULT([no])
+ else
+ AC_MSG_RESULT([yes])
+ fi
+ fi
+
+ if test x"$done" = xno; then
+ AC_MSG_CHECKING([whether -pthread is sufficient with -shared])
+ AC_TRY_LINK([#include <pthread.h>],
+ [pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+ [done=yes])
+
+ if test "x$done" = xyes; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ fi
+
+ #
+ # Linux gcc on some architectures such as mips/mipsel forgets
+ # about -lpthread
+ #
+ if test x"$done" = xno; then
+ AC_MSG_CHECKING([whether -lpthread fixes that])
+ LIBS="-lpthread $PTHREAD_LIBS $save_LIBS"
+ AC_TRY_LINK([#include <pthread.h>],
+ [pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+ [done=yes])
+
+ if test "x$done" = xyes; then
+ AC_MSG_RESULT([yes])
+ PTHREAD_LIBS="-lpthread $PTHREAD_LIBS"
+ else
+ AC_MSG_RESULT([no])
+ fi
+ fi
+ #
+ # FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc
+ #
+ if test x"$done" = xno; then
+ AC_MSG_CHECKING([whether -lc_r fixes that])
+ LIBS="-lc_r $PTHREAD_LIBS $save_LIBS"
+ AC_TRY_LINK([#include <pthread.h>],
+ [pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+ [done=yes])
+
+ if test "x$done" = xyes; then
+ AC_MSG_RESULT([yes])
+ PTHREAD_LIBS="-lc_r $PTHREAD_LIBS"
+ else
+ AC_MSG_RESULT([no])
+ fi
+ fi
+ if test x"$done" = xno; then
+ # OK, we have run out of ideas
+ AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries])
+
+ # so it's not safe to assume that we may use pthreads
+ acx_pthread_ok=no
+ fi
+
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+ CC="$save_CC"
else
PTHREAD_CC="$CC"
fi
diff --git a/packages/deb/changelog b/packages/deb/changelog
index 95e7117..11b0560 100644
--- a/packages/deb/changelog
+++ b/packages/deb/changelog
@@ -1,3 +1,9 @@
+google-perftools (0.98-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Mon, 09 Jun 2008 16:47:03 -0700
+
google-perftools (0.97-1) unstable; urgency=low
* New upstream release.
diff --git a/src/addressmap-inl.h b/src/addressmap-inl.h
index 1a1ab3b..c6041b0 100644
--- a/src/addressmap-inl.h
+++ b/src/addressmap-inl.h
@@ -77,8 +77,8 @@
// b. An array access in the cluster structure
// c. A traversal over the linked-list for a block
-#ifndef BASE_ADDRESSMAP_INL_H__
-#define BASE_ADDRESSMAP_INL_H__
+#ifndef BASE_ADDRESSMAP_INL_H_
+#define BASE_ADDRESSMAP_INL_H_
#include "config.h"
#include <stddef.h>
@@ -418,4 +418,4 @@ inline void AddressMap<Value>::Iterate(void (*callback)(Key, Value*, Type),
}
}
-#endif // BASE_ADDRESSMAP_INL_H__
+#endif // BASE_ADDRESSMAP_INL_H_
diff --git a/src/base/atomicops-internals-linuxppc.h b/src/base/atomicops-internals-linuxppc.h
index 09d227a..371dc8f 100644
--- a/src/base/atomicops-internals-linuxppc.h
+++ b/src/base/atomicops-internals-linuxppc.h
@@ -34,8 +34,8 @@
// be included directly. Clients should instead include
// "base/atomicops.h".
-#ifndef BASE_ATOMICOPS_INTERNALS_LINUXPPC_H__
-#define BASE_ATOMICOPS_INTERNALS_LINUXPPC_H__
+#ifndef BASE_ATOMICOPS_INTERNALS_LINUXPPC_H_
+#define BASE_ATOMICOPS_INTERNALS_LINUXPPC_H_
// int32_t and intptr_t seems to be equal on ppc-linux
// There are no Atomic64 implementations in this file.
@@ -222,4 +222,4 @@ inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
inline void MemoryBarrier() {
base::subtle::MemoryBarrier();
}
-#endif // BASE_ATOMICOPS_INTERNALS_LINUXPPC_H__
+#endif // BASE_ATOMICOPS_INTERNALS_LINUXPPC_H_
diff --git a/src/base/atomicops-internals-macosx.h b/src/base/atomicops-internals-macosx.h
index 18c2d3c..84f1d03 100644
--- a/src/base/atomicops-internals-macosx.h
+++ b/src/base/atomicops-internals-macosx.h
@@ -35,8 +35,8 @@
// be included directly. Clients should instead include
// "base/atomicops.h".
-#ifndef BASE_ATOMICOPS_INTERNALS_MACOSX_H__
-#define BASE_ATOMICOPS_INTERNALS_MACOSX_H__
+#ifndef BASE_ATOMICOPS_INTERNALS_MACOSX_H_
+#define BASE_ATOMICOPS_INTERNALS_MACOSX_H_
typedef int32_t Atomic32;
@@ -357,4 +357,4 @@ inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
inline void MemoryBarrier() {
base::subtle::MemoryBarrier();
}
-#endif // BASE_ATOMICOPS_INTERNALS_MACOSX_H__
+#endif // BASE_ATOMICOPS_INTERNALS_MACOSX_H_
diff --git a/src/base/atomicops-internals-x86-msvc.h b/src/base/atomicops-internals-x86-msvc.h
index 4fc2d6e..a2c685a 100644
--- a/src/base/atomicops-internals-x86-msvc.h
+++ b/src/base/atomicops-internals-x86-msvc.h
@@ -35,8 +35,8 @@
// be included directly. Clients should instead include
// "base/atomicops.h".
-#ifndef BASE_ATOMICOPS_INTERNALS_X86_MSVC_H__
-#define BASE_ATOMICOPS_INTERNALS_X86_MSVC_H__
+#ifndef BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
+#define BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
#include "base/basictypes.h" // For COMPILE_ASSERT
typedef int32 Atomic32;
@@ -52,6 +52,24 @@ typedef int64 Atomic64;
// 32-bit low-level operations on any platform
+// MinGW has a bug in the header files where it doesn't indicate the
+// first argument is volatile -- they're not up to date. See
+// http://readlist.com/lists/lists.sourceforge.net/mingw-users/0/3861.html
+// We have to const_cast away the volatile to avoid compiler warnings.
+// TODO(csilvers): remove this once MinGW has updated MinGW/include/winbase.h
+#ifdef __MINGW32__
+inline LONG InterlockedCompareExchange(volatile LONG* ptr,
+ LONG newval, LONG oldval) {
+ return ::InterlockedCompareExchange(const_cast<LONG*>(ptr), newval, oldval);
+}
+inline LONG InterlockedExchange(volatile LONG* ptr, LONG newval) {
+ return ::InterlockedExchange(const_cast<LONG*>(ptr), newval);
+}
+inline LONG InterlockedExchangeAdd(volatile LONG* ptr, LONG increment) {
+ return ::InterlockedExchangeAdd(const_cast<LONG*>(ptr), increment);
+}
+#endif // ifdef __MINGW32__
+
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
@@ -86,8 +104,9 @@ inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
} // namespace base
-// In msvc8/vs2005, winnt.h already contains a definition for MemoryBarrier.
-// Defined it outside the namespace.
+// In msvc8/vs2005, winnt.h already contains a definition for
+// MemoryBarrier in the global namespace. Add it there for earlier
+// versions and forward to it from within the namespace.
#if !(defined(_MSC_VER) && _MSC_VER >= 1400)
inline void MemoryBarrier() {
Atomic32 value = 0;
@@ -99,6 +118,10 @@ inline void MemoryBarrier() {
namespace base {
namespace subtle {
+inline void MemoryBarrier() {
+ ::MemoryBarrier();
+}
+
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
@@ -141,12 +164,29 @@ inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
// 64-bit operations
-#if defined(_WIN64)
+#if defined(_WIN64) || defined(__MINGW64__)
// 64-bit low-level operations on 64-bit platform.
COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic);
+// Like for the __MINGW32__ case above, this works around a header
+// error in mingw, where it's missing 'volatile'.
+#ifdef __MINGW64__
+inline PVOID InterlockedCompareExchangePointer(volatile PVOID* ptr,
+ PVOID newval, PVOID oldval) {
+ return ::InterlockedCompareExchangePointer(const_cast<PVOID*>(ptr),
+ newval, oldval);
+}
+inline PVOID InterlockedExchangePointer(volatile PVOID* ptr, PVOID newval) {
+ return ::InterlockedExchangePointer(const_cast<PVOID*>(ptr), newval);
+}
+inline LONGLONG InterlockedExchangeAdd64(volatile LONGLONG* ptr,
+ LONGLONG increment) {
+ return ::InterlockedExchangeAdd64(const_cast<LONGLONG*>(ptr), increment);
+}
+#endif // ifdef __MINGW64__
+
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
@@ -159,7 +199,7 @@ inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
Atomic64 new_value) {
PVOID result = InterlockedExchangePointer(
- const_cast<PVOID*>(reinterpret_cast<volatile PVOID*>(ptr)),
+ reinterpret_cast<volatile PVOID*>(ptr),
reinterpret_cast<PVOID>(new_value));
return reinterpret_cast<Atomic64>(result);
}
@@ -210,7 +250,7 @@ inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
return *ptr;
}
-#else // defined(_WIN64)
+#else // defined(_WIN64) || defined(__MINGW64__)
// 64-bit low-level operations on 32-bit platform
@@ -353,7 +393,7 @@ inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
return NoBarrier_Load(ptr);
}
-#endif // defined(_WIN64)
+#endif // defined(_WIN64) || defined(__MINGW64__)
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
@@ -371,4 +411,4 @@ inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
} // namespace base::subtle
} // namespace base
-#endif // BASE_ATOMICOPS_INTERNALS_X86_MSVC_H__
+#endif // BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
diff --git a/src/base/atomicops-internals-x86.cc b/src/base/atomicops-internals-x86.cc
index 1a6c24f..39ed73d 100644
--- a/src/base/atomicops-internals-x86.cc
+++ b/src/base/atomicops-internals-x86.cc
@@ -44,7 +44,7 @@
// depends on structs that are defined in that file. If atomicops.h
// doesn't sub-include that file, then we aren't needed, and shouldn't
// try to do anything.
-#ifdef BASE_ATOMICOPS_INTERNALS_X86_H__
+#ifdef BASE_ATOMICOPS_INTERNALS_X86_H_
// Inline cpuid instruction. In PIC compilations, %ebx contains the address
// of the global offset table. To avoid breaking such executables, this code
@@ -124,4 +124,4 @@ REGISTER_MODULE_INITIALIZER(atomicops_x86, {
#endif
-#endif /* ifdef BASE_ATOMICOPS_INTERNALS_X86_H__ */
+#endif /* ifdef BASE_ATOMICOPS_INTERNALS_X86_H_ */
diff --git a/src/base/atomicops-internals-x86.h b/src/base/atomicops-internals-x86.h
index 68839cc..03b4c81 100644
--- a/src/base/atomicops-internals-x86.h
+++ b/src/base/atomicops-internals-x86.h
@@ -35,8 +35,8 @@
// be included directly. Clients should instead include
// "base/atomicops.h".
-#ifndef BASE_ATOMICOPS_INTERNALS_X86_H__
-#define BASE_ATOMICOPS_INTERNALS_X86_H__
+#ifndef BASE_ATOMICOPS_INTERNALS_X86_H_
+#define BASE_ATOMICOPS_INTERNALS_X86_H_
typedef int32_t Atomic32;
#define BASE_HAS_ATOMIC64 1 // Use only in tests and base/atomic*
@@ -417,4 +417,4 @@ inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
inline void MemoryBarrier() {
base::subtle::MemoryBarrier();
}
-#endif // BASE_ATOMICOPS_INTERNALS_X86_H__
+#endif // BASE_ATOMICOPS_INTERNALS_X86_H_
diff --git a/src/base/atomicops.h b/src/base/atomicops.h
index 834f518..dcab3e8 100644
--- a/src/base/atomicops.h
+++ b/src/base/atomicops.h
@@ -63,11 +63,13 @@
// The intent is eventually to put all of these routines in namespace
// base::subtle
-#ifndef THREAD_ATOMICOPS_H__
-#define THREAD_ATOMICOPS_H__
+#ifndef THREAD_ATOMICOPS_H_
+#define THREAD_ATOMICOPS_H_
#include "config.h"
+#ifdef HAVE_STDINT_H
#include <stdint.h>
+#endif
// ------------------------------------------------------------------------
// Include the platform specific implementations of the types
@@ -87,10 +89,12 @@
// TODO(csilvers): match piii, not just __i386. Also, match k8
#if defined(__MACH__) && defined(__APPLE__)
#include "base/atomicops-internals-macosx.h"
+#elif defined(_MSC_VER) && defined(_M_IX86)
+#include "base/atomicops-internals-x86-msvc.h"
+#elif defined(__MINGW32__) && defined(__i386__)
+#include "base/atomicops-internals-x86-msvc.h"
#elif defined(__GNUC__) && (defined(__i386) || defined(ARCH_K8))
#include "base/atomicops-internals-x86.h"
-#elif defined(__i386) && defined(_MSC_VER)
-#include "base/atomicops-internals-x86-msvc.h"
#elif defined(__linux__) && defined(__PPC__)
#include "base/atomicops-internals-linuxppc.h"
#else
@@ -380,4 +384,4 @@ inline base::subtle::Atomic64 Release_Load(
#endif // BASE_HAS_ATOMIC64
-#endif // THREAD_ATOMICOPS_H__
+#endif // THREAD_ATOMICOPS_H_
diff --git a/src/base/commandlineflags.h b/src/base/commandlineflags.h
index 9514458..a5fcb8a 100644
--- a/src/base/commandlineflags.h
+++ b/src/base/commandlineflags.h
@@ -45,8 +45,8 @@
// We also put the type of the variable in the namespace, so that
// people can't DECLARE_int32 something that they DEFINE_bool'd
// elsewhere.
-#ifndef BASE_COMMANDLINEFLAGS_H__
-#define BASE_COMMANDLINEFLAGS_H__
+#ifndef BASE_COMMANDLINEFLAGS_H_
+#define BASE_COMMANDLINEFLAGS_H_
#include "config.h"
#include <string>
@@ -125,4 +125,4 @@
#define EnvToInt64(envname, dflt) \
(!getenv(envname) ? (dflt) : strtoll(getenv(envname), NULL, 10))
-#endif // BASE_COMMANDLINEFLAGS_H__
+#endif // BASE_COMMANDLINEFLAGS_H_
diff --git a/src/base/cycleclock.h b/src/base/cycleclock.h
index 9357cf6..bf014c4 100644
--- a/src/base/cycleclock.h
+++ b/src/base/cycleclock.h
@@ -34,8 +34,8 @@
// involve a system call and is much more precise.
// ----------------------------------------------------------------------
-#ifndef GOOGLE_BASE_CYCLECLOCK_H__
-#define GOOGLE_BASE_CYCLECLOCK_H__
+#ifndef GOOGLE_BASE_CYCLECLOCK_H_
+#define GOOGLE_BASE_CYCLECLOCK_H_
#include "base/basictypes.h" // make sure we get the def for int64
#if defined(__MACH__) && defined(__APPLE__)
@@ -99,4 +99,4 @@ struct CycleClock {
};
-#endif // GOOGLE_BASE_CYCLECLOCK_H__
+#endif // GOOGLE_BASE_CYCLECLOCK_H_
diff --git a/src/base/dynamic_annotations.cc b/src/base/dynamic_annotations.cc
index 0f441ed..66b3c45 100644
--- a/src/base/dynamic_annotations.cc
+++ b/src/base/dynamic_annotations.cc
@@ -36,28 +36,43 @@
// Each function is empty and called (via a macro) only in debug mode.
// The arguments are captured by dynamic tools at runtime.
-extern "C" void AnnotateRWLockCreate(const char *file, int line, void *lock){}
-extern "C" void AnnotateRWLockDestroy(const char *file, int line, void *lock){}
-extern "C" void AnnotateRWLockAcquired(const char *file, int line,
- void *lock, long is_w){}
-extern "C" void AnnotateRWLockReleased(const char *file, int line,
- void *lock, long is_w){}
-extern "C" void AnnotateCondVarWait(const char *file, int line, void *cv,
- void *lock){}
-extern "C" void AnnotateCondVarSignal(const char *file, int line, void *cv){}
-extern "C" void AnnotateCondVarSignalAll(const char *file, int line, void *cv){}
-extern "C" void AnnotatePCQCreate(const char *file, int line, void *pcq){}
-extern "C" void AnnotatePCQDestroy(const char *file, int line, void *pcq){}
-extern "C" void AnnotatePCQPut(const char *file, int line, void *pcq){}
-extern "C" void AnnotatePCQGet(const char *file, int line, void *pcq){}
-extern "C" void AnnotateNewMemory(const char *file, int line, void *mem,
+extern "C" void AnnotateRWLockCreate(const char *file, int line,
+ const volatile void *lock){}
+extern "C" void AnnotateRWLockDestroy(const char *file, int line,
+ const volatile void *lock){}
+extern "C" void AnnotateRWLockAcquired(const char *file, int line,
+ const volatile void *lock, long is_w){}
+extern "C" void AnnotateRWLockReleased(const char *file, int line,
+ const volatile void *lock, long is_w){}
+extern "C" void AnnotateCondVarWait(const char *file, int line,
+ const volatile void *cv,
+ const volatile void *lock){}
+extern "C" void AnnotateCondVarSignal(const char *file, int line,
+ const volatile void *cv){}
+extern "C" void AnnotateCondVarSignalAll(const char *file, int line,
+ const volatile void *cv){}
+extern "C" void AnnotatePCQCreate(const char *file, int line,
+ const volatile void *pcq){}
+extern "C" void AnnotatePCQDestroy(const char *file, int line,
+ const volatile void *pcq){}
+extern "C" void AnnotatePCQPut(const char *file, int line,
+ const volatile void *pcq){}
+extern "C" void AnnotatePCQGet(const char *file, int line,
+ const volatile void *pcq){}
+extern "C" void AnnotateNewMemory(const char *file, int line,
+ const volatile void *mem,
long size){}
-extern "C" void AnnotateExpectRace(const char *file, int line, void *mem,
+extern "C" void AnnotateExpectRace(const char *file, int line,
+ const volatile void *mem,
const char *description){}
-extern "C" void AnnotateBenignRace(const char *file, int line, void *mem,
+extern "C" void AnnotateBenignRace(const char *file, int line,
+ const volatile void *mem,
const char *description){}
-extern "C" void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
- void *mu){}
-extern "C" void AnnotateTraceMemory(const char *file, int line,
- const void *arg){}
-extern "C" void AnnotateNoOp(const char *file, int line, const void *arg){}
+extern "C" void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
+ const volatile void *mu){}
+extern "C" void AnnotateTraceMemory(const char *file, int line,
+ const volatile void *arg){}
+extern "C" void AnnotateIgnoreReadsBegin(const char *file, int line){}
+extern "C" void AnnotateIgnoreReadsEnd(const char *file, int line){}
+extern "C" void AnnotateNoOp(const char *file, int line,
+ const volatile void *arg){}
diff --git a/src/base/dynamic_annotations.h b/src/base/dynamic_annotations.h
index d619ffa..1a055cc 100644
--- a/src/base/dynamic_annotations.h
+++ b/src/base/dynamic_annotations.h
@@ -52,8 +52,8 @@
// Macros are defined as calls to non-inlinable empty functions
// that are intercepted by helgrind.
//
-#ifndef _BASE_DYNAMIC_ANNOTATIONS_H__
-#define _BASE_DYNAMIC_ANNOTATIONS_H__
+#ifndef BASE_DYNAMIC_ANNOTATIONS_H_
+#define BASE_DYNAMIC_ANNOTATIONS_H_
// All the annotation macros are in effect only in debug mode.
@@ -93,6 +93,9 @@
AnnotateCondVarSignalAll(__FILE__, __LINE__, cv)
// Report that "pcq" (ProducerConsumerQueue) has been created.
+ // The ANNOTATE_PCQ_* annotations should be used only for FIFO queues.
+ // For non-FIFO queues use ANNOTATE_CONDVAR_SIGNAL (for put) and
+ // ANNOTATE_CONDVAR_WAIT (for get).
#define ANNOTATE_PCQ_CREATE(pcq) \
AnnotatePCQCreate(__FILE__, __LINE__, pcq)
@@ -100,11 +103,11 @@
#define ANNOTATE_PCQ_DESTROY(pcq) \
AnnotatePCQDestroy(__FILE__, __LINE__, pcq)
- // Report that we are about to put an element into 'pcq'.
+ // Report that we are about to put an element into a FIFO queue 'pcq'.
#define ANNOTATE_PCQ_PUT(pcq) \
AnnotatePCQPut(__FILE__, __LINE__, pcq)
- // Report that we've just got an element from 'pcq'.
+ // Report that we've just got an element from a FIFO queue 'pcq'.
#define ANNOTATE_PCQ_GET(pcq) \
AnnotatePCQGet(__FILE__, __LINE__, pcq)
@@ -112,7 +115,7 @@
#define ANNOTATE_NEW_MEMORY(mem, size) \
AnnotateNewMemory(__FILE__, __LINE__, mem, size)
- // Report that we expect a race on 'mem'.
+ // Report that we expect a race on 'mem'.
// To use only in unit tests for a race detector.
#define ANNOTATE_EXPECT_RACE(mem, description) \
AnnotateExpectRace(__FILE__, __LINE__, mem, description)
@@ -120,10 +123,12 @@
// Report that we may have a benign race on 'mem'.
// Insert at the point where 'mem' exists, preferably close to the point
// where the race happens.
+ // See also ANNOTATE_BENIGN_RACE_STATIC.
#define ANNOTATE_BENIGN_RACE(mem, description) \
AnnotateBenignRace(__FILE__, __LINE__, mem, description)
- // Report that the mutex 'mu' will be used with LockWhen/Await.
+ // Instruct the tool to create a happens-before arc
+ // between mu->Unlock() and mu->Lock().
#define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) \
AnnotateMutexIsUsedAsCondVar(__FILE__, __LINE__, mu)
@@ -131,11 +136,23 @@
#define ANNOTATE_TRACE_MEMORY(arg) \
AnnotateTraceMemory(__FILE__, __LINE__, arg)
+ // Request the analysis tool to ignore all reads in the current thread
+ // until ANNOTATE_IGNORE_READS_END is called.
+ // Useful to ignore intentional racey reads, while still checking
+ // other reads and all writes.
+ // See also ANNOTATE_UNPROTECTED_READ.
+ #define ANNOTATE_IGNORE_READS_BEGIN() \
+ AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
+
+ // Stop ignoring reads.
+ #define ANNOTATE_IGNORE_READS_END() \
+ AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
+
// A no-op. Insert where you like to test the interceptors.
#define ANNOTATE_NO_OP(arg) \
AnnotateNoOp(__FILE__, __LINE__, arg)
-#else // NDEBUG is defined
+#else // NDEBUG is defined
#define ANNOTATE_RWLOCK_CREATE(lock) // empty
#define ANNOTATE_RWLOCK_DESTROY(lock) // empty
@@ -154,35 +171,83 @@
#define ANNOTATE_BENIGN_RACE(mem, description) // empty
#define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) // empty
#define ANNOTATE_TRACE_MEMORY(arg) // empty
+ #define ANNOTATE_IGNORE_READS_BEGIN() // empty
+ #define ANNOTATE_IGNORE_READS_END() // empty
#define ANNOTATE_NO_OP(arg) // empty
#endif // NDEBUG
// Use the macros above rather than using these functions directly.
-extern "C" void AnnotateRWLockCreate(const char *file, int line, void *lock);
-extern "C" void AnnotateRWLockDestroy(const char *file, int line, void *lock);
-extern "C" void AnnotateRWLockAcquired(const char *file, int line,
- void *lock, long is_w);
-extern "C" void AnnotateRWLockReleased(const char *file, int line,
- void *lock, long is_w);
-extern "C" void AnnotateCondVarWait(const char *file, int line, void *cv,
- void *lock);
-extern "C" void AnnotateCondVarSignal(const char *file, int line, void *cv);
-extern "C" void AnnotateCondVarSignalAll(const char *file, int line, void *cv);
-extern "C" void AnnotatePCQCreate(const char *file, int line, void *pcq);
-extern "C" void AnnotatePCQDestroy(const char *file, int line, void *pcq);
-extern "C" void AnnotatePCQPut(const char *file, int line, void *pcq);
-extern "C" void AnnotatePCQGet(const char *file, int line, void *pcq);
-extern "C" void AnnotateNewMemory(const char *file, int line, void *mem,
+extern "C" void AnnotateRWLockCreate(const char *file, int line,
+ const volatile void *lock);
+extern "C" void AnnotateRWLockDestroy(const char *file, int line,
+ const volatile void *lock);
+extern "C" void AnnotateRWLockAcquired(const char *file, int line,
+ const volatile void *lock, long is_w);
+extern "C" void AnnotateRWLockReleased(const char *file, int line,
+ const volatile void *lock, long is_w);
+extern "C" void AnnotateCondVarWait(const char *file, int line,
+ const volatile void *cv,
+ const volatile void *lock);
+extern "C" void AnnotateCondVarSignal(const char *file, int line,
+ const volatile void *cv);
+extern "C" void AnnotateCondVarSignalAll(const char *file, int line,
+ const volatile void *cv);
+extern "C" void AnnotatePCQCreate(const char *file, int line,
+ const volatile void *pcq);
+extern "C" void AnnotatePCQDestroy(const char *file, int line,
+ const volatile void *pcq);
+extern "C" void AnnotatePCQPut(const char *file, int line,
+ const volatile void *pcq);
+extern "C" void AnnotatePCQGet(const char *file, int line,
+ const volatile void *pcq);
+extern "C" void AnnotateNewMemory(const char *file, int line,
+ const volatile void *mem,
long size);
-extern "C" void AnnotateExpectRace(const char *file, int line, void *mem,
+extern "C" void AnnotateExpectRace(const char *file, int line,
+ const volatile void *mem,
const char *description);
-extern "C" void AnnotateBenignRace(const char *file, int line, void *mem,
+extern "C" void AnnotateBenignRace(const char *file, int line,
+ const volatile void *mem,
const char *description);
-extern "C" void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
- void *mu);
-extern "C" void AnnotateTraceMemory(const char *file, int line,
- const void *arg);
-extern "C" void AnnotateNoOp(const char *file, int line, const void *arg);
+extern "C" void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
+ const volatile void *mu);
+extern "C" void AnnotateTraceMemory(const char *file, int line,
+ const volatile void *arg);
+extern "C" void AnnotateIgnoreReadsBegin(const char *file, int line);
+extern "C" void AnnotateIgnoreReadsEnd(const char *file, int line);
+extern "C" void AnnotateNoOp(const char *file, int line,
+ const volatile void *arg);
-#endif // _BASE_DYNAMIC_ANNOTATIONS_H__
+
+// ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
+//
+// Instead of doing
+// ANNOTATE_IGNORE_READS_BEGIN();
+// ... = x;
+// ANNOTATE_IGNORE_READS_END();
+// one can use
+// ... = ANNOTATE_UNPROTECTED_READ(x);
+template <class T>
+inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x) {
+ ANNOTATE_IGNORE_READS_BEGIN();
+ T res = x;
+ ANNOTATE_IGNORE_READS_END();
+ return res;
+}
+
+// Apply ANNOTATE_BENIGN_RACE to a static variable.
+#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
+ namespace { \
+ class static_var ## _annotator { \
+ public: \
+ static_var ## _annotator() { \
+ ANNOTATE_BENIGN_RACE(&static_var, \
+ # static_var ": " description); \
+ } \
+ }; \
+ static static_var ## _annotator the ## static_var ## _annotator;\
+ }
+
+
+#endif // BASE_DYNAMIC_ANNOTATIONS_H_
diff --git a/src/base/linux_syscall_support.h b/src/base/linux_syscall_support.h
index 979452c..311be47 100644
--- a/src/base/linux_syscall_support.h
+++ b/src/base/linux_syscall_support.h
@@ -553,6 +553,26 @@ struct kernel_statfs {
#ifndef SA_RESTORER
#define SA_RESTORER 0x04000000
#endif
+#ifndef CPUCLOCK_PROF
+#define CPUCLOCK_PROF 0
+#endif
+#ifndef CPUCLOCK_VIRT
+#define CPUCLOCK_VIRT 1
+#endif
+#ifndef CPUCLOCK_SCHED
+#define CPUCLOCK_SCHED 2
+#endif
+#ifndef CPUCLOCK_PERTHREAD_MASK
+#define CPUCLOCK_PERTHREAD_MASK 4
+#endif
+#ifndef MAKE_PROCESS_CPUCLOCK
+#define MAKE_PROCESS_CPUCLOCK(pid, clock) \
+ ((~(int)(pid) << 3) | (int)(clock))
+#endif
+#ifndef MAKE_THREAD_CPUCLOCK
+#define MAKE_THREAD_CPUCLOCK(tid, clock) \
+ ((~(int)(tid) << 3) | (int)((clock) | CPUCLOCK_PERTHREAD_MASK))
+#endif
#if defined(__i386__)
#ifndef __NR_setresuid
@@ -609,6 +629,12 @@ struct kernel_statfs {
#ifndef __NR_lgetxattr
#define __NR_lgetxattr 230
#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr 232
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr 233
+#endif
#ifndef __NR_futex
#define __NR_futex 240
#endif
@@ -619,6 +645,12 @@ struct kernel_statfs {
#ifndef __NR_set_tid_address
#define __NR_set_tid_address 258
#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime 265
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres 266
+#endif
#ifndef __NR_statfs64
#define __NR_statfs64 268
#endif
@@ -628,6 +660,12 @@ struct kernel_statfs {
#ifndef __NR_fadvise64_64
#define __NR_fadvise64_64 272
#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set 289
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get 290
+#endif
#ifndef __NR_openat
#define __NR_openat 295
#endif
@@ -640,6 +678,9 @@ struct kernel_statfs {
#ifndef __NR_move_pages
#define __NR_move_pages 317
#endif
+#ifndef __NR_fallocate
+#define __NR_fallocate 324
+#endif
/* End of i386 definitions */
#elif defined(__ARM_ARCH_3__)
#ifndef __NR_setresuid
@@ -696,6 +737,12 @@ struct kernel_statfs {
#ifndef __NR_lgetxattr
#define __NR_lgetxattr (__NR_SYSCALL_BASE + 230)
#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr (__NR_SYSCALL_BASE + 232)
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr (__NR_SYSCALL_BASE + 233)
+#endif
#ifndef __NR_futex
#define __NR_futex (__NR_SYSCALL_BASE + 240)
#endif
@@ -706,17 +753,35 @@ struct kernel_statfs {
#ifndef __NR_set_tid_address
#define __NR_set_tid_address (__NR_SYSCALL_BASE + 256)
#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime (__NR_SYSCALL_BASE + 263)
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres (__NR_SYSCALL_BASE + 264)
+#endif
#ifndef __NR_statfs64
#define __NR_statfs64 (__NR_SYSCALL_BASE + 266)
#endif
#ifndef __NR_fstatfs64
#define __NR_fstatfs64 (__NR_SYSCALL_BASE + 267)
#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set (__NR_SYSCALL_BASE + 314)
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get (__NR_SYSCALL_BASE + 315)
+#endif
#ifndef __NR_move_pages
#define __NR_move_pages (__NR_SYSCALL_BASE + 344)
#endif
/* End of ARM 3 definitions */
#elif defined(__x86_64__)
+#ifndef __NR_pread64
+#define __NR_pread64 17
+#endif
+#ifndef __NR_pwrite64
+#define __NR_pwrite64 18
+#endif
#ifndef __NR_setresuid
#define __NR_setresuid 117
#define __NR_setresgid 119
@@ -739,6 +804,12 @@ struct kernel_statfs {
#ifndef __NR_lgetxattr
#define __NR_lgetxattr 192
#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr 194
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr 195
+#endif
#ifndef __NR_futex
#define __NR_futex 202
#endif
@@ -755,6 +826,18 @@ struct kernel_statfs {
#ifndef __NR_fadvise64
#define __NR_fadvise64 221
#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime 228
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres 229
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set 251
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get 252
+#endif
#ifndef __NR_openat
#define __NR_openat 257
#endif
@@ -767,6 +850,9 @@ struct kernel_statfs {
#ifndef __NR_move_pages
#define __NR_move_pages 279
#endif
+#ifndef __NR_fallocate
+#define __NR_fallocate 285
+#endif
/* End of x86-64 definitions */
#elif defined(__mips__)
#if _MIPS_SIM == _MIPS_SIM_ABI32
@@ -813,6 +899,12 @@ struct kernel_statfs {
#ifndef __NR_lgetxattr
#define __NR_lgetxattr (__NR_Linux + 228)
#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr (__NR_Linux + 230)
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr (__NR_Linux + 231)
+#endif
#ifndef __NR_futex
#define __NR_futex (__NR_Linux + 238)
#endif
@@ -829,6 +921,12 @@ struct kernel_statfs {
#ifndef __NR_fstatfs64
#define __NR_fstatfs64 (__NR_Linux + 256)
#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime (__NR_Linux + 263)
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres (__NR_Linux + 264)
+#endif
#ifndef __NR_openat
#define __NR_openat (__NR_Linux + 288)
#endif
@@ -841,8 +939,20 @@ struct kernel_statfs {
#ifndef __NR_move_pages
#define __NR_move_pages (__NR_Linux + 308)
#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set (__NR_Linux + 314)
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get (__NR_Linux + 315)
+#endif
/* End of MIPS (old 32bit API) definitions */
#elif _MIPS_SIM == _MIPS_SIM_ABI64
+#ifndef __NR_pread64
+#define __NR_pread64 (__NR_Linux + 16)
+#endif
+#ifndef __NR_pwrite64
+#define __NR_pwrite64 (__NR_Linux + 17)
+#endif
#ifndef __NR_setresuid
#define __NR_setresuid (__NR_Linux + 115)
#define __NR_setresgid (__NR_Linux + 117)
@@ -865,6 +975,12 @@ struct kernel_statfs {
#ifndef __NR_lgetxattr
#define __NR_lgetxattr (__NR_Linux + 184)
#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr (__NR_Linux + 186)
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr (__NR_Linux + 187)
+#endif
#ifndef __NR_futex
#define __NR_futex (__NR_Linux + 194)
#endif
@@ -875,6 +991,12 @@ struct kernel_statfs {
#ifndef __NR_set_tid_address
#define __NR_set_tid_address (__NR_Linux + 212)
#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime (__NR_Linux + 222)
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres (__NR_Linux + 223)
+#endif
#ifndef __NR_openat
#define __NR_openat (__NR_Linux + 247)
#endif
@@ -887,6 +1009,12 @@ struct kernel_statfs {
#ifndef __NR_move_pages
#define __NR_move_pages (__NR_Linux + 267)
#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set (__NR_Linux + 273)
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get (__NR_Linux + 274)
+#endif
/* End of MIPS (64bit API) definitions */
#else
#ifndef __NR_setresuid
@@ -911,6 +1039,12 @@ struct kernel_statfs {
#ifndef __NR_lgetxattr
#define __NR_lgetxattr (__NR_Linux + 184)
#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr (__NR_Linux + 186)
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr (__NR_Linux + 187)
+#endif
#ifndef __NR_futex
#define __NR_futex (__NR_Linux + 194)
#endif
@@ -927,6 +1061,12 @@ struct kernel_statfs {
#ifndef __NR_fstatfs64
#define __NR_fstatfs64 (__NR_Linux + 218)
#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime (__NR_Linux + 226)
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres (__NR_Linux + 227)
+#endif
#ifndef __NR_openat
#define __NR_openat (__NR_Linux + 251)
#endif
@@ -939,6 +1079,12 @@ struct kernel_statfs {
#ifndef __NR_move_pages
#define __NR_move_pages (__NR_Linux + 271)
#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set (__NR_Linux + 277)
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get (__NR_Linux + 278)
+#endif
/* End of MIPS (new 32bit API) definitions */
#endif
/* End of MIPS definitions */
@@ -993,6 +1139,12 @@ struct kernel_statfs {
#ifndef __NR_lgetxattr
#define __NR_lgetxattr 213
#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr 215
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr 216
+#endif
#ifndef __NR_futex
#define __NR_futex 221
#endif
@@ -1003,6 +1155,12 @@ struct kernel_statfs {
#ifndef __NR_set_tid_address
#define __NR_set_tid_address 232
#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime 246
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres 247
+#endif
#ifndef __NR_statfs64
#define __NR_statfs64 252
#endif
@@ -1012,6 +1170,12 @@ struct kernel_statfs {
#ifndef __NR_fadvise64_64
#define __NR_fadvise64_64 254
#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set 273
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get 274
+#endif
#ifndef __NR_openat
#define __NR_openat 286
#endif
@@ -1324,6 +1488,18 @@ struct kernel_statfs {
advice);
}
+ #define __NR__fallocate __NR_fallocate
+ LSS_INLINE _syscall6(int, _fallocate, int, fd,
+ int, mode,
+ unsigned, offset_lo, unsigned, offset_hi,
+ unsigned, len_lo, unsigned, len_hi)
+
+ LSS_INLINE int LSS_NAME(fallocate)(int fd, int mode,
+ loff_t offset, loff_t len) {
+ union { loff_t off; unsigned w[2]; } o = { offset }, l = { len };
+ return LSS_NAME(_fallocate)(fd, mode, o.w[0], o.w[1], l.w[0], l.w[1]);
+ }
+
LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) {
/* On i386, the kernel does not know how to return from a signal
* handler. Instead, it relies on user space to provide a
@@ -2055,6 +2231,10 @@ struct kernel_statfs {
#define __NR__mremap __NR_mremap
LSS_INLINE _syscall1(int, chdir, const char *,p)
LSS_INLINE _syscall1(int, close, int, f)
+ LSS_INLINE _syscall2(int, clock_getres, int, c,
+ struct kernel_timespec*, t)
+ LSS_INLINE _syscall2(int, clock_gettime, int, c,
+ struct kernel_timespec*, t)
LSS_INLINE _syscall1(int, dup, int, f)
LSS_INLINE _syscall2(int, dup2, int, s,
int, d)
@@ -2096,6 +2276,14 @@ struct kernel_statfs {
const char *, n, void *, v, size_t, s)
LSS_INLINE _syscall4(ssize_t, lgetxattr, const char *,p,
const char *, n, void *, v, size_t, s)
+ LSS_INLINE _syscall3(ssize_t, listxattr, const char *,p,
+ char *, l, size_t, s)
+ LSS_INLINE _syscall3(ssize_t, llistxattr, const char *,p,
+ char *, l, size_t, s)
+ LSS_INLINE _syscall2(int, ioprio_get, int, which,
+ int, who)
+ LSS_INLINE _syscall3(int, ioprio_set, int, which,
+ int, who, int, ioprio)
LSS_INLINE _syscall2(int, kill, pid_t, p,
int, s)
LSS_INLINE _syscall3(off_t, lseek, int, f,
@@ -2138,6 +2326,8 @@ struct kernel_statfs {
LSS_INLINE _syscall1(long, set_tid_address, int *, t)
LSS_INLINE _syscall1(int, setfsgid, gid_t, g)
LSS_INLINE _syscall1(int, setfsuid, uid_t, u)
+ LSS_INLINE _syscall1(int, setuid, uid_t, u)
+ LSS_INLINE _syscall1(int, setgid, gid_t, g)
LSS_INLINE _syscall2(int, setpgid, pid_t, p,
pid_t, g)
LSS_INLINE _syscall3(int, setpriority, int, a,
@@ -2177,6 +2367,8 @@ struct kernel_statfs {
int, t, int, p, int*, s)
#endif
#if defined(__x86_64__)
+ LSS_INLINE _syscall4(int, fallocate, int, fd, int, mode,
+ loff_t, offset, loff_t, len)
LSS_INLINE _syscall6(void*, mmap, void*, s,
size_t, l, int, p,
int, f, int, d,
@@ -2754,7 +2946,12 @@ struct kernel_statfs {
}
#if defined(__x86_64__) || \
(defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI64)
- /* pread64() and pwrite64() do not exist on 64-bit systems... */
+ LSS_INLINE _syscall4(ssize_t, pread64, int, f,
+ void *, b, size_t, c,
+ loff_t, o)
+ LSS_INLINE _syscall4(ssize_t, pwrite64, int, f,
+ const void *, b, size_t, c,
+ loff_t, o)
LSS_INLINE _syscall3(int, readahead, int, f,
loff_t, o, unsigned, c)
#else
diff --git a/src/base/low_level_alloc.cc b/src/base/low_level_alloc.cc
index d7f6c74..4fa78c4 100644
--- a/src/base/low_level_alloc.cc
+++ b/src/base/low_level_alloc.cc
@@ -40,6 +40,7 @@
#include "base/dynamic_annotations.h"
#include "base/spinlock.h"
#include "base/logging.h"
+#include "malloc_hook-inl.h"
#include <google/malloc_hook.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
@@ -102,6 +103,7 @@ static int IntLog2(size_t size, size_t base) {
// Return a random integer n: p(n)=1/(2**n) if 1 <= n; p(n)=0 if n < 1.
static int Random() {
static int32 r = 1; // no locking---it's not critical
+ ANNOTATE_BENIGN_RACE(&r, "benign race, not critical.");
int result = 1;
while ((((r = r*1103515245 + 12345) >> 30) & 1) == 0) {
result++;
diff --git a/src/base/low_level_alloc.h b/src/base/low_level_alloc.h
index c7bc363..6c8e751 100644
--- a/src/base/low_level_alloc.h
+++ b/src/base/low_level_alloc.h
@@ -34,10 +34,10 @@
#if !defined(_BASE_LOW_LEVEL_ALLOC_H_)
#define _BASE_LOW_LEVEL_ALLOC_H_
-// A simple memory allocator that does not depend on mutexes or
-// thread-specific data. It is intended to be used sparingly,
-// and only when malloc() would introduce an unwanted dependency,
-// such as inside the heap-checker.
+// A simple thread-safe memory allocator that does not depend on
+// mutexes or thread-specific data. It is intended to be used
+// sparingly, and only when malloc() would introduce an unwanted
+// dependency, such as inside the heap-checker.
#include "config.h"
#include <stddef.h> // for size_t
diff --git a/src/base/simple_mutex.h b/src/base/simple_mutex.h
index 2474b57..5bcccdf 100644
--- a/src/base/simple_mutex.h
+++ b/src/base/simple_mutex.h
@@ -46,8 +46,8 @@
* mode.
*/
-#ifndef GOOGLE_SIMPLE_MUTEX_H__
-#define GOOGLE_SIMPLE_MUTEX_H__
+#ifndef GOOGLE_SIMPLE_MUTEX_H_
+#define GOOGLE_SIMPLE_MUTEX_H_
#include "config.h" // to figure out pthreads support
@@ -56,8 +56,9 @@
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
// Needed for pthread_rwlock_*. If it causes problems, you could take it
// out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it
- // *does* cause problems for FreeBSD, but isn't needed for locking there.)
-# ifndef __FreeBSD__
+ // *does* cause problems for FreeBSD, or MacOSX, but isn't needed
+ // for locking there.)
+# ifdef __linux__
# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls
# endif
# include <pthread.h>
@@ -217,4 +218,4 @@ class WriterMutexLock {
#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
-#endif /* #define GOOGLE_SIMPLE_MUTEX_H__ */
+#endif /* #define GOOGLE_SIMPLE_MUTEX_H_ */
diff --git a/src/base/spinlock.h b/src/base/spinlock.h
index 466492f..8c54680 100644
--- a/src/base/spinlock.h
+++ b/src/base/spinlock.h
@@ -40,8 +40,8 @@
// If used within a signal handler, all lock holders
// should block the signal even outside the signal handler.
-#ifndef BASE_SPINLOCK_H__
-#define BASE_SPINLOCK_H__
+#ifndef BASE_SPINLOCK_H_
+#define BASE_SPINLOCK_H_
#include "config.h"
#include "base/basictypes.h"
@@ -158,4 +158,4 @@ class SCOPED_LOCKABLE SpinLockHolder {
#define SpinLockHolder(x) COMPILE_ASSERT(0, spin_lock_decl_missing_var_name)
-#endif // BASE_SPINLOCK_H__
+#endif // BASE_SPINLOCK_H_
diff --git a/src/base/stl_allocator.h b/src/base/stl_allocator.h
index 19d0afe..5aae092 100644
--- a/src/base/stl_allocator.h
+++ b/src/base/stl_allocator.h
@@ -32,8 +32,8 @@
*/
-#ifndef BASE_STL_ALLOCATOR_H__
-#define BASE_STL_ALLOCATOR_H__
+#ifndef BASE_STL_ALLOCATOR_H_
+#define BASE_STL_ALLOCATOR_H_
#include "config.h"
@@ -46,6 +46,10 @@
// that uses a given type-less allocator Alloc, which must provide:
// static void* Alloc::Allocate(size_t size);
// static void Alloc::Free(void* ptr);
+//
+// STL_Allocator<T, MyAlloc> provides the same thread-safety
+// guarantees as MyAlloc.
+//
// Usage example:
// set<T, less<T>, STL_Allocator<T, MyAlloc> > my_set;
// CAVEAT: Parts of the code below are probably specific
@@ -89,4 +93,4 @@ class STL_Allocator {
bool operator==(const STL_Allocator&) const { return true; }
};
-#endif // BASE_STL_ALLOCATOR_H__
+#endif // BASE_STL_ALLOCATOR_H_
diff --git a/src/base/sysinfo.h b/src/base/sysinfo.h
index 529a3da..2e1bcae 100644
--- a/src/base/sysinfo.h
+++ b/src/base/sysinfo.h
@@ -72,6 +72,8 @@ extern int NumCPUs();
extern double CyclesPerSecond(void);
+#ifndef SWIG // SWIG doesn't like struct Buffer and variable arguments.
+
// A ProcMapsIterator abstracts access to /proc/maps for a given
// process. Needs to be stack-allocatable and avoid using stdio/malloc
// so it can be used in the google stack dumper, heap-profiler, etc.
@@ -204,4 +206,6 @@ class ProcMapsIterator {
bool using_maps_backing_; // true if we are looking at maps_backing instead of maps.
};
+#endif /* #ifndef SWIG */
+
#endif /* #ifndef _SYSINFO_H_ */
diff --git a/src/config.h.in b/src/config.h.in
index d656452..142dd4d 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -117,6 +117,9 @@
/* Define to 1 if you have the <sys/prctl.h> header file. */
#undef HAVE_SYS_PRCTL_H
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
diff --git a/src/getpc.h b/src/getpc.h
index 74ba080..3d37851 100644
--- a/src/getpc.h
+++ b/src/getpc.h
@@ -40,8 +40,8 @@
// the signal triggered. How to get from a ucontext_t to a Program
// Counter is OS-dependent.
-#ifndef BASE_GETPC_H__
-#define BASE_GETPC_H__
+#ifndef BASE_GETPC_H_
+#define BASE_GETPC_H_
#include "config.h"
@@ -175,4 +175,4 @@ inline void* GetPC(const ucontext_t& signal_ucontext) {
#endif
-#endif // BASE_GETPC_H__
+#endif // BASE_GETPC_H_
diff --git a/src/google/heap-checker.h b/src/google/heap-checker.h
index d3a3c22..a043ceb 100644
--- a/src/google/heap-checker.h
+++ b/src/google/heap-checker.h
@@ -48,11 +48,12 @@
// a memory leak at program-exit, it will print instructions on how
// to track down the leak.
-#ifndef BASE_HEAP_CHECKER_H__
-#define BASE_HEAP_CHECKER_H__
+#ifndef BASE_HEAP_CHECKER_H_
+#define BASE_HEAP_CHECKER_H_
#include <sys/types.h> // for size_t
#include <stdint.h> // for uintptr_t
+#include <stdarg.h> // for va_list
#include <vector>
// Annoying stuff for windows -- makes sure clients can import these functions
@@ -75,9 +76,7 @@ class PERFTOOLS_DLL_DECL HeapLeakChecker {
// If heap leak checking is currently active in some mode
// e.g. if leak checking was started (and is still active now)
- // due to any valid non-empty --heap_check flag value
- // (including "local") on the command-line
- // or via a dependency on //base:heapcheck.
+ // due to HEAPCHECK=... defined in the environment.
// The return value reflects iff HeapLeakChecker objects manually
// constructed right now will be doing leak checking or nothing.
// Note that we can go from active to inactive state during InitGoogle()
@@ -464,4 +463,4 @@ class PERFTOOLS_DLL_DECL HeapCleaner {
static HeapCleaner heapcheck_cleaner_##name(&heapcheck_cleanup_##name); \
}
-#endif // BASE_HEAP_CHECKER_H__
+#endif // BASE_HEAP_CHECKER_H_
diff --git a/src/google/heap-profiler.h b/src/google/heap-profiler.h
index 6b22e4f..3c3f2b4 100644
--- a/src/google/heap-profiler.h
+++ b/src/google/heap-profiler.h
@@ -1,60 +1,58 @@
-// Copyright (c) 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// 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.
+/* Copyright (c) 2005, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * 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: Sanjay Ghemawat
+ *
+ * Module for heap-profiling.
+ *
+ * For full(er) information, see doc/heapprofile.html
+ *
+ * This module can be linked into your program with
+ * no slowdown caused by this unless you activate the profiler
+ * using one of the following methods:
+ *
+ * 1. Before starting the program, set the environment variable
+ * "HEAPPROFILE" to be the name of the file to which the profile
+ * data should be written.
+ *
+ * 2. Programmatically, start and stop the profiler using the
+ * routines "HeapProfilerStart(filename)" and "HeapProfilerStop()".
+ *
+ */
-// ---
-// Author: Sanjay Ghemawat
-//
-// Module for heap-profiling.
-//
-// For full(er) information, see doc/heapprofile.html
-//
-// This module can be linked into your program with
-// no slowdown caused by this unless you activate the profiler
-// using one of the following methods:
-//
-// 1. Before starting the program, set the environment variable
-// "HEAPPROFILE" to be the name of the file to which the profile
-// data should be written.
-//
-// 2. Programmatically, start and stop the profiler using the
-// routines "HeapProfilerStart(filename)" and "HeapProfilerStop()".
-//
-// Use pprof to view the resulting profile output.
-// % google3/perftools/pprof <path_to_executable> <profile_file_name>
-// % google3/perftools/pprof --gv <path_to_executable> <profile_file_name>
-
-#ifndef BASE_HEAP_PROFILER_H__
-#define BASE_HEAP_PROFILER_H__
+#ifndef BASE_HEAP_PROFILER_H_
+#define BASE_HEAP_PROFILER_H_
#include <stddef.h>
-// Annoying stuff for windows -- makes sure clients can import these functions
+/* Annoying stuff for windows; makes sure clients can import these functions */
#ifndef PERFTOOLS_DLL_DECL
# ifdef WIN32
# define PERFTOOLS_DLL_DECL __declspec(dllimport)
@@ -63,22 +61,36 @@
# endif
#endif
-// Start profiling and arrange to write profile data to file names
-// of the form: "prefix.0000", "prefix.0001", ...
-extern "C" PERFTOOLS_DLL_DECL void HeapProfilerStart(const char* prefix);
+/* All this code should be usable from within C apps. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Start profiling and arrange to write profile data to file names
+ * of the form: "prefix.0000", "prefix.0001", ...
+ */
+PERFTOOLS_DLL_DECL void HeapProfilerStart(const char* prefix);
-// Stop heap profiling. Can be restarted again with HeapProfilerStart(),
-// but the currently accumulated profiling information will be cleared.
-extern "C" PERFTOOLS_DLL_DECL void HeapProfilerStop();
+/* Stop heap profiling. Can be restarted again with HeapProfilerStart(),
+ * but the currently accumulated profiling information will be cleared.
+ */
+PERFTOOLS_DLL_DECL void HeapProfilerStop();
-// Dump a profile now - can be used for dumping at a hopefully
-// quiescent state in your program, in order to more easily track down
-// memory leaks. Will include the reason in the logged message
-extern "C" PERFTOOLS_DLL_DECL void HeapProfilerDump(const char *reason);
+/* Dump a profile now - can be used for dumping at a hopefully
+ * quiescent state in your program, in order to more easily track down
+ * memory leaks. Will include the reason in the logged message
+ */
+PERFTOOLS_DLL_DECL void HeapProfilerDump(const char *reason);
-// Generate current heap profiling information. The returned pointer
-// is a null-terminated string allocated using malloc() and should be
-// free()-ed as soon as the caller does not need it anymore.
-extern "C" PERFTOOLS_DLL_DECL char* GetHeapProfile();
+/* Generate current heap profiling information.
+ * Returns an empty string when heap profiling is not active.
+ * The returned pointer is a '\0'-terminated string allocated using malloc()
+ * and should be free()-ed as soon as the caller does not need it anymore.
+ */
+PERFTOOLS_DLL_DECL char* GetHeapProfile();
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
-#endif // BASE_HEAP_PROFILER_H__
+#endif /* BASE_HEAP_PROFILER_H_ */
diff --git a/src/google/malloc_extension.h b/src/google/malloc_extension.h
index 62d5d71..d41f1ef 100644
--- a/src/google/malloc_extension.h
+++ b/src/google/malloc_extension.h
@@ -35,8 +35,8 @@
// application can link against a malloc that does not implement these
// extensions, and it will get default versions that do nothing.
-#ifndef BASE_MALLOC_EXTENSION_H__
-#define BASE_MALLOC_EXTENSION_H__
+#ifndef BASE_MALLOC_EXTENSION_H_
+#define BASE_MALLOC_EXTENSION_H_
#include <stddef.h>
#include <string>
@@ -53,6 +53,8 @@
static const int kMallocHistogramSize = 64;
// The default implementations of the following routines do nothing.
+// All implementations should be thread-safe; the current one
+// (TCMallocImplementation) is.
class PERFTOOLS_DLL_DECL MallocExtension {
public:
virtual ~MallocExtension();
@@ -199,4 +201,4 @@ class PERFTOOLS_DLL_DECL MallocExtension {
virtual void** ReadHeapGrowthStackTraces();
};
-#endif // BASE_MALLOC_EXTENSION_H__
+#endif // BASE_MALLOC_EXTENSION_H_
diff --git a/src/google/malloc_hook.h b/src/google/malloc_hook.h
index ab580b6..8383c2e 100644
--- a/src/google/malloc_hook.h
+++ b/src/google/malloc_hook.h
@@ -32,7 +32,17 @@
//
// Some of our malloc implementations can invoke the following hooks
// whenever memory is allocated or deallocated. If the hooks are
-// NULL, they are not invoked.
+// NULL, they are not invoked. MallocHook is thread-safe, and things
+// you do before calling SetFooHook(MyHook) are visible to any
+// resulting calls to MyHook. Hooks must be thread-safe, and if you
+// write:
+//
+// MallocHook::NewHook old_new_hook_ = NULL;
+// ...
+// old_new_hook_ = MallocHook::SetNewHook(&MyNewHook);
+//
+// old_new_hook_ could still be NULL the first couple times MyNewHook
+// is called.
//
// One important user of these hooks is the heap profiler.
//
@@ -40,9 +50,18 @@
// then those calls must be directly in the code of the (de)allocation
// function that is provided to the user and that function must have
// an ATTRIBUTE_SECTION(malloc_hook) attribute.
+//
+// Note: Get*Hook() and Invoke*Hook() functions are defined in
+// malloc_hook-inl.h. If you need to get or invoke a hook (which you
+// shouldn't unless you're part of tcmalloc), be sure to #include
+// malloc_hook-inl.h in addition to malloc_hook.h.
+//
+// TODO(csilvers): support a non-inlined function called
+// Assert*HookIs()? This is the context in which I normally see
+// Get*Hook() called in non-tcmalloc code.
-#ifndef _MALLOC_HOOK_H
-#define _MALLOC_HOOK_H
+#ifndef _MALLOC_HOOK_H_
+#define _MALLOC_HOOK_H_
#include <stddef.h>
#include <sys/types.h>
@@ -56,34 +75,21 @@
# endif
#endif
-
class PERFTOOLS_DLL_DECL MallocHook {
public:
// The NewHook is invoked whenever an object is allocated.
// It may be passed NULL if the allocator returned NULL.
typedef void (*NewHook)(const void* ptr, size_t size);
- inline static NewHook GetNewHook() { return new_hook_; }
- inline static NewHook SetNewHook(NewHook hook) {
- NewHook result = new_hook_;
- new_hook_ = hook;
- return result;
- }
- inline static void InvokeNewHook(const void* p, size_t s) {
- if (new_hook_ != NULL) (*new_hook_)(p, s);
- }
+ inline static NewHook GetNewHook();
+ static NewHook SetNewHook(NewHook hook);
+ inline static void InvokeNewHook(const void* p, size_t s);
// The DeleteHook is invoked whenever an object is deallocated.
// It may be passed NULL if the caller is trying to delete NULL.
typedef void (*DeleteHook)(const void* ptr);
- inline static DeleteHook GetDeleteHook() { return delete_hook_; }
- inline static DeleteHook SetDeleteHook(DeleteHook hook) {
- DeleteHook result = delete_hook_;
- delete_hook_ = hook;
- return result;
- }
- inline static void InvokeDeleteHook(const void* p) {
- if (delete_hook_ != NULL) (*delete_hook_)(p);
- }
+ inline static DeleteHook GetDeleteHook();
+ static DeleteHook SetDeleteHook(DeleteHook hook);
+ inline static void InvokeDeleteHook(const void* p);
// The MmapHook is invoked whenever a region of memory is mapped.
// It may be passed MAP_FAILED if the mmap failed.
@@ -94,36 +100,21 @@ class PERFTOOLS_DLL_DECL MallocHook {
int flags,
int fd,
off_t offset);
- inline static MmapHook GetMmapHook() { return mmap_hook_; }
- inline static MmapHook SetMmapHook(MmapHook hook) {
- MmapHook result = mmap_hook_;
- mmap_hook_ = hook;
- return result;
- }
+ inline static MmapHook GetMmapHook();
+ static MmapHook SetMmapHook(MmapHook hook);
inline static void InvokeMmapHook(const void* result,
const void* start,
size_t size,
int protection,
int flags,
int fd,
- off_t offset) {
- if (mmap_hook_ != NULL) (*mmap_hook_)(result,
- start, size,
- protection, flags,
- fd, offset);
- }
+ off_t offset);
// The MunmapHook is invoked whenever a region of memory is unmapped.
typedef void (*MunmapHook)(const void* ptr, size_t size);
- inline static MunmapHook GetMunmapHook() { return munmap_hook_; }
- inline static MunmapHook SetMunmapHook(MunmapHook hook) {
- MunmapHook result = munmap_hook_;
- munmap_hook_ = hook;
- return result;
- }
- inline static void InvokeMunmapHook(const void* p, size_t size) {
- if (munmap_hook_ != NULL) (*munmap_hook_)(p, size);
- }
+ inline static MunmapHook GetMunmapHook();
+ static MunmapHook SetMunmapHook(MunmapHook hook);
+ inline static void InvokeMunmapHook(const void* p, size_t size);
// The MremapHook is invoked whenever a region of memory is remapped.
typedef void (*MremapHook)(const void* result,
@@ -132,37 +123,23 @@ class PERFTOOLS_DLL_DECL MallocHook {
size_t new_size,
int flags,
const void* new_addr);
- inline static MremapHook GetMremapHook() { return mremap_hook_; }
- inline static MremapHook SetMremapHook(MremapHook hook) {
- MremapHook result = mremap_hook_;
- mremap_hook_ = hook;
- return result;
- }
+ inline static MremapHook GetMremapHook();
+ static MremapHook SetMremapHook(MremapHook hook);
inline static void InvokeMremapHook(const void* result,
const void* old_addr,
size_t old_size,
size_t new_size,
int flags,
- const void* new_addr) {
- if (mremap_hook_ != NULL) (*mremap_hook_)(result,
- old_addr, old_size,
- new_size, flags, new_addr);
- }
+ const void* new_addr);
// The SbrkHook is invoked whenever sbrk is called -- except when
// the increment is 0. This is because sbrk(0) is often called
// to get the top of the memory stack, and is not actually a
// memory-allocation call.
typedef void (*SbrkHook)(const void* result, ptrdiff_t increment);
- inline static SbrkHook GetSbrkHook() { return sbrk_hook_; }
- inline static SbrkHook SetSbrkHook(SbrkHook hook) {
- SbrkHook result = sbrk_hook_;
- sbrk_hook_ = hook;
- return result;
- }
- inline static void InvokeSbrkHook(const void* result, ptrdiff_t increment) {
- if (sbrk_hook_ != NULL && increment != 0) (*sbrk_hook_)(result, increment);
- }
+ inline static SbrkHook GetSbrkHook();
+ static SbrkHook SetSbrkHook(SbrkHook hook);
+ inline static void InvokeSbrkHook(const void* result, ptrdiff_t increment);
// Get the current stack trace. Try to skip all routines up to and
// and including the caller of MallocHook::Invoke*.
@@ -170,15 +147,6 @@ class PERFTOOLS_DLL_DECL MallocHook {
// as a hint about how many routines to skip if better information
// is not available.
static int GetCallerStackTrace(void** result, int max_depth, int skip_count);
-
- private:
-
- static NewHook new_hook_;
- static DeleteHook delete_hook_;
- static MmapHook mmap_hook_;
- static MunmapHook munmap_hook_;
- static MremapHook mremap_hook_;
- static SbrkHook sbrk_hook_;
};
-#endif /* _MALLOC_HOOK_H */
+#endif /* _MALLOC_HOOK_H_ */
diff --git a/src/google/profiler.h b/src/google/profiler.h
index 8104861..46bd844 100644
--- a/src/google/profiler.h
+++ b/src/google/profiler.h
@@ -1,66 +1,67 @@
-// Copyright (c) 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// 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: Sanjay Ghemawat
-//
-// Module for CPU profiling based on periodic pc-sampling.
-//
-// For full(er) information, see doc/cpuprofile.html
-//
-// This module is linked into your program with
-// no slowdown caused by this unless you activate the profiler
-// using one of the following methods:
-//
-// 1. Before starting the program, set the environment variable
-// "PROFILE" to be the name of the file to which the profile
-// data should be written.
-//
-// 2. Programmatically, start and stop the profiler using the
-// routines "ProfilerStart(filename)" and "ProfilerStop()".
-//
-// All threads in the program are profiled whenever profiling is on.
-// (Note: if using linux 2.4 or earlier, only the main thread may be
-// profiled.)
-//
-// Use pprof to view the resulting profile output.
-// % pprof <path_to_executable> <profile_file_name>
-// % pprof --gv <path_to_executable> <profile_file_name>
-//
-// These functions are thread-safe.
-
-#ifndef BASE_PROFILER_H__
-#define BASE_PROFILER_H__
-
-#include <time.h> // For time_t
-
-// Annoying stuff for windows -- makes sure clients can import these functions
+/* Copyright (c) 2005, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * 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: Sanjay Ghemawat
+ *
+ * Module for CPU profiling based on periodic pc-sampling.
+ *
+ * For full(er) information, see doc/cpuprofile.html
+ *
+ * This module is linked into your program with
+ * no slowdown caused by this unless you activate the profiler
+ * using one of the following methods:
+ *
+ * 1. Before starting the program, set the environment variable
+ * "PROFILE" to be the name of the file to which the profile
+ * data should be written.
+ *
+ * 2. Programmatically, start and stop the profiler using the
+ * routines "ProfilerStart(filename)" and "ProfilerStop()".
+ *
+ *
+ * (Note: if using linux 2.4 or earlier, only the main thread may be
+ * profiled.)
+ *
+ * Use pprof to view the resulting profile output.
+ * % pprof <path_to_executable> <profile_file_name>
+ * % pprof --gv <path_to_executable> <profile_file_name>
+ *
+ * These functions are thread-safe.
+ */
+
+#ifndef BASE_PROFILER_H_
+#define BASE_PROFILER_H_
+
+#include <time.h> /* For time_t */
+
+/* Annoying stuff for windows; makes sure clients can import these functions */
#ifndef PERFTOOLS_DLL_DECL
# ifdef WIN32
# define PERFTOOLS_DLL_DECL __declspec(dllimport)
@@ -69,58 +70,99 @@
# endif
#endif
-// Start profiling and write profile info into fname.
-extern "C" PERFTOOLS_DLL_DECL bool ProfilerStart(const char* fname);
-
-// Start profiling and write profile info into fname, filtering out
-// threads using a filter function.
-//
-// When a profiling tick is delivered, the profiler will call:
-//
-// (*filter_in_thread)(filter_in_thread_arg)
-//
-// If it returns true, the sample will be included in the profile.
-// Note that filter_in_thread runs in a signal handler, so must be
-// async-signal-safe.
-//
-// A typical use would be to set up filter results for each thread in
-// the system before starting the profiler, then to make
-// filter_in_thread be a very simple function which retrieves those
-// results in an async-signal-safe way. Retrieval could be done using
-// thread-specific data, or using a shared data structure that
-// supports async-signal-safe lookups.
-extern "C" bool ProfilerStartFiltered(const char* fname,
- bool (*filter_in_thread)(void* arg),
- void *filter_in_thread_arg);
-
-// Stop profiling. Can be started again with ProfilerStart(), but
-// the currently accumulated profiling data will be cleared.
-extern "C" PERFTOOLS_DLL_DECL void ProfilerStop();
-
-// Flush any currently buffered profiling state to the profile file.
-// Has no effect if the profiler has not been started.
-extern "C" PERFTOOLS_DLL_DECL void ProfilerFlush();
-
-
-// DEPRECATED: these functions were used to enable/disable profiling
-// in the current thread, but no longer do anything.
-extern "C" PERFTOOLS_DLL_DECL void ProfilerEnable();
-extern "C" PERFTOOLS_DLL_DECL void ProfilerDisable();
-
-// Returns true if profile is currently enabled
-extern "C" PERFTOOLS_DLL_DECL bool ProfilingIsEnabledForAllThreads();
-
-// Routine for registering new threads with the profiler. This is
-// most usefully called when a new thread is first entered.
-extern "C" PERFTOOLS_DLL_DECL void ProfilerRegisterThread();
-
-// Stores state about profiler's current status into "*state".
+/* All this code should be usable from within C apps. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Profiler options, for use with ProfilerStartWithOptions. To use:
+ *
+ * struct ProfilerOptions options;
+ * memset(&options, 0, sizeof options);
+ *
+ * then fill in fields as needed.
+ *
+ * This structure is intended to be usable from C code, so no constructor
+ * is provided to initialize it. (Use memset as described above).
+ */
+struct ProfilerOptions {
+ /* Filter function and argument.
+ *
+ * If filter_in_thread is not NULL, when a profiling tick is delivered
+ * the profiler will call:
+ *
+ * (*filter_in_thread)(filter_in_thread_arg)
+ *
+ * If it returns nonzero, the sample will be included in the profile.
+ * Note that filter_in_thread runs in a signal handler, so must be
+ * async-signal-safe.
+ *
+ * A typical use would be to set up filter results for each thread
+ * in the system before starting the profiler, then to make
+ * filter_in_thread be a very simple function which retrieves those
+ * results in an async-signal-safe way. Retrieval could be done
+ * using thread-specific data, or using a shared data structure that
+ * supports async-signal-safe lookups.
+ */
+ int (*filter_in_thread)(void *arg);
+ void *filter_in_thread_arg;
+};
+
+/* Start profiling and write profile info into fname.
+ *
+ * This is equivalent to calling ProfilerStartWithOptions(fname, NULL).
+ */
+PERFTOOLS_DLL_DECL int ProfilerStart(const char* fname);
+
+/* Start profiling and write profile into fname.
+ *
+ * The profiler is configured using the options given by 'options'.
+ * Options which are not specified are given default values.
+ *
+ * 'options' may be NULL, in which case all are given default values.
+ *
+ * Returns nonzero if profiling was started sucessfully, or zero else.
+ */
+PERFTOOLS_DLL_DECL int ProfilerStartWithOptions(
+ const char *fname, const struct ProfilerOptions *options);
+
+/* Stop profiling. Can be started again with ProfilerStart(), but
+ * the currently accumulated profiling data will be cleared.
+ */
+PERFTOOLS_DLL_DECL void ProfilerStop();
+
+/* Flush any currently buffered profiling state to the profile file.
+ * Has no effect if the profiler has not been started.
+ */
+PERFTOOLS_DLL_DECL void ProfilerFlush();
+
+
+/* DEPRECATED: these functions were used to enable/disable profiling
+ * in the current thread, but no longer do anything.
+ */
+PERFTOOLS_DLL_DECL void ProfilerEnable();
+PERFTOOLS_DLL_DECL void ProfilerDisable();
+
+/* Returns nonzero if profile is currently enabled, zero if it's not. */
+PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads();
+
+/* Routine for registering new threads with the profiler. This routine
+ * is called by the Thread module in google3/thread whenever a new
+ * thread is created.
+ */
+PERFTOOLS_DLL_DECL void ProfilerRegisterThread();
+
+/* Stores state about profiler's current status into "*state". */
struct ProfilerState {
- bool enabled; // Is profiling currently enabled?
- time_t start_time; // If enabled, when was profiling started?
- char profile_name[1024]; // Name of profile file being written, or '\0'
- int samples_gathered; // Number of samples gatheered to far (or 0)
+ int enabled; /* Is profiling currently enabled? */
+ time_t start_time; /* If enabled, when was profiling started? */
+ char profile_name[1024]; /* Name of profile file being written, or '\0' */
+ int samples_gathered; /* Number of samples gatheered to far (or 0) */
};
-extern "C" PERFTOOLS_DLL_DECL void ProfilerGetCurrentState(ProfilerState* state);
+PERFTOOLS_DLL_DECL void ProfilerGetCurrentState(ProfilerState* state);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
-#endif /* BASE_PROFILER_H__ */
+#endif /* BASE_PROFILER_H_ */
diff --git a/src/google/stacktrace.h b/src/google/stacktrace.h
index 2140f9b..a59286c 100644
--- a/src/google/stacktrace.h
+++ b/src/google/stacktrace.h
@@ -30,10 +30,11 @@
// ---
// Author: Sanjay Ghemawat
//
-// Routine to extract the current stack trace.
+// Routines to extract the current stack trace. These functions are
+// thread-safe.
-#ifndef _GOOGLE_STACKTRACE_H
-#define _GOOGLE_STACKTRACE_H
+#ifndef GOOGLE_STACKTRACE_H_
+#define GOOGLE_STACKTRACE_H_
// Annoying stuff for windows -- makes sure clients can import these functions
#ifndef PERFTOOLS_DLL_DECL
@@ -98,4 +99,4 @@ extern PERFTOOLS_DLL_DECL int GetStackFrames(void** pcs, int* sizes, int max_dep
extern PERFTOOLS_DLL_DECL int GetStackTrace(void** result, int max_depth,
int skip_count);
-#endif /* _GOOGLE_STACKTRACE_H */
+#endif /* GOOGLE_STACKTRACE_H_ */
diff --git a/src/heap-checker.cc b/src/heap-checker.cc
index 312e5aa..84ab03b 100644
--- a/src/heap-checker.cc
+++ b/src/heap-checker.cc
@@ -74,6 +74,7 @@
#include "base/thread_lister.h"
#include "heap-profile-table.h"
#include "base/low_level_alloc.h"
+#include "malloc_hook-inl.h"
#include <google/malloc_hook.h>
#include <google/malloc_extension.h>
#include "memory_region_map.h"
@@ -248,16 +249,6 @@ static const int heap_checker_info_level = 0;
// The larger it can be, the lesser is the chance of missing real leaks.
static const size_t kPointerSourceAlignment = sizeof(void*);
-// Alignment at which all pointers (in)to heap memory objects
-// are supposed to point; use 1 if any alignment is ok.
-// sizeof(void*) is good enough for all the cases we want to support
-// -- see PointsIntoHeapObject
-// The larger it can be, the lesser is the chance of missing real leaks.
-static const size_t kPointerDestAlignment = sizeof(uint32);
- // need sizeof(uint32) even for 64 bit binaries to support
- // e.g. the internal structure of UnicodeString in ICU.
-static const size_t kPointerDestAlignmentMask = kPointerDestAlignment - 1;
-
//----------------------------------------------------------------------
// HeapLeakChecker's own memory allocator that is
// independent of the normal program allocator.
@@ -1175,9 +1166,6 @@ static size_t pointer_source_alignment = kPointerSourceAlignment;
// to protect pointer_source_alignment.
static SpinLock alignment_checker_lock(SpinLock::LINKER_INITIALIZED);
-static const size_t kUnicodeStringOffset = sizeof(uint32);
-static const size_t kUnicodeStringAlignmentMask = kUnicodeStringOffset - 1;
-
// This function changes the live bits in the heap_profile-table's state:
// we only record the live objects to be skipped.
//
@@ -1247,10 +1235,8 @@ static const size_t kUnicodeStringAlignmentMask = kUnicodeStringOffset - 1;
// (which is already slower) or by a factor of 1.5..1.91 in 64 bit mode.
#if defined(__x86_64__)
addr < max_heap_address &&
- (addr & kUnicodeStringAlignmentMask) == 0 && // must be aligned
min_heap_address <= addr;
#else
- (addr & kUnicodeStringAlignmentMask) == 0 && // must be aligned
min_heap_address <= addr &&
addr < max_heap_address;
#endif
@@ -1956,7 +1942,7 @@ static bool internal_init_start_has_run = false;
char name_buf[15+15];
snprintf(name_buf, sizeof(name_buf),
"/proc/%d/cmdline", static_cast<int>(getppid()));
- char cmdline[1024*8];
+ char cmdline[1024*8]; // /proc/*/cmdline is at most 4Kb anyway usually
int size = GetCommandLineFrom(name_buf, cmdline, sizeof(cmdline)-1);
cmdline[size] = '\0';
// look for "gdb" in the executable's name:
@@ -2303,10 +2289,10 @@ void HeapLeakChecker::TurnItselfOffLocked() {
}
// Read in the command line from 'file' into 'cmdline' and return the size read
-// 'size' is the space available in 'cmdline'
+// 'size' is the space available in 'cmdline'.
// We need this because we don't yet have argv/argc.
-// CAVEAT: 'file' (some /proc/*/cmdline) might contain
-// the command line truncated.
+// CAVEAT: 'file' (some /proc/*/cmdline) usually contains the command line
+// already truncated (to 4K on Linux).
// Arguments in cmdline will be '\0'-terminated,
// the first one will be the binary's name.
static int GetCommandLineFrom(const char* file, char* cmdline, int size) {
@@ -2477,17 +2463,9 @@ inline bool HeapLeakChecker::HaveOnHeapLocked(const void** ptr,
const uintptr_t addr = AsInt(*ptr);
if (heap_profile->FindInsideAlloc(
*ptr, max_heap_object_size, ptr, object_size)) {
- const size_t offset = addr - AsInt(*ptr);
- // must be aligned to kPointerDestAlignmentMask,
- // kUnicodeStringOffset is a special case.
- if ((offset & kPointerDestAlignmentMask) == 0 ||
- offset == kUnicodeStringOffset) {
- RAW_VLOG(7, "Got pointer into %p at +%"PRIuS" offset", *ptr, offset);
- RAW_DCHECK((addr & kUnicodeStringAlignmentMask) == 0, "");
- // alignment of at least kUnicodeStringAlignment
- // must have been already ensured
- return true;
- }
+ RAW_VLOG(7, "Got pointer into %p at +%"PRIuS" offset",
+ *ptr, addr - AsInt(*ptr));
+ return true;
}
return false;
}
diff --git a/src/heap-profile-table.h b/src/heap-profile-table.h
index 5348197..fc60d1c 100644
--- a/src/heap-profile-table.h
+++ b/src/heap-profile-table.h
@@ -32,15 +32,15 @@
// Maxim Lifantsev (refactoring)
//
-#ifndef BASE_HEAP_PROFILE_TABLE_H__
-#define BASE_HEAP_PROFILE_TABLE_H__
+#ifndef BASE_HEAP_PROFILE_TABLE_H_
+#define BASE_HEAP_PROFILE_TABLE_H_
#include "addressmap-inl.h"
#include "base/basictypes.h"
// Table to maintain a heap profile data inside,
// i.e. the set of currently active heap memory allocations.
-// Not thread-safe and non-reentrant code:
+// thread-unsafe and non-reentrant code:
// each instance object must be used by one thread
// at a time w/o self-recursion.
//
@@ -258,4 +258,4 @@ class HeapProfileTable {
DISALLOW_EVIL_CONSTRUCTORS(HeapProfileTable);
};
-#endif // BASE_HEAP_PROFILE_TABLE_H__
+#endif // BASE_HEAP_PROFILE_TABLE_H_
diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc
index 547d698..6db35f5 100644
--- a/src/heap-profiler.cc
+++ b/src/heap-profiler.cc
@@ -53,6 +53,7 @@
#include "base/basictypes.h" // for PRId64, among other things
#include "base/googleinit.h"
#include "base/commandlineflags.h"
+#include "malloc_hook-inl.h"
#include <google/malloc_hook.h>
#include <google/malloc_extension.h>
#include "base/spinlock.h"
@@ -75,6 +76,9 @@ using STL_NAMESPACE::sort;
//----------------------------------------------------------------------
// Flags that control heap-profiling
+//
+// The thread-safety of the profiler depends on these being immutable
+// after main starts, so don't change them.
//----------------------------------------------------------------------
DEFINE_int64(heap_profile_allocation_interval,
@@ -175,16 +179,19 @@ static char* DoGetHeapProfile(void* (*alloc_func)(size_t)) {
// Grab the lock and generate the profile.
SpinLockHolder l(&heap_lock);
- HeapProfileTable::Stats const stats = heap_profile->total();
- AddRemoveMMapDataLocked(ADD);
- int buflen = is_on ? heap_profile->FillOrderedProfile(buf, size - 1) : 0;
- buf[buflen] = '\0';
- // FillOrderedProfile should not reduce the set of active mmap-ed regions,
- // hence MemoryRegionMap will let us remove everything we've added above:
- AddRemoveMMapDataLocked(REMOVE);
- RAW_DCHECK(stats.Equivalent(heap_profile->total()), "");
+ int buflen = 0;
+ if (is_on) {
+ HeapProfileTable::Stats const stats = heap_profile->total();
+ AddRemoveMMapDataLocked(ADD);
+ buflen = heap_profile->FillOrderedProfile(buf, size - 1);
+ // FillOrderedProfile should not reduce the set of active mmap-ed regions,
+ // hence MemoryRegionMap will let us remove everything we've added above:
+ AddRemoveMMapDataLocked(REMOVE);
+ RAW_DCHECK(stats.Equivalent(heap_profile->total()), "");
// if this fails, we somehow removed by AddRemoveMMapDataLocked
// more than we have added.
+ }
+ buf[buflen] = '\0';
RAW_DCHECK(buflen == strlen(buf), "");
return buf;
diff --git a/src/internal_logging.h b/src/internal_logging.h
index 9091143..8edaa47 100644
--- a/src/internal_logging.h
+++ b/src/internal_logging.h
@@ -32,8 +32,8 @@
//
// Internal logging and related utility routines.
-#ifndef TCMALLOC_INTERNAL_LOGGING_H__
-#define TCMALLOC_INTERNAL_LOGGING_H__
+#ifndef TCMALLOC_INTERNAL_LOGGING_H_
+#define TCMALLOC_INTERNAL_LOGGING_H_
#include "config.h"
#include <stdlib.h> // for abort()
@@ -99,4 +99,4 @@ class TCMalloc_Printer {
;
};
-#endif // TCMALLOC_INTERNAL_LOGGING_H__
+#endif // TCMALLOC_INTERNAL_LOGGING_H_
diff --git a/src/malloc_hook-inl.h b/src/malloc_hook-inl.h
new file mode 100644
index 0000000..3f5e4b8
--- /dev/null
+++ b/src/malloc_hook-inl.h
@@ -0,0 +1,161 @@
+// Copyright (c) 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// 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: Sanjay Ghemawat
+//
+// This has the implementation details of malloc_hook that are needed
+// to use malloc-hook inside the tcmalloc system. It does not hold
+// any of the client-facing calls that are used to add new hooks.
+
+#ifndef _MALLOC_HOOK_INL_H_
+#define _MALLOC_HOOK_INL_H_
+
+#include <stddef.h>
+#include <sys/types.h>
+#include "base/atomicops.h"
+#include "base/basictypes.h"
+#include <google/malloc_hook.h>
+
+namespace base { namespace internal {
+
+// A simple atomic pointer class that can be initialized by the linker
+// when you define a namespace-scope variable as:
+//
+// AtomicPtr<Foo*> my_global = { &initial_value };
+//
+// This isn't suitable for a general atomic<> class because of the
+// public access to data_.
+template<typename PtrT>
+class AtomicPtr {
+ public:
+ COMPILE_ASSERT(sizeof(PtrT) <= sizeof(AtomicWord),
+ PtrT_should_fit_in_AtomicWord);
+
+ PtrT Get() const {
+ // Depending on the system, Acquire_Load(AtomicWord*) may have
+ // been defined to return an AtomicWord, Atomic32, or Atomic64.
+ // We hide that implementation detail here with an explicit cast.
+ // This prevents MSVC 2005, at least, from complaining (it has to
+ // do with __wp64; AtomicWord is __wp64, but Atomic32/64 aren't).
+ return reinterpret_cast<PtrT>(static_cast<AtomicWord>(
+ base::subtle::Acquire_Load(&data_)));
+ }
+
+ // Sets the contained value to new_val and returns the old value,
+ // atomically, with acquire and release semantics.
+ PtrT Exchange(PtrT new_val);
+
+ // Not private so that the class is an aggregate and can be
+ // initialized by the linker. Don't access this directly.
+ AtomicWord data_;
+};
+
+// These are initialized in malloc_hook.cc
+extern AtomicPtr<MallocHook::NewHook> new_hook_;
+extern AtomicPtr<MallocHook::DeleteHook> delete_hook_;
+extern AtomicPtr<MallocHook::MmapHook> mmap_hook_;
+extern AtomicPtr<MallocHook::MunmapHook> munmap_hook_;
+extern AtomicPtr<MallocHook::MremapHook> mremap_hook_;
+extern AtomicPtr<MallocHook::SbrkHook> sbrk_hook_;
+
+} } // namespace base::internal
+
+inline MallocHook::NewHook MallocHook::GetNewHook() {
+ return base::internal::new_hook_.Get();
+}
+
+inline void MallocHook::InvokeNewHook(const void* p, size_t s) {
+ MallocHook::NewHook hook = MallocHook::GetNewHook();
+ if (hook != NULL) (*hook)(p, s);
+}
+
+inline MallocHook::DeleteHook MallocHook::GetDeleteHook() {
+ return base::internal::delete_hook_.Get();
+}
+
+inline void MallocHook::InvokeDeleteHook(const void* p) {
+ MallocHook::DeleteHook hook = MallocHook::GetDeleteHook();
+ if (hook != NULL) (*hook)(p);
+}
+
+inline MallocHook::MmapHook MallocHook::GetMmapHook() {
+ return base::internal::mmap_hook_.Get();
+}
+
+inline void MallocHook::InvokeMmapHook(const void* result,
+ const void* start,
+ size_t size,
+ int protection,
+ int flags,
+ int fd,
+ off_t offset) {
+ MallocHook::MmapHook hook = MallocHook::GetMmapHook();
+ if (hook != NULL) (*hook)(result,
+ start, size,
+ protection, flags,
+ fd, offset);
+}
+
+inline MallocHook::MunmapHook MallocHook::GetMunmapHook() {
+ return base::internal::munmap_hook_.Get();
+}
+
+inline void MallocHook::InvokeMunmapHook(const void* p, size_t size) {
+ MallocHook::MunmapHook hook = MallocHook::GetMunmapHook();
+ if (hook != NULL) (*hook)(p, size);
+}
+
+inline MallocHook::MremapHook MallocHook::GetMremapHook() {
+ return base::internal::mremap_hook_.Get();
+}
+
+inline void MallocHook::InvokeMremapHook(const void* result,
+ const void* old_addr,
+ size_t old_size,
+ size_t new_size,
+ int flags,
+ const void* new_addr) {
+ MallocHook::MremapHook hook = MallocHook::GetMremapHook();
+ if (hook != NULL) (*hook)(result,
+ old_addr, old_size,
+ new_size, flags, new_addr);
+}
+
+inline MallocHook::SbrkHook MallocHook::GetSbrkHook() {
+ return base::internal::sbrk_hook_.Get();
+}
+
+inline void MallocHook::InvokeSbrkHook(const void* result,
+ ptrdiff_t increment) {
+ MallocHook::SbrkHook hook = MallocHook::GetSbrkHook();
+ if (hook != NULL && increment != 0) (*hook)(result, increment);
+}
+
+#endif /* _MALLOC_HOOK_INL_H_ */
diff --git a/src/malloc_hook.cc b/src/malloc_hook.cc
index 4fbb956..0f1e61f 100644
--- a/src/malloc_hook.cc
+++ b/src/malloc_hook.cc
@@ -42,9 +42,10 @@
#endif
#include <algorithm>
-#include <google/malloc_hook.h>
#include "base/basictypes.h"
#include "base/logging.h"
+#include "malloc_hook-inl.h"
+#include <google/malloc_hook.h>
#include <google/stacktrace.h>
// __THROW is defined in glibc systems. It means, counter-intuitively,
@@ -86,12 +87,72 @@ extern void InitialMallocHook_MMap(const void* result,
ATTRIBUTE_WEAK
extern void InitialMallocHook_Sbrk(const void* result, ptrdiff_t increment);
-MallocHook::NewHook MallocHook::new_hook_ = InitialMallocHook_New;
-MallocHook::DeleteHook MallocHook::delete_hook_ = NULL;
-MallocHook::MmapHook MallocHook::mmap_hook_ = InitialMallocHook_MMap;
-MallocHook::MunmapHook MallocHook::munmap_hook_ = NULL;
-MallocHook::MremapHook MallocHook::mremap_hook_ = NULL;
-MallocHook::SbrkHook MallocHook::sbrk_hook_ = InitialMallocHook_Sbrk;
+namespace base { namespace internal {
+template<typename PtrT>
+PtrT AtomicPtr<PtrT>::Exchange(PtrT new_val) {
+ base::subtle::MemoryBarrier(); // Release semantics.
+ // Depending on the system, NoBarrier_AtomicExchange(AtomicWord*)
+ // may have been defined to return an AtomicWord, Atomic32, or
+ // Atomic64. We hide that implementation detail here with an
+ // explicit cast. This prevents MSVC 2005, at least, from complaining.
+ PtrT old_val = reinterpret_cast<PtrT>(static_cast<AtomicWord>(
+ base::subtle::NoBarrier_AtomicExchange(
+ &data_,
+ reinterpret_cast<AtomicWord>(new_val))));
+ base::subtle::MemoryBarrier(); // And acquire semantics.
+ return old_val;
+}
+
+AtomicPtr<MallocHook::NewHook> new_hook_ = {
+ reinterpret_cast<AtomicWord>(InitialMallocHook_New) };
+AtomicPtr<MallocHook::DeleteHook> delete_hook_ = { 0 };
+AtomicPtr<MallocHook::MmapHook> mmap_hook_ = {
+ reinterpret_cast<AtomicWord>(InitialMallocHook_MMap) };
+AtomicPtr<MallocHook::MunmapHook> munmap_hook_ = { 0 };
+AtomicPtr<MallocHook::MremapHook> mremap_hook_ = { 0 };
+AtomicPtr<MallocHook::SbrkHook> sbrk_hook_ = {
+ reinterpret_cast<AtomicWord>(InitialMallocHook_Sbrk) };
+
+} } // namespace base::internal
+
+using base::internal::new_hook_;
+using base::internal::delete_hook_;
+using base::internal::mmap_hook_;
+using base::internal::munmap_hook_;
+using base::internal::mremap_hook_;
+using base::internal::sbrk_hook_;
+
+
+// static
+MallocHook::NewHook MallocHook::SetNewHook(NewHook hook) {
+ return new_hook_.Exchange(hook);
+}
+
+// static
+MallocHook::DeleteHook MallocHook::SetDeleteHook(DeleteHook hook) {
+ return delete_hook_.Exchange(hook);
+}
+
+// static
+MallocHook::MmapHook MallocHook::SetMmapHook(MmapHook hook) {
+ return mmap_hook_.Exchange(hook);
+}
+
+// static
+MallocHook::MunmapHook MallocHook::SetMunmapHook(MunmapHook hook) {
+ return munmap_hook_.Exchange(hook);
+}
+
+// static
+MallocHook::MremapHook MallocHook::SetMremapHook(MremapHook hook) {
+ return mremap_hook_.Exchange(hook);
+}
+
+// static
+MallocHook::SbrkHook MallocHook::SetSbrkHook(SbrkHook hook) {
+ return sbrk_hook_.Exchange(hook);
+}
+
// The definitions of weak default malloc hooks (New, MMap, and Sbrk)
// that self deinstall on their first call. This is entirely for
@@ -186,7 +247,9 @@ static inline void CheckInHookCaller() {
// into the implementations for GetStackTrace instead of the skip_count.
int MallocHook::GetCallerStackTrace(void** result, int max_depth,
int skip_count) {
-#ifndef HAVE_ATTRIBUTE_SECTION_START
+#if defined(NO_TCMALLOC_SAMPLES)
+ return 0;
+#elif !defined(HAVE_ATTRIBUTE_SECTION_START)
// Fall back to GetStackTrace and good old but fragile frame skip counts.
// Note: this path is inaccurate when a hook is not called directly by an
// allocation function but is daisy-chained through another hook,
@@ -194,7 +257,7 @@ int MallocHook::GetCallerStackTrace(void** result, int max_depth,
return GetStackTrace(result, max_depth, skip_count + int(DEBUG_MODE));
// due to -foptimize-sibling-calls in opt mode
// there's no need for extra frame skip here then
-#endif
+#else
CheckInHookCaller();
// MallocHook caller determination via InHookCaller works, use it:
static const int kMaxSkip = 32 + 6 + 3;
@@ -230,6 +293,7 @@ int MallocHook::GetCallerStackTrace(void** result, int max_depth,
// e.g. for every section used in InHookCaller
// all functions in that section must be inside the same library.
return 0;
+#endif
}
// On Linux/x86, we override mmap/munmap/mremap/sbrk
diff --git a/src/maybe_threads.cc b/src/maybe_threads.cc
index f1a8f76..6b7d7b9 100644
--- a/src/maybe_threads.cc
+++ b/src/maybe_threads.cc
@@ -68,7 +68,7 @@ extern "C" {
#define MAX_PERTHREAD_VALS 16
static void *perftools_pthread_specific_vals[MAX_PERTHREAD_VALS];
-static pthread_key_t next_key;
+static int next_key;
int perftools_pthread_key_create(pthread_key_t *key,
void (*destr_function) (void *)) {
@@ -76,7 +76,7 @@ int perftools_pthread_key_create(pthread_key_t *key,
return pthread_key_create(key, destr_function);
} else {
assert(next_key < MAX_PERTHREAD_VALS);
- *key = next_key++;
+ *key = (pthread_key_t)(next_key++);
return 0;
}
}
@@ -85,7 +85,7 @@ void *perftools_pthread_getspecific(pthread_key_t key) {
if (pthread_getspecific) {
return pthread_getspecific(key);
} else {
- return perftools_pthread_specific_vals[key];
+ return perftools_pthread_specific_vals[(int)key];
}
}
@@ -93,7 +93,7 @@ int perftools_pthread_setspecific(pthread_key_t key, void *val) {
if (pthread_setspecific) {
return pthread_setspecific(key, val);
} else {
- perftools_pthread_specific_vals[key] = val;
+ perftools_pthread_specific_vals[(int)key] = val;
return 0;
}
}
diff --git a/src/maybe_threads.h b/src/maybe_threads.h
index 70fa7e2..5f35e00 100644
--- a/src/maybe_threads.h
+++ b/src/maybe_threads.h
@@ -35,8 +35,8 @@
// against non-pthreads apps.
//-------------------------------------------------------------------
-#ifndef GOOGLE_MAYBE_THREADS_H__
-#define GOOGLE_MAYBE_THREADS_H__
+#ifndef GOOGLE_MAYBE_THREADS_H_
+#define GOOGLE_MAYBE_THREADS_H_
#ifdef HAVE_PTHREAD
#include <pthread.h>
@@ -49,4 +49,4 @@ int perftools_pthread_setspecific(pthread_key_t key, void *val);
int perftools_pthread_once(pthread_once_t *ctl,
void (*init_routine) (void));
-#endif /* GOOGLE_MAYBE_THREADS_H__ */
+#endif /* GOOGLE_MAYBE_THREADS_H_ */
diff --git a/src/memory_region_map.cc b/src/memory_region_map.cc
index 1a19618..0c2dd20 100644
--- a/src/memory_region_map.cc
+++ b/src/memory_region_map.cc
@@ -102,6 +102,8 @@
#endif
#ifdef HAVE_MMAP
#include <sys/mman.h>
+#elif !defined(MAP_FAILED)
+#define MAP_FAILED -1 // the only thing we need from mman.h
#endif
#ifdef HAVE_PTHREAD
#include <pthread.h> // for pthread_t, pthread_self()
@@ -114,6 +116,7 @@
#include "base/linux_syscall_support.h"
#include "base/logging.h"
#include "base/low_level_alloc.h"
+#include "malloc_hook-inl.h"
#include <google/stacktrace.h>
#include <google/malloc_hook.h>
diff --git a/src/memory_region_map.h b/src/memory_region_map.h
index 7b7f052..a76a179 100644
--- a/src/memory_region_map.h
+++ b/src/memory_region_map.h
@@ -31,8 +31,8 @@
* Author: Maxim Lifantsev
*/
-#ifndef BASE_MEMORY_REGION_MAP_H__
-#define BASE_MEMORY_REGION_MAP_H__
+#ifndef BASE_MEMORY_REGION_MAP_H_
+#define BASE_MEMORY_REGION_MAP_H_
#include "config.h"
@@ -49,8 +49,8 @@
// execute a bunch of mmap/munmup and compare memory map with
// own accounting of what those mmaps generated
-// Class to collect and query the map of all memory regions in a process
-// that have been created with mmap, munmap, mremap, sbrk.
+// Thread-safe class to collect and query the map of all memory regions
+// in a process that have been created with mmap, munmap, mremap, sbrk.
// For each memory region, we keep track of (and provide to users)
// the stack trace that allocated that memory region.
// The recorded stack trace depth is bounded by
@@ -69,7 +69,10 @@ class MemoryRegionMap {
// Every client of MemoryRegionMap must call Init() before first use,
// and Shutdown() after last use. This allows us to reference count
- // this (singleton) class properly.
+ // this (singleton) class properly. MemoryRegionMap assumes it's the
+ // only client of MallocHooks, so a client can only register other
+ // MallocHooks after calling Init() and must unregister them before
+ // calling Shutdown().
// Initialize this module to record memory allocation stack traces.
// Stack traces that have more than "max_stack_depth" frames
@@ -117,7 +120,7 @@ class MemoryRegionMap {
// A memory region that we know about through malloc_hook-s.
// This is essentially an interface through which MemoryRegionMap
- // exports the collected data to its clients.
+ // exports the collected data to its clients. Thread-compatible.
struct Region {
uintptr_t start_addr; // region start address
uintptr_t end_addr; // region end address
@@ -326,4 +329,4 @@ class MemoryRegionMap {
DISALLOW_EVIL_CONSTRUCTORS(MemoryRegionMap);
};
-#endif // BASE_MEMORY_REGION_MAP_H__
+#endif // BASE_MEMORY_REGION_MAP_H_
diff --git a/src/packed-cache-inl.h b/src/packed-cache-inl.h
index ff1ac23..32d92fa 100644
--- a/src/packed-cache-inl.h
+++ b/src/packed-cache-inl.h
@@ -108,8 +108,8 @@
//
// Alternatives to this scheme will be added as needed.
-#ifndef TCMALLOC_PACKED_CACHE_INL_H__
-#define TCMALLOC_PACKED_CACHE_INL_H__
+#ifndef TCMALLOC_PACKED_CACHE_INL_H_
+#define TCMALLOC_PACKED_CACHE_INL_H_
#include "base/basictypes.h" // for COMPILE_ASSERT
#include "base/logging.h" // for DCHECK
@@ -225,4 +225,4 @@ class PackedCache {
#undef N_ONES_
-#endif // TCMALLOC_PACKED_CACHE_INL_H__
+#endif // TCMALLOC_PACKED_CACHE_INL_H_
diff --git a/src/pagemap.h b/src/pagemap.h
index 1fdde99..6393ffc 100644
--- a/src/pagemap.h
+++ b/src/pagemap.h
@@ -42,8 +42,8 @@
// a page number. E.g., with 32 bit pointers and 4K pages (i.e.,
// page offset fits in lower 12 bits), BITS == 20.
-#ifndef TCMALLOC_PAGEMAP_H__
-#define TCMALLOC_PAGEMAP_H__
+#ifndef TCMALLOC_PAGEMAP_H_
+#define TCMALLOC_PAGEMAP_H_
#include "config.h"
#if defined HAVE_STDINT_H
@@ -59,6 +59,8 @@
template <int BITS>
class TCMalloc_PageMap1 {
private:
+ static const int LENGTH = 1 << BITS;
+
void** array_;
public:
@@ -72,8 +74,11 @@ class TCMalloc_PageMap1 {
// Ensure that the map contains initialized entries "x .. x+n-1".
// Returns true if successful, false if we could not allocate memory.
bool Ensure(Number x, size_t n) {
- // Nothing to do since flat array was allocate at start
- return true;
+ // Nothing to do since flat array was allocated at start. All
+ // that's left is to check for overflow (that is, we don't want to
+ // ensure a number y where array_[y] would be an out-of-bounds
+ // access).
+ return n <= LENGTH - x; // an overflow-free way to do "x + n <= LENGTH"
}
void PreallocateMoreMemory() {}
@@ -141,6 +146,10 @@ class TCMalloc_PageMap2 {
for (Number key = start; key <= start + n - 1; ) {
const Number i1 = key >> LEAF_BITS;
+ // Check for overflow
+ if (i1 >= ROOT_LENGTH)
+ return false;
+
// Make 2nd level node if necessary
if (root_[i1] == NULL) {
Leaf* leaf = reinterpret_cast<Leaf*>((*allocator_)(sizeof(Leaf)));
@@ -223,6 +232,10 @@ class TCMalloc_PageMap3 {
const Number i1 = key >> (LEAF_BITS + INTERIOR_BITS);
const Number i2 = (key >> LEAF_BITS) & (INTERIOR_LENGTH-1);
+ // Check for overflow
+ if (i1 >= INTERIOR_LENGTH || i2 >= INTERIOR_LENGTH)
+ return false;
+
// Make 2nd level node if necessary
if (root_->ptrs[i1] == NULL) {
Node* n = NewNode();
@@ -248,4 +261,4 @@ class TCMalloc_PageMap3 {
}
};
-#endif // TCMALLOC_PAGEMAP_H__
+#endif // TCMALLOC_PAGEMAP_H_
diff --git a/src/pprof b/src/pprof
index 2e1276f..52730b5 100755
--- a/src/pprof
+++ b/src/pprof
@@ -72,7 +72,7 @@ use strict;
use warnings;
use Getopt::Long;
-my $PPROF_VERSION = "0.97";
+my $PPROF_VERSION = "0.98";
# These are the object tools we use, which come from various sources.
# We want to invoke them directly, rather than via users' aliases and/or
@@ -103,9 +103,10 @@ my $SYMBOL_PAGE = "/pprof/symbol"; # must support symbol lookup via POST
my $PROGRAM_NAME_PAGE = "/pprof/cmdline";
-# There is a pervasive dependency on the length (in hex characters, i.e.,
-# nibbles) of an address, distinguishing between 32-bit and 64-bit profiles:
-my $address_length = 8; # Hope for 32-bit, reset if 64-bit detected.
+# There is a pervasive dependency on the length (in hex characters,
+# i.e., nibbles) of an address, distinguishing between 32-bit and
+# 64-bit profiles. To err on the safe size, default to 64-bit here:
+my $address_length = 16;
# A list of paths to search for shared object files
my @prefix_list = ();
@@ -149,6 +150,7 @@ Reporting Granularity:
Output type:
--text Generate text report
+ --callgrind Generate callgrind format to stdout
--gv Generate Postscript and display
--list=<regexp> Generate source listing of matching routines
--disasm=<regexp> Generate disassembly of matching routines
@@ -250,6 +252,7 @@ sub Init() {
$main::opt_lib_prefix = "";
$main::opt_text = 0;
+ $main::opt_callgrind = 0;
$main::opt_list = "";
$main::opt_disasm = "";
$main::opt_gv = 0;
@@ -307,6 +310,7 @@ sub Init() {
"addresses!" => \$main::opt_addresses,
"files!" => \$main::opt_files,
"text!" => \$main::opt_text,
+ "callgrind!" => \$main::opt_callgrind,
"list=s" => \$main::opt_list,
"disasm=s" => \$main::opt_disasm,
"gv!" => \$main::opt_gv,
@@ -380,6 +384,7 @@ sub Init() {
# Check output modes
my $modes =
$main::opt_text +
+ $main::opt_callgrind +
($main::opt_list eq '' ? 0 : 1) +
($main::opt_disasm eq '' ? 0 : 1) +
$main::opt_gv +
@@ -503,6 +508,8 @@ sub Main() {
$symbols = ExtractSymbols($libs, $profile, $pcs);
}
+ my $calls = ExtractCalls($symbols, $profile);
+
# Remove uniniteresting stack items
$profile = RemoveUninterestingFrames($symbols, $profile);
@@ -532,6 +539,8 @@ sub Main() {
PrintListing($libs, $flat, $cumulative, $main::opt_list);
} elsif ($main::opt_text) {
PrintText($symbols, $flat, $cumulative, $total, -1);
+ } elsif ($main::opt_callgrind) {
+ PrintCallgrind($calls);
} else {
if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {
if ($main::opt_gv) {
@@ -638,6 +647,7 @@ sub InteractiveCommand {
}
# Clear all the mode options -- mode is controlled by "$command"
$main::opt_text = 0;
+ $main::opt_callgrind = 0;
$main::opt_disasm = 0;
$main::opt_list = 0;
$main::opt_gv = 0;
@@ -864,6 +874,31 @@ sub PrintText {
}
}
+# Print the call graph in a way that's suiteable for callgrind.
+sub PrintCallgrind {
+ my $calls = shift;
+ printf("events: Hits\n\n");
+ foreach my $call ( map { $_->[0] }
+ sort { $a->[1] cmp $b ->[1] ||
+ $a->[2] <=> $b->[2] }
+ map { /([^:]+):(\d+):([^ ]+)( -> ([^:]+):(\d+):(.+))?/;
+ [$_, $1, $2] }
+ keys %$calls ) {
+ my $count = $calls->{$call};
+ $call =~ /([^:]+):(\d+):([^ ]+)( -> ([^:]+):(\d+):(.+))?/;
+ my ( $caller_file, $caller_line, $caller_function,
+ $callee_file, $callee_line, $callee_function ) =
+ ( $1, $2, $3, $5, $6, $7 );
+ printf("fl=$caller_file\nfn=$caller_function\n");
+ if (defined $6) {
+ printf("cfl=$callee_file\n");
+ printf("cfn=$callee_function\n");
+ printf("calls=$count $callee_line\n");
+ }
+ printf("$caller_line $count\n\n");
+ }
+}
+
# Print disassembly for all all routines that match $main::opt_disasm
sub PrintDisassembly {
my $libs = shift;
@@ -1480,6 +1515,33 @@ sub IsSecondPcAlwaysTheSame {
return $second_pc;
}
+# Extracts a graph of calls.
+sub ExtractCalls {
+ my $symbols = shift;
+ my $profile = shift;
+
+ my $calls = {};
+ while( my ($stack_trace, $count) = each %$profile ) {
+ my @address = split(/\n/, $stack_trace);
+ for (my $i = 1; $i <= $#address; $i++) {
+ if (exists $symbols->{$address[$i]}) {
+ my $source = $symbols->{$address[$i]}->[1] . ":" .
+ $symbols->{$address[$i]}->[0];
+ my $destination = $symbols->{$address[$i-1]}->[1] . ":" .
+ $symbols->{$address[$i-1]}->[0];
+ my $call = "$source -> $destination";
+ AddEntry($calls, $call, $count);
+
+ if ($i == 1) {
+ AddEntry($calls, $destination, $count);
+ }
+ }
+ }
+ }
+
+ return $calls;
+}
+
sub RemoveUninterestingFrames {
my $symbols = shift;
my $profile = shift;
@@ -2413,6 +2475,11 @@ sub HexExtend {
my $addr = shift;
$addr =~ s/^0x//;
+
+ if (length $addr > $address_length) {
+ printf STDERR "Warning: address $addr is longer than address length $address_length\n";
+ }
+
return substr("000000000000000".$addr, -$address_length);
}
@@ -2780,6 +2847,7 @@ sub MapToSymbols {
$main::opt_lines ||
$main::opt_files ||
$main::opt_list ||
+ $main::opt_callgrind ||
!$got_symbols) {
GetLineNumbers($image, $offset, $pclist, $symbols);
}
diff --git a/src/profiledata.h b/src/profiledata.h
index aa50241..d9a8e7b 100644
--- a/src/profiledata.h
+++ b/src/profiledata.h
@@ -37,8 +37,8 @@
// doc/cpuprofile-fileformat.html
-#ifndef BASE_PROFILEDATA_H__
-#define BASE_PROFILEDATA_H__
+#ifndef BASE_PROFILEDATA_H_
+#define BASE_PROFILEDATA_H_
#include "config.h"
#include <time.h> // for time_t
@@ -159,4 +159,4 @@ class ProfileData {
DISALLOW_EVIL_CONSTRUCTORS(ProfileData);
};
-#endif // BASE_PROFILEDATA_H__
+#endif // BASE_PROFILEDATA_H_
diff --git a/src/profiler.cc b/src/profiler.cc
index 1ea5601..3149a89 100644
--- a/src/profiler.cc
+++ b/src/profiler.cc
@@ -68,7 +68,7 @@ class CpuProfiler {
~CpuProfiler();
// Start profiler to write profile info into fname
- bool Start(const char* fname, bool (*filter)(void*), void* filter_arg);
+ bool Start(const char* fname, const ProfilerOptions* options);
// Stop profiling and write the data to disk.
void Stop();
@@ -131,7 +131,7 @@ class CpuProfiler {
// all samples). Set at start, read-only while running. Written
// while holding both control_lock_ and signal_lock_, read and
// executed under signal_lock_.
- bool (*filter_)(void*);
+ int (*filter_)(void*);
void* filter_arg_;
// Whether or not the threading system provides interval timers
@@ -206,14 +206,14 @@ CpuProfiler::CpuProfiler()
return;
#endif
- if (!Start(fname, NULL, NULL)) {
+ if (!Start(fname, NULL)) {
RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n",
fname, strerror(errno));
}
}
bool CpuProfiler::Start(const char* fname,
- bool (*filter)(void*), void* filter_arg) {
+ const ProfilerOptions* options) {
SpinLockHolder cl(&control_lock_);
if (collector_.enabled()) {
@@ -233,8 +233,11 @@ bool CpuProfiler::Start(const char* fname,
return false;
}
- filter_ = filter;
- filter_arg_ = filter_arg;
+ filter_ = NULL;
+ if (options != NULL && options->filter_in_thread != NULL) {
+ filter_ = options->filter_in_thread;
+ filter_arg_ = options->filter_in_thread_arg;
+ }
// Must unlock before setting prof_handler to avoid deadlock
// with signal delivered to this thread.
@@ -286,7 +289,7 @@ void CpuProfiler::FlushTable() {
return;
}
- // Disable timer signal while hoding signal_lock_, to prevent deadlock
+ // Disable timer signal while holding signal_lock_, to prevent deadlock
// if we take a timer signal while flushing.
DisableHandler();
{
@@ -454,19 +457,17 @@ extern "C" void ProfilerFlush() {
CpuProfiler::instance_.FlushTable();
}
-extern "C" bool ProfilingIsEnabledForAllThreads() {
+extern "C" int ProfilingIsEnabledForAllThreads() {
return CpuProfiler::instance_.Enabled();
}
-extern "C" bool ProfilerStart(const char* fname) {
- return CpuProfiler::instance_.Start(fname, NULL, NULL);
+extern "C" int ProfilerStart(const char* fname) {
+ return CpuProfiler::instance_.Start(fname, NULL);
}
-extern "C" bool ProfilerStartFiltered(const char* fname,
- bool (*filter_in_thread)(void* arg),
- void *filter_in_thread_arg) {
- return CpuProfiler::instance_.Start(fname, filter_in_thread,
- filter_in_thread_arg);
+extern "C" int ProfilerStartWithOptions(const char *fname,
+ const ProfilerOptions *options) {
+ return CpuProfiler::instance_.Start(fname, options);
}
extern "C" void ProfilerStop() {
diff --git a/src/stacktrace_generic-inl.h b/src/stacktrace_generic-inl.h
index 9392ffc..490cd9d 100644
--- a/src/stacktrace_generic-inl.h
+++ b/src/stacktrace_generic-inl.h
@@ -35,7 +35,7 @@
// Note: The glibc implementation may cause a call to malloc.
// This can cause a deadlock in HeapProfiler.
#include <execinfo.h>
-#include <stdlib.h>
+#include <string.h>
#include "google/stacktrace.h"
// If you change this function, also change GetStackFrames below.
diff --git a/src/system-alloc.cc b/src/system-alloc.cc
index 3a0d665..b262b42 100644
--- a/src/system-alloc.cc
+++ b/src/system-alloc.cc
@@ -65,6 +65,14 @@
extern "C" { extern int madvise(caddr_t, size_t, int); }
#endif
+// Set kDebugMode mode so that we can have use C++ conditionals
+// instead of preprocessor conditionals.
+#ifdef NDEBUG
+static const bool kDebugMode = false;
+#else
+static const bool kDebugMode = true;
+#endif
+
// Structure for discovering alignment
union MemoryAligner {
void* p;
@@ -74,8 +82,10 @@ union MemoryAligner {
static SpinLock spinlock(SpinLock::LINKER_INITIALIZED);
-// Page size is initialized on demand
+#if defined(HAVE_MMAP) || defined(MADV_DONTNEED)
+// Page size is initialized on demand (only needed for mmap-based allocators)
static size_t pagesize = 0;
+#endif
// Configuration parameters.
@@ -147,6 +157,19 @@ void* SbrkSysAllocator::Alloc(size_t size, size_t *actual_size,
// This doesn't overflow because TCMalloc_SystemAlloc has already
// tested for overflow at the alignment boundary.
size = ((size + alignment - 1) / alignment) * alignment;
+
+ // Check that we we're not asking for so much more memory that we'd
+ // wrap around the end of the virtual address space. (This seems
+ // like something sbrk() should check for us, and indeed opensolaris
+ // does, but glibc does not:
+ // http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/sys/sbrk.c?a=true
+ // http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/libc/misc/sbrk.c?rev=1.1.2.1&content-type=text/plain&cvsroot=glibc
+ // Without this check, sbrk may succeed when it ought to fail.)
+ if (reinterpret_cast<intptr_t>(sbrk(0)) + size < size) {
+ failed_ = true;
+ return NULL;
+ }
+
void* result = sbrk(size);
if (result == reinterpret_cast<void*>(-1)) {
failed_ = true;
@@ -185,6 +208,10 @@ void SbrkSysAllocator::DumpStats(TCMalloc_Printer* printer) {
void* MmapSysAllocator::Alloc(size_t size, size_t *actual_size,
size_t alignment) {
+#ifndef HAVE_MMAP
+ failed_ = true;
+ return NULL;
+#else
// Check if we should use mmap allocation.
// FLAGS_malloc_skip_mmap starts out as false (its uninitialized
// state) and eventually gets initialized to the specified value. Note
@@ -246,6 +273,7 @@ void* MmapSysAllocator::Alloc(size_t size, size_t *actual_size,
ptr += adjust;
return reinterpret_cast<void*>(ptr);
+#endif // HAVE_MMAP
}
void MmapSysAllocator::DumpStats(TCMalloc_Printer* printer) {
@@ -254,6 +282,10 @@ void MmapSysAllocator::DumpStats(TCMalloc_Printer* printer) {
void* DevMemSysAllocator::Alloc(size_t size, size_t *actual_size,
size_t alignment) {
+#ifndef HAVE_MMAP
+ failed_ = true;
+ return NULL;
+#else
static bool initialized = false;
static off_t physmem_base; // next physical memory address to allocate
static off_t physmem_limit; // maximum physical address allowed
@@ -338,6 +370,7 @@ void* DevMemSysAllocator::Alloc(size_t size, size_t *actual_size,
physmem_base += adjust + size;
return reinterpret_cast<void*>(ptr);
+#endif // HAVE_MMAP
}
void DevMemSysAllocator::DumpStats(TCMalloc_Printer* printer) {
@@ -349,8 +382,21 @@ void InitSystemAllocators(void) {
// This determines the order in which system allocators are called
int i = kMaxDynamicAllocators;
allocators[i++] = new (devmem_space) DevMemSysAllocator();
- allocators[i++] = new (sbrk_space) SbrkSysAllocator();
- allocators[i++] = new (mmap_space) MmapSysAllocator();
+
+ // In 64-bit debug mode, place the mmap allocator first since it
+ // allocates pointers that do not fit in 32 bits and therefore gives
+ // us better testing of code's 64-bit correctness. It also leads to
+ // less false negatives in heap-checking code. (Numbers are less
+ // likely to look like pointers and therefore the conservative gc in
+ // the heap-checker is less likely to misinterpret a number as a
+ // pointer).
+ if (kDebugMode && sizeof(void*) > 4) {
+ allocators[i++] = new (mmap_space) MmapSysAllocator();
+ allocators[i++] = new (sbrk_space) SbrkSysAllocator();
+ } else {
+ allocators[i++] = new (sbrk_space) SbrkSysAllocator();
+ allocators[i++] = new (mmap_space) MmapSysAllocator();
+ }
}
void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size,
diff --git a/src/system-alloc.h b/src/system-alloc.h
index 2859a54..5b0fbb6 100644
--- a/src/system-alloc.h
+++ b/src/system-alloc.h
@@ -33,8 +33,8 @@
// Routine that uses sbrk/mmap to allocate memory from the system.
// Useful for implementing malloc.
-#ifndef TCMALLOC_SYSTEM_ALLOC_H__
-#define TCMALLOC_SYSTEM_ALLOC_H__
+#ifndef TCMALLOC_SYSTEM_ALLOC_H_
+#define TCMALLOC_SYSTEM_ALLOC_H_
#include "config.h"
#include "internal_logging.h"
@@ -110,4 +110,4 @@ static const int kMaxDynamicAllocators = 2;
// Retrieve the current state of various system allocators.
extern PERFTOOLS_DLL_DECL void DumpSystemAllocatorStats(TCMalloc_Printer* printer);
-#endif /* TCMALLOC_SYSTEM_ALLOC_H__ */
+#endif /* TCMALLOC_SYSTEM_ALLOC_H_ */
diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc
index 0b4e715..94287ba 100644
--- a/src/tcmalloc.cc
+++ b/src/tcmalloc.cc
@@ -64,6 +64,19 @@
// in Populate() for pages with sizeclass > 0 objects, and in do_malloc() and
// do_memalign() for all other relevant pages.
//
+// PAGEMAP
+// -------
+// Page map contains a mapping from page id to Span.
+//
+// If Span s occupies pages [p..q],
+// pagemap[p] == s
+// pagemap[q] == s
+// pagemap[p+1..q-1] are undefined
+// pagemap[p-1] and pagemap[q+1] are defined:
+// NULL if the corresponding page is not yet in the address space.
+// Otherwise it points to a Span. This span may be free
+// or allocated. If free, it is in one of pageheap's freelist.
+//
// TODO: Bias reclamation to larger addresses
// TODO: implement mallinfo/mallopt
// TODO: Better testing
@@ -101,6 +114,7 @@
#include "base/basictypes.h" // gets us PRIu64
#include "base/sysinfo.h"
#include "base/spinlock.h"
+#include "malloc_hook-inl.h"
#include <google/malloc_hook.h>
#include <google/malloc_extension.h>
#include "internal_logging.h"
@@ -216,7 +230,7 @@ static const size_t kMaxPages = kMinSystemAlloc;
static unsigned int primes_list[] = {
// Small values might cause high rates of sampling
// and hence commented out.
- // 2, 5, 11, 17, 37, 67, 131, 257,
+ // 2, 5, 11, 17, 37, 67, 131, 257,
// 521, 1031, 2053, 4099, 8209, 16411,
32771, 65537, 131101, 262147, 524309, 1048583,
2097169, 4194319, 8388617, 16777259, 33554467 };
@@ -627,19 +641,6 @@ static inline Length pages(size_t bytes) {
((bytes & (kPageSize - 1)) > 0 ? 1 : 0);
}
-// Convert a user size into the number of bytes that will actually be
-// allocated
-static size_t AllocationSize(size_t bytes) {
- if (bytes > kMaxSize) {
- // Large object: we allocate an integral number of pages
- ASSERT(bytes <= (kMaxValidPages << kPageShift));
- return pages(bytes) << kPageShift;
- } else {
- // Small object: find the size class to which it belongs
- return ByteSizeForClass(SizeClass(bytes));
- }
-}
-
// Information kept for a span (a contiguous run of pages).
struct Span {
PageID start; // Starting page number
@@ -649,7 +650,7 @@ struct Span {
void* objects; // Linked list of free objects
unsigned int refcount : 16; // Number of non-free objects
unsigned int sizeclass : 8; // Size-class for small objects (or 0)
- unsigned int free : 1; // Is the span free
+ unsigned int location : 2; // Is the span on a freelist, and if so, which?
unsigned int sample : 1; // Sampled object?
#undef SPAN_HISTORY
@@ -659,6 +660,9 @@ struct Span {
char history[64];
int value[64];
#endif
+
+ // What freelist the span is on: IN_USE if on none, or normal or returned
+ enum { IN_USE, ON_NORMAL_FREELIST, ON_RETURNED_FREELIST };
};
#ifdef SPAN_HISTORY
@@ -818,7 +822,7 @@ class TCMalloc_PageHeap {
// Returns a pointer to the second span.
//
// REQUIRES: "0 < n < span->length"
- // REQUIRES: !span->free
+ // REQUIRES: span->location == IN_USE
// REQUIRES: span->sizeclass == 0
Span* Split(Span* span, Length n);
@@ -839,7 +843,8 @@ class TCMalloc_PageHeap {
}
bool Check();
- bool CheckList(Span* list, Length min_pages, Length max_pages);
+ bool CheckList(Span* list, Length min_pages, Length max_pages,
+ int freelist); // ON_NORMAL_FREELIST or ON_RETURNED_FREELIST
// Release all pages on the free list for reuse by the OS:
void ReleaseFreePages();
@@ -883,15 +888,14 @@ class TCMalloc_PageHeap {
bool GrowHeap(Length n);
- // REQUIRES span->length >= n
+ // REQUIRES: span->length >= n
+ // REQUIRES: span->location != IN_USE
// Remove span from its free list, and move any leftover part of
// span into appropriate free lists. Also update "span" to have
// length exactly "n" and mark it as non-free so it can be returned
// to the client. After all that, decrease free_pages_ by n and
// return span.
- //
- // "released" is true iff "span" was found on a "returned" list.
- Span* Carve(Span* span, Length n, bool released);
+ Span* Carve(Span* span, Length n);
void RecordSpan(Span* span) {
pagemap_.set(span->start, span);
@@ -939,18 +943,18 @@ Span* TCMalloc_PageHeap::New(Length n) {
// Find first size >= n that has a non-empty list
for (Length s = n; s < kMaxPages; s++) {
Span* ll = &free_[s].normal;
- bool released = false;
// If we're lucky, ll is non-empty, meaning it has a suitable span.
- if (DLL_IsEmpty(ll)) {
- // Alternatively, maybe there's a usable returned span.
- ll = &free_[s].returned;
- released = true;
- if (DLL_IsEmpty(ll)) {
- // Still no luck, so keep looking in larger classes.
- continue;
- }
+ if (!DLL_IsEmpty(ll)) {
+ ASSERT(ll->next->location == Span::ON_NORMAL_FREELIST);
+ return Carve(ll->next, n);
+ }
+ // Alternatively, maybe there's a usable returned span.
+ ll = &free_[s].returned;
+ if (!DLL_IsEmpty(ll)) {
+ ASSERT(ll->next->location == Span::ON_RETURNED_FREELIST);
+ return Carve(ll->next, n);
}
- return Carve(ll->next, n, released);
+ // Still no luck, so keep looking in larger classes.
}
Span* result = AllocLarge(n);
@@ -968,7 +972,6 @@ Span* TCMalloc_PageHeap::New(Length n) {
Span* TCMalloc_PageHeap::AllocLarge(Length n) {
// find the best span (closest to n in size).
// The following loops implements address-ordered best-fit.
- bool from_released = false;
Span *best = NULL;
// Search through normal list
@@ -980,7 +983,7 @@ Span* TCMalloc_PageHeap::AllocLarge(Length n) {
|| (span->length < best->length)
|| ((span->length == best->length) && (span->start < best->start))) {
best = span;
- from_released = false;
+ ASSERT(best->location == Span::ON_NORMAL_FREELIST);
}
}
}
@@ -994,23 +997,24 @@ Span* TCMalloc_PageHeap::AllocLarge(Length n) {
|| (span->length < best->length)
|| ((span->length == best->length) && (span->start < best->start))) {
best = span;
- from_released = true;
+ ASSERT(best->location == Span::ON_RETURNED_FREELIST);
}
}
}
- return best == NULL ? NULL : Carve(best, n, from_released);
+ return best == NULL ? NULL : Carve(best, n);
}
Span* TCMalloc_PageHeap::Split(Span* span, Length n) {
ASSERT(0 < n);
ASSERT(n < span->length);
- ASSERT(!span->free);
+ ASSERT(span->location == Span::IN_USE);
ASSERT(span->sizeclass == 0);
Event(span, 'T', n);
const int extra = span->length - n;
Span* leftover = NewSpan(span->start + n, extra);
+ ASSERT(leftover->location == Span::IN_USE);
Event(leftover, 'U', extra);
RecordSpan(leftover);
pagemap_.set(span->start + n - 1, span); // Update map from pageid to span
@@ -1019,23 +1023,26 @@ Span* TCMalloc_PageHeap::Split(Span* span, Length n) {
return leftover;
}
-Span* TCMalloc_PageHeap::Carve(Span* span, Length n, bool released) {
+Span* TCMalloc_PageHeap::Carve(Span* span, Length n) {
ASSERT(n > 0);
+ ASSERT(span->location != Span::IN_USE);
+ const int old_location = span->location;
DLL_Remove(span);
- span->free = 0;
+ span->location = Span::IN_USE;
Event(span, 'A', n);
const int extra = span->length - n;
ASSERT(extra >= 0);
if (extra > 0) {
Span* leftover = NewSpan(span->start + n, extra);
- leftover->free = 1;
+ leftover->location = old_location;
Event(leftover, 'S', extra);
RecordSpan(leftover);
// Place leftover span on appropriate free list
SpanList* listpair = (extra < kMaxPages) ? &free_[extra] : &large_;
- Span* dst = released ? &listpair->returned : &listpair->normal;
+ Span* dst = (leftover->location == Span::ON_RETURNED_FREELIST
+ ? &listpair->returned : &listpair->normal);
DLL_Prepend(dst, leftover);
span->length = n;
@@ -1048,7 +1055,7 @@ Span* TCMalloc_PageHeap::Carve(Span* span, Length n, bool released) {
void TCMalloc_PageHeap::Delete(Span* span) {
ASSERT(Check());
- ASSERT(!span->free);
+ ASSERT(span->location == Span::IN_USE);
ASSERT(span->length > 0);
ASSERT(GetDescriptor(span->start) == span);
ASSERT(GetDescriptor(span->start + span->length - 1) == span);
@@ -1066,7 +1073,7 @@ void TCMalloc_PageHeap::Delete(Span* span) {
const PageID p = span->start;
const Length n = span->length;
Span* prev = GetDescriptor(p-1);
- if (prev != NULL && prev->free) {
+ if (prev != NULL && prev->location != Span::IN_USE) {
// Merge preceding span into this span
ASSERT(prev->start + prev->length == p);
const Length len = prev->length;
@@ -1078,7 +1085,7 @@ void TCMalloc_PageHeap::Delete(Span* span) {
Event(span, 'L', len);
}
Span* next = GetDescriptor(p+n);
- if (next != NULL && next->free) {
+ if (next != NULL && next->location != Span::IN_USE) {
// Merge next span into this span
ASSERT(next->start == p+n);
const Length len = next->length;
@@ -1090,7 +1097,7 @@ void TCMalloc_PageHeap::Delete(Span* span) {
}
Event(span, 'D', span->length);
- span->free = 1;
+ span->location = Span::ON_NORMAL_FREELIST;
if (span->length < kMaxPages) {
DLL_Prepend(&free_[span->length].normal, span);
} else {
@@ -1131,9 +1138,11 @@ void TCMalloc_PageHeap::IncrementalScavenge(Length n) {
if (!DLL_IsEmpty(&slist->normal)) {
// Release the last span on the normal portion of this list
Span* s = slist->normal.prev;
+ ASSERT(s->location == Span::ON_NORMAL_FREELIST);
DLL_Remove(s);
TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift),
static_cast<size_t>(s->length << kPageShift));
+ s->location = Span::ON_RETURNED_FREELIST;
DLL_Prepend(&slist->returned, s);
// Compute how long to wait until we return memory.
@@ -1159,7 +1168,7 @@ void TCMalloc_PageHeap::IncrementalScavenge(Length n) {
void TCMalloc_PageHeap::RegisterSizeClass(Span* span, size_t sc) {
// Associate span object with all interior pages as well
- ASSERT(!span->free);
+ ASSERT(span->location == Span::IN_USE);
ASSERT(GetDescriptor(span->start) == span);
ASSERT(GetDescriptor(span->start+span->length-1) == span);
Event(span, 'C', sc);
@@ -1296,18 +1305,19 @@ bool TCMalloc_PageHeap::GrowHeap(Length n) {
bool TCMalloc_PageHeap::Check() {
ASSERT(free_[0].normal.next == &free_[0].normal);
ASSERT(free_[0].returned.next == &free_[0].returned);
- CheckList(&large_.normal, kMaxPages, 1000000000);
- CheckList(&large_.returned, kMaxPages, 1000000000);
+ CheckList(&large_.normal, kMaxPages, 1000000000, Span::ON_NORMAL_FREELIST);
+ CheckList(&large_.returned, kMaxPages, 1000000000, Span::ON_RETURNED_FREELIST);
for (Length s = 1; s < kMaxPages; s++) {
- CheckList(&free_[s].normal, s, s);
- CheckList(&free_[s].returned, s, s);
+ CheckList(&free_[s].normal, s, s, Span::ON_NORMAL_FREELIST);
+ CheckList(&free_[s].returned, s, s, Span::ON_RETURNED_FREELIST);
}
return true;
}
-bool TCMalloc_PageHeap::CheckList(Span* list, Length min_pages, Length max_pages) {
+bool TCMalloc_PageHeap::CheckList(Span* list, Length min_pages, Length max_pages,
+ int freelist) {
for (Span* s = list->next; s != list; s = s->next) {
- CHECK_CONDITION(s->free);
+ CHECK_CONDITION(s->location == freelist); // NORMAL or RETURNED
CHECK_CONDITION(s->length >= min_pages);
CHECK_CONDITION(s->length <= max_pages);
CHECK_CONDITION(GetDescriptor(s->start) == s);
@@ -1323,6 +1333,8 @@ static void ReleaseFreeList(Span* list, Span* returned) {
Span* s = list->prev;
DLL_Remove(s);
DLL_Prepend(returned, s);
+ ASSERT(s->location == Span::ON_NORMAL_FREELIST);
+ s->location = Span::ON_RETURNED_FREELIST;
TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift),
static_cast<size_t>(s->length << kPageShift));
}
@@ -2503,6 +2515,7 @@ class TCMallocImplementation : public MallocExtension {
*value = stats.system_bytes
- stats.thread_bytes
- stats.central_bytes
+ - stats.transfer_bytes
- stats.pageheap_bytes;
return true;
}
@@ -2963,9 +2976,23 @@ extern "C" void* realloc(void* old_ptr, size_t new_size) __THROW {
// Reallocate if the new size is larger than the old size,
// or if the new size is significantly smaller than the old size.
- if ((new_size > old_size) || (AllocationSize(new_size) < old_size)) {
- // Need to reallocate
- void* new_ptr = do_malloc(new_size);
+ // We do hysteresis to avoid resizing ping-pongs:
+ // . If we need to grow, grow to max(new_size, old_size * 1.X)
+ // . Don't shrink unless new_size < old_size * 0.Y
+ // X and Y trade-off time for wasted space. For now we do 1.25 and 0.5.
+ const int lower_bound_to_grow = old_size + old_size / 4;
+ const int upper_bound_to_shrink = old_size / 2;
+ if ((new_size > old_size) || (new_size < upper_bound_to_shrink)) {
+ // Need to reallocate.
+ void* new_ptr = NULL;
+
+ if (new_size > old_size && new_size < lower_bound_to_grow) {
+ new_ptr = do_malloc(lower_bound_to_grow);
+ }
+ if (new_ptr == NULL) {
+ // Either new_size is not a tiny increment, or last do_malloc failed.
+ new_ptr = do_malloc(new_size);
+ }
if (new_ptr == NULL) {
return NULL;
}
diff --git a/src/tests/maybe_threads_unittest.sh b/src/tests/maybe_threads_unittest.sh
index f2ba73d..77b3b78 100755
--- a/src/tests/maybe_threads_unittest.sh
+++ b/src/tests/maybe_threads_unittest.sh
@@ -63,13 +63,13 @@ UNITTEST_DIR=`$UNITTEST_DIR/low_level_alloc_unittest --help 2>&1 \
# Figure out where libtcmalloc lives. It should be in UNITTEST_DIR,
# but with libtool it might be in a subdir.
-if [ -e "$UNITTEST_DIR/libtcmalloc_minimal.so" ]; then
+if [ -r "$UNITTEST_DIR/libtcmalloc_minimal.so" ]; then
LIB_PATH="$UNITTEST_DIR/libtcmalloc_minimal.so"
-elif [ -e "$UNITTEST_DIR/.libs/libtcmalloc_minimal.so" ]; then
+elif [ -r "$UNITTEST_DIR/.libs/libtcmalloc_minimal.so" ]; then
LIB_PATH="$UNITTEST_DIR/.libs/libtcmalloc_minimal.so"
-elif [ -e "$UNITTEST_DIR/libtcmalloc_minimal.dylib" ]; then # for os x
+elif [ -r "$UNITTEST_DIR/libtcmalloc_minimal.dylib" ]; then # for os x
LIB_PATH="$UNITTEST_DIR/libtcmalloc_minimal.dylib"
-elif [ -e "$UNITTEST_DIR/.libs/libtcmalloc_minimal.dylib" ]; then
+elif [ -r "$UNITTEST_DIR/.libs/libtcmalloc_minimal.dylib" ]; then
LIB_PATH="$UNITTEST_DIR/.libs/libtcmalloc_minimal.dylib"
else
echo "Cannot run $0: cannot find libtcmalloc_minimal.so"
diff --git a/src/tests/memalign_unittest.cc b/src/tests/memalign_unittest.cc
index f83f57d..a8d418e 100644
--- a/src/tests/memalign_unittest.cc
+++ b/src/tests/memalign_unittest.cc
@@ -54,8 +54,15 @@
#ifdef HAVE_STDINT_H
#include <stdint.h> // for uintptr_t
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for getpagesize()
+#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
#include "base/basictypes.h"
#include "base/logging.h"
+#include "tests/testutil.h"
// Return the next interesting size/delta to check. Returns -1 if no more.
@@ -115,6 +122,8 @@ static bool Valid(const void* p, int n, char seed) {
}
int main(int argc, char** argv) {
+ SetTestResourceLimit();
+
// Try allocating data with a bunch of alignments and sizes
for (int a = 1; a < 1048576; a *= 2) {
for (int s = 0; s != -1; s = NextSize(s)) {
diff --git a/src/tests/tcmalloc_unittest.cc b/src/tests/tcmalloc_unittest.cc
index d3df596..0b6230d 100644
--- a/src/tests/tcmalloc_unittest.cc
+++ b/src/tests/tcmalloc_unittest.cc
@@ -516,6 +516,29 @@ static void TestCalloc(size_t n, size_t s, bool ok) {
}
}
+// This makes sure that reallocing a small number of bytes in either
+// direction doesn't cause us to allocate new memory.
+static void TestRealloc() {
+ int start_sizes[] = { 100, 1000, 10000, 100000 };
+ int deltas[] = { 1, -2, 4, -8, 16, -32, 64, -128 };
+
+ for (int s = 0; s < sizeof(start_sizes)/sizeof(*start_sizes); ++s) {
+ void* p = malloc(start_sizes[s]);
+ CHECK(p);
+ // The larger the start-size, the larger the non-reallocing delta.
+ for (int d = 0; d < s*2; ++d) {
+ void* new_p = realloc(p, start_sizes[s] + deltas[d]);
+ CHECK(p == new_p); // realloc should not allocate new memory
+ }
+ // Test again, but this time reallocing smaller first.
+ for (int d = 0; d < s*2; ++d) {
+ void* new_p = realloc(p, start_sizes[s] - deltas[d]);
+ CHECK(p == new_p); // realloc should not allocate new memory
+ }
+ free(p);
+ }
+}
+
static void TestNewHandler() throw (std::bad_alloc) {
++news_handled;
throw std::bad_alloc();
@@ -647,6 +670,20 @@ int main(int argc, char** argv) {
// Optional argv[1] is the seed
AllocatorState rnd(argc > 1 ? atoi(argv[1]) : 100);
+ SetTestResourceLimit();
+
+ // TODO(odo): This test has been disabled because it is only by luck that it
+ // does not result in fragmentation. When tcmalloc makes an allocation which
+ // spans previously unused leaves of the pagemap it will allocate and fill in
+ // the leaves to cover the new allocation. The leaves happen to be 256MiB in
+ // the 64-bit build, and with the sbrk allocator these allocations just
+ // happen to fit in one leaf by luck. With other allocators (mmap,
+ // memfs_malloc when used with small pages) the allocations generally span
+ // two leaves and this results in a very bad fragmentation pattern with this
+ // code. The same failure can be forced with the sbrk allocator just by
+ // allocating something on the order of 128MiB prior to starting this test so
+ // that the test allocations straddle a 256MiB boundary.
+
// TODO(csilvers): port MemoryUsage() over so the test can use that
#if 0
# include <unistd.h> // for getpid()
@@ -825,6 +862,10 @@ int main(int argc, char** argv) {
TestCalloc(3, kMaxSignedSize, false);
TestCalloc(kMaxSignedSize, kMaxSignedSize, false);
+ // Test that realloc doesn't always reallocate and copy memory.
+ fprintf(LOGSTREAM, "Testing realloc\n");
+ TestRealloc();
+
fprintf(LOGSTREAM, "Testing operator new(nothrow).\n");
TestNothrowNew(&::operator new);
fprintf(LOGSTREAM, "Testing operator new[](nothrow).\n");
diff --git a/src/tests/testutil.cc b/src/tests/testutil.cc
index 9ab4c3c..edc16c8 100644
--- a/src/tests/testutil.cc
+++ b/src/tests/testutil.cc
@@ -34,8 +34,47 @@
#include "config_for_unittests.h"
#include <stdlib.h> // for NULL, abort()
+// On FreeBSD, if you #include <sys/resource.h>, you have to get stdint first.
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
#include "tests/testutil.h"
+
+// When compiled 64-bit and run on systems with swap several unittests will end
+// up trying to consume all of RAM+swap, and that can take quite some time. By
+// limiting the address-space size we get sufficient coverage without blowing
+// out job limits.
+void SetTestResourceLimit() {
+#ifdef HAVE_SYS_RESOURCE_H
+ // The actual resource we need to set varies depending on which flavour of
+ // unix. On Linux we need RLIMIT_AS because that covers the use of mmap.
+ // Otherwise hopefully RLIMIT_RSS is good enough. (Unfortunately 64-bit
+ // and 32-bit headers disagree on the type of these constants!)
+#ifdef RLIMIT_AS
+#define USE_RESOURCE RLIMIT_AS
+#else
+#define USE_RESOURCE RLIMIT_RSS
+#endif
+
+ // Restrict the test to 1GiB, which should fit comfortably well on both
+ // 32-bit and 64-bit hosts, and executes in ~1s.
+ const rlim_t kMaxMem = 1<<30;
+
+ struct rlimit rlim;
+ if (getrlimit(USE_RESOURCE, &rlim) == 0) {
+ if (rlim.rlim_cur == RLIM_INFINITY || rlim.rlim_cur > kMaxMem) {
+ rlim.rlim_cur = kMaxMem;
+ setrlimit(USE_RESOURCE, &rlim); // ignore result
+ }
+ }
+#endif /* HAVE_SYS_RESOURCE_H */
+}
+
+
struct FunctionAndId {
void (*ptr_to_function)(int);
int id;
diff --git a/src/tests/testutil.h b/src/tests/testutil.h
index a55dfdf..26b04e4 100644
--- a/src/tests/testutil.h
+++ b/src/tests/testutil.h
@@ -30,8 +30,8 @@
// ---
// Author: Craig Silverstein
-#ifndef TCMALLOC_TOOLS_TESTUTIL_H__
-#define TCMALLOC_TOOLS_TESTUTIL_H__
+#ifndef TCMALLOC_TOOLS_TESTUTIL_H_
+#define TCMALLOC_TOOLS_TESTUTIL_H_
// Run a function in a thread of its own and wait for it to finish.
// The function you pass in must have the signature
@@ -52,4 +52,10 @@ extern "C" void RunManyThreads(void (*fn)(), int count);
// where idx is the index of the thread (which of the X threads this is).
extern "C" void RunManyThreadsWithId(void (*fn)(int), int count, int stacksize);
-#endif // TCMALLOC_TOOLS_TESTUTIL_H__
+// When compiled 64-bit and run on systems with swap several unittests will end
+// up trying to consume all of RAM+swap, and that can take quite some time. By
+// limiting the address-space size we get sufficient coverage without blowing
+// out job limits.
+void SetTestResourceLimit();
+
+#endif // TCMALLOC_TOOLS_TESTUTIL_H_
diff --git a/src/windows/config.h b/src/windows/config.h
index 8a74cda..d42da35 100644
--- a/src/windows/config.h
+++ b/src/windows/config.h
@@ -6,11 +6,11 @@
*/
#ifdef __MINGW32__
#include "../config.h"
-#define GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H__
+#define GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_
#endif
-#ifndef GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H__
-#define GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H__
+#ifndef GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_
+#define GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_
/* the location of <hash_map> */
#define HASH_MAP_H <hash_map>
@@ -129,6 +129,9 @@
/* Define to 1 if you have the <sys/prctl.h> header file. */
#undef HAVE_SYS_PRCTL_H
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
@@ -239,4 +242,4 @@
// TODO(csilvers): include windows/port.h in every relevant source file instead?
#include "windows/port.h"
-#endif /* GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H__ */
+#endif /* GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_ */
diff --git a/src/windows/mingw.h b/src/windows/mingw.h
index 40bc104..ed13e52 100644
--- a/src/windows/mingw.h
+++ b/src/windows/mingw.h
@@ -35,8 +35,8 @@
* stuff that MinGW doesn't support, like pthreads.
*/
-#ifndef GOOGLE_PERFTOOLS_WINDOWS_MINGW_H__
-#define GOOGLE_PERFTOOLS_WINDOWS_MINGW_H__
+#ifndef GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_
+#define GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_
#ifdef __MINGW32__
@@ -44,4 +44,4 @@
#endif /* __MINGW32__ */
-#endif /* GOOGLE_PERFTOOLS_WINDOWS_MINGW_H__ */
+#endif /* GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_ */
diff --git a/src/windows/mini_disassembler.h b/src/windows/mini_disassembler.h
index e0bbd76..87c686f 100644
--- a/src/windows/mini_disassembler.h
+++ b/src/windows/mini_disassembler.h
@@ -33,8 +33,8 @@
* Definition of MiniDisassembler.
*/
-#ifndef GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H__
-#define GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H__
+#ifndef GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H_
+#define GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H_
#include <windows.h>
#include "mini_disassembler_types.h"
@@ -187,4 +187,4 @@ class MiniDisassembler {
}; // namespace sidestep
-#endif // GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H__
+#endif // GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H_
diff --git a/src/windows/mini_disassembler_types.h b/src/windows/mini_disassembler_types.h
index 43a6369..513cd02 100644
--- a/src/windows/mini_disassembler_types.h
+++ b/src/windows/mini_disassembler_types.h
@@ -34,8 +34,8 @@
* mechanisms.
*/
-#ifndef GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H__
-#define GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H__
+#ifndef GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H_
+#define GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H_
namespace sidestep {
@@ -223,4 +223,4 @@ struct ModrmEntry {
}; // namespace sidestep
-#endif // GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H__
+#endif // GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H_
diff --git a/src/windows/patch_functions.cc b/src/windows/patch_functions.cc
index 8679a15..6c29a2f 100644
--- a/src/windows/patch_functions.cc
+++ b/src/windows/patch_functions.cc
@@ -37,6 +37,7 @@
#include <tlhelp32.h> // for CreateToolhelp32Snapshot()
#include <base/logging.h>
#include "google/malloc_hook.h"
+#include "malloc_hook-inl.h"
#include "preamble_patcher.h"
// MinGW doesn't seem to define this, perhaps some windowsen don't either.
diff --git a/src/windows/port.h b/src/windows/port.h
index 8bbdeb7..8ab5fb8 100644
--- a/src/windows/port.h
+++ b/src/windows/port.h
@@ -37,13 +37,13 @@
* http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
*/
-#ifndef GOOGLE_BASE_WINDOWS_H__
-#define GOOGLE_BASE_WINDOWS_H__
+#ifndef GOOGLE_BASE_WINDOWS_H_
+#define GOOGLE_BASE_WINDOWS_H_
// You should never include this file directly, but always include it
// from either config.h (MSVC) or mingw.h (MinGW/msys).
-#if !defined(GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H__) && \
- !defined(GOOGLE_PERFTOOLS_WINDOWS_MINGW_H__)
+#if !defined(GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_) && \
+ !defined(GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_)
# error "port.h should only be included from config.h or mingw.h"
#endif
@@ -239,7 +239,9 @@ extern PERFTOOLS_DLL_DECL int getpagesize(); // in port.cc
// By defining this, we get away without having to get a StackTrace
// But maybe play around with ExperimentalGetStackTrace in port.cc
+#ifndef NO_TCMALLOC_SAMPLES
#define NO_TCMALLOC_SAMPLES
+#endif
// tcmalloc.cc calls this so we can patch VirtualAlloc() et al.
// TODO(csilvers): instead of patching the functions, consider just replacing
@@ -262,10 +264,10 @@ extern PERFTOOLS_DLL_DECL void UnpatchWindowsFunctions();
// windows/port.h defines compatibility APIs for several .h files, which
// we therefore shouldn't be #including directly. This hack keeps us from
// doing so. TODO(csilvers): do something more principled.
-#define BASE_SPINLOCK_H__ 1
-#define GOOGLE_MAYBE_THREADS_H__ 1
+#define BASE_SPINLOCK_H_ 1
+#define GOOGLE_MAYBE_THREADS_H_ 1
#endif /* WIN32 */
-#endif /* GOOGLE_BASE_WINDOWS_H__ */
+#endif /* GOOGLE_BASE_WINDOWS_H_ */
diff --git a/src/windows/preamble_patcher.h b/src/windows/preamble_patcher.h
index dc6d4db..5d21104 100644
--- a/src/windows/preamble_patcher.h
+++ b/src/windows/preamble_patcher.h
@@ -33,8 +33,8 @@
* Definition of PreamblePatcher
*/
-#ifndef GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H__
-#define GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H__
+#ifndef GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_
+#define GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_
#include <windows.h>
@@ -317,4 +317,4 @@ class PreamblePatcher {
}; // namespace sidestep
-#endif // GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H__
+#endif // GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_
diff --git a/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj b/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
index 0a8ba08..1742c6b 100755
--- a/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
+++ b/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
@@ -450,6 +450,15 @@
RelativePath="..\..\src\google\malloc_hook.h">
</File>
<File
+ RelativePath="..\..\src\malloc_hook-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
+ </File>
+ <File
RelativePath="..\..\src\memory_region_map.h">
</File>
<File
diff --git a/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj b/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
index 0c0b8d0..3292713 100755
--- a/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
+++ b/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
@@ -241,6 +241,15 @@
RelativePath="..\..\src\google\malloc_hook.h">
</File>
<File
+ RelativePath="..\..\src\malloc_hook-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
+ </File>
+ <File
RelativePath="..\..\src\windows\port.h">
</File>
</Filter>
diff --git a/vsprojects/memalign_unittest/memalign_unittest.vcproj b/vsprojects/memalign_unittest/memalign_unittest.vcproj
index 22c2ce7..9eb45b8 100755
--- a/vsprojects/memalign_unittest/memalign_unittest.vcproj
+++ b/vsprojects/memalign_unittest/memalign_unittest.vcproj
@@ -129,6 +129,23 @@
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
+ <File
+ RelativePath="..\..\src\tests\testutil.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>
</Filter>
<Filter
Name="Header Files"
@@ -143,6 +160,9 @@
<File
RelativePath="..\..\src\windows\port.h">
</File>
+ <File
+ RelativePath="..\..\src\tests\testutil.h">
+ </File>
</Filter>
</Files>
<Globals>
diff --git a/vsprojects/system_alloc_unittest/system_alloc_unittest.vcproj b/vsprojects/system_alloc_unittest/system_alloc_unittest.vcproj
deleted file mode 100755
index 1026a57..0000000
--- a/vsprojects/system_alloc_unittest/system_alloc_unittest.vcproj
+++ /dev/null
@@ -1,150 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="7.10"
- Name="system_alloc_unittest"
- ProjectGUID="{8249D44B-4CF5-4BDC-9183-C5D6F12413E7}"
- Keyword="Win32Proj">
- <Platforms>
- <Platform
- Name="Win32"/>
- </Platforms>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="1"
- CharacterSet="2">
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
- MinimalRebuild="TRUE"
- BasicRuntimeChecks="3"
- RuntimeLibrary="5"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
- DebugInformationFormat="4"/>
- <Tool
- Name="VCCustomBuildTool"/>
- <Tool
- Name="VCLinkerTool"
- OutputFile="$(OutDir)/system_alloc_unittest.exe"
- LinkIncremental="2"
- GenerateDebugInformation="TRUE"
- ProgramDatabaseFile="$(OutDir)/system_alloc_unittest.pdb"
- SubSystem="1"
- TargetMachine="1"/>
- <Tool
- Name="VCMIDLTool"/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCXMLDataGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- <Tool
- Name="VCManagedWrapperGeneratorTool"/>
- <Tool
- Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="1"
- CharacterSet="2">
- <Tool
- Name="VCCLCompilerTool"
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
- RuntimeLibrary="4"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
- DebugInformationFormat="3"/>
- <Tool
- Name="VCCustomBuildTool"/>
- <Tool
- Name="VCLinkerTool"
- OutputFile="$(OutDir)/system_alloc_unittest.exe"
- LinkIncremental="1"
- GenerateDebugInformation="TRUE"
- SubSystem="1"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"/>
- <Tool
- Name="VCMIDLTool"/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCXMLDataGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- <Tool
- Name="VCManagedWrapperGeneratorTool"/>
- <Tool
- Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
- <File
- RelativePath="..\..\src\tests\system-alloc_unittest.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>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
- <File
- RelativePath="..\..\src\windows\config.h">
- </File>
- <File
- RelativePath="..\..\src\config_for_unittests.h">
- </File>
- <File
- RelativePath="..\..\src\windows\port.h">
- </File>
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/vsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj b/vsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj
index eda0f08..a98470f 100755
--- a/vsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj
+++ b/vsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj
@@ -507,6 +507,15 @@
RelativePath="..\..\src\google\malloc_hook.h">
</File>
<File
+ RelativePath="..\..\src\malloc_hook-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
+ </File>
+ <File
RelativePath="..\..\src\memory_region_map.h">
</File>
<File