Skip to content

Commit

Permalink
discardable_memory: Using mojo IPC to replace Chrome IPC
Browse files Browse the repository at this point in the history
It also moves ClientDiscardableSharedMemoryManager from ChildThreadImpl
to RenderThreadImpl and PpapiThread

BUG=654678

Committed: https://crrev.com/a083f971261bcccc53b64e40c911435857ce3bfd
Review-Url: https://codereview.chromium.org/2485623002
Cr-Original-Commit-Position: refs/heads/master@{#435969}
Cr-Commit-Position: refs/heads/master@{#436010}
  • Loading branch information
phuang authored and Commit bot committed Dec 2, 2016
1 parent 466e984 commit 342762b
Show file tree
Hide file tree
Showing 35 changed files with 459 additions and 424 deletions.
3 changes: 3 additions & 0 deletions components/discardable_memory/DEPS
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include_rules = [
"+mojo/public/cpp",
]
1 change: 1 addition & 0 deletions components/discardable_memory/client/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ component("client") {
deps = [
"//base",
"//components/discardable_memory/common",
"//components/discardable_memory/public/interfaces",
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
#include "base/process/process_metrics.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "mojo/public/cpp/system/platform_handle.h"

namespace discardable_memory {
namespace {
Expand Down Expand Up @@ -82,29 +84,51 @@ class DiscardableMemoryImpl : public base::DiscardableMemory {
DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryImpl);
};

void SendDeletedDiscardableSharedMemoryMessage(
ClientDiscardableSharedMemoryManager::Delegate* delegate,
DiscardableSharedMemoryId id) {
delegate->DeletedDiscardableSharedMemory(id);
void InitManagerMojoOnIO(mojom::DiscardableSharedMemoryManagerPtr* manager_mojo,
mojom::DiscardableSharedMemoryManagerPtrInfo info) {
manager_mojo->Bind(std::move(info));
}

void DeletedDiscardableSharedMemoryOnIO(
mojom::DiscardableSharedMemoryManagerPtr* manager_mojo,
int32_t id) {
(*manager_mojo)->DeletedDiscardableSharedMemory(id);
}

} // namespace

ClientDiscardableSharedMemoryManager::ClientDiscardableSharedMemoryManager(
Delegate* delegate)
: heap_(base::GetPageSize()), delegate_(delegate) {
mojom::DiscardableSharedMemoryManagerPtr manager,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
: io_task_runner_(std::move(io_task_runner)),
manager_mojo_(new mojom::DiscardableSharedMemoryManagerPtr),
heap_(new DiscardableSharedMemoryHeap(base::GetPageSize())) {
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
this, "ClientDiscardableSharedMemoryManager",
base::ThreadTaskRunnerHandle::Get());
mojom::DiscardableSharedMemoryManagerPtrInfo info = manager.PassInterface();
io_task_runner_->PostTask(
FROM_HERE, base::Bind(&InitManagerMojoOnIO, manager_mojo_.get(),
base::Passed(&info)));
}

ClientDiscardableSharedMemoryManager::~ClientDiscardableSharedMemoryManager() {
base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
this);
// TODO(reveman): Determine if this DCHECK can be enabled. crbug.com/430533
// DCHECK_EQ(heap_.GetSize(), heap_.GetSizeOfFreeLists());
if (heap_.GetSize())
// DCHECK_EQ(heap_->GetSize(), heap_->GetSizeOfFreeLists());
if (heap_->GetSize())
MemoryUsageChanged(0, 0);

// Releasing the |heap_| before posting a task for deleting |manager_mojo_|.
// It is because releasing |heap_| will invoke DeletedDiscardableSharedMemory
// which needs |manager_mojo_|.
heap_.reset();

// Delete the |manager_mojo_| on IO thread, so any pending tasks on IO thread
// will be executed before the |manager_mojo_| is deleted.
bool posted = io_task_runner_->DeleteSoon(FROM_HERE, manager_mojo_.release());
DCHECK(posted);
}

std::unique_ptr<base::DiscardableMemory>
Expand Down Expand Up @@ -138,11 +162,11 @@ ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
if (pages < allocation_pages)
slack = allocation_pages - pages;

size_t heap_size_prior_to_releasing_purged_memory = heap_.GetSize();
size_t heap_size_prior_to_releasing_purged_memory = heap_->GetSize();
for (;;) {
// Search free lists for suitable span.
std::unique_ptr<DiscardableSharedMemoryHeap::Span> free_span =
heap_.SearchFreeLists(pages, slack);
heap_->SearchFreeLists(pages, slack);
if (!free_span.get())
break;

Expand All @@ -155,7 +179,7 @@ ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
base::DiscardableSharedMemory::FAILED) {
DCHECK(!free_span->shared_memory()->IsMemoryResident());
// We have to release purged memory before |free_span| can be destroyed.
heap_.ReleasePurgedMemory();
heap_->ReleasePurgedMemory();
DCHECK(!free_span->shared_memory());
continue;
}
Expand All @@ -164,50 +188,53 @@ ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(

// Memory usage is guaranteed to have changed after having removed
// at least one span from the free lists.
MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists());
MemoryUsageChanged(heap_->GetSize(), heap_->GetSizeOfFreeLists());

return base::MakeUnique<DiscardableMemoryImpl>(this, std::move(free_span));
}

// Release purged memory to free up the address space before we attempt to
// allocate more memory.
heap_.ReleasePurgedMemory();
heap_->ReleasePurgedMemory();

// Make sure crash keys are up to date in case allocation fails.
if (heap_.GetSize() != heap_size_prior_to_releasing_purged_memory)
MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists());
if (heap_->GetSize() != heap_size_prior_to_releasing_purged_memory)
MemoryUsageChanged(heap_->GetSize(), heap_->GetSizeOfFreeLists());

size_t pages_to_allocate =
std::max(kAllocationSize / base::GetPageSize(), pages);
size_t allocation_size_in_bytes = pages_to_allocate * base::GetPageSize();

DiscardableSharedMemoryId new_id =
g_next_discardable_shared_memory_id.GetNext();
int32_t new_id = g_next_discardable_shared_memory_id.GetNext();

// Ask parent process to allocate a new discardable shared memory segment.
std::unique_ptr<base::DiscardableSharedMemory> shared_memory(
AllocateLockedDiscardableSharedMemory(allocation_size_in_bytes, new_id));
std::unique_ptr<base::DiscardableSharedMemory> shared_memory =
AllocateLockedDiscardableSharedMemory(allocation_size_in_bytes, new_id);

// Create span for allocated memory.
std::unique_ptr<DiscardableSharedMemoryHeap::Span> new_span(
heap_.Grow(std::move(shared_memory), allocation_size_in_bytes, new_id,
base::Bind(&SendDeletedDiscardableSharedMemoryMessage,
delegate_, new_id)));
// Spans are managed by |heap_| (the member of
// the ClientDiscardableSharedMemoryManager), so it is safe to use
// base::Unretained(this) here.
std::unique_ptr<DiscardableSharedMemoryHeap::Span> new_span(heap_->Grow(
std::move(shared_memory), allocation_size_in_bytes, new_id,
base::Bind(
&ClientDiscardableSharedMemoryManager::DeletedDiscardableSharedMemory,
base::Unretained(this), new_id)));
new_span->set_is_locked(true);

// Unlock and insert any left over memory into free lists.
if (pages < pages_to_allocate) {
std::unique_ptr<DiscardableSharedMemoryHeap::Span> leftover =
heap_.Split(new_span.get(), pages);
heap_->Split(new_span.get(), pages);
leftover->shared_memory()->Unlock(
leftover->start() * base::GetPageSize() -
reinterpret_cast<size_t>(leftover->shared_memory()->memory()),
leftover->length() * base::GetPageSize());
leftover->set_is_locked(false);
heap_.MergeIntoFreeLists(std::move(leftover));
heap_->MergeIntoFreeLists(std::move(leftover));
}

MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists());
MemoryUsageChanged(heap_->GetSize(), heap_->GetSizeOfFreeLists());

return base::MakeUnique<DiscardableMemoryImpl>(this, std::move(new_span));
}
Expand All @@ -222,8 +249,8 @@ bool ClientDiscardableSharedMemoryManager::OnMemoryDump(
pmd->CreateAllocatorDump(
base::StringPrintf("discardable/child_0x%" PRIXPTR,
reinterpret_cast<uintptr_t>(this)));
const size_t total_size = heap_.GetSize();
const size_t freelist_size = heap_.GetSizeOfFreeLists();
const size_t total_size = heap_->GetSize();
const size_t freelist_size = heap_->GetSizeOfFreeLists();
total_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
total_size - freelist_size);
Expand All @@ -233,29 +260,29 @@ bool ClientDiscardableSharedMemoryManager::OnMemoryDump(
return true;
}

