summaryrefslogtreecommitdiff
path: root/src/tcmalloc.cc
diff options
context:
space:
mode:
authorcsilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50>2009-04-18 00:02:25 +0000
committercsilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50>2009-04-18 00:02:25 +0000
commitbeb6a9a183c1ca25c99e4401b58266ce73b8c846 (patch)
treeb02a2cfe46761e177303c1dbaf420f7cfb14642f /src/tcmalloc.cc
parentedd03a831f350bc72d76d4fad2b390d43faccb79 (diff)
downloadgperftools-beb6a9a183c1ca25c99e4401b58266ce73b8c846.tar.gz
Fri Apr 17 16:40:48 2009 Google Inc. <opensource@google.com>
* google-perftools: version 1.2 release * Allow large_alloc_threshold=0 to turn it off entirely (csilvers) * Die more helpfully when out of memory for internal data (csilvers) * Refactor profile-data gathering, add a new unittest (cgd, nabeelmian) * BUGFIX: fix rounding errors with static thread-size caches (addi) * BUGFIX: disable hooks better when forking in leak-checker (csilvers) * BUGFIX: fix realloc of crt pointers on windows (csilvers) * BUGFIX: do a better job of finding binaries in .sh tests (csilvers) * WINDOWS: allow overriding malloc/etc instead of patching (mbelshe) * PORTING: fix compilation error in a ppc-specific file (csilvers) * PORTING: deal with quirks in cygwin's /proc/self/maps (csilvers) * PORTING: use 'A' version of functions for ascii input (mbelshe) * PORTING: generate .so's on cygwin and mingw (ajenjo) * PORTING: disable profiler methods on cygwin (jperkins) * Updated autoconf version to 2.61 and libtool version to 1.5.26 git-svn-id: http://gperftools.googlecode.com/svn/trunk@68 6b5cf1ce-ec42-a296-1ba9-69fdba395a50
Diffstat (limited to 'src/tcmalloc.cc')
-rw-r--r--src/tcmalloc.cc47
1 files changed, 25 insertions, 22 deletions
diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc
index ca88b91..e5022e3 100644
--- a/src/tcmalloc.cc
+++ b/src/tcmalloc.cc
@@ -131,6 +131,10 @@
#include "tcmalloc_guard.h"
#include "thread_cache.h"
+#if (defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)) && !defined(WIN32_OVERRIDE_ALLOCATORS)
+# define WIN32_DO_PATCHING 1
+#endif
+
using tcmalloc::PageHeap;
using tcmalloc::PageHeapAllocator;
using tcmalloc::SizeMap;
@@ -171,7 +175,8 @@ DEFINE_int64(tcmalloc_large_alloc_report_threshold,
"messages. This bounds the amount of extra logging "
"generated by this flag. Default value of this flag "
"is very large and therefore you should see no extra "
- "logging unless the flag is overridden.");
+ "logging unless the flag is overridden. Set to 0 to "
+ "disable reporting entirely.");
// These routines are called by free(), realloc(), etc. if the pointer is
// invalid. This is a cheap (source-editing required) kind of exception
@@ -181,12 +186,6 @@ void InvalidFree(void* ptr) {
CRASH("Attempt to free invalid pointer: %p\n", ptr);
}
-void* InvalidRealloc(void* old_ptr, size_t new_size) {
- CRASH("Attempt to realloc invalid pointer: %p (realloc to %" PRIuS ")\n",
- old_ptr, new_size);
- return NULL;
-}
-
size_t InvalidGetSizeForRealloc(void* old_ptr) {
CRASH("Attempt to realloc invalid pointer: %p\n", old_ptr);
return 0;
@@ -492,7 +491,8 @@ TCMallocGuard::TCMallocGuard() {
// Check whether the kernel also supports TLS (needs to happen at runtime)
tcmalloc::CheckIfKernelSupportsTLS();
#endif
-#ifdef _WIN32 // patch the windows VirtualAlloc, etc.
+#ifdef WIN32_DO_PATCHING
+ // patch the windows VirtualAlloc, etc.
PatchWindowsFunctions(); // defined in windows/patch_functions.cc
#endif
free(malloc(1));
@@ -512,7 +512,9 @@ TCMallocGuard::~TCMallocGuard() {
}
}
}
+#ifndef WIN32_OVERRIDE_ALLOCATORS
static TCMallocGuard module_enter_exit_hook;
+#endif
//-------------------------------------------------------------------
// Helpers for the exported routines below
@@ -578,8 +580,8 @@ static void ReportLargeAlloc(Length num_pages, void* result) {
static const int N = 1000;
char buffer[N];
TCMalloc_Printer printer(buffer, N);
- printer.printf("tcmalloc: large alloc %lld bytes == %p @ ",
- static_cast<long long>(num_pages) << kPageShift,
+ printer.printf("tcmalloc: large alloc %llu bytes == %p @ ",
+ static_cast<unsigned long long>(num_pages) << kPageShift,
result);
for (int i = 0; i < stack.depth; i++) {
printer.printf(" %p", stack.stack[i]);
@@ -598,7 +600,7 @@ inline void* do_malloc_pages(Length num_pages) {
SpinLockHolder h(Static::pageheap_lock());
span = Static::pageheap()->New(num_pages);
const int64 threshold = large_alloc_threshold;
- if (num_pages >= (threshold >> kPageShift)) {
+ if (threshold > 0 && num_pages >= (threshold >> kPageShift)) {
// Increase the threshold by 1/8 every time we generate a report.
// We cap the threshold at 8GB to avoid overflow problems.
large_alloc_threshold = (threshold + threshold/8 < 8ll<<30
@@ -716,7 +718,7 @@ inline size_t GetSizeWithCallback(void* ptr,
return Static::sizemap()->ByteSizeForClass(cl);
} else {
Span *span = Static::pageheap()->GetDescriptor(p);
- if (span == NULL) { // means we do now own this memory
+ if (span == NULL) { // means we do not own this memory
return (*invalid_getsize_fn)(ptr);
} else if (span->sizeclass != 0) {
Static::pageheap()->CacheSizeClass(p, span->sizeclass);
@@ -729,12 +731,12 @@ inline size_t GetSizeWithCallback(void* ptr,
// This lets you call back to a given function pointer if ptr is invalid.
// It is used primarily by windows code which wants a specialized callback.
-inline void* do_realloc_with_callback(void* old_ptr, size_t new_size,
- void* (*invalid_realloc_fn)(void*,
- size_t)) {
+inline void* do_realloc_with_callback(
+ void* old_ptr, size_t new_size,
+ void (*invalid_free_fn)(void*),
+ size_t (*invalid_get_size_fn)(void*)) {
// Get the size of the old entry
- const size_t old_size = GetSizeWithCallback(old_ptr,
- &InvalidGetSizeForRealloc);
+ const size_t old_size = GetSizeWithCallback(old_ptr, invalid_get_size_fn);
// Reallocate if the new size is larger than the old size,
// or if the new size is significantly smaller than the old size.
@@ -764,7 +766,7 @@ inline void* do_realloc_with_callback(void* old_ptr, size_t new_size,
// We could use a variant of do_free() that leverages the fact
// that we already know the sizeclass of old_ptr. The benefit
// would be small, so don't bother.
- do_free(old_ptr);
+ do_free_with_callback(old_ptr, invalid_free_fn);
return new_ptr;
} else {
// We still need to call hooks to report the updated size:
@@ -775,7 +777,8 @@ inline void* do_realloc_with_callback(void* old_ptr, size_t new_size,
}
inline void* do_realloc(void* old_ptr, size_t new_size) {
- return do_realloc_with_callback(old_ptr, new_size, &InvalidRealloc);
+ return do_realloc_with_callback(old_ptr, new_size,
+ &InvalidFree, &InvalidGetSizeForRealloc);
}
// For use by exported routines below that want specific alignments
@@ -893,7 +896,7 @@ static SpinLock set_new_handler_lock(SpinLock::LINKER_INITIALIZED);
inline void* cpp_alloc(size_t size, bool nothrow) {
for (;;) {
void* p = do_malloc(size);
-#ifdef PREANSINEW
+#if defined(PREANSINEW) || (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
return p;
#else
if (p == NULL) { // allocation failed
@@ -939,7 +942,7 @@ size_t TCMallocImplementation::GetAllocatedSize(void* ptr) {
// Exported routines
//-------------------------------------------------------------------
-#ifndef _WIN32 // windows doesn't allow overriding; use the do_* fns instead
+#ifndef WIN32_DO_PATCHING
// CAVEAT: The code structure below ensures that MallocHook methods are always
// called from the stack frame of the invoked allocation function.
@@ -1198,4 +1201,4 @@ static void *MemalignOverride(size_t align, size_t size, const void *caller)
}
void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride;
-#endif // #ifndef _WIN32
+#endif // #ifndef WIN32_DO_PATCHING