diff options
Diffstat (limited to 'base/memory/discardable_memory_allocator_android.cc')
| -rw-r--r-- | base/memory/discardable_memory_allocator_android.cc | 34 |
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( |
