summaryrefslogtreecommitdiff
path: root/src/tcmalloc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/tcmalloc.cc')
-rw-r--r--src/tcmalloc.cc98
1 files changed, 53 insertions, 45 deletions
diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc
index d34d477..80bb6d9 100644
--- a/src/tcmalloc.cc
+++ b/src/tcmalloc.cc
@@ -62,7 +62,7 @@
// * allocation of a reasonably complicated struct
// goes from about 1100 ns to about 300 ns.
-#include "google/perftools/config.h"
+#include "config.h"
#include <new>
#include <stdio.h>
#include <stddef.h>
@@ -80,12 +80,13 @@
#include <errno.h>
#include <stdarg.h>
#include "google/malloc_hook.h"
-#include "google/malloc_interface.h"
+#include "google/malloc_extension.h"
#include "google/stacktrace.h"
#include "internal_logging.h"
#include "internal_spinlock.h"
#include "pagemap.h"
#include "system-alloc.h"
+#include "maybe_threads.h"
#if defined HAVE_INTTYPES_H
#define __STDC_FORMAT_MACROS
@@ -1240,11 +1241,11 @@ void TCMalloc_ThreadCache::FetchFromCentralCache(size_t cl) {
SpinLockHolder h(&src->lock_);
for (int i = 0; i < kNumObjectsToMove; i++) {
void* object = src->Remove();
- if (object == NULL) {
+ if (object == NULL) {
if (i == 0) {
src->Populate(); // Temporarily releases src->lock_
object = src->Remove();
- }
+ }
if (object == NULL) {
break;
}
@@ -1297,7 +1298,7 @@ inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetCache() {
if (!tsd_inited) {
InitModule();
} else {
- ptr = pthread_getspecific(heap_key);
+ ptr = perftools_pthread_getspecific(heap_key);
}
if (ptr == NULL) ptr = CreateCacheIfNecessary();
return reinterpret_cast<TCMalloc_ThreadCache*>(ptr);
@@ -1308,7 +1309,8 @@ inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetCache() {
// already cleaned up the cache for this thread.
inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetCacheIfPresent() {
if (!tsd_inited) return NULL;
- return reinterpret_cast<TCMalloc_ThreadCache*>(pthread_getspecific(heap_key));
+ return reinterpret_cast<TCMalloc_ThreadCache*>
+ (perftools_pthread_getspecific(heap_key));
}
void TCMalloc_ThreadCache::PickNextSample() {
@@ -1344,11 +1346,9 @@ void TCMalloc_ThreadCache::InitModule() {
}
}
-
-
void TCMalloc_ThreadCache::InitTSD() {
ASSERT(!tsd_inited);
- pthread_key_create(&heap_key, DeleteCache);
+ perftools_pthread_key_create(&heap_key, DeleteCache);
tsd_inited = true;
// We may have used a fake pthread_t for the main thread. Fix it.
@@ -1405,7 +1405,7 @@ void* TCMalloc_ThreadCache::CreateCacheIfNecessary() {
// linked list of heaps.
if (!heap->setspecific_ && tsd_inited) {
heap->setspecific_ = true;
- pthread_setspecific(heap_key, heap);
+ perftools_pthread_setspecific(heap_key, heap);
}
return heap;
}
@@ -1592,7 +1592,7 @@ static void** DumpStackTraces() {
}
// TCMalloc's support for extra malloc interfaces
-class TCMallocImplementation : public MallocInterface {
+class TCMallocImplementation : public MallocExtension {
public:
virtual void GetStats(char* buffer, int buffer_length) {
ASSERT(buffer_length > 0);
@@ -1668,40 +1668,6 @@ class TCMallocImplementation : public MallocInterface {
};
-
-// The constructor allocates an object to ensure that initialization
-// runs before main(), and therefore we do not have a chance to become
-// multi-threaded before initialization. We also create the TSD key
-// here. Presumably by the time this constructor runs, glibc is in
-// good enough shape to handle pthread_key_create().
-//
-// The destructor prints stats when the program exits.
-
-class TCMallocGuard {
- public:
- TCMallocGuard() {
- char *envval;
- if ((envval = getenv("TCMALLOC_DEBUG"))) {
- TCMallocDebug::level = atoi(envval);
- MESSAGE("Set tcmalloc debugging level to %d\n", TCMallocDebug::level);
- }
- free(malloc(1));
- TCMalloc_ThreadCache::InitTSD();
- free(malloc(1));
- MallocInterface::Register(new TCMallocImplementation);
- }
-
- ~TCMallocGuard() {
- const char* env = getenv("MALLOCSTATS");
- if (env != NULL) {
- int level = atoi(env);
- if (level < 1) level = 1;
- PrintStats(level);
- }
- }
-};
-static TCMallocGuard module_enter_exit_hook;
-
//-------------------------------------------------------------------
// Helpers for the exported routines below
//-------------------------------------------------------------------
@@ -1857,6 +1823,48 @@ static void* do_memalign(size_t align, size_t size) {
return reinterpret_cast<void*>(span->start << kPageShift);
}
+
+
+// The constructor allocates an object to ensure that initialization
+// runs before main(), and therefore we do not have a chance to become
+// multi-threaded before initialization. We also create the TSD key
+// here. Presumably by the time this constructor runs, glibc is in
+// good enough shape to handle pthread_key_create().
+//
+// The constructor also takes the opportunity to tell STL to use
+// tcmalloc. We want to do this early, before construct time, so
+// all user STL allocations go through tcmalloc (which works really
+// well for STL).
+//
+// The destructor prints stats when the program exits.
+
+class TCMallocGuard {
+ public:
+ TCMallocGuard() {
+ char *envval;
+ if ((envval = getenv("TCMALLOC_DEBUG"))) {
+ TCMallocDebug::level = atoi(envval);
+ MESSAGE("Set tcmalloc debugging level to %d\n", TCMallocDebug::level);
+ }
+ do_free(do_malloc(1));
+ TCMalloc_ThreadCache::InitTSD();
+ do_free(do_malloc(1));
+ MallocExtension::Register(new TCMallocImplementation);
+ }
+
+ ~TCMallocGuard() {
+ const char* env = getenv("MALLOCSTATS");
+ if (env != NULL) {
+ int level = atoi(env);
+ if (level < 1) level = 1;
+ PrintStats(level);
+ }
+ }
+};
+
+static TCMallocGuard module_enter_exit_hook;
+
+
//-------------------------------------------------------------------
// Exported routines
//-------------------------------------------------------------------