diff options
author | csilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50> | 2008-06-14 02:30:53 +0000 |
---|---|---|
committer | csilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50> | 2008-06-14 02:30:53 +0000 |
commit | 100e657c5092bc274424286a728db5116a4bbc54 (patch) | |
tree | 3a688677e9366e218b25651d0a75567e8ecacf4f | |
parent | 7ec719093b1c9fda979ba0d07eed288e2a7c3c9b (diff) | |
download | gperftools-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
72 files changed, 2536 insertions, 1436 deletions
@@ -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 @@ -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_ @@ -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
|