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() {} |