summaryrefslogtreecommitdiff
path: root/src/system-alloc.cc
diff options
context:
space:
mode:
authorcsilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50>2007-07-18 18:30:50 +0000
committercsilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50>2007-07-18 18:30:50 +0000
commitc437e1fcdd1e6ff3f032928d460cbfc115e2324f (patch)
tree482360b82db4bc64880e187b9b5af82e840df47c /src/system-alloc.cc
parent6878379d5bab87c787cdd3487b5620a9c8adf376 (diff)
downloadgperftools-c437e1fcdd1e6ff3f032928d460cbfc115e2324f.tar.gz
Tue Jul 17 22:26:27 2007 Google Inc. <opensource@google.com>
* google-perftools: version 0.92 release * PERFORMANCE: use a packed cache to speed up tcmalloc * PORTING: preliminary windows support! (see README.windows) * PORTING: better support for solaris, OS X, FreeBSD (see INSTALL) * Envvar support for running the heap-checker under gdb * Add weak declarations to maybe_threads to fix no-pthreads compile bugs * Some 64bit fixes, especially with pprof * Better heap-checker support for some low-level allocations * Fix bug where heap-profiles would sometimes get truncated * New documentation about how to handle common heap leak situations * Use computed includes for hash_map/set: easier config * Added all used .m4 templates to the distribution git-svn-id: http://gperftools.googlecode.com/svn/trunk@36 6b5cf1ce-ec42-a296-1ba9-69fdba395a50
Diffstat (limited to 'src/system-alloc.cc')
-rw-r--r--src/system-alloc.cc130
1 files changed, 83 insertions, 47 deletions
diff --git a/src/system-alloc.cc b/src/system-alloc.cc
index 5e69817..60fdf70 100644
--- a/src/system-alloc.cc
+++ b/src/system-alloc.cc
@@ -38,12 +38,17 @@
#else
#include <sys/types.h>
#endif
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
+#endif
+#include <fcntl.h> // for open()
+#ifdef HAVE_MMAP
#include <sys/mman.h>
+#endif
+#include <errno.h>
#include "system-alloc.h"
#include "internal_logging.h"
+#include "base/logging.h"
#include "base/commandlineflags.h"
#include "base/spinlock.h"
@@ -78,14 +83,6 @@ static size_t pagesize = 0;
// For 2.2 kernels, it looks like the sbrk address space (500MBish) and
// the mmap address space (1300MBish) are disjoint, so we need both allocators
// to get as much virtual memory as possible.
-static bool use_devmem = true;
-static bool use_sbrk = true;
-static bool use_mmap = true;
-
-// Flags to keep us from retrying allocators that failed.
-static bool devmem_failure = false;
-static bool sbrk_failure = false;
-static bool mmap_failure = false;
DEFINE_int32(malloc_devmem_start, 0,
"Physical memory starting location in MB for /dev/mem allocation."
@@ -94,9 +91,48 @@ DEFINE_int32(malloc_devmem_limit, 0,
"Physical memory limit location in MB for /dev/mem allocation."
" Setting this to 0 means no limit.");
-#ifdef HAVE_SBRK
+// static allocators
+class SbrkSysAllocator : public SysAllocator {
+public:
+ SbrkSysAllocator() : SysAllocator() {
+ }
+ void* Alloc(size_t size, size_t alignment);
+};
+static char sbrk_space[sizeof(SbrkSysAllocator)];
+
+class MmapSysAllocator : public SysAllocator {
+public:
+ MmapSysAllocator() : SysAllocator() {
+ }
+ void* Alloc(size_t size, size_t alignment);
+};
+static char mmap_space[sizeof(MmapSysAllocator)];
+
+class DevMemSysAllocator : public SysAllocator {
+public:
+ DevMemSysAllocator() : SysAllocator() {
+ }
+ void* Alloc(size_t size, size_t alignment);
+};
+static char devmem_space[sizeof(DevMemSysAllocator)];
+
+static const int kStaticAllocators = 3;
+// kMaxDynamicAllocators + kStaticAllocators;
+static const int kMaxAllocators = 4;
+SysAllocator *allocators[kMaxAllocators];
+
+bool RegisterSystemAllocator(SysAllocator *a, int priority) {
+ SpinLockHolder lock_holder(&spinlock);
+
+ // No two allocators should have a priority conflict, since the order
+ // is determined at compile time.
+ CHECK(allocators[priority] == NULL);
+ allocators[priority] = a;
+ return true;
+}
+
-static void* TrySbrk(size_t size, size_t alignment) {
+void* SbrkSysAllocator::Alloc(size_t size, size_t alignment) {
// sbrk will release memory if passed a negative number, so we do
// a strict check here
if (static_cast<ptrdiff_t>(size + alignment) < 0) return NULL;
@@ -104,7 +140,7 @@ static void* TrySbrk(size_t size, size_t alignment) {
size = ((size + alignment - 1) / alignment) * alignment;
void* result = sbrk(size);
if (result == reinterpret_cast<void*>(-1)) {
- sbrk_failure = true;
+ failed_ = true;
return NULL;
}
@@ -124,7 +160,7 @@ static void* TrySbrk(size_t size, size_t alignment) {
// that we can find an aligned region within it.
result = sbrk(size + alignment - 1);
if (result == reinterpret_cast<void*>(-1)) {
- sbrk_failure = true;
+ failed_ = true;
return NULL;
}
ptr = reinterpret_cast<uintptr_t>(result);
@@ -134,11 +170,7 @@ static void* TrySbrk(size_t size, size_t alignment) {
return reinterpret_cast<void*>(ptr);
}
-#endif /* HAVE_SBRK */
-
-#ifdef HAVE_MMAP
-
-static void* TryMmap(size_t size, size_t alignment) {
+void* MmapSysAllocator::Alloc(size_t size, size_t alignment) {
// Enforce page alignment
if (pagesize == 0) pagesize = getpagesize();
if (alignment < pagesize) alignment = pagesize;
@@ -159,7 +191,7 @@ static void* TryMmap(size_t size, size_t alignment) {
MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0);
if (result == reinterpret_cast<void*>(MAP_FAILED)) {
- mmap_failure = true;
+ failed_ = true;
return NULL;
}
@@ -182,9 +214,7 @@ static void* TryMmap(size_t size, size_t alignment) {
return reinterpret_cast<void*>(ptr);
}
-#endif /* HAVE_MMAP */
-
-static void* TryDevMem(size_t size, size_t alignment) {
+void* DevMemSysAllocator::Alloc(size_t size, size_t alignment) {
static bool initialized = false;
static off_t physmem_base; // next physical memory address to allocate
static off_t physmem_limit; // maximum physical address allowed
@@ -203,7 +233,7 @@ static void* TryDevMem(size_t size, size_t alignment) {
if (!initialized) {
physmem_fd = open("/dev/mem", O_RDWR);
if (physmem_fd < 0) {
- devmem_failure = true;
+ failed_ = true;
return NULL;
}
physmem_base = FLAGS_malloc_devmem_start*1024LL*1024LL;
@@ -225,7 +255,7 @@ static void* TryDevMem(size_t size, size_t alignment) {
// check to see if we have any memory left
if (physmem_limit != 0 &&
((size + extra) > (physmem_limit - physmem_base))) {
- devmem_failure = true;
+ failed_ = true;
return NULL;
}
@@ -236,7 +266,7 @@ static void* TryDevMem(size_t size, size_t alignment) {
void *result = mmap(0, size + extra, PROT_WRITE|PROT_READ,
MAP_SHARED, physmem_fd, physmem_base);
if (result == reinterpret_cast<void*>(MAP_FAILED)) {
- devmem_failure = true;
+ failed_ = true;
return NULL;
}
uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
@@ -261,41 +291,47 @@ static void* TryDevMem(size_t size, size_t alignment) {
return reinterpret_cast<void*>(ptr);
}
+static bool system_alloc_inited = false;
+void InitSystemAllocators(void) {
+ // This determines the order in which system allocators are called
+ int i = kMaxDynamicAllocators;
+ allocators[i++] = new (devmem_space) DevMemSysAllocator();
+ allocators[i++] = new (sbrk_space) SbrkSysAllocator();
+ allocators[i++] = new (mmap_space) MmapSysAllocator();
+}
+
void* TCMalloc_SystemAlloc(size_t size, size_t alignment) {
// Discard requests that overflow
if (size + alignment < size) return NULL;
SpinLockHolder lock_holder(&spinlock);
+ if (!system_alloc_inited) {
+ InitSystemAllocators();
+ system_alloc_inited = true;
+ }
+
// Enforce minimum alignment
if (alignment < sizeof(MemoryAligner)) alignment = sizeof(MemoryAligner);
// Try twice, once avoiding allocators that failed before, and once
// more trying all allocators even if they failed before.
for (int i = 0; i < 2; i++) {
- if (use_devmem && !devmem_failure) {
- void* result = TryDevMem(size, alignment);
- if (result != NULL) return result;
+ for (int j = 0; j < kMaxAllocators; j++) {
+ SysAllocator *a = allocators[j];
+ if (a == NULL) continue;
+ if (a->usable_ && !a->failed_) {
+ void* result = a->Alloc(size, alignment);
+ if (result != NULL) return result;
+ }
}
-
-#ifdef HAVE_SBRK
- if (use_sbrk && !sbrk_failure) {
- void* result = TrySbrk(size, alignment);
- if (result != NULL) return result;
- }
-#endif
-#ifdef HAVE_MMAP
- if (use_mmap && !mmap_failure) {
- void* result = TryMmap(size, alignment);
- if (result != NULL) return result;
+ // nothing worked - reset failed_ flags and try again
+ for (int j = 0; j < kMaxAllocators; j++) {
+ SysAllocator *a = allocators[j];
+ if (a == NULL) continue;
+ a->failed_ = false;
}
-#endif
-
- // nothing worked - reset failure flags and try again
- devmem_failure = false;
- sbrk_failure = false;
- mmap_failure = false;
}
return NULL;
}
@@ -327,7 +363,7 @@ void TCMalloc_SystemRelease(void* start, size_t length) {
if (new_end > new_start) {
// Note -- ignoring most return codes, because if this fails it
// doesn't matter...
- while (madvise(reinterpret_cast<void*>(new_start), new_end - new_start,
+ while (madvise(reinterpret_cast<char*>(new_start), new_end - new_start,
MADV_DONTNEED) == -1 &&
errno == EAGAIN) {
// NOP