summaryrefslogtreecommitdiffstats
path: root/base/memory/discardable_memory_allocator_android.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/memory/discardable_memory_allocator_android.cc')
-rw-r--r--base/memory/discardable_memory_allocator_android.cc34
1 files changed, 23 insertions, 11 deletions
diff --git a/base/memory/discardable_memory_allocator_android.cc b/base/memory/discardable_memory_allocator_android.cc
index 5e10817..a0a3aff 100644
--- a/base/memory/discardable_memory_allocator_android.cc
+++ b/base/memory/discardable_memory_allocator_android.cc
@@ -44,6 +44,8 @@ namespace {
// issues.
const size_t kMaxChunkFragmentationBytes = 4096 - 1;
+const size_t kMinAshmemRegionSize = 32 * 1024 * 1024;
+
} // namespace
namespace internal {
@@ -104,6 +106,7 @@ class DiscardableMemoryAllocator::AshmemRegion {
size_t size,
const std::string& name,
DiscardableMemoryAllocator* allocator) {
+ DCHECK_EQ(size, internal::AlignToNextPage(size));
int fd;
void* base;
if (!internal::CreateAshmemRegion(name.c_str(), size, &fd, &base))
@@ -364,8 +367,12 @@ DiscardableMemoryAllocator::DiscardableAshmemChunk::~DiscardableAshmemChunk() {
ashmem_region_->OnChunkDeletion(address_, size_);
}
-DiscardableMemoryAllocator::DiscardableMemoryAllocator(const std::string& name)
- : name_(name) {
+DiscardableMemoryAllocator::DiscardableMemoryAllocator(
+ const std::string& name,
+ size_t ashmem_region_size)
+ : name_(name),
+ ashmem_region_size_(std::max(kMinAshmemRegionSize, ashmem_region_size)) {
+ DCHECK_GE(ashmem_region_size_, kMinAshmemRegionSize);
}
DiscardableMemoryAllocator::~DiscardableMemoryAllocator() {
@@ -389,16 +396,21 @@ scoped_ptr<DiscardableMemory> DiscardableMemoryAllocator::Allocate(
if (memory)
return memory.Pass();
}
- scoped_ptr<AshmemRegion> new_region(
- AshmemRegion::Create(
- std::max(static_cast<size_t>(kMinAshmemRegionSize), aligned_size),
- name_.c_str(), this));
- if (!new_region) {
- // TODO(pliard): consider adding an histogram to see how often this happens.
- return scoped_ptr<DiscardableMemory>();
+ // The creation of the (large) ashmem region might fail if the address space
+ // is too fragmented. In case creation fails the allocator retries by
+ // repetitively dividing the size by 2.
+ const size_t min_region_size = std::max(kMinAshmemRegionSize, aligned_size);
+ for (size_t region_size = std::max(ashmem_region_size_, aligned_size);
+ region_size >= min_region_size; region_size /= 2) {
+ scoped_ptr<AshmemRegion> new_region(
+ AshmemRegion::Create(region_size, name_.c_str(), this));
+ if (!new_region)
+ continue;
+ ashmem_regions_.push_back(new_region.release());
+ return ashmem_regions_.back()->Allocate_Locked(size, aligned_size);
}
- ashmem_regions_.push_back(new_region.release());
- return ashmem_regions_.back()->Allocate_Locked(size, aligned_size);
+ // TODO(pliard): consider adding an histogram to see how often this happens.
+ return scoped_ptr<DiscardableMemory>();
}
void DiscardableMemoryAllocator::DeleteAshmemRegion_Locked(