return heap_.OnMemoryDump(pmd);
return heap_->OnMemoryDump(pmd);
}

ClientDiscardableSharedMemoryManager::Statistics
ClientDiscardableSharedMemoryManager::GetStatistics() const {
base::AutoLock lock(lock_);
Statistics stats;
stats.total_size = heap_.GetSize();
stats.freelist_size = heap_.GetSizeOfFreeLists();
stats.total_size = heap_->GetSize();
stats.freelist_size = heap_->GetSizeOfFreeLists();
return stats;
}

void ClientDiscardableSharedMemoryManager::ReleaseFreeMemory() {
base::AutoLock lock(lock_);

size_t heap_size_prior_to_releasing_memory = heap_.GetSize();
size_t heap_size_prior_to_releasing_memory = heap_->GetSize();

// Release both purged and free memory.
heap_.ReleasePurgedMemory();
heap_.ReleaseFreeMemory();
heap_->ReleasePurgedMemory();
heap_->ReleaseFreeMemory();

if (heap_.GetSize() != heap_size_prior_to_releasing_memory)
MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists());
if (heap_->GetSize() != heap_size_prior_to_releasing_memory)
MemoryUsageChanged(heap_->GetSize(), heap_->GetSizeOfFreeLists());
}

bool ClientDiscardableSharedMemoryManager::LockSpan(
Expand Down Expand Up @@ -306,10 +333,10 @@ void ClientDiscardableSharedMemoryManager::ReleaseSpan(
if (!span->shared_memory())
return;

heap_.MergeIntoFreeLists(std::move(span));
heap_->MergeIntoFreeLists(std::move(span));

// Bytes of free memory changed.
MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists());
MemoryUsageChanged(heap_->GetSize(), heap_->GetSizeOfFreeLists());
}

