| Index: third_party/tcmalloc/chromium/src/memfs_malloc.cc | 
| =================================================================== | 
| --- third_party/tcmalloc/chromium/src/memfs_malloc.cc	(revision 88335) | 
| +++ 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 */ | 
|  |