| Index: base/memory/discardable_memory_android.cc
|
| diff --git a/base/memory/discardable_memory_android.cc b/base/memory/discardable_memory_android.cc
|
| index 7e84967055f1ba9d35f8c6efaeb84b12833586ad..330b080a8d306b6b889435ede9fe9e40a8f45167 100644
|
| --- a/base/memory/discardable_memory_android.cc
|
| +++ b/base/memory/discardable_memory_android.cc
|
| @@ -18,6 +18,7 @@
|
| #include "base/logging.h"
|
| #include "base/memory/discardable_memory.h"
|
| #include "base/memory/discardable_memory_allocator_android.h"
|
| +#include "base/memory/discardable_memory_emulated.h"
|
| #include "base/synchronization/lock.h"
|
| #include "third_party/ashmem/ashmem.h"
|
|
|
| @@ -87,7 +88,7 @@ class DiscardableMemoryAndroidSimple : public DiscardableMemory {
|
| }
|
|
|
| // DiscardableMemory:
|
| - virtual LockDiscardableMemoryStatus Lock() OVERRIDE {
|
| + virtual DiscardableMemoryLockStatus Lock() OVERRIDE {
|
| return internal::LockAshmemRegion(fd_, 0, size_, memory_);
|
| }
|
|
|
| @@ -177,14 +178,14 @@ bool CloseAshmemRegion(int fd, size_t size, void* address) {
|
| return close(fd) == 0;
|
| }
|
|
|
| -LockDiscardableMemoryStatus LockAshmemRegion(int fd,
|
| +DiscardableMemoryLockStatus LockAshmemRegion(int fd,
|
| size_t off,
|
| size_t size,
|
| const void* address) {
|
| const int result = ashmem_pin_region(fd, off, size);
|
| DCHECK_EQ(0, mprotect(address, size, PROT_READ | PROT_WRITE));
|
| - return result == ASHMEM_WAS_PURGED ?
|
| - DISCARDABLE_MEMORY_PURGED : DISCARDABLE_MEMORY_SUCCESS;
|
| + return result == ASHMEM_WAS_PURGED ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED
|
| + : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
|
| }
|
|
|
| bool UnlockAshmemRegion(int fd, size_t off, size_t size, const void* address) {
|
| @@ -199,8 +200,10 @@ bool UnlockAshmemRegion(int fd, size_t off, size_t size, const void* address) {
|
| } // namespace internal
|
|
|
| // static
|
| -bool DiscardableMemory::SupportedNatively() {
|
| - return true;
|
| +void DiscardableMemory::GetSupportedTypes(
|
| + std::vector<DiscardableMemoryType>* types) {
|
| + types->push_back(DISCARDABLE_MEMORY_TYPE_ANDROID);
|
| + types->push_back(DISCARDABLE_MEMORY_TYPE_EMULATED);
|
| }
|
|
|
| // Allocation can happen in two ways:
|
| @@ -221,29 +224,48 @@ bool DiscardableMemory::SupportedNatively() {
|
| // static
|
| scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemory(
|
| size_t size) {
|
| - if (!CheckSizeCanBeAlignedToNextPage(size))
|
| - return scoped_ptr<DiscardableMemory>();
|
| - // Pinning & unpinning works with page granularity therefore align the size
|
| - // upfront.
|
| - const size_t aligned_size = internal::AlignToNextPage(size);
|
| - // Note that the following code is slightly racy. The worst that can happen in
|
| - // practice though is taking the wrong decision (e.g. using the allocator
|
| - // rather than DiscardableMemoryAndroidSimple). Moreover keeping the lock
|
| - // acquired for the whole allocation would cause a deadlock when the allocator
|
| - // tries to create an ashmem region.
|
| - const size_t kAllocatorRegionSize =
|
| - internal::DiscardableMemoryAllocator::kMinAshmemRegionSize;
|
| - GlobalContext* const global_context = g_context.Pointer();
|
| - if (aligned_size >= kAllocatorRegionSize ||
|
| - GetCurrentNumberOfAshmemFDs() < 0.9 * global_context->ashmem_fd_limit) {
|
| - int fd;
|
| - void* address;
|
| - if (internal::CreateAshmemRegion("", aligned_size, &fd, &address)) {
|
| - return scoped_ptr<DiscardableMemory>(
|
| - new DiscardableMemoryAndroidSimple(fd, address, aligned_size));
|
| + switch (GetType()) {
|
| + case DISCARDABLE_MEMORY_TYPE_NONE:
|
| + case DISCARDABLE_MEMORY_TYPE_MAC:
|
| + return scoped_ptr<DiscardableMemory>();
|
| + case DISCARDABLE_MEMORY_TYPE_ANDROID: {
|
| + if (!CheckSizeCanBeAlignedToNextPage(size))
|
| + return scoped_ptr<DiscardableMemory>();
|
| + // Pinning & unpinning works with page granularity therefore align the
|
| + // size upfront.
|
| + const size_t aligned_size = internal::AlignToNextPage(size);
|
| + // Note that the following code is slightly racy. The worst that can
|
| + // happen in practice though is taking the wrong decision (e.g. using
|
| + // the allocator rather than DiscardableMemoryAndroidSimple). Moreover
|
| + // keeping the lock acquired for the whole allocation would cause a
|
| + // deadlock when the allocator tries to create an ashmem region.
|
| + const size_t kAllocatorRegionSize =
|
| + internal::DiscardableMemoryAllocator::kMinAshmemRegionSize;
|
| + GlobalContext* const global_context = g_context.Pointer();
|
| + if (aligned_size >= kAllocatorRegionSize ||
|
| + GetCurrentNumberOfAshmemFDs() <
|
| + 0.9 * global_context->ashmem_fd_limit) {
|
| + int fd;
|
| + void* address;
|
| + if (internal::CreateAshmemRegion("", aligned_size, &fd, &address)) {
|
| + return scoped_ptr<DiscardableMemory>(
|
| + new DiscardableMemoryAndroidSimple(fd, address, aligned_size));
|
| + }
|
| + }
|
| + return global_context->allocator.Allocate(size);
|
| + }
|
| + case DISCARDABLE_MEMORY_TYPE_EMULATED: {
|
| + scoped_ptr<internal::DiscardableMemoryEmulated> memory(
|
| + new internal::DiscardableMemoryEmulated(size));
|
| + if (!memory->Initialize())
|
| + return scoped_ptr<DiscardableMemory>();
|
| +
|
| + return memory.PassAs<DiscardableMemory>();
|
| }
|
| }
|
| - return global_context->allocator.Allocate(size);
|
| +
|
| + NOTREACHED();
|
| + return scoped_ptr<DiscardableMemory>();
|
| }
|
|
|
| // static
|
|
|