base::trace_event::MemoryAllocatorDump*
Expand All @@ -318,25 +345,69 @@ ClientDiscardableSharedMemoryManager::CreateMemoryAllocatorDump(
const char* name,
base::trace_event::ProcessMemoryDump* pmd) const {
base::AutoLock lock(lock_);
return heap_.CreateMemoryAllocatorDump(span, name, pmd);
return heap_->CreateMemoryAllocatorDump(span, name, pmd);
}

std::unique_ptr<base::DiscardableSharedMemory>
ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
size_t size,
DiscardableSharedMemoryId id) {
int32_t id) {
TRACE_EVENT2("renderer",
"ClientDiscardableSharedMemoryManager::"
"AllocateLockedDiscardableSharedMemory",
"size", size, "id", id);
std::unique_ptr<base::DiscardableSharedMemory> memory;
base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
base::ScopedClosureRunner event_signal_runner(
base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
io_task_runner_->PostTask(
FROM_HERE, base::Bind(&ClientDiscardableSharedMemoryManager::AllocateOnIO,
base::Unretained(this), size, id, &memory,
base::Passed(&event_signal_runner)));
// Waiting until IPC has finished on the IO thread.
event.Wait();
return memory;
}

void ClientDiscardableSharedMemoryManager::AllocateOnIO(
size_t size,
int32_t id,
std::unique_ptr<base::DiscardableSharedMemory>* memory,
base::ScopedClosureRunner closure_runner) {
(*manager_mojo_)
->AllocateLockedDiscardableSharedMemory(
static_cast<uint32_t>(size), id,
base::Bind(
&ClientDiscardableSharedMemoryManager::AllocateCompletedOnIO,
base::Unretained(this), memory, base::Passed(&closure_runner)));
}

void ClientDiscardableSharedMemoryManager::AllocateCompletedOnIO(
std::unique_ptr<base::DiscardableSharedMemory>* memory,
base::ScopedClosureRunner closure_runner,
mojo::ScopedSharedBufferHandle mojo_handle) {
if (!mojo_handle.is_valid())
return;
base::SharedMemoryHandle handle = base::SharedMemory::NULLHandle();
delegate_->AllocateLockedDiscardableSharedMemory(size, id, &handle);
std::unique_ptr<base::DiscardableSharedMemory> memory(
new base::DiscardableSharedMemory(handle));
if (!memory->Map(size))
base::TerminateBecauseOutOfMemory(size);
return memory;
size_t memory_size = 0;
bool read_only = false;
auto result = mojo::UnwrapSharedMemoryHandle(std::move(mojo_handle), &handle,
&memory_size, &read_only);
if (result != MOJO_RESULT_OK)
return;
auto discardable_shared_memory =
base::MakeUnique<base::DiscardableSharedMemory>(handle);
if (!discardable_shared_memory->Map(memory_size))
base::TerminateBecauseOutOfMemory(memory_size);
*memory = std::move(discardable_shared_memory);
}

void ClientDiscardableSharedMemoryManager::DeletedDiscardableSharedMemory(
int32_t id) {
io_task_runner_->PostTask(
FROM_HERE,
base::Bind(&DeletedDiscardableSharedMemoryOnIO, manager_mojo_.get(), id));
}

void ClientDiscardableSharedMemoryManager::MemoryUsageChanged(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <stddef.h>

#include "base/callback_helpers.h"
#include "base/macros.h"
#include "base/memory/discardable_memory_allocator.h"
#include "base/memory/ref_counted.h"
Expand All @@ -15,7 +16,11 @@
#include "base/trace_event/memory_dump_provider.h"
#include "components/discardable_memory/common/discardable_memory_export.h"
#include "components/discardable_memory/common/discardable_shared_memory_heap.h"
#include "components/discardable_memory/common/discardable_shared_memory_id.h"
#include "components/discardable_memory/public/interfaces/discardable_shared_memory_manager.mojom.h"

namespace base {
class SingleThreadTaskRunner;
}

namespace discardable_memory {

Expand All @@ -25,20 +30,9 @@ class DISCARDABLE_MEMORY_EXPORT ClientDiscardableSharedMemoryManager
: public base::DiscardableMemoryAllocator,
public base::trace_event::MemoryDumpProvider {
public:
class Delegate {
public:
virtual void AllocateLockedDiscardableSharedMemory(
size_t size,
DiscardableSharedMemoryId id,
base::SharedMemoryHandle* handle) = 0;
virtual void DeletedDiscardableSharedMemory(
DiscardableSharedMemoryId id) = 0;

protected:
virtual ~Delegate() {}
};

explicit ClientDiscardableSharedMemoryManager(Delegate* delegate);
ClientDiscardableSharedMemoryManager(
mojom::DiscardableSharedMemoryManagerPtr manager,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
~ClientDiscardableSharedMemoryManager() override;

// Overridden from base::DiscardableMemoryAllocator:
Expand Down Expand Up @@ -70,14 +64,27 @@ class DISCARDABLE_MEMORY_EXPORT ClientDiscardableSharedMemoryManager

private:
std::unique_ptr<base::DiscardableSharedMemory>
AllocateLockedDiscardableSharedMemory(size_t size,
DiscardableSharedMemoryId id);
AllocateLockedDiscardableSharedMemory(size_t size, int32_t id);
void AllocateOnIO(size_t size,
int32_t id,
std::unique_ptr<base::DiscardableSharedMemory>* memory,
base::ScopedClosureRunner closure_runner);
void AllocateCompletedOnIO(
std::unique_ptr<base::DiscardableSharedMemory>* memory,
base::ScopedClosureRunner closure_runner,
mojo::ScopedSharedBufferHandle mojo_handle);

void DeletedDiscardableSharedMemory(int32_t id);
void MemoryUsageChanged(size_t new_bytes_allocated,
size_t new_bytes_free) const;

scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
// TODO(penghuang): Switch to ThreadSafeInterfacePtr when it starts supporting
// sync method call.
std::unique_ptr<mojom::DiscardableSharedMemoryManagerPtr> manager_mojo_;

mutable base::Lock lock_;
DiscardableSharedMemoryHeap heap_;
Delegate* const delegate_;
std::unique_ptr<DiscardableSharedMemoryHeap> heap_;

DISALLOW_COPY_AND_ASSIGN(ClientDiscardableSharedMemoryManager);
};
Expand Down
1 change: 0 additions & 1 deletion components/discardable_memory/common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ component("common") {
"discardable_memory_export.h",
"discardable_shared_memory_heap.cc",
"discardable_shared_memory_heap.h",
"discardable_shared_memory_id.h",
]

deps = [
Expand Down
Loading

0 comments on commit 342762b

Please sign in to comment.