summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am8
-rw-r--r--Makefile.in184
-rwxr-xr-xconfigure27
-rw-r--r--configure.ac4
-rw-r--r--src/base/arm_instruction_set_select.h79
-rw-r--r--src/base/cycleclock.h35
-rw-r--r--src/base/logging.h11
-rw-r--r--src/base/low_level_alloc.cc4
-rw-r--r--src/base/spinlock_linux-inl.h5
-rw-r--r--src/base/stl_allocator.h1
-rw-r--r--src/base/sysinfo.cc8
-rw-r--r--src/config.h.in6
-rw-r--r--src/debugallocation.cc656
-rw-r--r--src/google/tcmalloc.h.in2
-rw-r--r--src/heap-checker.cc18
-rw-r--r--src/internal_logging.cc7
-rw-r--r--src/raw_printer.cc2
-rw-r--r--src/tcmalloc.cc42
-rw-r--r--src/tests/debugallocation_test.cc2
-rw-r--r--src/tests/heap-checker_unittest.cc7
-rw-r--r--src/tests/memalign_unittest.cc9
-rwxr-xr-xsrc/tests/sampler_test.cc2
-rw-r--r--src/windows/config.h4
-rw-r--r--src/windows/google/tcmalloc.h.in (renamed from src/windows/google/tcmalloc.h)13
-rw-r--r--src/windows/port.cc45
-rw-r--r--src/windows/port.h352
26 files changed, 921 insertions, 612 deletions
diff --git a/Makefile.am b/Makefile.am
index e18e9ae..a8a2527 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -23,7 +23,8 @@ AM_CXXFLAGS =
# builtins now in any case, but it's best to be explicit in case that
# changes one day. gcc ignores functions it doesn't understand.
if GCC
-AM_CXXFLAGS += -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare \
+AM_CXXFLAGS += -Wall -Wwrite-strings -Woverloaded-virtual \
+ -Wno-sign-compare -Wno-unused-result \
-fno-builtin-malloc -fno-builtin-free -fno-builtin-realloc \
-fno-builtin-calloc -fno-builtin-cfree \
-fno-builtin-memalign -fno-builtin-posix_memalign \
@@ -162,6 +163,7 @@ SYSINFO_INCLUDES = src/base/sysinfo.h \
src/base/logging.h \
src/base/commandlineflags.h \
src/base/cycleclock.h \
+ src/base/arm_instruction_set_select.h \
src/base/basictypes.h
noinst_LTLIBRARIES += libsysinfo.la
libsysinfo_la_SOURCES = src/base/sysinfo.cc \
@@ -716,6 +718,9 @@ realloc_debug_unittest_CXXFLAGS = $(realloc_unittest_CXXFLAGS)
realloc_debug_unittest_LDFLAGS = $(realloc_unittest_LDFLAGS)
realloc_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS)
+# debugallocation_test checks that we print a proper stacktrace when
+# debug-allocs fail, so we can't run it if we don't have stacktrace info.
+if WITH_STACK_TRACE
TESTS += debugallocation_test.sh$(EXEEXT)
debugallocation_test_sh_SOURCES = src/tests/debugallocation_test.sh
noinst_SCRIPTS += $(debugallocation_test_sh_SOURCES)
@@ -730,6 +735,7 @@ debugallocation_test_SOURCES = src/tests/debugallocation_test.cc
debugallocation_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
debugallocation_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
debugallocation_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS)
+endif WITH_STACK_TRACE
endif WITH_DEBUGALLOC
diff --git a/Makefile.in b/Makefile.in
index 693230b..e173564 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -51,7 +51,8 @@ host_triplet = @host@
# are supported since gcc 3.1.1). gcc doesn't think most of them are
# builtins now in any case, but it's best to be explicit in case that
# changes one day. gcc ignores functions it doesn't understand.
-@GCC_TRUE@am__append_2 = -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare \
+@GCC_TRUE@am__append_2 = -Wall -Wwrite-strings -Woverloaded-virtual \
+@GCC_TRUE@ -Wno-sign-compare -Wno-unused-result \
@GCC_TRUE@ -fno-builtin-malloc -fno-builtin-free -fno-builtin-realloc \
@GCC_TRUE@ -fno-builtin-calloc -fno-builtin-cfree \
@GCC_TRUE@ -fno-builtin-memalign -fno-builtin-posix_memalign \
@@ -67,7 +68,7 @@ host_triplet = @host@
@MINGW_TRUE@am__append_5 = -Wl,-u__tcmalloc
noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
$(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \
- $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_23)
+ $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_24)
bin_PROGRAMS =
@MINGW_TRUE@am__append_6 = libwindows.la libspinlock.la
@@ -128,13 +129,16 @@ bin_PROGRAMS =
@WITH_DEBUGALLOC_TRUE@am__append_24 = tcmalloc_minimal_debug_unittest \
@WITH_DEBUGALLOC_TRUE@ malloc_extension_debug_test \
@WITH_DEBUGALLOC_TRUE@ memalign_debug_unittest \
-@WITH_DEBUGALLOC_TRUE@ realloc_debug_unittest \
-@WITH_DEBUGALLOC_TRUE@ debugallocation_test.sh$(EXEEXT)
-@WITH_DEBUGALLOC_TRUE@am__append_25 = $(debugallocation_test_sh_SOURCES)
+@WITH_DEBUGALLOC_TRUE@ realloc_debug_unittest
+
+# debugallocation_test checks that we print a proper stacktrace when
+# debug-allocs fail, so we can't run it if we don't have stacktrace info.
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_25 = debugallocation_test.sh$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_26 = $(debugallocation_test_sh_SOURCES)
# This is the sub-program used by debugallocation_test.sh
-@WITH_DEBUGALLOC_TRUE@am__append_26 = debugallocation_test
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_27 = $(SG_TCMALLOC_INCLUDES)
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_27 = debugallocation_test
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_28 = $(SG_TCMALLOC_INCLUDES)
### Making the library
@@ -142,12 +146,12 @@ bin_PROGRAMS =
# for all files in this library -- except tcmalloc.cc which needs them
# to fulfill its API. Automake doesn't allow per-file CXXFLAGS, so we need
# to separate into two libraries.
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_28 = libtcmalloc_internal.la
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_29 = libtcmalloc.la
-@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_30 = $(HEAP_CHECKER_SOURCES)
-@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_31 = -DNO_HEAP_CHECK
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_29 = libtcmalloc_internal.la
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_30 = libtcmalloc.la
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_31 = $(HEAP_CHECKER_SOURCES)
@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_32 = -DNO_HEAP_CHECK
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_33 = libtcmalloc.la
+@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_33 = -DNO_HEAP_CHECK
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_34 = libtcmalloc.la
### Unittests
@@ -155,7 +159,7 @@ bin_PROGRAMS =
# 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.
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_34 = tcmalloc_unittest \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_35 = tcmalloc_unittest \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_both_unittest \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_large_unittest \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ raw_printer_test \
@@ -166,74 +170,74 @@ bin_PROGRAMS =
# on, which it's not by default. Use the "standard" value of 2^19.
# These unittests often need to run binaries. They're in the current dir
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_35 = TCMALLOC_SAMPLE_PARAMETER=524288 \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_36 = TCMALLOC_SAMPLE_PARAMETER=524288 \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ BINDIR=. \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ TMPDIR=/tmp/perftools
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_36 = vsprojects/sampler_test/sampler_test.vcproj
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_37 = $(sampling_test_sh_SOURCES)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_37 = vsprojects/sampler_test/sampler_test.vcproj
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_38 = $(sampling_test_sh_SOURCES)
# This is the sub-program used by sampling_test.sh
# The -g is so pprof can get symbol information.
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_38 = sampling_test
-@WITH_HEAP_PROFILER_TRUE@am__append_39 = heap-profiler_unittest.sh$(EXEEXT)
-@WITH_HEAP_PROFILER_TRUE@am__append_40 = $(heap_profiler_unittest_sh_SOURCES)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_39 = sampling_test
+@WITH_HEAP_PROFILER_TRUE@am__append_40 = heap-profiler_unittest.sh$(EXEEXT)
+@WITH_HEAP_PROFILER_TRUE@am__append_41 = $(heap_profiler_unittest_sh_SOURCES)
# These are sub-programs used by heap-profiler_unittest.sh
-@WITH_HEAP_PROFILER_TRUE@am__append_41 = heap-profiler_unittest
-@WITH_HEAP_CHECKER_TRUE@am__append_42 = \
+@WITH_HEAP_PROFILER_TRUE@am__append_42 = heap-profiler_unittest
+@WITH_HEAP_CHECKER_TRUE@am__append_43 = \
@WITH_HEAP_CHECKER_TRUE@ heap-checker_unittest.sh$(EXEEXT) \
@WITH_HEAP_CHECKER_TRUE@ heap-checker-death_unittest.sh$(EXEEXT)
-@WITH_HEAP_CHECKER_TRUE@am__append_43 = \
+@WITH_HEAP_CHECKER_TRUE@am__append_44 = \
@WITH_HEAP_CHECKER_TRUE@ $(heap_checker_unittest_sh_SOURCES) \
@WITH_HEAP_CHECKER_TRUE@ $(top_srcdir)/$(heap_checker_death_unittest_sh_SOURCES)
# These are sub-programs used by heap-checker_unittest.sh
-@WITH_HEAP_CHECKER_TRUE@am__append_44 = heap-checker_unittest
+@WITH_HEAP_CHECKER_TRUE@am__append_45 = heap-checker_unittest
### Documentation (above and beyond tcmalloc_minimal documentation)
-@WITH_HEAP_PROFILER_TRUE@am__append_45 = doc/heapprofile.html doc/heap-example1.png
-@WITH_HEAP_CHECKER_TRUE@am__append_46 = doc/heap_checker.html
+@WITH_HEAP_PROFILER_TRUE@am__append_46 = doc/heapprofile.html doc/heap-example1.png
+@WITH_HEAP_CHECKER_TRUE@am__append_47 = doc/heap_checker.html
### ------- tcmalloc with debugallocation
-@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_47 = libtcmalloc_debug.la
@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_48 = libtcmalloc_debug.la
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_49 = libtcmalloc_debug.la
### Unittests
-@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_49 = tcmalloc_debug_unittest \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_50 = tcmalloc_debug_unittest \
@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_debug_test \
@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_debug_test.sh$(EXEEXT)
# This is the sub-program using by sampling_debug_test.sh
# The -g is so pprof can get symbol information.
-@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_50 = sampling_debug_test
-@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_51 = heap-profiler_debug_unittest.sh$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_51 = sampling_debug_test
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_52 = heap-profiler_debug_unittest.sh$(EXEEXT)
# These are sub-programs used by heap-profiler_debug_unittest.sh
-@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_52 = heap-profiler_debug_unittest
-@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_53 = heap-checker_debug_unittest.sh$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_53 = heap-profiler_debug_unittest
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_54 = heap-checker_debug_unittest.sh$(EXEEXT)
# These are sub-programs used by heap-checker_debug_unittest.sh
-@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_54 = heap-checker_debug_unittest
-@WITH_CPU_PROFILER_TRUE@am__append_55 = $(SG_CPU_PROFILER_INCLUDES)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_55 = heap-checker_debug_unittest
+@WITH_CPU_PROFILER_TRUE@am__append_56 = $(SG_CPU_PROFILER_INCLUDES)
### Making the library
-@WITH_CPU_PROFILER_TRUE@am__append_56 = libprofiler.la
+@WITH_CPU_PROFILER_TRUE@am__append_57 = libprofiler.la
### Unittests
-@WITH_CPU_PROFILER_TRUE@am__append_57 = getpc_test \
+@WITH_CPU_PROFILER_TRUE@am__append_58 = getpc_test \
@WITH_CPU_PROFILER_TRUE@ profiledata_unittest \
@WITH_CPU_PROFILER_TRUE@ profile_handler_unittest \
@WITH_CPU_PROFILER_TRUE@ profiler_unittest.sh$(EXEEXT)
-@WITH_CPU_PROFILER_TRUE@am__append_58 = $(profiler_unittest_sh_SOURCES)
+@WITH_CPU_PROFILER_TRUE@am__append_59 = $(profiler_unittest_sh_SOURCES)
# These are sub-programs used by profiler_unittest.sh
-@WITH_CPU_PROFILER_TRUE@am__append_59 = profiler1_unittest profiler2_unittest profiler3_unittest \
+@WITH_CPU_PROFILER_TRUE@am__append_60 = profiler1_unittest profiler2_unittest profiler3_unittest \
@WITH_CPU_PROFILER_TRUE@ profiler4_unittest
@WITH_CPU_PROFILER_FALSE@profiler2_unittest_DEPENDENCIES =
### Documentation
-@WITH_CPU_PROFILER_TRUE@am__append_60 = doc/cpuprofile.html \
+@WITH_CPU_PROFILER_TRUE@am__append_61 = doc/cpuprofile.html \
@WITH_CPU_PROFILER_TRUE@ doc/cpuprofile-fileformat.html \
@WITH_CPU_PROFILER_TRUE@ doc/pprof-test-big.gif \
@WITH_CPU_PROFILER_TRUE@ doc/pprof-test.gif \
@@ -248,14 +252,15 @@ bin_PROGRAMS =
# works fine for .so files, it does not for .a files. The easiest way
# around this -- and I've tried a bunch of the hard ways -- is to just
# to create another set of libraries that has both functionality in it.
-@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_61 = libtcmalloc_and_profiler.la
-@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_62 = tcmalloc_and_profiler_unittest
-@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_63 = libtcmalloc_and_profiler.la
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_62 = libtcmalloc_and_profiler.la
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_63 = tcmalloc_and_profiler_unittest
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_64 = libtcmalloc_and_profiler.la
DIST_COMMON = README $(am__configure_deps) $(am__dist_doc_DATA_DIST) \
$(am__googleinclude_HEADERS_DIST) $(dist_man_MANS) \
$(noinst_HEADERS) $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(top_srcdir)/configure $(top_srcdir)/src/config.h.in \
- $(top_srcdir)/src/google/tcmalloc.h.in AUTHORS COPYING \
+ $(top_srcdir)/src/google/tcmalloc.h.in \
+ $(top_srcdir)/src/windows/google/tcmalloc.h.in AUTHORS COPYING \
ChangeLog INSTALL NEWS TODO compile config.guess config.sub \
depcomp install-sh ltmain.sh missing mkinstalldirs
subdir = .
@@ -277,7 +282,8 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno configure.status.lineno
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/src/config.h
-CONFIG_CLEAN_FILES = src/google/tcmalloc.h
+CONFIG_CLEAN_FILES = src/google/tcmalloc.h \
+ src/windows/google/tcmalloc.h
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@@ -710,7 +716,7 @@ am__libwindows_la_SOURCES_DIST = src/windows/port.h \
libwindows_la_OBJECTS = $(am_libwindows_la_OBJECTS)
@MINGW_TRUE@am_libwindows_la_rpath =
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
-@WITH_DEBUGALLOC_TRUE@am__EXEEXT_1 = debugallocation_test$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__EXEEXT_1 = debugallocation_test$(EXEEXT)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_2 = \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test$(EXEEXT)
@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_3 = \
@@ -731,30 +737,30 @@ binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
@WITH_DEBUGALLOC_TRUE@am__EXEEXT_14 = tcmalloc_minimal_debug_unittest$(EXEEXT) \
@WITH_DEBUGALLOC_TRUE@ malloc_extension_debug_test$(EXEEXT) \
@WITH_DEBUGALLOC_TRUE@ memalign_debug_unittest$(EXEEXT) \
-@WITH_DEBUGALLOC_TRUE@ realloc_debug_unittest$(EXEEXT) \
-@WITH_DEBUGALLOC_TRUE@ debugallocation_test.sh$(EXEEXT)
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_15 = tcmalloc_unittest$(EXEEXT) \
+@WITH_DEBUGALLOC_TRUE@ realloc_debug_unittest$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__EXEEXT_15 = debugallocation_test.sh$(EXEEXT)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_16 = tcmalloc_unittest$(EXEEXT) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_both_unittest$(EXEEXT) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_large_unittest$(EXEEXT) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ raw_printer_test$(EXEEXT) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_test$(EXEEXT) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test.sh$(EXEEXT)
-@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_16 = \
+@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_17 = \
@WITH_HEAP_PROFILER_TRUE@ heap-profiler_unittest.sh$(EXEEXT)
-@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_17 = \
+@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_18 = \
@WITH_HEAP_CHECKER_TRUE@ heap-checker_unittest.sh$(EXEEXT) \
@WITH_HEAP_CHECKER_TRUE@ heap-checker-death_unittest.sh$(EXEEXT)
-@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_18 = tcmalloc_debug_unittest$(EXEEXT) \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_19 = tcmalloc_debug_unittest$(EXEEXT) \
@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_debug_test$(EXEEXT) \
@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_debug_test.sh$(EXEEXT)
-@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_19 = heap-profiler_debug_unittest.sh$(EXEEXT)
-@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_20 = heap-checker_debug_unittest.sh$(EXEEXT)
-@WITH_CPU_PROFILER_TRUE@am__EXEEXT_21 = getpc_test$(EXEEXT) \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_20 = heap-profiler_debug_unittest.sh$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_21 = heap-checker_debug_unittest.sh$(EXEEXT)
+@WITH_CPU_PROFILER_TRUE@am__EXEEXT_22 = getpc_test$(EXEEXT) \
@WITH_CPU_PROFILER_TRUE@ profiledata_unittest$(EXEEXT) \
@WITH_CPU_PROFILER_TRUE@ profile_handler_unittest$(EXEEXT) \
@WITH_CPU_PROFILER_TRUE@ profiler_unittest.sh$(EXEEXT)
-@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_22 = tcmalloc_and_profiler_unittest$(EXEEXT)
-am__EXEEXT_23 = low_level_alloc_unittest$(EXEEXT) \
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_23 = tcmalloc_and_profiler_unittest$(EXEEXT)
+am__EXEEXT_24 = low_level_alloc_unittest$(EXEEXT) \
atomicops_unittest$(EXEEXT) $(am__EXEEXT_9) \
tcmalloc_minimal_unittest$(EXEEXT) \
tcmalloc_minimal_large_unittest$(EXEEXT) $(am__EXEEXT_10) \
@@ -767,7 +773,7 @@ am__EXEEXT_23 = low_level_alloc_unittest$(EXEEXT) \
thread_dealloc_unittest$(EXEEXT) $(am__EXEEXT_14) \
$(am__EXEEXT_15) $(am__EXEEXT_16) $(am__EXEEXT_17) \
$(am__EXEEXT_18) $(am__EXEEXT_19) $(am__EXEEXT_20) \
- $(am__EXEEXT_21) $(am__EXEEXT_22)
+ $(am__EXEEXT_21) $(am__EXEEXT_22) $(am__EXEEXT_23)
PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
am__addressmap_unittest_SOURCES_DIST = \
src/tests/addressmap_unittest.cc src/addressmap-inl.h \
@@ -787,11 +793,10 @@ atomicops_unittest_OBJECTS = $(am_atomicops_unittest_OBJECTS)
atomicops_unittest_DEPENDENCIES = $(am__DEPENDENCIES_2)
am__debugallocation_test_SOURCES_DIST = \
src/tests/debugallocation_test.cc
-@WITH_DEBUGALLOC_TRUE@am_debugallocation_test_OBJECTS = debugallocation_test-debugallocation_test.$(OBJEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am_debugallocation_test_OBJECTS = debugallocation_test-debugallocation_test.$(OBJEXT)
debugallocation_test_OBJECTS = $(am_debugallocation_test_OBJECTS)
-@WITH_DEBUGALLOC_TRUE@debugallocation_test_DEPENDENCIES = \
-@WITH_DEBUGALLOC_TRUE@ libtcmalloc_debug.la \
-@WITH_DEBUGALLOC_TRUE@ $(am__DEPENDENCIES_1)
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_DEPENDENCIES = libtcmalloc_debug.la \
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@ $(am__DEPENDENCIES_1)
am__debugallocation_test_sh_SOURCES_DIST = \
src/tests/debugallocation_test.sh
am_debugallocation_test_sh_OBJECTS =
@@ -1631,14 +1636,14 @@ TCMALLOC_FLAGS = $(am__append_5)
@HAVE_OBJCOPY_WEAKEN_TRUE@ -W __ZdlPv -W __ZdaPv
LIBS_TO_WEAKEN = libtcmalloc_minimal.la $(am__append_23) \
- $(am__append_33) $(am__append_48) $(am__append_63)
+ $(am__append_34) $(am__append_49) $(am__append_64)
googleincludedir = $(includedir)/google
# The .h files you want to install (that is, .h files that people
# who install this package can include in their own applications.)
# We'll add to this later, on a library-by-library basis
googleinclude_HEADERS = $(am__append_9) \
- $(SG_TCMALLOC_MINIMAL_INCLUDES) $(am__append_27) \
- $(am__append_55)
+ $(SG_TCMALLOC_MINIMAL_INCLUDES) $(am__append_28) \
+ $(am__append_56)
# tcmalloc.h is a special case, because it's a .h.in file
nodist_googleinclude_HEADERS = src/google/tcmalloc.h
noinst_HEADERS = src/google/tcmalloc.h.in
@@ -1680,13 +1685,13 @@ 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_45) $(am__append_46) $(am__append_60)
+ $(am__append_46) $(am__append_47) $(am__append_61)
# The libraries (.so's) you want to install
# We'll add to this later, on a library-by-library basis
lib_LTLIBRARIES = libtcmalloc_minimal.la $(am__append_22) \
- $(am__append_29) $(am__append_47) $(am__append_56) \
- $(am__append_61)
+ $(am__append_30) $(am__append_48) $(am__append_57) \
+ $(am__append_62)
# This is for 'convenience libraries' -- basically just a container for sources
### Making the library
@@ -1697,7 +1702,7 @@ lib_LTLIBRARIES = libtcmalloc_minimal.la $(am__append_22) \
# to separate into two libraries.
noinst_LTLIBRARIES = liblogging.la libsysinfo.la $(am__append_6) \
$(am__append_8) $(am__append_10) \
- libtcmalloc_minimal_internal.la $(am__append_28)
+ libtcmalloc_minimal_internal.la $(am__append_29)
WINDOWS_PROJECTS = google-perftools.sln \
vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj \
$(am__append_14) \
@@ -1715,7 +1720,7 @@ WINDOWS_PROJECTS = google-perftools.sln \
vsprojects/realloc_unittest/realloc_unittest.vcproj \
vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj \
vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj \
- $(am__append_36)
+ $(am__append_37)
# unittests you want to run when people type 'make check'.
# Note: tests cannot take any arguments!
@@ -1741,16 +1746,17 @@ TESTS = low_level_alloc_unittest atomicops_unittest $(am__append_11) \
malloc_extension_test $(am__append_19) $(am__append_21) \
page_heap_test pagemap_unittest realloc_unittest \
stack_trace_table_test thread_dealloc_unittest \
- $(am__append_24) $(am__append_34) $(am__append_39) \
- $(am__append_42) $(am__append_49) $(am__append_51) \
- $(am__append_53) $(am__append_57) $(am__append_62)
+ $(am__append_24) $(am__append_25) $(am__append_35) \
+ $(am__append_40) $(am__append_43) $(am__append_50) \
+ $(am__append_52) $(am__append_54) $(am__append_58) \
+ $(am__append_63)
# 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_13) $(am__append_35)
+TESTS_ENVIRONMENT = $(am__append_13) $(am__append_36)
# All script tests should be added here
-noinst_SCRIPTS = $(am__append_16) $(am__append_25) $(am__append_37) \
- $(am__append_40) $(am__append_43) $(am__append_58)
+noinst_SCRIPTS = $(am__append_16) $(am__append_26) $(am__append_38) \
+ $(am__append_41) $(am__append_44) $(am__append_59)
# This is my own var, used for extra libraries I make that I need installed
EXTRA_INSTALL =
@@ -1772,6 +1778,7 @@ SYSINFO_INCLUDES = src/base/sysinfo.h \
src/base/logging.h \
src/base/commandlineflags.h \
src/base/cycleclock.h \
+ src/base/arm_instruction_set_select.h \
src/base/basictypes.h
libsysinfo_la_SOURCES = src/base/sysinfo.cc \
@@ -2131,11 +2138,11 @@ thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
@WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_CXXFLAGS = $(realloc_unittest_CXXFLAGS)
@WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_LDFLAGS = $(realloc_unittest_LDFLAGS)
@WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS)
-@WITH_DEBUGALLOC_TRUE@debugallocation_test_sh_SOURCES = src/tests/debugallocation_test.sh
-@WITH_DEBUGALLOC_TRUE@debugallocation_test_SOURCES = src/tests/debugallocation_test.cc
-@WITH_DEBUGALLOC_TRUE@debugallocation_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
-@WITH_DEBUGALLOC_TRUE@debugallocation_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
-@WITH_DEBUGALLOC_TRUE@debugallocation_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS)
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_sh_SOURCES = src/tests/debugallocation_test.sh
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_SOURCES = src/tests/debugallocation_test.cc
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS)
### ------- tcmalloc (thread-caching malloc + heap profiler + heap checker)
@@ -2170,17 +2177,17 @@ thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(PTHREAD_CFLAGS) -DNDEBUG \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(AM_CXXFLAGS) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(NO_EXCEPTIONS) \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_31)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_32)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_LDFLAGS = $(PTHREAD_CFLAGS)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_LIBADD = libstacktrace.la $(PTHREAD_LIBS)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_SOURCES = \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_CC) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_INCLUDES) \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_30)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_31)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_CXXFLAGS = \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(PTHREAD_CFLAGS) -DNDEBUG \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(AM_CXXFLAGS) \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_32)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_33)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_LDFLAGS = $(PTHREAD_CFLAGS) -version-info @TCMALLOC_SO_VERSION@
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_LIBADD = libtcmalloc_internal.la $(PTHREAD_LIBS)
@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@HEAP_CHECKER_SOURCES =
@@ -2494,6 +2501,8 @@ distclean-hdr:
-rm -f src/config.h src/stamp-h1
src/google/tcmalloc.h: $(top_builddir)/config.status $(top_srcdir)/src/google/tcmalloc.h.in
cd $(top_builddir) && $(SHELL) ./config.status $@
+src/windows/google/tcmalloc.h: $(top_builddir)/config.status $(top_srcdir)/src/windows/google/tcmalloc.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
@@ -2603,6 +2612,9 @@ debugallocation_test$(EXEEXT): $(debugallocation_test_OBJECTS) $(debugallocation
@WITH_DEBUGALLOC_FALSE@debugallocation_test.sh$(EXEEXT): $(debugallocation_test_sh_OBJECTS) $(debugallocation_test_sh_DEPENDENCIES)
@WITH_DEBUGALLOC_FALSE@ @rm -f debugallocation_test.sh$(EXEEXT)
@WITH_DEBUGALLOC_FALSE@ $(LINK) $(debugallocation_test_sh_LDFLAGS) $(debugallocation_test_sh_OBJECTS) $(debugallocation_test_sh_LDADD) $(LIBS)
+@WITH_STACK_TRACE_FALSE@debugallocation_test.sh$(EXEEXT): $(debugallocation_test_sh_OBJECTS) $(debugallocation_test_sh_DEPENDENCIES)
+@WITH_STACK_TRACE_FALSE@ @rm -f debugallocation_test.sh$(EXEEXT)
+@WITH_STACK_TRACE_FALSE@ $(LINK) $(debugallocation_test_sh_LDFLAGS) $(debugallocation_test_sh_OBJECTS) $(debugallocation_test_sh_LDADD) $(LIBS)
frag_unittest$(EXEEXT): $(frag_unittest_OBJECTS) $(frag_unittest_DEPENDENCIES)
@rm -f frag_unittest$(EXEEXT)
$(CXXLINK) $(frag_unittest_LDFLAGS) $(frag_unittest_OBJECTS) $(frag_unittest_LDADD) $(LIBS)
@@ -4827,10 +4839,10 @@ uninstall-man: uninstall-man1
@ENABLE_STATIC_FALSE@@MINGW_FALSE@ low_level_alloc_unittest
@ENABLE_STATIC_FALSE@@MINGW_FALSE@ rm -f $@
@ENABLE_STATIC_FALSE@@MINGW_FALSE@ cp -p $(top_srcdir)/$(maybe_threads_unittest_sh_SOURCES) $@
-@WITH_DEBUGALLOC_TRUE@debugallocation_test.sh$(EXEEXT): $(top_srcdir)/$(debugallocation_test_sh_SOURCES) \
-@WITH_DEBUGALLOC_TRUE@ debugallocation_test
-@WITH_DEBUGALLOC_TRUE@ rm -f $@
-@WITH_DEBUGALLOC_TRUE@ cp -p $(top_srcdir)/$(debugallocation_test_sh_SOURCES) $@
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test.sh$(EXEEXT): $(top_srcdir)/$(debugallocation_test_sh_SOURCES) \
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@ debugallocation_test
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@ rm -f $@
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@ cp -p $(top_srcdir)/$(debugallocation_test_sh_SOURCES) $@
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_test.sh$(EXEEXT): $(top_srcdir)/$(sampling_test_sh_SOURCES) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ rm -f $@
diff --git a/configure b/configure
index 0a54ed7..5f554b1 100755
--- a/configure
+++ b/configure
@@ -15004,6 +15004,30 @@ fi
done
# some systems define stuff there, others not
+for ac_header in sys/malloc.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/malloc.h" "ac_cv_header_sys_malloc_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_malloc_h" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_MALLOC_H 1
+_ACEOF
+
+fi
+
+done
+ # where some versions of OS X put malloc.h
+for ac_header in malloc/malloc.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "malloc/malloc.h" "ac_cv_header_malloc_malloc_h" "$ac_includes_default"
+if test "x$ac_cv_header_malloc_malloc_h" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_MALLOC_MALLOC_H 1
+_ACEOF
+
+fi
+
+done
+ # another place OS X puts malloc.h (?)
for ac_header in glob.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "glob.h" "ac_cv_header_glob_h" "$ac_includes_default"
@@ -16996,7 +17020,7 @@ fi
# Write generated configuration file
-ac_config_files="$ac_config_files Makefile src/google/tcmalloc.h"
+ac_config_files="$ac_config_files Makefile src/google/tcmalloc.h src/windows/google/tcmalloc.h"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -18115,6 +18139,7 @@ do
"libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"src/google/tcmalloc.h") CONFIG_FILES="$CONFIG_FILES src/google/tcmalloc.h" ;;
+ "src/windows/google/tcmalloc.h") CONFIG_FILES="$CONFIG_FILES src/windows/google/tcmalloc.h" ;;
*) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac
diff --git a/configure.ac b/configure.ac
index 43ae558..90c015f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -123,6 +123,8 @@ AC_CHECK_FUNCS(sbrk) # for tcmalloc to get memory
AC_CHECK_FUNCS(geteuid) # for turning off services when run as root
AC_CHECK_HEADERS(features.h) # for vdso_support.h
AC_CHECK_HEADERS(malloc.h) # some systems define stuff there, others not
+AC_CHECK_HEADERS(sys/malloc.h) # where some versions of OS X put malloc.h
+AC_CHECK_HEADERS(malloc/malloc.h) # another place OS X puts malloc.h (?)
AC_CHECK_HEADERS(glob.h) # for heap-profile-table (cleaning up profiles)
AC_CHECK_HEADERS(execinfo.h) # for stacktrace? and heapchecker_unittest
AC_CHECK_HEADERS(libunwind.h) # for stacktrace
@@ -359,5 +361,5 @@ AM_CONDITIONAL(WITH_STACK_TRACE, test "$enable_cpu_profiler" = yes -o \
"$enable_heap_checker" = yes)
# Write generated configuration file
-AC_CONFIG_FILES([Makefile src/google/tcmalloc.h])
+AC_CONFIG_FILES([Makefile src/google/tcmalloc.h src/windows/google/tcmalloc.h])
AC_OUTPUT
diff --git a/src/base/arm_instruction_set_select.h b/src/base/arm_instruction_set_select.h
new file mode 100644
index 0000000..a47e6bb
--- /dev/null
+++ b/src/base/arm_instruction_set_select.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2011, 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: Alexander Levitskiy
+//
+// Generalizes the plethora of ARM flavors available to an easier to manage set
+// Defs reference is at https://wiki.edubuntu.org/ARM/Thumb2PortingHowto
+
+#ifndef ARM_INSTRUCTION_SET_SELECT_H_
+#define ARM_INSTRUCTION_SET_SELECT_H_
+
+#if defined(__ARM_ARCH_7__) || \
+ defined(__ARM_ARCH_7R__) || \
+ defined(__ARM_ARCH_7A__)
+# define ARMV7 1
+#endif
+
+#if defined(ARMV7) || \
+ defined(__ARM_ARCH_6__) || \
+ defined(__ARM_ARCH_6J__) || \
+ defined(__ARM_ARCH_6K__) || \
+ defined(__ARM_ARCH_6Z__) || \
+ defined(__ARM_ARCH_6T2__) || \
+ defined(__ARM_ARCH_6ZK__)
+# define ARMV6 1
+#endif
+
+#if defined(ARMV6) || \
+ defined(__ARM_ARCH_5T__) || \
+ defined(__ARM_ARCH_5E__) || \
+ defined(__ARM_ARCH_5TE__) || \
+ defined(__ARM_ARCH_5TEJ__)
+# define ARMV5 1
+#endif
+
+#if defined(ARMV5) || \
+ defined(__ARM_ARCH_4__) || \
+ defined(__ARM_ARCH_4T__)
+# define ARMV4 1
+#endif
+
+#if defined(ARMV4) || \
+ defined(__ARM_ARCH_3__) || \
+ defined(__ARM_ARCH_3M__)
+# define ARMV3 1
+#endif
+
+#if defined(ARMV3) || \
+ defined(__ARM_ARCH_2__)
+# define ARMV2 1
+#endif
+
+#endif // ARM_INSTRUCTION_SET_SELECT_H_
diff --git a/src/base/cycleclock.h b/src/base/cycleclock.h
index 02cddf3..a5ce138 100644
--- a/src/base/cycleclock.h
+++ b/src/base/cycleclock.h
@@ -46,11 +46,11 @@
#define GOOGLE_BASE_CYCLECLOCK_H_
#include "base/basictypes.h" // make sure we get the def for int64
+#include "base/arm_instruction_set_select.h"
#if defined(__MACH__) && defined(__APPLE__)
# include <mach/mach_time.h>
-#elif defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_3__)
-# include <sys/time.h>
#endif
+#include <sys/time.h>
// NOTE: only i386 and x86_64 have been well tested.
// PPC, sparc, alpha, and ia64 are based on
@@ -99,20 +99,29 @@ struct CycleClock {
return itc;
#elif defined(_MSC_VER) && defined(_M_IX86)
_asm rdtsc
-
-// If none of the above cases trigger, we use a solution based on
-// a system call (gettimeofday or similar). We do these in order
-// from fastest to slowest. We do not have an '#else' catch-all
-// case here that just calls gettimeofday(); that system call is
-// slow, and this function is expected to be fast, so we don't want
-// to use it without an explicit decision that it's the only way.
-#elif defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_3__)
+#elif defined(ARMV3)
+#if defined(ARMV6) // V6 is the earliest arch that has a standard cyclecount
+ uint32 pmccntr;
+ uint32 pmuseren;
+ uint32 pmcntenset;
+ // Read the user mode perf monitor counter access permissions.
+ asm("mrc p15, 0, %0, c9, c14, 0" : "=r" (pmuseren));
+ if (pmuseren & 1) { // Allows reading perfmon counters for user mode code.
+ asm("mrc p15, 0, %0, c9, c12, 1" : "=r" (pmcntenset));
+ if (pmcntenset & 0x80000000ul) { // Is it counting?
+ asm("mrc p15, 0, %0, c9, c13, 0" : "=r" (pmccntr));
+ // The counter is set up to count every 64th cycle
+ return static_cast<int64>(pmccntr) * 64; // Should optimize to << 6
+ }
+ }
+#endif
struct timeval tv;
gettimeofday(&tv, NULL);
- return static_cast<uint64>(tv.tv_sec) * 1000000 + tv.tv_usec;
+ return static_cast<int64>(tv.tv_sec) * 1000000 + tv.tv_usec;
#else
- // We could define __alpha here as well, but it only has a 32-bit
- // timer (good for like 4 seconds), which isn't very useful.
+// The soft failover to a generic implementation is automatic only for ARM.
+// For other platforms the developer is expected to make an attempt to create
+// a fast implementation and use generic version if nothing better is available.
#error You need to define CycleTimer for your O/S and CPU
#endif
}
diff --git a/src/base/logging.h b/src/base/logging.h
index 5c3e546..70491ba 100644
--- a/src/base/logging.h
+++ b/src/base/logging.h
@@ -62,6 +62,13 @@
#define WRITE_TO_STDERR(buf, len) write(STDERR_FILENO, buf, len)
#endif
+// MSVC and mingw define their own, safe version of vnsprintf (the
+// windows one in broken) in port.cc. Everyone else can use the
+// version here. We had to give it a unique name for windows.
+#ifndef _WIN32
+# define perftools_vsnprintf vsnprintf
+#endif
+
// We log all messages at this log-level and below.
// INFO == -1, WARNING == -2, ERROR == -3, FATAL == -4
@@ -191,7 +198,7 @@ inline void LogPrintf(int severity, const char* pat, va_list ap) {
// We write directly to the stderr file descriptor and avoid FILE
// buffering because that may invoke malloc()
char buf[600];
- vsnprintf(buf, sizeof(buf)-1, pat, ap);
+ perftools_vsnprintf(buf, sizeof(buf)-1, pat, ap);
if (buf[0] != '\0' && buf[strlen(buf)-1] != '\n') {
assert(strlen(buf)+1 < sizeof(buf));
strcat(buf, "\n");
@@ -233,7 +240,9 @@ inline void LOG_IF(int lvl, bool cond, const char* pat, ...) {
// Like other "raw" routines, these functions are best effort, and
// thus don't return error codes (except RawOpenForWriting()).
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__)
+#ifndef NOMINMAX
#define NOMINMAX // @#!$& windows
+#endif
#include <windows.h>
typedef HANDLE RawFD;
const RawFD kIllegalRawFD = INVALID_HANDLE_VALUE;
diff --git a/src/base/low_level_alloc.cc b/src/base/low_level_alloc.cc
index 8864629..532c594 100644
--- a/src/base/low_level_alloc.cc
+++ b/src/base/low_level_alloc.cc
@@ -212,7 +212,7 @@ static const intptr_t kMagicAllocated = 0x4c833e95;
static const intptr_t kMagicUnallocated = ~kMagicAllocated;
namespace {
- class ArenaLock {
+ class SCOPED_LOCKABLE ArenaLock {
public:
explicit ArenaLock(LowLevelAlloc::Arena *arena)
EXCLUSIVE_LOCK_FUNCTION(arena->mu)
@@ -233,7 +233,7 @@ namespace {
this->arena_->mu.Lock();
}
~ArenaLock() { RAW_CHECK(this->left_, "haven't left Arena region"); }
- void Leave() UNLOCK_FUNCTION(arena_->mu) {
+ void Leave() UNLOCK_FUNCTION() {
this->arena_->mu.Unlock();
#if 0
if (this->mask_valid_) {
diff --git a/src/base/spinlock_linux-inl.h b/src/base/spinlock_linux-inl.h
index 5e571b1..a178dd5 100644
--- a/src/base/spinlock_linux-inl.h
+++ b/src/base/spinlock_linux-inl.h
@@ -49,8 +49,13 @@ static struct InitModule {
int x = 0;
// futexes are ints, so we can use them only when
// that's the same size as the lockword_ in SpinLock.
+#ifdef __arm__
+ // ARM linux doesn't support sys_futex1(void*, int, int, struct timespec*);
+ have_futex = 0;
+#else
have_futex = (sizeof (Atomic32) == sizeof (int) &&
sys_futex(&x, FUTEX_WAKE, 1, 0) >= 0);
+#endif
if (have_futex &&
sys_futex(&x, FUTEX_WAKE | futex_private_flag, 1, 0) < 0) {
futex_private_flag = 0;
diff --git a/src/base/stl_allocator.h b/src/base/stl_allocator.h
index d9d2983..3152cf9 100644
--- a/src/base/stl_allocator.h
+++ b/src/base/stl_allocator.h
@@ -40,7 +40,6 @@
#include <stddef.h> // for ptrdiff_t
#include <limits>
-#include "base/basictypes.h"
#include "base/logging.h"
// Generic allocator class for STL objects
diff --git a/src/base/sysinfo.cc b/src/base/sysinfo.cc
index c1e2aef..3e97ac9 100644
--- a/src/base/sysinfo.cc
+++ b/src/base/sysinfo.cc
@@ -231,6 +231,8 @@ static int64 EstimateCyclesPerSecond(const int estimate_time_ms) {
return guess;
}
+// ReadIntFromFile is only called on linux and cygwin platforms.
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
// Helper function for reading an int from a file. Returns true if successful
// and the memory location pointed to by value is set to the value read.
static bool ReadIntFromFile(const char *file, int *value) {
@@ -250,6 +252,7 @@ static bool ReadIntFromFile(const char *file, int *value) {
}
return ret;
}
+#endif
// WARNING: logging calls back to InitializeSystemInfo() so it must
// not invoke any logging code. Also, InitializeSystemInfo() can be
@@ -491,7 +494,7 @@ static void ConstructFilename(const char* spec, pid_t pid,
char* buf, int buf_size) {
CHECK_LT(snprintf(buf, buf_size,
spec,
- pid ? pid : getpid()), buf_size);
+ static_cast<int>(pid ? pid : getpid())), buf_size);
}
#endif
@@ -804,7 +807,8 @@ bool ProcMapsIterator::NextExt(uint64 *start, uint64 *end, char **flags,
Buffer::kBufSize);
} else {
CHECK_LT(snprintf(object_path.buf_, Buffer::kBufSize,
- "/proc/%d/path/%s", pid_, mapinfo->pr_mapname),
+ "/proc/%d/path/%s",
+ static_cast<int>(pid_), mapinfo->pr_mapname),
Buffer::kBufSize);
}
ssize_t len = readlink(object_path.buf_, current_filename_, PATH_MAX);
diff --git a/src/config.h.in b/src/config.h.in
index 6ee2db0..3b8d6f3 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -77,6 +77,9 @@
/* Define to 1 if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H
+/* Define to 1 if you have the <malloc/malloc.h> header file. */
+#undef HAVE_MALLOC_MALLOC_H
+
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
@@ -119,6 +122,9 @@
/* Define to 1 if the system has the type `struct mallinfo'. */
#undef HAVE_STRUCT_MALLINFO
+/* Define to 1 if you have the <sys/malloc.h> header file. */
+#undef HAVE_SYS_MALLOC_H
+
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
diff --git a/src/debugallocation.cc b/src/debugallocation.cc
index d149ec4..12865eb 100644
--- a/src/debugallocation.cc
+++ b/src/debugallocation.cc
@@ -31,8 +31,16 @@
// Author: Urs Holzle <opensource@google.com>
#include "config.h"
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
+// We only need malloc.h for struct mallinfo.
+#ifdef HAVE_STRUCT_MALLINFO
+// Malloc can be in several places on older versions of OS X.
+# if defined(HAVE_MALLOC_H)
+# include <malloc.h>
+# elif defined(HAVE_SYS_MALLOC_H)
+# include <sys/malloc.h>
+# elif defined(HAVE_MALLOC_MALLOC_H)
+# include <malloc/malloc.h>
+# endif
#endif
#include <pthread.h>
#include <stdio.h>
@@ -127,6 +135,23 @@ static void TracePrintf(int fd, const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
//
+// Define the malloc/free/mallopt/mallinfo implementations
+// we will be working on top of:
+#ifdef TCMALLOC_FOR_DEBUGALLOCATION
+
+// The do_* functions are defined in tcmalloc/tcmalloc.cc,
+// which is included before this file
+// when TCMALLOC_FOR_DEBUGALLOCATION is defined
+#define BASE_MALLOC_NEW(size) cpp_alloc(size, false)
+#define BASE_MALLOC do_malloc
+#define BASE_FREE do_free
+#define BASE_MALLOC_STATS do_malloc_stats
+#define BASE_MALLOPT do_mallopt
+#define BASE_MALLINFO do_mallinfo
+#define BASE_MALLOC_SIZE(ptr) GetSizeWithCallback(ptr, &InvalidGetAllocatedSize)
+
+#else
+
// GNU has some weird "weak aliasing" thing that permits us to define our
// own malloc(), free(), and realloc() which can use the normal versions of
// of themselves by calling __libc_malloc(), __libc_free(), and
@@ -141,32 +166,21 @@ extern "C" {
#ifdef HAVE_STRUCT_MALLINFO
extern struct mallinfo __libc_mallinfo(void);
#endif
+ static void noop_malloc_stats(void) {}
}
-// Define the malloc/free/mallopt/mallinfo implementations
-// we will be working on top of.
-// TODO(csilvers): provide debugallocation on top of libc alloc,
-// so this #ifdef might sometimes be false.
-#ifdef TCMALLOC_FOR_DEBUGALLOCATION
-
-// The do_* functions are defined in tcmalloc.cc,
-// which is included before this file
-// when TCMALLOC_FOR_DEBUGALLOCATION is defined.
-#define BASE_MALLOC_NEW(size) cpp_alloc(size, false)
-#define BASE_MALLOC do_malloc_or_cpp_alloc
-#define BASE_FREE do_free
-#define BASE_MALLOPT do_mallopt
-#define BASE_MALLINFO do_mallinfo
-
-#else
-
// We are working on top of standard libc's malloc library
-#define BASE_MALLOC_NEW __libc_malloc
-#define BASE_MALLOC __libc_malloc
-#define BASE_FREE __libc_free
-#define BASE_MALLOPT __libc_mallopt
-#define BASE_MALLINFO __libc_mallinfo
-
+#define BASE_MALLOC_NEW __libc_malloc
+#define BASE_MALLOC __libc_malloc
+#define BASE_FREE __libc_free
+#define BASE_MALLOC_STATS noop_malloc_stats
+#define BASE_MALLOPT __libc_mallopt
+#ifdef HAVE_STRUCT_MALLINFO
+#define BASE_MALLINFO __libc_mallinfo
+#endif
+// This is malloc_size() on OS X, malloc_usable_size() on libc,
+// _msize() on windows. Rather than trying to pick, we just bail.
+#define BASE_MALLOC_SIZE(ptr) 0 // TODO(csilvers): do better
#endif
// ========================================================================= //
@@ -190,7 +204,7 @@ class FreeQueue {
return (q_front_ + 1) % kFreeQueueSize == q_back_;
}
- void Push(QueueEntry block) {
+ void Push(const QueueEntry& block) {
q_[q_front_] = block;
q_front_ = (q_front_ + 1) % kFreeQueueSize;
}
@@ -982,71 +996,184 @@ static inline void DebugDeallocate(void* ptr, int type) {
// ========================================================================= //
-// Alloc/free stuff for debug hooks for malloc & friends
+// The following functions may be called via MallocExtension::instance()
+// for memory verification and statistics.
+#ifdef TCMALLOC_FOR_DEBUGALLOCATION
+// Inherit from tcmalloc's version
+typedef TCMallocImplementation ParentImplementation;
+#else
+// Inherit from default version
+typedef MallocExtension ParentImplementation;
+#endif
+
+class DebugMallocImplementation : public ParentImplementation {
+ public:
+ virtual bool GetNumericProperty(const char* name, size_t* value) {
+ bool result = ParentImplementation::GetNumericProperty(name, value);
+ if (result && (strcmp(name, "generic.current_allocated_bytes") == 0)) {
+ // Subtract bytes kept in the free queue
+ size_t qsize = MallocBlock::FreeQueueSize();
+ if (*value >= qsize) {
+ *value -= qsize;
+ }
+ }
+ return result;
+ }
-// CAVEAT: The code structure below ensures that MallocHook methods are always
-// called from the stack frame of the invoked allocation function.
-// heap-checker.cc depends on this to start a stack trace from
-// the call to the (de)allocation function.
+ virtual bool VerifyNewMemory(void* p) {
+ if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kNewType);
+ return true;
+ }
-// Put all callers of MallocHook::Invoke* in this module into
-// ATTRIBUTE_SECTION(google_malloc) section,
-// so that MallocHook::GetCallerStackTrace can function accurately:
+ virtual bool VerifyArrayNewMemory(void* p) {
+ if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kArrayNewType);
+ return true;
+ }
-extern "C" {
- void* malloc(size_t size) __THROW ATTRIBUTE_SECTION(google_malloc);
- void free(void* ptr) __THROW ATTRIBUTE_SECTION(google_malloc);
- void* realloc(void* ptr, size_t size) __THROW
- ATTRIBUTE_SECTION(google_malloc);
- void* calloc(size_t nmemb, size_t size) __THROW
- ATTRIBUTE_SECTION(google_malloc);
- void cfree(void* ptr) __THROW ATTRIBUTE_SECTION(google_malloc);
-
- void* memalign(size_t __alignment, size_t __size) __THROW
- ATTRIBUTE_SECTION(google_malloc);
- int posix_memalign(void** ptr, size_t align, size_t size) __THROW
- ATTRIBUTE_SECTION(google_malloc);
- void* valloc(size_t __size) __THROW
- ATTRIBUTE_SECTION(google_malloc);
- void* pvalloc(size_t __size) __THROW
- ATTRIBUTE_SECTION(google_malloc);
+ virtual bool VerifyMallocMemory(void* p) {
+ if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kMallocType);
+ return true;
+ }
+
+ virtual bool VerifyAllMemory() {
+ return MallocBlock::CheckEverything();
+ }
+
+ virtual bool MallocMemoryStats(int* blocks, size_t* total,
+ int histogram[kMallocHistogramSize]) {
+ return MallocBlock::MemoryStats(blocks, total, histogram);
+ }
+
+ virtual size_t GetAllocatedSize(void* p) {
+ if (p) {
+ return MallocBlock::FromRawPointer(p)->data_size();
+ }
+ return 0;
+ }
+ virtual size_t GetEstimatedAllocatedSize(size_t size) {
+ return size;
+ }
+
+ virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* v) {
+ static const char* kDebugFreeQueue = "debug.free_queue";
+
+ ParentImplementation::GetFreeListSizes(v);
+
+ MallocExtension::FreeListInfo i;
+ i.type = kDebugFreeQueue;
+ i.min_object_size = 0;
+ i.max_object_size = numeric_limits<size_t>::max();
+ i.total_bytes_free = MallocBlock::FreeQueueSize();
+ v->push_back(i);
+ }
+
+ };
+
+static DebugMallocImplementation debug_malloc_implementation;
+
+REGISTER_MODULE_INITIALIZER(debugallocation, {
+ // Either we or valgrind will control memory management. We
+ // register our extension if we're the winner.
+ if (RunningOnValgrind()) {
+ // Let Valgrind uses its own malloc (so don't register our extension).
+ } else {
+ MallocExtension::Register(&debug_malloc_implementation);
+ // When the program exits, check all blocks still in the free
+ // queue for corruption.
+ atexit(DanglingWriteChecker);
+ }
+});
+
+// ========================================================================= //
+
+// This is mostly the same a cpp_alloc in tcmalloc.cc.
+// TODO(csilvers): write a wrapper for new-handler so we don't have to
+// copy this code so much.
+inline void* debug_cpp_alloc(size_t size, int new_type, bool nothrow) {
+ for (;;) {
+ void* p = DebugAllocate(size, new_type);
+#ifdef PREANSINEW
+ return p;
+#else
+ if (p == NULL) { // allocation failed
+ // Get the current new handler. NB: this function is not
+ // thread-safe. We make a feeble stab at making it so here, but
+ // this lock only protects against tcmalloc interfering with
+ // itself, not with other libraries calling set_new_handler.
+ std::new_handler nh;
+ {
+ SpinLockHolder h(&set_new_handler_lock);
+ nh = std::set_new_handler(0);
+ (void) std::set_new_handler(nh);
+ }
+#if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
+ if (nh) {
+ // Since exceptions are disabled, we don't really know if new_handler
+ // failed. Assume it will abort if it fails.
+ (*nh)();
+ continue;
+ }
+ return 0;
+#else
+ // If no new_handler is established, the allocation failed.
+ if (!nh) {
+ if (nothrow) return 0;
+ throw std::bad_alloc();
+ }
+ // Otherwise, try the new_handler. If it returns, retry the
+ // allocation. If it throws std::bad_alloc, fail the allocation.
+ // if it throws something else, don't interfere.
+ try {
+ (*nh)();
+ } catch (const std::bad_alloc&) {
+ if (!nothrow) throw;
+ return p;
+ }
+#endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
+ } else { // allocation success
+ return p;
+ }
+#endif // PREANSINEW
+ }
}
-static void *MemalignOverride(size_t align, size_t size,
- const void *caller) __THROW
- ATTRIBUTE_SECTION(google_malloc);
-
-void* operator new(size_t size) throw (std::bad_alloc)
- ATTRIBUTE_SECTION(google_malloc);
-void* operator new(size_t size, const std::nothrow_t&) __THROW
- ATTRIBUTE_SECTION(google_malloc);
-void operator delete(void* p) __THROW
- ATTRIBUTE_SECTION(google_malloc);
-void operator delete(void* p, const std::nothrow_t&) __THROW
- ATTRIBUTE_SECTION(google_malloc);
-void* operator new[](size_t size) throw (std::bad_alloc)
- ATTRIBUTE_SECTION(google_malloc);
-void* operator new[](size_t size, const std::nothrow_t&) __THROW
- ATTRIBUTE_SECTION(google_malloc);
-void operator delete[](void* p) __THROW
- ATTRIBUTE_SECTION(google_malloc);
-void operator delete[](void* p, const std::nothrow_t&) __THROW
- ATTRIBUTE_SECTION(google_malloc);
-
-extern "C" void* malloc(size_t size) __THROW {
- void* ptr = DebugAllocate(size, MallocBlock::kMallocType);
+inline void* do_debug_malloc_or_debug_cpp_alloc(size_t size) {
+ return tc_new_mode ? debug_cpp_alloc(size, MallocBlock::kMallocType, true)
+ : DebugAllocate(size, MallocBlock::kMallocType);
+}
+
+// Exported routines
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW {
+ void* ptr = do_debug_malloc_or_debug_cpp_alloc(size);
MallocHook::InvokeNewHook(ptr, size);
return ptr;
}
-extern "C" void free(void* ptr) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW {
+ MallocHook::InvokeDeleteHook(ptr);
+ DebugDeallocate(ptr, MallocBlock::kMallocType);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_calloc(size_t count, size_t size) __THROW {
+ // Overflow check
+ const size_t total_size = count * size;
+ if (size != 0 && total_size / size != count) return NULL;
+
+ void* block = do_debug_malloc_or_debug_cpp_alloc(total_size);
+ MallocHook::InvokeNewHook(block, total_size);
+ if (block) memset(block, 0, total_size);
+ return block;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) __THROW {
MallocHook::InvokeDeleteHook(ptr);
DebugDeallocate(ptr, MallocBlock::kMallocType);
}
-extern "C" void* realloc(void* ptr, size_t size) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW {
if (ptr == NULL) {
- ptr = DebugAllocate(size, MallocBlock::kMallocType);
+ ptr = do_debug_malloc_or_debug_cpp_alloc(size);
MallocHook::InvokeNewHook(ptr, size);
return ptr;
}
@@ -1072,20 +1199,59 @@ extern "C" void* realloc(void* ptr, size_t size) __THROW {
return p->data_addr();
}
-extern "C" void* calloc(size_t count, size_t size) __THROW {
- // Overflow check
- const size_t total_size = count * size;
- if (size != 0 && total_size / size != count) return NULL;
+extern "C" PERFTOOLS_DLL_DECL void* tc_new(size_t size) {
+ void* ptr = debug_cpp_alloc(size, MallocBlock::kNewType, false);
+ MallocHook::InvokeNewHook(ptr, size);
+ if (ptr == NULL) {
+ RAW_LOG(FATAL, "Unable to allocate %"PRIuS" bytes: new failed.", size);
+ }
+ return ptr;
+}
- void* block = DebugAllocate(total_size, MallocBlock::kMallocType);
- MallocHook::InvokeNewHook(block, total_size);
- if (block) memset(block, 0, total_size);
- return block;
+extern "C" PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size, const std::nothrow_t&) __THROW {
+ void* ptr = debug_cpp_alloc(size, MallocBlock::kNewType, true);
+ MallocHook::InvokeNewHook(ptr, size);
+ return ptr;
}
-extern "C" void cfree(void* ptr) __THROW {
- MallocHook::InvokeDeleteHook(ptr);
- DebugDeallocate(ptr, MallocBlock::kMallocType);
+extern "C" PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ DebugDeallocate(p, MallocBlock::kNewType);
+}
+
+// Some STL implementations explicitly invoke this.
+// It is completely equivalent to a normal delete (delete never throws).
+extern "C" PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p, const std::nothrow_t&) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ DebugDeallocate(p, MallocBlock::kNewType);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_newarray(size_t size) {
+ void* ptr = debug_cpp_alloc(size, MallocBlock::kArrayNewType, false);
+ MallocHook::InvokeNewHook(ptr, size);
+ if (ptr == NULL) {
+ RAW_LOG(FATAL, "Unable to allocate %"PRIuS" bytes: new[] failed.", size);
+ }
+ return ptr;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, const std::nothrow_t&)
+ __THROW {
+ void* ptr = debug_cpp_alloc(size, MallocBlock::kArrayNewType, true);
+ MallocHook::InvokeNewHook(ptr, size);
+ return ptr;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ DebugDeallocate(p, MallocBlock::kArrayNewType);
+}
+
+// Some STL implementations explicitly invoke this.
+// It is completely equivalent to a normal delete (delete never throws).
+extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p, const std::nothrow_t&) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ DebugDeallocate(p, MallocBlock::kArrayNewType);
}
// Round "value" up to next "alignment" boundary.
@@ -1094,6 +1260,7 @@ static intptr_t RoundUp(intptr_t value, intptr_t alignment) {
return (value + alignment - 1) & ~(alignment - 1);
}
+// This is mostly the same as do_memalign in tcmalloc.cc.
static void *do_debug_memalign(size_t alignment, size_t size) {
// Allocate >= size bytes aligned on "alignment" boundary
// "alignment" is a power of two.
@@ -1123,83 +1290,10 @@ static void *do_debug_memalign(size_t alignment, size_t size) {
return p;
}
-// Override __libc_memalign in libc on linux boxes.
-// They have a bug in libc that causes them (very rarely) to allocate
-// with __libc_memalign() yet deallocate with free().
-// This function is an exception to the rule of calling MallocHook method
-// from the stack frame of the allocation function;
-// heap-checker handles this special case explicitly.
-static void *MemalignOverride(size_t align, size_t size,
- const void *caller) __THROW {
- void *p = do_debug_memalign(align, size);
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride;
-
-extern "C" void* memalign(size_t align, size_t size) __THROW {
- void *p = do_debug_memalign(align, size);
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-
-// Implementation taken from tcmalloc/tcmalloc.cc
-extern "C" int posix_memalign(void** result_ptr,
- size_t align, size_t size) __THROW {
- if (((align % sizeof(void*)) != 0) ||
- ((align & (align - 1)) != 0) ||
- (align == 0)) {
- return EINVAL;
- }
-
- void* result = do_debug_memalign(align, size);
- MallocHook::InvokeNewHook(result, size);
- if (result == NULL) {
- return ENOMEM;
- } else {
- *result_ptr = result;
- return 0;
- }
-}
-
-extern "C" void* valloc(size_t size) __THROW {
- // Allocate >= size bytes starting on a page boundary
- void *p = do_debug_memalign(getpagesize(), size);
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-
-extern "C" void* pvalloc(size_t size) __THROW {
- // Round size up to a multiple of pages
- // then allocate memory on a page boundary
- int pagesize = getpagesize();
- size = RoundUp(size, pagesize);
- if (size == 0) { // pvalloc(0) should allocate one page, according to
- size = pagesize; // http://man.free4web.biz/man3/libmpatrol.3.html
- }
- void *p = do_debug_memalign(pagesize, size);
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-
-extern "C" int mallopt(int cmd, int value) __THROW {
- return BASE_MALLOPT(cmd, value);
-}
-
-#ifdef HAVE_STRUCT_MALLINFO
-extern "C" struct mallinfo mallinfo(void) __THROW {
- return BASE_MALLINFO();
-}
-#endif
-
-// ========================================================================= //
-
-// Alloc/free stuff for debug operator new & friends
-
-// This is mostly the same a cpp_alloc in tcmalloc.cc.
-inline void* cpp_debug_alloc(size_t size, int new_type, bool nothrow) {
+// This is mostly the same as cpp_memalign in tcmalloc.cc.
+static void* debug_cpp_memalign(size_t align, size_t size) {
for (;;) {
- void* p = DebugAllocate(size, new_type);
+ void* p = do_debug_memalign(align, size);
#ifdef PREANSINEW
return p;
#else
@@ -1224,17 +1318,15 @@ inline void* cpp_debug_alloc(size_t size, int new_type, bool nothrow) {
return 0;
#else
// If no new_handler is established, the allocation failed.
- if (!nh) {
- if (nothrow) return 0;
- throw std::bad_alloc();
- }
+ if (!nh)
+ return 0;
+
// Otherwise, try the new_handler. If it returns, retry the
// allocation. If it throws std::bad_alloc, fail the allocation.
// if it throws something else, don't interfere.
try {
(*nh)();
} catch (const std::bad_alloc&) {
- if (!nothrow) throw;
return p;
}
#endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
@@ -1245,185 +1337,89 @@ inline void* cpp_debug_alloc(size_t size, int new_type, bool nothrow) {
}
}
-void* operator new(size_t size) throw (std::bad_alloc) {
- void* ptr = cpp_debug_alloc(size, MallocBlock::kNewType, false);
- MallocHook::InvokeNewHook(ptr, size);
- if (ptr == NULL) {
- RAW_LOG(FATAL, "Unable to allocate %"PRIuS" bytes: new failed.", size);
- }
- return ptr;
+inline void* do_debug_memalign_or_debug_cpp_memalign(size_t align,
+ size_t size) {
+ return tc_new_mode ? debug_cpp_memalign(align, size)
+ : do_debug_memalign(align, size);
}
-void* operator new(size_t size, const std::nothrow_t&) __THROW {
- void* ptr = cpp_debug_alloc(size, MallocBlock::kNewType, true);
- MallocHook::InvokeNewHook(ptr, size);
- return ptr;
+extern "C" PERFTOOLS_DLL_DECL void* tc_memalign(size_t align, size_t size) __THROW {
+ void *p = do_debug_memalign_or_debug_cpp_memalign(align, size);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
}
-void operator delete(void* ptr) __THROW {
- MallocHook::InvokeDeleteHook(ptr);
- DebugDeallocate(ptr, MallocBlock::kNewType);
-}
+// Implementation taken from tcmalloc/tcmalloc.cc
+extern "C" PERFTOOLS_DLL_DECL int tc_posix_memalign(void** result_ptr, size_t align, size_t size)
+ __THROW {
+ if (((align % sizeof(void*)) != 0) ||
+ ((align & (align - 1)) != 0) ||
+ (align == 0)) {
+ return EINVAL;
+ }
-// Some STL implementations explicitly invoke this.
-// It is completely equivalent to a normal delete (delete never throws).
-void operator delete(void* ptr, const std::nothrow_t&) __THROW {
- MallocHook::InvokeDeleteHook(ptr);
- DebugDeallocate(ptr, MallocBlock::kNewType);
+ void* result = do_debug_memalign_or_debug_cpp_memalign(align, size);
+ MallocHook::InvokeNewHook(result, size);
+ if (result == NULL) {
+ return ENOMEM;
+ } else {
+ *result_ptr = result;
+ return 0;
+ }
}
-// ========================================================================= //
-
-// Alloc/free stuff for debug operator new[] & friends
+extern "C" PERFTOOLS_DLL_DECL void* tc_valloc(size_t size) __THROW {
+ // Allocate >= size bytes starting on a page boundary
+ void *p = do_debug_memalign_or_debug_cpp_memalign(getpagesize(), size);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
-void* operator new[](size_t size) throw (std::bad_alloc) {
- void* ptr = cpp_debug_alloc(size, MallocBlock::kArrayNewType, false);
- MallocHook::InvokeNewHook(ptr, size);
- if (ptr == NULL) {
- RAW_LOG(FATAL, "Unable to allocate %"PRIuS" bytes: new[] failed.", size);
+extern "C" PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t size) __THROW {
+ // Round size up to a multiple of pages
+ // then allocate memory on a page boundary
+ int pagesize = getpagesize();
+ size = RoundUp(size, pagesize);
+ if (size == 0) { // pvalloc(0) should allocate one page, according to
+ size = pagesize; // http://man.free4web.biz/man3/libmpatrol.3.html
}
- return ptr;
+ void *p = do_debug_memalign_or_debug_cpp_memalign(pagesize, size);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
}
-void* operator new[](size_t size, const std::nothrow_t&) __THROW {
- void* ptr = cpp_debug_alloc(size, MallocBlock::kArrayNewType, true);
- MallocHook::InvokeNewHook(ptr, size);
- return ptr;
+// malloc_stats just falls through to the base implementation.
+extern "C" PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW {
+ BASE_MALLOC_STATS();
}
-void operator delete[](void* ptr) __THROW {
- MallocHook::InvokeDeleteHook(ptr);
- DebugDeallocate(ptr, MallocBlock::kArrayNewType);
+extern "C" PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW {
+ return BASE_MALLOPT(cmd, value);
}
-// Some STL implementations explicitly invoke this.
-// It is completely equivalent to a normal delete (delete never throws).
-void operator delete[](void* ptr, const std::nothrow_t&) __THROW {
- MallocHook::InvokeDeleteHook(ptr);
- DebugDeallocate(ptr, MallocBlock::kArrayNewType);
+#ifdef HAVE_STRUCT_MALLINFO
+extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW {
+ return BASE_MALLINFO();
}
-
-// ========================================================================= //
-
-// The following functions may be called via MallocExtension::instance()
-// for memory verification and statistics.
-#ifdef TCMALLOC_FOR_DEBUGALLOCATION
-// Inherit from tcmalloc's version
-typedef TCMallocImplementation ParentImplementation;
-#else
-// Inherit from default version
-typedef MallocExtension ParentImplementation;
#endif
-class DebugMallocImplementation : public ParentImplementation {
- public:
- virtual bool GetNumericProperty(const char* name, size_t* value) {
- bool result = ParentImplementation::GetNumericProperty(name, value);
- if (result && (strcmp(name, "generic.current_allocated_bytes") == 0)) {
- // Subtract bytes kept in the free queue
- size_t qsize = MallocBlock::FreeQueueSize();
- if (*value >= qsize) {
- *value -= qsize;
- }
- }
- return result;
- }
-
- virtual bool VerifyNewMemory(void* p) {
- if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kNewType);
- return true;
- }
-
- virtual bool VerifyArrayNewMemory(void* p) {
- if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kArrayNewType);
- return true;
- }
-
- virtual bool VerifyMallocMemory(void* p) {
- if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kMallocType);
- return true;
- }
-
- virtual bool VerifyAllMemory() {
- return MallocBlock::CheckEverything();
- }
-
- virtual bool MallocMemoryStats(int* blocks, size_t* total,
- int histogram[kMallocHistogramSize]) {
- return MallocBlock::MemoryStats(blocks, total, histogram);
- }
-
- virtual size_t GetAllocatedSize(void* p) {
- if (p) {
- return MallocBlock::FromRawPointer(p)->data_size();
- }
- return 0;
- }
- virtual size_t GetEstimatedAllocatedSize(size_t size) {
- return size;
- }
-
- virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* v) {
- static const char* kDebugFreeQueue = "debug.free_queue";
-
- ParentImplementation::GetFreeListSizes(v);
-
- MallocExtension::FreeListInfo i;
- i.type = kDebugFreeQueue;
- i.min_object_size = 0;
- i.max_object_size = numeric_limits<size_t>::max();
- i.total_bytes_free = MallocBlock::FreeQueueSize();
- v->push_back(i);
- }
-
- };
-
-static DebugMallocImplementation debug_malloc_implementation;
-
-REGISTER_MODULE_INITIALIZER(debugallocation, {
- // Either we or valgrind will control memory management. We
- // register our extension if we're the winner.
- if (RunningOnValgrind()) {
- // Let Valgrind uses its own malloc (so don't register our extension).
- } else {
- MallocExtension::Register(&debug_malloc_implementation);
- // When the program exits, check all blocks still in the free
- // queue for corruption.
- atexit(DanglingWriteChecker);
- }
-});
-
-#ifdef TCMALLOC_FOR_DEBUGALLOCATION
-
-// Redefine malloc_stats to use tcmalloc's implementation:
-extern "C" void malloc_stats(void) __THROW {
- do_malloc_stats();
+extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW {
+ return BASE_MALLOC_SIZE(ptr);
}
-// Some library routines on RedHat 9 allocate memory using malloc()
-// and free it using __libc_free() (or vice-versa). Since we provide
-// our own implementations of malloc/free using tcmalloc.cc,
-// we need to make sure that the __libc_XXX variants
-// also point to the same implementations.
-//
-// Note: this might not override __libc_XXX calls withing libc itself,
-// but it can be important for other libraries that mention these functions
-// or when this code is LD_PRELOAD-ed.
-// TODO: In case these __libc_* definitions do not actually matter,
-// they should go away from here and from tcmalloc/tcmalloc.cc.
-//
-extern "C" {
- void* __libc_malloc(size_t size) { return malloc(size); }
- void __libc_free(void* ptr) { free(ptr); }
- void* __libc_realloc(void* ptr, size_t size) { return realloc(ptr, size); }
- void* __libc_calloc(size_t n, size_t size) { return calloc(n, size); }
- void __libc_cfree(void* ptr) { cfree(ptr); }
- void* __libc_memalign(size_t align, size_t s) { return memalign(align, s); }
- void* __libc_valloc(size_t size) { return valloc(size); }
- void* __libc_pvalloc(size_t size) { return pvalloc(size); }
- int __posix_memalign(void** r, size_t a, size_t s) {
- return posix_memalign(r, a, s);
- }
-}
+// Override __libc_memalign in libc on linux boxes.
+// They have a bug in libc that causes them (very rarely) to allocate
+// with __libc_memalign() yet deallocate with free().
+// This function is an exception to the rule of calling MallocHook method
+// from the stack frame of the allocation function;
+// heap-checker handles this special case explicitly.
+static void *MemalignOverride(size_t align, size_t size, const void *caller)
+ __THROW ATTRIBUTE_SECTION(google_malloc);
-#endif // #ifdef TCMALLOC_FOR_DEBUGALLOCATION
+static void *MemalignOverride(size_t align, size_t size, const void *caller)
+ __THROW {
+ void *p = do_debug_memalign_or_debug_cpp_memalign(align, size);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride;
diff --git a/src/google/tcmalloc.h.in b/src/google/tcmalloc.h.in
index cdaaaa0..d42f4e6 100644
--- a/src/google/tcmalloc.h.in
+++ b/src/google/tcmalloc.h.in
@@ -94,7 +94,7 @@ extern "C" {
// OS X: malloc_size()
// glibc: malloc_usable_size()
// Windows: _msize()
- size_t tc_malloc_size(void* ptr) __THROW;
+ PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW;
#ifdef __cplusplus
PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) __THROW;
diff --git a/src/heap-checker.cc b/src/heap-checker.cc
index bfb1cd3..dfda9ad 100644
--- a/src/heap-checker.cc
+++ b/src/heap-checker.cc
@@ -897,10 +897,19 @@ HeapLeakChecker::ProcMapsResult HeapLeakChecker::UseProcMapsLocked(
// do things in this loop.
continue;
}
- // Determine if any shared libraries are present.
- if (inode != 0 && strstr(filename, "lib") && strstr(filename, ".so")) {
+ // Determine if any shared libraries are present. This is the same
+ // list of extensions as is found in pprof.
+ if (strstr(filename, ".dll")) { // for windows, which doesn't have inodes
saw_shared_lib = true;
+ } else if (inode != 0) { // ignore fake files
+ if ((strstr(filename, "lib") && strstr(filename, ".so")) ||
+ // not all .dylib filenames start with lib. .dylib is big enough
+ // that we are unlikely to get false matches just checking that.
+ strstr(filename, ".dylib") || strstr(filename, ".bundle")) {
+ saw_shared_lib = true;
+ }
}
+
switch (proc_maps_task) {
case DISABLE_LIBRARY_ALLOCS:
// All lines starting like
@@ -1887,6 +1896,11 @@ static bool internal_init_start_has_run = false;
// turns out we do not need checking in the end; can stop profiling
TurnItselfOffLocked();
return;
+ } else if (RunningOnValgrind()) {
+ // There is no point in trying -- we'll just fail.
+ RAW_LOG(WARNING, "Can't run under Valgrind; will turn itself off");
+ TurnItselfOffLocked();
+ return;
}
}
diff --git a/src/internal_logging.cc b/src/internal_logging.cc
index ea8e56f..4e46ba8 100644
--- a/src/internal_logging.cc
+++ b/src/internal_logging.cc
@@ -39,6 +39,7 @@
#include <string.h>
#include <google/malloc_extension.h>
#include "internal_logging.h"
+#include "base/logging.h" // for perftools_vsnprintf
static const int kLogBufSize = 800;
@@ -50,7 +51,7 @@ void TCMalloc_MESSAGE(const char* filename,
if (n < kLogBufSize) {
va_list ap;
va_start(ap, format);
- vsnprintf(buf + n, kLogBufSize - n, format, ap);
+ perftools_vsnprintf(buf + n, kLogBufSize - n, format, ap);
va_end(ap);
}
write(STDERR_FILENO, buf, strlen(buf));
@@ -66,7 +67,7 @@ static void TCMalloc_CRASH_internal(bool dump_stats,
char buf[kLogBufSize];
const int n = snprintf(buf, sizeof(buf), "%s:%d] ", filename, line_number);
if (n < kLogBufSize) {
- vsnprintf(buf + n, kLogBufSize - n, format, ap);
+ perftools_vsnprintf(buf + n, kLogBufSize - n, format, ap);
}
write(STDERR_FILENO, buf, strlen(buf));
if (dump_stats) {
@@ -99,7 +100,7 @@ void TCMalloc_Printer::printf(const char* format, ...) {
if (left_ > 0) {
va_list ap;
va_start(ap, format);
- const int r = vsnprintf(buf_, left_, format, ap);
+ const int r = perftools_vsnprintf(buf_, left_, format, ap);
va_end(ap);
if (r < 0) {
// Perhaps an old glibc that returns -1 on truncation?
diff --git a/src/raw_printer.cc b/src/raw_printer.cc
index 019555a..730d6e2 100644
--- a/src/raw_printer.cc
+++ b/src/raw_printer.cc
@@ -54,7 +54,7 @@ void RawPrinter::Printf(const char* format, ...) {
int avail = limit_ - ptr_;
// We pass avail+1 to vsnprintf() since that routine needs room
// to store the trailing \0.
- const int r = vsnprintf(ptr_, avail+1, format, ap);
+ const int r = perftools_vsnprintf(ptr_, avail+1, format, ap);
va_end(ap);
if (r < 0) {
// Perhaps an old glibc that returns -1 on truncation?
diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc
index 8d94d20..b037f57 100644
--- a/src/tcmalloc.cc
+++ b/src/tcmalloc.cc
@@ -97,8 +97,16 @@
#else
#include <sys/types.h>
#endif
-#if defined(HAVE_MALLOC_H) && defined(HAVE_STRUCT_MALLINFO)
-#include <malloc.h> // for struct mallinfo
+// We only need malloc.h for struct mallinfo.
+#ifdef HAVE_STRUCT_MALLINFO
+// Malloc can be in several places on older versions of OS X.
+# if defined(HAVE_MALLOC_H)
+# include <malloc.h>
+# elif defined(HAVE_SYS_MALLOC_H)
+# include <sys/malloc.h>
+# elif defined(HAVE_MALLOC_MALLOC_H)
+# include <malloc/malloc.h>
+# endif
#endif
#include <string.h>
#ifdef HAVE_PTHREAD
@@ -259,7 +267,7 @@ extern "C" {
// exception: in windows, by default, we patch our code into these
// functions (via src/windows/patch_function.cc) rather than override
// them. In that case, we don't want to do this overriding here.
-#if !defined(WIN32_DO_PATCHING) && !defined(TCMALLOC_FOR_DEBUGALLOCATION)
+#if !defined(WIN32_DO_PATCHING)
#if defined(__GNUC__) && !defined(__MACH__)
// Potentially faster variants that use the gcc alias extension.
@@ -373,7 +381,7 @@ extern "C" {
#undef ALIAS
-#endif // #ifndef(WIN32_DO_PATCHING) && ndef(TCMALLOC_FOR_DEBUGALLOCATION)
+#endif // #ifndef(WIN32_DO_PATCHING)
// ----------------------- IMPLEMENTATION -------------------------------
@@ -1474,6 +1482,19 @@ extern "C" PERFTOOLS_DLL_DECL const char* tc_version(
return TC_VERSION_STRING;
}
+// This function behaves similarly to MSVC's _set_new_mode.
+// If flag is 0 (default), calls to malloc will behave normally.
+// If flag is 1, calls to malloc will behave like calls to new,
+// and the std_new_handler will be invoked on failure.
+// Returns the previous mode.
+extern "C" PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) __THROW {
+ int old_mode = tc_new_mode;
+ tc_new_mode = flag;
+ return old_mode;
+}
+
+#ifndef TCMALLOC_FOR_DEBUGALLOCATION // debugallocation.cc defines its own
+
// CAVEAT: The code structure below ensures that MallocHook methods are always
// called from the stack frame of the invoked allocation function.
// heap-checker.cc depends on this to start a stack trace from
@@ -1640,17 +1661,6 @@ extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW {
return GetSizeWithCallback(ptr, &InvalidGetAllocatedSize);
}
-// This function behaves similarly to MSVC's _set_new_mode.
-// If flag is 0 (default), calls to malloc will behave normally.
-// If flag is 1, calls to malloc will behave like calls to new,
-// and the std_new_handler will be invoked on failure.
-// Returns the previous mode.
-extern "C" PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) __THROW {
- int old_mode = tc_new_mode;
- tc_new_mode = flag;
- return old_mode;
-}
-
// Override __libc_memalign in libc on linux boxes specially.
// They have a bug in libc that causes them to (very rarely) allocate
@@ -1659,7 +1669,6 @@ extern "C" PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) __THROW {
// This function is an exception to the rule of calling MallocHook method
// from the stack frame of the allocation function;
// heap-checker handles this special case explicitly.
-#ifndef TCMALLOC_FOR_DEBUGALLOCATION
static void *MemalignOverride(size_t align, size_t size, const void *caller)
__THROW ATTRIBUTE_SECTION(google_malloc);
@@ -1670,4 +1679,5 @@ static void *MemalignOverride(size_t align, size_t size, const void *caller)
return result;
}
void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride;
+
#endif // #ifndef TCMALLOC_FOR_DEBUGALLOCATION
diff --git a/src/tests/debugallocation_test.cc b/src/tests/debugallocation_test.cc
index dd5af13..07b8604 100644
--- a/src/tests/debugallocation_test.cc
+++ b/src/tests/debugallocation_test.cc
@@ -220,7 +220,7 @@ TEST(DebugAllocationTest, StackTraceWithDanglingWriteAtExitTest) {
*x = 1;
// verify that we also get a stack trace when we have a dangling write.
// The " @ " is part of the stack trace output.
- IF_DEBUG_EXPECT_DEATH(exit(0), " @ .* main");
+ IF_DEBUG_EXPECT_DEATH(exit(0), " @ .*main");
*x = old_x_value; // restore x so that the test can exit successfully.
}
diff --git a/src/tests/heap-checker_unittest.cc b/src/tests/heap-checker_unittest.cc
index b282941..e33e068 100644
--- a/src/tests/heap-checker_unittest.cc
+++ b/src/tests/heap-checker_unittest.cc
@@ -76,11 +76,6 @@
#include <sys/mman.h>
#endif
#include <fcntl.h> // for open(), close()
-// FreeBSD has malloc.h, but complains if you use it
-#if defined(HAVE_MALLOC_H) && !defined(__FreeBSD__)
-#include <malloc.h>
-#endif
-
#ifdef HAVE_EXECINFO_H
#include <execinfo.h> // backtrace
#endif
@@ -684,7 +679,7 @@ static void ScopedDisabledLeaks() {
HeapLeakChecker::Disabler disabler;
AllocHidden(3 * sizeof(int));
TransLeaks();
- malloc(10); // Direct leak
+ (void)malloc(10); // Direct leak
}
// have different disabled leaks
diff --git a/src/tests/memalign_unittest.cc b/src/tests/memalign_unittest.cc
index d5b60db..ce2c1f3 100644
--- a/src/tests/memalign_unittest.cc
+++ b/src/tests/memalign_unittest.cc
@@ -57,8 +57,13 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h> // for getpagesize()
#endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
+// Malloc can be in several places on older versions of OS X.
+#if defined(HAVE_MALLOC_H)
+#include <malloc.h> // for memalign() and valloc()
+#elif defined(HAVE_SYS_MALLOC_H)
+#include <sys/malloc.h>
+#elif defined(HAVE_MALLOC_MALLOC_H)
+#include <malloc/malloc.h>
#endif
#include "base/basictypes.h"
#include "base/logging.h"
diff --git a/src/tests/sampler_test.cc b/src/tests/sampler_test.cc
index 045cd02..31c87cd 100755
--- a/src/tests/sampler_test.cc
+++ b/src/tests/sampler_test.cc
@@ -87,7 +87,7 @@ static std::string StringPrintf(const char* format, ...) {
char buf[256]; // should be big enough for all logging
va_list ap;
va_start(ap, format);
- vsnprintf(buf, sizeof(buf), format, ap);
+ perftools_vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
return buf;
}
diff --git a/src/windows/config.h b/src/windows/config.h
index fb0327d..1d93c4f 100644
--- a/src/windows/config.h
+++ b/src/windows/config.h
@@ -210,7 +210,7 @@
#define PACKAGE_NAME "google-perftools"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "google-perftools 1.4"
+#define PACKAGE_STRING "google-perftools 1.7"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "google-perftools"
@@ -219,7 +219,7 @@
#undef PACKAGE_URL
/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.4"
+#define PACKAGE_VERSION "1.7"
/* How to access the PC from a struct ucontext */
#undef PC_FROM_UCONTEXT
diff --git a/src/windows/google/tcmalloc.h b/src/windows/google/tcmalloc.h.in
index 5bd4c59..a031b35 100644
--- a/src/windows/google/tcmalloc.h
+++ b/src/windows/google/tcmalloc.h.in
@@ -29,18 +29,12 @@
*
* ---
* Author: Sanjay Ghemawat <opensource@google.com>
- * .h file by Craig Silverstein <opensource@google.com>
+ * .h.in file by Craig Silverstein <opensource@google.com>
*/
#ifndef TCMALLOC_TCMALLOC_H_
#define TCMALLOC_TCMALLOC_H_
-// Define the version number so folks can check against it
-#define TC_VERSION_MAJOR 1
-#define TC_VERSION_MINOR 4
-#define TC_VERSION_PATCH ""
-#define TC_VERSION_STRING "google-perftools 1.4"
-
// __THROW is defined in glibc systems. It means, counter-intuitively,
// "This function will never throw an exception." It's an optional
// optimization tool, but we may need to use it to match glibc prototypes.
@@ -48,6 +42,11 @@
# define __THROW /* __THROW is just an optimization, so ok to make it "" */
#endif
+// Define the version number so folks can check against it
+#define TC_VERSION_MAJOR @TC_VERSION_MAJOR@
+#define TC_VERSION_MINOR @TC_VERSION_MINOR@
+#define TC_VERSION_PATCH "@TC_VERSION_PATCH@"
+#define TC_VERSION_STRING "google-perftools @TC_VERSION_MAJOR@.@TC_VERSION_MINOR@@TC_VERSION_PATCH@"
#include <stdlib.h> // for struct mallinfo, if it's defined
diff --git a/src/windows/port.cc b/src/windows/port.cc
index 32f3c31..aa972d0 100644
--- a/src/windows/port.cc
+++ b/src/windows/port.cc
@@ -49,24 +49,6 @@
// -----------------------------------------------------------------------
// Basic libraries
-// These call the windows _vsnprintf, but always NUL-terminate.
-int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
- if (size == 0) // not even room for a \0?
- return -1; // not what C99 says to do, but what windows does
- str[size-1] = '\0';
- return _vsnprintf(str, size-1, format, ap);
-}
-
-#ifndef HAVE_SNPRINTF
-int snprintf(char *str, size_t size, const char *format, ...) {
- va_list ap;
- va_start(ap, format);
- const int r = vsnprintf(str, size, format, ap);
- va_end(ap);
- return r;
-}
-#endif
-
int getpagesize() {
static int pagesize = 0;
if (pagesize == 0) {
@@ -98,6 +80,7 @@ extern "C" PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len) {
// -----------------------------------------------------------------------
// Threads code
+// Declared (not extern "C") in thread_cache.h
bool CheckIfKernelSupportsTLS() {
// TODO(csilvers): return true (all win's since win95, at least, support this)
return false;
@@ -186,7 +169,7 @@ BOOL WINAPI DllMain(HINSTANCE h, DWORD dwReason, PVOID pv) {
#endif // #ifdef _MSC_VER
-pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)) {
+extern "C" pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)) {
// Semantics are: we create a new key, and then promise to call
// destr_fn with TlsGetValue(key) when the thread is destroyed
// (as long as TlsGetValue(key) is not NULL).
@@ -200,6 +183,30 @@ pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)) {
return key;
}
+// NOTE: this is Win2K and later. For Win98 we could use a CRITICAL_SECTION...
+extern "C" int perftools_pthread_once(pthread_once_t *once_control,
+ void (*init_routine)(void)) {
+ // Try for a fast path first. Note: this should be an acquire semantics read.
+ // It is on x86 and x64, where Windows runs.
+ if (*once_control != 1) {
+ while (true) {
+ switch (InterlockedCompareExchange(once_control, 2, 0)) {
+ case 0:
+ init_routine();
+ InterlockedExchange(once_control, 1);
+ return 0;
+ case 1:
+ // The initializer has already been executed
+ return 0;
+ default:
+ // The initializer is being processed by another thread
+ SwitchToThread();
+ }
+ }
+ }
+ return 0;
+}
+
// -----------------------------------------------------------------------
// These functions replace system-alloc.cc
diff --git a/src/windows/port.h b/src/windows/port.h
index ff6b714..0faba01 100644
--- a/src/windows/port.h
+++ b/src/windows/port.h
@@ -40,8 +40,8 @@
#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).
+/* 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_)
# error "port.h should only be included from config.h or mingw.h"
@@ -54,21 +54,45 @@
#endif
#include <windows.h>
#include <io.h> /* because we so often use open/close/etc */
+#include <direct.h> /* for _getcwd */
#include <process.h> /* for _getpid */
+#include <limits.h> /* for PATH_MAX */
#include <stdarg.h> /* for va_list */
#include <stdio.h> /* need this to override stdio's (v)snprintf */
-
-// 4018: signed/unsigned mismatch is common (and ok for signed_i < unsigned_i)
-// 4244: otherwise we get problems when substracting two size_t's to an int
-// 4288: VC++7 gets confused when a var is defined in a loop and then after it
-// 4267: too many false positives for "conversion gives possible data loss"
-// 4290: it's ok windows ignores the "throw" directive
-// 4996: Yes, we're ok using "unsafe" functions like vsnprintf and getenv()
+#include <sys/types.h> /* for _off_t */
+#include <assert.h>
+#include <stdlib.h> /* for rand, srand, _strtoxxx */
+
+/*
+ * 4018: signed/unsigned mismatch is common (and ok for signed_i < unsigned_i)
+ * 4244: otherwise we get problems when substracting two size_t's to an int
+ * 4288: VC++7 gets confused when a var is defined in a loop and then after it
+ * 4267: too many false positives for "conversion gives possible data loss"
+ * 4290: it's ok windows ignores the "throw" directive
+ * 4996: Yes, we're ok using "unsafe" functions like vsnprintf and getenv()
+ */
#ifdef _MSC_VER
#pragma warning(disable:4018 4244 4288 4267 4290 4996)
#endif
-// ----------------------------------- BASIC TYPES
+#ifndef __cplusplus
+/* MSVC does not support C99 */
+# if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
+# ifdef _MSC_VER
+# define inline __inline
+# else
+# define inline static
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+# define EXTERN_C extern "C"
+#else
+# define EXTERN_C extern
+#endif
+
+/* ----------------------------------- BASIC TYPES */
#ifndef HAVE_STDINT_H
#ifndef HAVE___INT64 /* we need to have all the __intX names */
@@ -83,53 +107,78 @@ typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
-#endif // #ifndef HAVE_STDINT_H
+#endif /* #ifndef HAVE_STDINT_H */
-// I guess MSVC's <types.h> doesn't include ssize_t by default?
+/* I guess MSVC's <types.h> doesn't include ssize_t by default? */
#ifdef _MSC_VER
typedef intptr_t ssize_t;
#endif
-// ----------------------------------- THREADS
+/* ----------------------------------- THREADS */
-#ifndef HAVE_PTHREAD // not true for MSVC, but may be true for MSYS
+#ifndef HAVE_PTHREAD /* not true for MSVC, but may be true for MSYS */
typedef DWORD pthread_t;
typedef DWORD pthread_key_t;
typedef LONG pthread_once_t;
-enum { PTHREAD_ONCE_INIT = 0 }; // important that this be 0! for SpinLock
-#define pthread_self GetCurrentThreadId
-#define pthread_equal(pthread_t_1, pthread_t_2) ((pthread_t_1)==(pthread_t_2))
+enum { PTHREAD_ONCE_INIT = 0 }; /* important that this be 0! for SpinLock */
+
+inline pthread_t pthread_self(void) {
+ return GetCurrentThreadId();
+}
#ifdef __cplusplus
-// This replaces maybe_threads.{h,cc}
-extern pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)); // in port.cc
-#define perftools_pthread_key_create(pkey, destr_fn) \
- *(pkey) = PthreadKeyCreate(destr_fn)
+inline bool pthread_equal(pthread_t left, pthread_t right) {
+ return left == right;
+}
+
+/* This replaces maybe_threads.{h,cc} */
+EXTERN_C pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)); /* port.cc */
+
+inline int perftools_pthread_key_create(pthread_key_t *pkey,
+ void (*destructor)(void*)) {
+ pthread_key_t key = PthreadKeyCreate(destructor);
+ if (key != TLS_OUT_OF_INDEXES) {
+ *(pkey) = key;
+ return 0;
+ } else {
+ return GetLastError();
+ }
+}
+
inline void* perftools_pthread_getspecific(DWORD key) {
DWORD err = GetLastError();
void* rv = TlsGetValue(key);
if (err) SetLastError(err);
return rv;
}
-#define perftools_pthread_setspecific(key, val) \
- TlsSetValue((key), (val))
-// NOTE: this is Win2K and later. For Win98 we could use a CRITICAL_SECTION...
-#define perftools_pthread_once(once, init) do { \
- if (InterlockedCompareExchange(once, 1, 0) == 0) (init)(); \
-} while (0)
-#endif // __cplusplus
-#endif // HAVE_PTHREAD
-
-// __declspec(thread) isn't usable in a dll opened via LoadLibrary().
-// But it doesn't work to LoadLibrary() us anyway, because of all the
-// things we need to do before main()! So this kind of TLS is safe for us.
+
+inline int perftools_pthread_setspecific(pthread_key_t key, const void *value) {
+ if (TlsSetValue(key, (LPVOID)value))
+ return 0;
+ else
+ return GetLastError();
+}
+
+EXTERN_C int perftools_pthread_once(pthread_once_t *once_control,
+ void (*init_routine)(void));
+
+#endif /* __cplusplus */
+#endif /* HAVE_PTHREAD */
+
+/*
+ * __declspec(thread) isn't usable in a dll opened via LoadLibrary().
+ * But it doesn't work to LoadLibrary() us anyway, because of all the
+ * things we need to do before main()! So this kind of TLS is safe for us.
+ */
#define __thread __declspec(thread)
-// This code is obsolete, but I keep it around in case we are ever in
-// an environment where we can't or don't want to use google spinlocks
-// (from base/spinlock.{h,cc}). In that case, uncommenting this out,
-// and removing spinlock.cc from the build, should be enough to revert
-// back to using native spinlocks.
+/*
+ * This code is obsolete, but I keep it around in case we are ever in
+ * an environment where we can't or don't want to use google spinlocks
+ * (from base/spinlock.{h,cc}). In that case, uncommenting this out,
+ * and removing spinlock.cc from the build, should be enough to revert
+ * back to using native spinlocks.
+ */
#if 0
// Windows uses a spinlock internally for its mutexes, making our life easy!
// However, the Windows spinlock must always be initialized, making life hard,
@@ -197,51 +246,80 @@ class SpinLockHolder { // Acquires a spinlock for as long as the scope lasts
// This keeps us from using base/spinlock.h's implementation of SpinLock.
#define BASE_SPINLOCK_H_ 1
-#endif // #if 0
-
-// This replaces testutil.{h,cc}
-extern PERFTOOLS_DLL_DECL void RunInThread(void (*fn)());
-extern PERFTOOLS_DLL_DECL void RunManyInThread(void (*fn)(), int count);
-extern PERFTOOLS_DLL_DECL void RunManyInThreadWithId(void (*fn)(int), int count,
- int stacksize);
+#endif /* #if 0 */
+/* ----------------------------------- MMAP and other memory allocation */
-// ----------------------------------- MMAP and other memory allocation
-
-#ifndef HAVE_MMAP // not true for MSVC, but may be true for msys
+#ifndef HAVE_MMAP /* not true for MSVC, but may be true for msys */
#define MAP_FAILED 0
-#define MREMAP_FIXED 2 // the value in linux, though it doesn't really matter
-// These, when combined with the mmap invariants below, yield the proper action
+#define MREMAP_FIXED 2 /* the value in linux, though it doesn't really matter */
+/* These, when combined with the mmap invariants below, yield the proper action */
#define PROT_READ PAGE_READWRITE
#define PROT_WRITE PAGE_READWRITE
#define MAP_ANONYMOUS MEM_RESERVE
#define MAP_PRIVATE MEM_COMMIT
-#define MAP_SHARED MEM_RESERVE // value of this #define is 100% arbitrary
+#define MAP_SHARED MEM_RESERVE /* value of this #define is 100% arbitrary */
-// VirtualAlloc is only a replacement for mmap when certain invariants are kept
-#define mmap(start, length, prot, flags, fd, offset) \
- ( (start) == NULL && (fd) == -1 && (offset) == 0 && \
- (prot) == (PROT_READ|PROT_WRITE) && (flags) == (MAP_PRIVATE|MAP_ANONYMOUS)\
- ? VirtualAlloc(0, length, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) \
- : NULL )
+#if __STDC__
+typedef _off_t off_t;
+#endif
-#define munmap(start, length) (VirtualFree(start, 0, MEM_RELEASE) ? 0 : -1)
-#endif // HAVE_MMAP
+/* VirtualAlloc only replaces for mmap when certain invariants are kept. */
+inline void *mmap(void *addr, size_t length, int prot, int flags,
+ int fd, off_t offset) {
+ if (addr == NULL && fd == -1 && offset == 0 &&
+ prot == (PROT_READ|PROT_WRITE) && flags == (MAP_PRIVATE|MAP_ANONYMOUS)) {
+ return VirtualAlloc(0, length, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ } else {
+ return NULL;
+ }
+}
-// We could maybe use VirtualAlloc for sbrk as well, but no need
-#define sbrk(increment) ( (void*)-1 ) // sbrk returns -1 on failure
+inline int munmap(void *addr, size_t length) {
+ return VirtualFree(addr, 0, MEM_RELEASE) ? 0 : -1;
+}
+#endif /* HAVE_MMAP */
+/* We could maybe use VirtualAlloc for sbrk as well, but no need */
+inline void *sbrk(intptr_t increment) {
+ // sbrk returns -1 on failure
+ return (void*)-1;
+}
-// ----------------------------------- STRING ROUTINES
-// We can't just use _vsnprintf and _snprintf as drop-in-replacements,
-// because they don't always NUL-terminate. :-( We also can't use the
-// name vsnprintf, since windows defines that (but not snprintf (!)).
-extern PERFTOOLS_DLL_DECL int snprintf(char *str, size_t size,
- const char *format, ...);
-extern PERFTOOLS_DLL_DECL int safe_vsnprintf(char *str, size_t size,
- const char *format, va_list ap);
-#define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap)
+/* ----------------------------------- STRING ROUTINES */
+
+/*
+ * We can't just use _vsnprintf and _snprintf as drop-in-replacements,
+ * because they don't always NUL-terminate. :-( We also can't use the
+ * name vsnprintf, since windows defines that (but not snprintf (!)).
+ */
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+/* We can use safe CRT functions, which the required functionality */
+inline int perftools_vsnprintf(char *str, size_t size, const char *format,
+ va_list ap) {
+ return vsnprintf_s(str, size, _TRUNCATE, format, ap);
+}
+#else
+inline int perftools_vsnprintf(char *str, size_t size, const char *format,
+ va_list ap) {
+ if (size == 0) /* not even room for a \0? */
+ return -1; /* not what C99 says to do, but what windows does */
+ str[size-1] = '\0';
+ return _vsnprintf(str, size-1, format, ap);
+}
+#endif
+
+#ifndef HAVE_SNPRINTF
+inline int snprintf(char *str, size_t size, const char *format, ...) {
+ va_list ap;
+ int r;
+ va_start(ap, format);
+ r = perftools_vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return r;
+}
+#endif
#define PRIx64 "I64x"
#define SCNx64 "I64x"
@@ -256,84 +334,132 @@ extern PERFTOOLS_DLL_DECL int safe_vsnprintf(char *str, size_t size,
# define PRIxPTR "lx"
#endif
-// ----------------------------------- FILE IO
+/* ----------------------------------- FILE IO */
+
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
#ifndef __MINGW32__
enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
#endif
-#define getcwd _getcwd
-#define access _access
-#define open _open
-#define read _read
-#define write _write
-#define lseek _lseek
-#define close _close
-#define popen _popen
-#define pclose _pclose
-#define mkdir(dirname, mode) _mkdir(dirname)
#ifndef O_RDONLY
#define O_RDONLY _O_RDONLY
#endif
-#ifdef __cplusplus
-extern "C"
+#if __STDC__ && !defined(__MINGW32__)
+/* These functions are considered non-standard */
+inline int access(const char *pathname, int mode) {
+ return _access(pathname, mode);
+}
+inline int open(const char *pathname, int flags, int mode = 0) {
+ return _open(pathname, flags, mode);
+}
+inline int close(int fd) {
+ return _close(fd);
+}
+inline ssize_t read(int fd, void *buf, size_t count) {
+ return _read(fd, buf, count);
+}
+inline ssize_t write(int fd, const void *buf, size_t count) {
+ return _write(fd, buf, count);
+}
+inline off_t lseek(int fd, off_t offset, int whence) {
+ return _lseek(fd, offset, whence);
+}
+inline char *getcwd(char *buf, size_t size) {
+ return _getcwd(buf, size);
+}
+inline int mkdir(const char *pathname, int) {
+ return _mkdir(pathname);
+}
#endif
-PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len);
-// ----------------------------------- SYSTEM/PROCESS
-typedef int pid_t;
-#define getpid _getpid
-#define getppid() (0)
+inline FILE *popen(const char *command, const char *type) {
+ return _popen(command, type);
+}
+inline int pclose(FILE *stream) {
+ return _pclose(stream);
+}
+
+EXTERN_C PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len);
+
+/* ----------------------------------- SYSTEM/PROCESS */
-// Handle case when poll is used to simulate sleep.
-#define poll(r, w, t) \
- do { \
- assert(r == 0); \
- assert(w == 0); \
- Sleep(t); \
- } while(0)
+typedef int pid_t;
+#if __STDC__
+inline pid_t getpid(void) { return _getpid(); }
+#endif
+inline pid_t getppid(void) { return 0; }
+
+/* Handle case when poll is used to simulate sleep. */
+inline int poll(struct pollfd* fds, int nfds, int timeout) {
+ assert(fds == NULL);
+ assert(nfds == 0);
+ Sleep(timeout);
+ return 0;
+}
-extern PERFTOOLS_DLL_DECL int getpagesize(); // in port.cc
+EXTERN_C int getpagesize(); /* in port.cc */
-// ----------------------------------- OTHER
+/* ----------------------------------- OTHER */
-#define srandom srand
-#define random rand
-#define sleep(t) Sleep(t * 1000)
+inline void srandom(unsigned int seed) { srand(seed); }
+inline long random(void) { return rand(); }
+inline unsigned int sleep(unsigned int seconds) {
+ Sleep(seconds * 1000);
+ return 0;
+}
struct timespec {
int tv_sec;
int tv_nsec;
};
-#define nanosleep(tm_ptr, ignored) \
- Sleep((tm_ptr)->tv_sec * 1000 + (tm_ptr)->tv_nsec / 1000000)
+inline int nanosleep(const struct timespec *req, struct timespec *rem) {
+ Sleep(req->tv_sec * 1000 + req->tv_nsec / 1000000);
+ return 0;
+}
#ifndef __MINGW32__
-#define strtoq _strtoi64
-#define strtouq _strtoui64
-#define strtoll _strtoi64
-#define strtoull _strtoui64
-#define atoll _atoi64
+inline long long int strtoll(const char *nptr, char **endptr, int base) {
+ return _strtoi64(nptr, endptr, base);
+}
+inline unsigned long long int strtoull(const char *nptr, char **endptr,
+ int base) {
+ return _strtoui64(nptr, endptr, base);
+}
+inline long long int strtoq(const char *nptr, char **endptr, int base) {
+ return _strtoi64(nptr, endptr, base);
+}
+inline unsigned long long int strtouq(const char *nptr, char **endptr,
+ int base) {
+ return _strtoui64(nptr, endptr, base);
+}
+inline long long atoll(const char *nptr) {
+ return _atoi64(nptr);
+}
#endif
#define __THROW throw()
-// ----------------------------------- TCMALLOC-SPECIFIC
+/* ----------------------------------- TCMALLOC-SPECIFIC */
-// tcmalloc.cc calls this so we can patch VirtualAlloc() et al.
-extern PERFTOOLS_DLL_DECL void PatchWindowsFunctions();
+/* tcmalloc.cc calls this so we can patch VirtualAlloc() et al. */
+extern void PatchWindowsFunctions();
// ----------------------------------- BUILD-SPECIFIC
-// windows/port.h defines compatibility APIs for several .h files, which
-// we therefore shouldn't be #including directly. This hack keeps us from
-// doing so. TODO(csilvers): do something more principled.
+/*
+ * windows/port.h defines compatibility APIs for several .h files, which
+ * we therefore shouldn't be #including directly. This hack keeps us from
+ * doing so. TODO(csilvers): do something more principled.
+ */
#define GOOGLE_MAYBE_THREADS_H_ 1
#endif /* _WIN32 */
+#undef inline
+#undef EXTERN_C
+
#endif /* GOOGLE_BASE_WINDOWS_H_ */