| Index: third_party/tcmalloc/chromium/src/memfs_malloc.cc
|
| ===================================================================
|
| --- third_party/tcmalloc/chromium/src/memfs_malloc.cc (revision 87277)
|
| +++ third_party/tcmalloc/chromium/src/memfs_malloc.cc (working copy)
|
| @@ -38,16 +38,23 @@
|
| #ifdef __linux
|
|
|
| #include <config.h>
|
| -#include <errno.h>
|
| -#include <fcntl.h>
|
| -#include <unistd.h>
|
| -#include <inttypes.h>
|
| -#include <sys/mman.h>
|
| -#include <sys/param.h>
|
| -#include <sys/types.h>
|
| -#include <sys/vfs.h> // for statfs
|
| +#include <errno.h> // for errno, EINVAL
|
| +#include <inttypes.h> // for PRId64
|
| +#include <limits.h> // for PATH_MAX
|
| +#include <stddef.h> // for size_t, NULL
|
| +#ifdef HAVE_STDINT_H
|
| +#include <stdint.h> // for int64_t, uintptr_t
|
| +#endif
|
| +#include <stdio.h> // for snprintf
|
| +#include <stdlib.h> // for mkstemp
|
| +#include <string.h> // for strerror
|
| +#include <sys/mman.h> // for mmap, MAP_FAILED, etc
|
| +#include <sys/statfs.h> // for fstatfs, statfs
|
| +#include <unistd.h> // for ftruncate, off_t, unlink
|
| +#include <new> // for operator new
|
| #include <string>
|
|
|
| +#include <google/malloc_extension.h>
|
| #include "base/basictypes.h"
|
| #include "base/googleinit.h"
|
| #include "base/sysinfo.h"
|
| @@ -71,55 +78,75 @@
|
| DEFINE_bool(memfs_malloc_ignore_mmap_fail,
|
| EnvToBool("TCMALLOC_MEMFS_IGNORE_MMAP_FAIL", false),
|
| "Ignore failures from mmap");
|
| +DEFINE_bool(memfs_malloc_map_private,
|
| + EnvToBool("TCMALLOC_MEMFS_MAP_PRIVATE", false),
|
| + "Use MAP_PRIVATE with mmap");
|
|
|
| // Hugetlbfs based allocator for tcmalloc
|
| class HugetlbSysAllocator: public SysAllocator {
|
| public:
|
| - HugetlbSysAllocator(int fd, int page_size)
|
| - : big_page_size_(page_size),
|
| - hugetlb_fd_(fd),
|
| - hugetlb_base_(0) {
|
| + explicit HugetlbSysAllocator(SysAllocator* fallback)
|
| + : failed_(true), // Unusable until FlagsInitialized() is called
|
| + big_page_size_(0),
|
| + hugetlb_fd_(-1),
|
| + hugetlb_base_(0),
|
| + fallback_(fallback) {
|
| }
|
|
|
| void* Alloc(size_t size, size_t *actual_size, size_t alignment);
|
|
|
| - void DumpStats(TCMalloc_Printer* printer);
|
| + void FlagsInitialized();
|
|
|
| + bool failed_; // Whether failed to allocate memory.
|
| private:
|
| + void* AllocInternal(size_t size, size_t *actual_size, size_t alignment);
|
| +
|
| int64 big_page_size_;
|
| - int hugetlb_fd_; // file descriptor for hugetlb
|
| + int hugetlb_fd_; // file descriptor for hugetlb
|
| off_t hugetlb_base_;
|
| +
|
| + SysAllocator* fallback_; // Default system allocator to fall back to.
|
| };
|
| +static char hugetlb_space[sizeof(HugetlbSysAllocator)];
|
|
|
| -void HugetlbSysAllocator::DumpStats(TCMalloc_Printer* printer) {
|
| - printer->printf("HugetlbSysAllocator: failed_=%d allocated=%"PRId64"\n",
|
| - failed_, static_cast<int64_t>(hugetlb_base_));
|
| -}
|
| -
|
| // No locking needed here since we assume that tcmalloc calls
|
| // us with an internal lock held (see tcmalloc/system-alloc.cc).
|
| void* HugetlbSysAllocator::Alloc(size_t size, size_t *actual_size,
|
| size_t alignment) {
|
| -
|
| - // don't go any further if we haven't opened the backing file
|
| - if (hugetlb_fd_ == -1) {
|
| - return NULL;
|
| + if (failed_) {
|
| + return fallback_->Alloc(size, actual_size, alignment);
|
| }
|
|
|
| // We don't respond to allocation requests smaller than big_page_size_ unless
|
| - // the caller is willing to take more than they asked for.
|
| + // the caller is ok to take more than they asked for. Used by MetaDataAlloc.
|
| if (actual_size == NULL && size < big_page_size_) {
|
| - return NULL;
|
| + return fallback_->Alloc(size, actual_size, alignment);
|
| }
|
|
|
| // Enforce huge page alignment. Be careful to deal with overflow.
|
| - if (alignment < big_page_size_) alignment = big_page_size_;
|
| - size_t aligned_size = ((size + alignment - 1) / alignment) * alignment;
|
| + size_t new_alignment = alignment;
|
| + if (new_alignment < big_page_size_) new_alignment = big_page_size_;
|
| + size_t aligned_size = ((size + new_alignment - 1) /
|
| + new_alignment) * new_alignment;
|
| if (aligned_size < size) {
|
| - return NULL;
|
| + return fallback_->Alloc(size, actual_size, alignment);
|
| }
|
| - size = aligned_size;
|
|
|
| + void* result = AllocInternal(aligned_size, actual_size, new_alignment);
|
| + if (result != NULL) {
|
| + return result;
|
| + }
|
| + TCMalloc_MESSAGE(__FILE__, __LINE__,
|
| + "HugetlbSysAllocator: failed_=%d allocated=%"PRId64"\n",
|
| + failed_, static_cast<int64_t>(hugetlb_base_));
|
| + if (FLAGS_memfs_malloc_abort_on_fail) {
|
| + CRASH("memfs_malloc_abort_on_fail is set\n");
|
| + }
|
| + return fallback_->Alloc(size, actual_size, alignment);
|
| +}
|
| +
|
| +void* HugetlbSysAllocator::AllocInternal(size_t size, size_t* actual_size,
|
| + size_t alignment) {
|
| // Ask for extra memory if alignment > pagesize
|
| size_t extra = 0;
|
| if (alignment > big_page_size_) {
|
| @@ -139,9 +166,6 @@
|
| " too large while %"PRId64" bytes remain\n",
|
| size, static_cast<int64_t>(limit - hugetlb_base_));
|
| }
|
| - if (FLAGS_memfs_malloc_abort_on_fail) {
|
| - CRASH("memfs_malloc_abort_on_fail is set\n");
|
| - }
|
| return NULL;
|
| }
|
|
|
| @@ -152,9 +176,6 @@
|
| TCMalloc_MESSAGE(__FILE__, __LINE__, "ftruncate failed: %s\n",
|
| strerror(errno));
|
| failed_ = true;
|
| - if (FLAGS_memfs_malloc_abort_on_fail) {
|
| - CRASH("memfs_malloc_abort_on_fail is set\n");
|
| - }
|
| return NULL;
|
| }
|
|
|
| @@ -162,16 +183,15 @@
|
| // size + alignment < (1<<NBITS).
|
| // and extra <= alignment
|
| // therefore size + extra < (1<<NBITS)
|
| - void *result = mmap(0, size + extra, PROT_WRITE|PROT_READ,
|
| - MAP_SHARED, hugetlb_fd_, hugetlb_base_);
|
| + void *result;
|
| + result = mmap(0, size + extra, PROT_WRITE|PROT_READ,
|
| + FLAGS_memfs_malloc_map_private ? MAP_PRIVATE : MAP_SHARED,
|
| + hugetlb_fd_, hugetlb_base_);
|
| if (result == reinterpret_cast<void*>(MAP_FAILED)) {
|
| if (!FLAGS_memfs_malloc_ignore_mmap_fail) {
|
| TCMalloc_MESSAGE(__FILE__, __LINE__, "mmap of size %"PRIuS" failed: %s\n",
|
| size + extra, strerror(errno));
|
| failed_ = true;
|
| - if (FLAGS_memfs_malloc_abort_on_fail) {
|
| - CRASH("memfs_malloc_abort_on_fail is set\n");
|
| - }
|
| }
|
| return NULL;
|
| }
|
| @@ -192,7 +212,7 @@
|
| return reinterpret_cast<void*>(ptr);
|
| }
|
|
|
| -static void InitSystemAllocator() {
|
| +void HugetlbSysAllocator::FlagsInitialized() {
|
| if (FLAGS_memfs_malloc_path.length()) {
|
| char path[PATH_MAX];
|
| int rc = snprintf(path, sizeof(path), "%s.XXXXXX",
|
| @@ -223,12 +243,18 @@
|
| }
|
| int64 page_size = sfs.f_bsize;
|
|
|
| - SysAllocator *alloc = new HugetlbSysAllocator(hugetlb_fd, page_size);
|
| - // Register ourselves with tcmalloc
|
| - RegisterSystemAllocator(alloc, 0);
|
| + hugetlb_fd_ = hugetlb_fd;
|
| + big_page_size_ = page_size;
|
| + failed_ = false;
|
| }
|
| }
|
|
|
| +static void InitSystemAllocator() {
|
| + SysAllocator *alloc = MallocExtension::instance()->GetSystemAllocator();
|
| + HugetlbSysAllocator *hugetlb = new (hugetlb_space) HugetlbSysAllocator(alloc);
|
| + MallocExtension::instance()->SetSystemAllocator(hugetlb);
|
| +}
|
| +
|
| REGISTER_MODULE_INITIALIZER(memfs_malloc, { InitSystemAllocator(); });
|
|
|
| #endif /* ifdef __linux */
|
|
|