| Index: base/metrics/persistent_memory_allocator.cc
|
| diff --git a/base/metrics/persistent_memory_allocator.cc b/base/metrics/persistent_memory_allocator.cc
|
| index dfa408f44d2be244e859727515c16d402c39ad78..fd8a73d0ad2921178fdca61e4becbd21e281c9d6 100644
|
| --- a/base/metrics/persistent_memory_allocator.cc
|
| +++ b/base/metrics/persistent_memory_allocator.cc
|
| @@ -17,6 +17,7 @@
|
| #include "base/logging.h"
|
| #include "base/memory/shared_memory.h"
|
| #include "base/metrics/histogram_macros.h"
|
| +#include "base/metrics/sparse_histogram.h"
|
|
|
| namespace {
|
|
|
| @@ -247,14 +248,27 @@ bool PersistentMemoryAllocator::IsMemoryAcceptable(const void* base,
|
| (page_size == 0 || size % page_size == 0 || readonly));
|
| }
|
|
|
| -PersistentMemoryAllocator::PersistentMemoryAllocator(
|
| - void* base,
|
| - size_t size,
|
| - size_t page_size,
|
| - uint64_t id,
|
| - base::StringPiece name,
|
| - bool readonly)
|
| - : mem_base_(static_cast<char*>(base)),
|
| +PersistentMemoryAllocator::PersistentMemoryAllocator(void* base,
|
| + size_t size,
|
| + size_t page_size,
|
| + uint64_t id,
|
| + base::StringPiece name,
|
| + bool readonly)
|
| + : PersistentMemoryAllocator(Memory(base, MEM_EXTERNAL),
|
| + size,
|
| + page_size,
|
| + id,
|
| + name,
|
| + readonly) {}
|
| +
|
| +PersistentMemoryAllocator::PersistentMemoryAllocator(Memory memory,
|
| + size_t size,
|
| + size_t page_size,
|
| + uint64_t id,
|
| + base::StringPiece name,
|
| + bool readonly)
|
| + : mem_base_(static_cast<char*>(memory.base)),
|
| + mem_type_(memory.type),
|
| mem_size_(static_cast<uint32_t>(size)),
|
| mem_page_(static_cast<uint32_t>((page_size ? page_size : size))),
|
| readonly_(readonly),
|
| @@ -269,7 +283,7 @@ PersistentMemoryAllocator::PersistentMemoryAllocator(
|
| "\"queue\" is not aligned properly; must be at end of struct");
|
|
|
| // Ensure that memory segment is of acceptable size.
|
| - CHECK(IsMemoryAcceptable(base, size, page_size, readonly));
|
| + CHECK(IsMemoryAcceptable(memory.base, size, page_size, readonly));
|
|
|
| // These atomics operate inter-process and so must be lock-free. The local
|
| // casts are to make sure it can be evaluated at compile time to a constant.
|
| @@ -355,7 +369,7 @@ PersistentMemoryAllocator::PersistentMemoryAllocator(
|
| *const_cast<uint32_t*>(&mem_page_) = shared_meta()->page_size;
|
|
|
| // Ensure that settings are still valid after the above adjustments.
|
| - if (!IsMemoryAcceptable(base, mem_size_, mem_page_, readonly))
|
| + if (!IsMemoryAcceptable(memory.base, mem_size_, mem_page_, readonly))
|
| SetCorrupt();
|
| }
|
| }
|
| @@ -739,37 +753,60 @@ LocalPersistentMemoryAllocator::LocalPersistentMemoryAllocator(
|
| size, 0, id, name, false) {}
|
|
|
| LocalPersistentMemoryAllocator::~LocalPersistentMemoryAllocator() {
|
| - DeallocateLocalMemory(const_cast<char*>(mem_base_), mem_size_);
|
| + DeallocateLocalMemory(const_cast<char*>(mem_base_), mem_size_, mem_type_);
|
| }
|
|
|
| // static
|
| -void* LocalPersistentMemoryAllocator::AllocateLocalMemory(size_t size) {
|
| +PersistentMemoryAllocator::Memory
|
| +LocalPersistentMemoryAllocator::AllocateLocalMemory(size_t size) {
|
| + void* address;
|
| +
|
| #if defined(OS_WIN)
|
| - void* address =
|
| + address =
|
| ::VirtualAlloc(nullptr, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
| - DPCHECK(address);
|
| - return address;
|
| + if (address)
|
| + return Memory(address, MEM_VIRTUAL);
|
| + UMA_HISTOGRAM_SPARSE_SLOWLY("UMA.LocalPersistentMemoryAllocator.Failures.Win",
|
| + ::GetLastError());
|
| #elif defined(OS_POSIX)
|
| // MAP_ANON is deprecated on Linux but MAP_ANONYMOUS is not universal on Mac.
|
| // MAP_SHARED is not available on Linux <2.4 but required on Mac.
|
| - void* address = ::mmap(nullptr, size, PROT_READ | PROT_WRITE,
|
| - MAP_ANON | MAP_SHARED, -1, 0);
|
| - DPCHECK(MAP_FAILED != address);
|
| - return address;
|
| + address = ::mmap(nullptr, size, PROT_READ | PROT_WRITE,
|
| + MAP_ANON | MAP_SHARED, -1, 0);
|
| + if (address != MAP_FAILED)
|
| + return Memory(address, MEM_VIRTUAL);
|
| + UMA_HISTOGRAM_SPARSE_SLOWLY(
|
| + "UMA.LocalPersistentMemoryAllocator.Failures.Posix", errno);
|
| #else
|
| #error This architecture is not (yet) supported.
|
| #endif
|
| +
|
| + // As a last resort, just allocate the memory from the heap. This will
|
| + // achieve the same basic result but the acquired memory has to be
|
| + // explicitly zeroed and thus realized immediately (i.e. all pages are
|
| + // added to the process now istead of only when first accessed).
|
| + address = malloc(size);
|
| + DPCHECK(address);
|
| + memset(address, 0, size);
|
| + return Memory(address, MEM_MALLOC);
|
| }
|
|
|
| // static
|
| void LocalPersistentMemoryAllocator::DeallocateLocalMemory(void* memory,
|
| - size_t size) {
|
| + size_t size,
|
| + MemoryType type) {
|
| + if (type == MEM_MALLOC) {
|
| + free(memory);
|
| + return;
|
| + }
|
| +
|
| + DCHECK_EQ(MEM_VIRTUAL, type);
|
| #if defined(OS_WIN)
|
| BOOL success = ::VirtualFree(memory, 0, MEM_DECOMMIT);
|
| - DPCHECK(success);
|
| + DCHECK(success);
|
| #elif defined(OS_POSIX)
|
| int result = ::munmap(memory, size);
|
| - DPCHECK(0 == result);
|
| + DCHECK_EQ(0, result);
|
| #else
|
| #error This architecture is not (yet) supported.
|
| #endif
|
| @@ -783,12 +820,13 @@ SharedPersistentMemoryAllocator::SharedPersistentMemoryAllocator(
|
| uint64_t id,
|
| base::StringPiece name,
|
| bool read_only)
|
| - : PersistentMemoryAllocator(static_cast<uint8_t*>(memory->memory()),
|
| - memory->mapped_size(),
|
| - 0,
|
| - id,
|
| - name,
|
| - read_only),
|
| + : PersistentMemoryAllocator(
|
| + Memory(static_cast<uint8_t*>(memory->memory()), MEM_SHARED),
|
| + memory->mapped_size(),
|
| + 0,
|
| + id,
|
| + name,
|
| + read_only),
|
| shared_memory_(std::move(memory)) {}
|
|
|
| SharedPersistentMemoryAllocator::~SharedPersistentMemoryAllocator() {}
|
| @@ -809,12 +847,13 @@ FilePersistentMemoryAllocator::FilePersistentMemoryAllocator(
|
| uint64_t id,
|
| base::StringPiece name,
|
| bool read_only)
|
| - : PersistentMemoryAllocator(const_cast<uint8_t*>(file->data()),
|
| - max_size != 0 ? max_size : file->length(),
|
| - 0,
|
| - id,
|
| - name,
|
| - read_only),
|
| + : PersistentMemoryAllocator(
|
| + Memory(const_cast<uint8_t*>(file->data()), MEM_FILE),
|
| + max_size != 0 ? max_size : file->length(),
|
| + 0,
|
| + id,
|
| + name,
|
| + read_only),
|
| mapped_file_(std::move(file)) {}
|
|
|
| FilePersistentMemoryAllocator::~FilePersistentMemoryAllocator() {}
|
|
|