Skip to content

Commit

Permalink
Revert 267170 "Use DiscardableMemoryManager on Android."
Browse files Browse the repository at this point in the history
> Use DiscardableMemoryManager on Android.
> 
> This allows userspace (DiscardableMemoryManager) to control eviction of
> unlocked DiscardableMemory instances to prevent the process from running out of
> address space in cases of heavy use of unlocked DiscardableMemory.
> 
> This also removes all the occurences of 'Android' from the ashmem allocator to
> allow it to be later used on ChromeOS.
> 
> BUG=327516, 334996
> R=reveman@chromium.org, willchan@chromium.org
> 
> Review URL: https://codereview.chromium.org/195863005

TBR=pliard@chromium.org

Review URL: https://codereview.chromium.org/257383004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267175 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
pliard@chromium.org committed Apr 30, 2014
1 parent 766be77 commit cb39c52
Show file tree
Hide file tree
Showing 20 changed files with 286 additions and 428 deletions.
6 changes: 1 addition & 5 deletions base/base.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@
'mac/scoped_sending_event_unittest.mm',
'md5_unittest.cc',
'memory/aligned_memory_unittest.cc',
'memory/discardable_memory_allocator_android_unittest.cc',
'memory/discardable_memory_manager_unittest.cc',
'memory/discardable_memory_unittest.cc',
'memory/linked_ptr_unittest.cc',
Expand Down Expand Up @@ -755,11 +756,6 @@
['include', '^sys_string_conversions_mac_unittest\\.mm$'],
],
}],
['OS == "android" and _toolset == "target"', {
'sources': [
'memory/discardable_memory_ashmem_allocator_unittest.cc',
],
}],
['OS == "android"', {
'sources/': [
['include', '^debug/proc_maps_linux_unittest\\.cc$'],
Expand Down
10 changes: 2 additions & 8 deletions base/base.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@
'memory/aligned_memory.h',
'memory/discardable_memory.cc',
'memory/discardable_memory.h',
'memory/discardable_memory_allocator_android.cc',
'memory/discardable_memory_allocator_android.h',
'memory/discardable_memory_android.cc',
'memory/discardable_memory_emulated.cc',
'memory/discardable_memory_emulated.h',
Expand Down Expand Up @@ -768,14 +770,6 @@
['include', '^threading/platform_thread_linux\\.cc$'],
],
}],
['OS == "android" and _toolset == "target"', {
'sources': [
'memory/discardable_memory_ashmem_allocator.cc',
'memory/discardable_memory_ashmem_allocator.h',
'memory/discardable_memory_ashmem.cc',
'memory/discardable_memory_ashmem.h',
],
}],
['OS == "android" and >(nacl_untrusted_build)==0', {
'sources!': [
'base_paths_posix.cc',
Expand Down
2 changes: 1 addition & 1 deletion base/memory/discardable_memory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const struct TypeNamePair {
DiscardableMemoryType type;
const char* name;
} kTypeNamePairs[] = {
{ DISCARDABLE_MEMORY_TYPE_ASHMEM, "ashmem" },
{ DISCARDABLE_MEMORY_TYPE_ANDROID, "android" },
{ DISCARDABLE_MEMORY_TYPE_MAC, "mac" },
{ DISCARDABLE_MEMORY_TYPE_EMULATED, "emulated" },
{ DISCARDABLE_MEMORY_TYPE_MALLOC, "malloc" }
Expand Down
6 changes: 5 additions & 1 deletion base/memory/discardable_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace base {

enum DiscardableMemoryType {
DISCARDABLE_MEMORY_TYPE_NONE,
DISCARDABLE_MEMORY_TYPE_ASHMEM,
DISCARDABLE_MEMORY_TYPE_ANDROID,
DISCARDABLE_MEMORY_TYPE_MAC,
DISCARDABLE_MEMORY_TYPE_EMULATED,
DISCARDABLE_MEMORY_TYPE_MALLOC
Expand Down Expand Up @@ -115,6 +115,10 @@ class BASE_EXPORT DiscardableMemory {

// Testing utility calls.

// Check whether a purge of all discardable memory in the system is supported.
// Use only for testing!
static bool PurgeForTestingSupported();

// Purge all discardable memory in the system. This call has global effects
// across all running processes, so it should only be used for testing!
static void PurgeForTesting();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/memory/discardable_memory_ashmem_allocator.h"
#include "base/memory/discardable_memory_allocator_android.h"

#include <sys/mman.h>
#include <unistd.h>
Expand All @@ -18,17 +18,22 @@
#include "base/file_util.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/memory/discardable_memory.h"
#include "base/memory/scoped_vector.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "third_party/ashmem/ashmem.h"

// The allocator consists of three parts (classes):
// - DiscardableMemoryAshmemAllocator: entry point of all allocations (through
// its Allocate() method) that are dispatched to the AshmemRegion instances
// (which it owns).
// - DiscardableMemoryAllocator: entry point of all allocations (through its
// Allocate() method) that are dispatched to the AshmemRegion instances (which
// it owns).
// - AshmemRegion: manages allocations and destructions inside a single large
// (e.g. 32 MBytes) ashmem region.
// - DiscardableAshmemChunk: class mimicking the DiscardableMemory interface
// whose instances are returned to the client.
// - DiscardableAshmemChunk: class implementing the DiscardableMemory interface
// whose instances are returned to the client. DiscardableAshmemChunk lets the
// client seamlessly operate on a subrange of the ashmem region managed by
// AshmemRegion.

namespace base {
namespace {
Expand Down Expand Up @@ -97,8 +102,10 @@ bool CloseAshmemRegion(int fd, size_t size, void* address) {
return close(fd) == 0;
}

bool LockAshmemRegion(int fd, size_t off, size_t size) {
return ashmem_pin_region(fd, off, size) != ASHMEM_WAS_PURGED;
DiscardableMemoryLockStatus LockAshmemRegion(int fd, size_t off, size_t size) {
const int result = ashmem_pin_region(fd, off, size);
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) {
Expand All @@ -112,13 +119,62 @@ bool UnlockAshmemRegion(int fd, size_t off, size_t size) {

namespace internal {

class AshmemRegion {
class DiscardableMemoryAllocator::DiscardableAshmemChunk
: public DiscardableMemory {
public:
// Note that |ashmem_region| must outlive |this|.
DiscardableAshmemChunk(AshmemRegion* ashmem_region,
int fd,
void* address,
size_t offset,
size_t size)
: ashmem_region_(ashmem_region),
fd_(fd),
address_(address),
offset_(offset),
size_(size),
locked_(true) {
}

// Implemented below AshmemRegion since this requires the full definition of
// AshmemRegion.
virtual ~DiscardableAshmemChunk();

// DiscardableMemory:
virtual DiscardableMemoryLockStatus Lock() OVERRIDE {
DCHECK(!locked_);
locked_ = true;
return LockAshmemRegion(fd_, offset_, size_);
}

virtual void Unlock() OVERRIDE {
DCHECK(locked_);
locked_ = false;
UnlockAshmemRegion(fd_, offset_, size_);
}

virtual void* Memory() const OVERRIDE {
return address_;
}

private:
AshmemRegion* const ashmem_region_;
const int fd_;
void* const address_;
const size_t offset_;
const size_t size_;
bool locked_;

DISALLOW_COPY_AND_ASSIGN(DiscardableAshmemChunk);
};

class DiscardableMemoryAllocator::AshmemRegion {
public:
// Note that |allocator| must outlive |this|.
static scoped_ptr<AshmemRegion> Create(
size_t size,
const std::string& name,
DiscardableMemoryAshmemAllocator* allocator) {
DiscardableMemoryAllocator* allocator) {
DCHECK_EQ(size, AlignToNextPage(size));
int fd;
void* base;
Expand All @@ -133,8 +189,8 @@ class AshmemRegion {
DCHECK(!highest_allocated_chunk_);
}

// Returns a new instance of DiscardableAshmemChunk whose size is greater or
// equal than |actual_size| (which is expected to be greater or equal than
// Returns a new instance of DiscardableMemory whose size is greater or equal
// than |actual_size| (which is expected to be greater or equal than
// |client_requested_size|).
// Allocation works as follows:
// 1) Reuse a previously freed chunk and return it if it succeeded. See
Expand All @@ -144,9 +200,8 @@ class AshmemRegion {
// 3) If there is enough room in the ashmem region then a new chunk is
// returned. This new chunk starts at |offset_| which is the end of the
// previously highest chunk in the region.
scoped_ptr<DiscardableAshmemChunk> Allocate_Locked(
size_t client_requested_size,
size_t actual_size) {
scoped_ptr<DiscardableMemory> Allocate_Locked(size_t client_requested_size,
size_t actual_size) {
DCHECK_LE(client_requested_size, actual_size);
allocator_->lock_.AssertAcquired();

Expand All @@ -158,14 +213,14 @@ class AshmemRegion {
used_to_previous_chunk_map_.find(highest_allocated_chunk_) !=
used_to_previous_chunk_map_.end());

scoped_ptr<DiscardableAshmemChunk> memory = ReuseFreeChunk_Locked(
scoped_ptr<DiscardableMemory> memory = ReuseFreeChunk_Locked(
client_requested_size, actual_size);
if (memory)
return memory.Pass();

if (size_ - offset_ < actual_size) {
// This region does not have enough space left to hold the requested size.
return scoped_ptr<DiscardableAshmemChunk>();
return scoped_ptr<DiscardableMemory>();
}

void* const address = static_cast<char*>(base_) + offset_;
Expand Down Expand Up @@ -218,7 +273,7 @@ class AshmemRegion {
AshmemRegion(int fd,
size_t size,
void* base,
DiscardableMemoryAshmemAllocator* allocator)
DiscardableMemoryAllocator* allocator)
: fd_(fd),
size_(size),
base_(base),
Expand All @@ -232,14 +287,14 @@ class AshmemRegion {
}

// Tries to reuse a previously freed chunk by doing a closest size match.
scoped_ptr<DiscardableAshmemChunk> ReuseFreeChunk_Locked(
scoped_ptr<DiscardableMemory> ReuseFreeChunk_Locked(
size_t client_requested_size,
size_t actual_size) {
allocator_->lock_.AssertAcquired();
const FreeChunk reused_chunk = RemoveFreeChunkFromIterator_Locked(
free_chunks_.lower_bound(FreeChunk(actual_size)));
if (reused_chunk.is_null())
return scoped_ptr<DiscardableAshmemChunk>();
return scoped_ptr<DiscardableMemory>();

used_to_previous_chunk_map_.insert(
std::make_pair(reused_chunk.start, reused_chunk.previous_chunk));
Expand Down Expand Up @@ -275,9 +330,9 @@ class AshmemRegion {
const size_t offset =
static_cast<char*>(reused_chunk.start) - static_cast<char*>(base_);
LockAshmemRegion(fd_, offset, reused_chunk_size);
scoped_ptr<DiscardableAshmemChunk> memory(
new DiscardableAshmemChunk(
this, fd_, reused_chunk.start, offset, reused_chunk_size));
scoped_ptr<DiscardableMemory> memory(
new DiscardableAshmemChunk(this, fd_, reused_chunk.start, offset,
reused_chunk_size));
return memory.Pass();
}

Expand Down Expand Up @@ -394,7 +449,7 @@ class AshmemRegion {
const int fd_;
const size_t size_;
void* const base_;
DiscardableMemoryAshmemAllocator* const allocator_;
DiscardableMemoryAllocator* const allocator_;
// Points to the chunk with the highest address in the region. This pointer
// needs to be carefully updated when chunks are merged/split.
void* highest_allocated_chunk_;
Expand All @@ -418,43 +473,13 @@ class AshmemRegion {
DISALLOW_COPY_AND_ASSIGN(AshmemRegion);
};

DiscardableAshmemChunk::~DiscardableAshmemChunk() {
DiscardableMemoryAllocator::DiscardableAshmemChunk::~DiscardableAshmemChunk() {
if (locked_)
UnlockAshmemRegion(fd_, offset_, size_);
ashmem_region_->OnChunkDeletion(address_, size_);
}

bool DiscardableAshmemChunk::Lock() {
DCHECK(!locked_);
locked_ = true;
return LockAshmemRegion(fd_, offset_, size_);
}

void DiscardableAshmemChunk::Unlock() {
DCHECK(locked_);
locked_ = false;
UnlockAshmemRegion(fd_, offset_, size_);
}

void* DiscardableAshmemChunk::Memory() const {
return address_;
}

// Note that |ashmem_region| must outlive |this|.
DiscardableAshmemChunk::DiscardableAshmemChunk(AshmemRegion* ashmem_region,
int fd,
void* address,
size_t offset,
size_t size)
: ashmem_region_(ashmem_region),
fd_(fd),
address_(address),
offset_(offset),
size_(size),
locked_(true) {
}

DiscardableMemoryAshmemAllocator::DiscardableMemoryAshmemAllocator(
DiscardableMemoryAllocator::DiscardableMemoryAllocator(
const std::string& name,
size_t ashmem_region_size)
: name_(name),
Expand All @@ -464,15 +489,16 @@ DiscardableMemoryAshmemAllocator::DiscardableMemoryAshmemAllocator(
DCHECK_GE(ashmem_region_size_, kMinAshmemRegionSize);
}

DiscardableMemoryAshmemAllocator::~DiscardableMemoryAshmemAllocator() {
DiscardableMemoryAllocator::~DiscardableMemoryAllocator() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(ashmem_regions_.empty());
}

scoped_ptr<DiscardableAshmemChunk> DiscardableMemoryAshmemAllocator::Allocate(
scoped_ptr<DiscardableMemory> DiscardableMemoryAllocator::Allocate(
size_t size) {
const size_t aligned_size = AlignToNextPage(size);
if (!aligned_size)
return scoped_ptr<DiscardableAshmemChunk>();
return scoped_ptr<DiscardableMemory>();
// TODO(pliard): make this function less naive by e.g. moving the free chunks
// multiset to the allocator itself in order to decrease even more
// fragmentation/speedup allocation. Note that there should not be more than a
Expand All @@ -481,7 +507,7 @@ scoped_ptr<DiscardableAshmemChunk> DiscardableMemoryAshmemAllocator::Allocate(
DCHECK_LE(ashmem_regions_.size(), 5U);
for (ScopedVector<AshmemRegion>::iterator it = ashmem_regions_.begin();
it != ashmem_regions_.end(); ++it) {
scoped_ptr<DiscardableAshmemChunk> memory(
scoped_ptr<DiscardableMemory> memory(
(*it)->Allocate_Locked(size, aligned_size));
if (memory)
return memory.Pass();
Expand All @@ -502,15 +528,15 @@ scoped_ptr<DiscardableAshmemChunk> DiscardableMemoryAshmemAllocator::Allocate(
return ashmem_regions_.back()->Allocate_Locked(size, aligned_size);
}
// TODO(pliard): consider adding an histogram to see how often this happens.
return scoped_ptr<DiscardableAshmemChunk>();
return scoped_ptr<DiscardableMemory>();
}

size_t DiscardableMemoryAshmemAllocator::last_ashmem_region_size() const {
size_t DiscardableMemoryAllocator::last_ashmem_region_size() const {
AutoLock auto_lock(lock_);
return last_ashmem_region_size_;
}

void DiscardableMemoryAshmemAllocator::DeleteAshmemRegion_Locked(
void DiscardableMemoryAllocator::DeleteAshmemRegion_Locked(
AshmemRegion* region) {
lock_.AssertAcquired();
// Note that there should not be more than a couple of ashmem region instances
Expand Down
Loading

0 comments on commit cb39c52

Please sign in to comment.