Delete chrome.mediaGalleriesPrivate because the functionality unique to it has since...
[chromium-blink-merge.git] / content / child / child_discardable_shared_memory_manager.cc
blobd5b97a06153fec7c0a0dcbacfc7cfba4b20d36a6
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/child/child_discardable_shared_memory_manager.h"
7 #include "base/memory/discardable_shared_memory.h"
8 #include "base/process/process_metrics.h"
9 #include "content/child/child_thread.h"
10 #include "content/common/child_process_messages.h"
12 namespace content {
13 namespace {
15 // Default allocation size.
16 const size_t kAllocationSize = 4 * 1024 * 1024;
18 class DiscardableMemoryShmemChunkImpl
19 : public base::DiscardableMemoryShmemChunk {
20 public:
21 DiscardableMemoryShmemChunkImpl(
22 ChildDiscardableSharedMemoryManager* manager,
23 scoped_ptr<DiscardableSharedMemoryHeap::Span> span)
24 : manager_(manager), span_(span.Pass()) {}
25 ~DiscardableMemoryShmemChunkImpl() override {
26 manager_->ReleaseSpan(span_.Pass());
29 // Overridden from DiscardableMemoryShmemChunk:
30 bool Lock() override { return manager_->LockSpan(span_.get()); }
31 void Unlock() override { manager_->UnlockSpan(span_.get()); }
32 void* Memory() const override {
33 return reinterpret_cast<void*>(span_->start() * base::GetPageSize());
35 bool IsMemoryResident() const override {
36 return manager_->IsSpanResident(span_.get());
39 private:
40 ChildDiscardableSharedMemoryManager* manager_;
41 scoped_ptr<DiscardableSharedMemoryHeap::Span> span_;
43 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryShmemChunkImpl);
46 } // namespace
48 ChildDiscardableSharedMemoryManager::ChildDiscardableSharedMemoryManager(
49 ThreadSafeSender* sender)
50 : heap_(base::GetPageSize()), sender_(sender) {
53 ChildDiscardableSharedMemoryManager::~ChildDiscardableSharedMemoryManager() {
56 scoped_ptr<base::DiscardableMemoryShmemChunk>
57 ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
58 size_t size) {
59 base::AutoLock lock(lock_);
61 DCHECK_NE(size, 0u);
63 // Round up to multiple of page size.
64 size_t pages = (size + base::GetPageSize() - 1) / base::GetPageSize();
66 for (;;) {
67 // Search free list for available space.
68 scoped_ptr<DiscardableSharedMemoryHeap::Span> free_span =
69 heap_.SearchFreeList(pages);
70 if (!free_span.get())
71 break;
73 // Attempt to lock |free_span|. Delete span and search free list again
74 // if locking failed.
75 if (!free_span->shared_memory()->Lock(
76 free_span->start() * base::GetPageSize() -
77 reinterpret_cast<size_t>(free_span->shared_memory()->memory()),
78 free_span->length() * base::GetPageSize())) {
79 heap_.DeleteSpan(free_span.Pass());
80 continue;
83 return make_scoped_ptr(
84 new DiscardableMemoryShmemChunkImpl(this, free_span.Pass()));
87 size_t pages_to_allocate =
88 std::max(kAllocationSize / base::GetPageSize(), pages);
89 size_t allocation_size_in_bytes = pages_to_allocate * base::GetPageSize();
91 // Ask parent process to allocate a new discardable shared memory segment.
92 scoped_ptr<base::DiscardableSharedMemory> shared_memory(
93 AllocateLockedDiscardableSharedMemory(allocation_size_in_bytes));
95 // Create span for allocated memory.
96 scoped_ptr<DiscardableSharedMemoryHeap::Span> new_span(
97 heap_.Grow(shared_memory.Pass(), allocation_size_in_bytes));
99 // Unlock and insert any left over memory into free list.
100 if (pages < pages_to_allocate) {
101 scoped_ptr<DiscardableSharedMemoryHeap::Span> leftover =
102 heap_.Split(new_span.get(), pages);
103 leftover->shared_memory()->Unlock(
104 leftover->start() * base::GetPageSize() -
105 reinterpret_cast<size_t>(leftover->shared_memory()->memory()),
106 leftover->length() * base::GetPageSize());
107 heap_.MergeIntoFreeList(leftover.Pass());
110 return make_scoped_ptr(
111 new DiscardableMemoryShmemChunkImpl(this, new_span.Pass()));
114 bool ChildDiscardableSharedMemoryManager::LockSpan(
115 DiscardableSharedMemoryHeap::Span* span) {
116 base::AutoLock lock(lock_);
117 return span->shared_memory()->Lock(
118 span->start() * base::GetPageSize() -
119 reinterpret_cast<size_t>(span->shared_memory()->memory()),
120 span->length() * base::GetPageSize());
123 void ChildDiscardableSharedMemoryManager::UnlockSpan(
124 DiscardableSharedMemoryHeap::Span* span) {
125 base::AutoLock lock(lock_);
126 return span->shared_memory()->Unlock(
127 span->start() * base::GetPageSize() -
128 reinterpret_cast<size_t>(span->shared_memory()->memory()),
129 span->length() * base::GetPageSize());
132 bool ChildDiscardableSharedMemoryManager::IsSpanResident(
133 DiscardableSharedMemoryHeap::Span* span) const {
134 base::AutoLock lock(lock_);
135 return span->shared_memory()->IsMemoryResident();
138 void ChildDiscardableSharedMemoryManager::ReleaseSpan(
139 scoped_ptr<DiscardableSharedMemoryHeap::Span> span) {
140 base::AutoLock lock(lock_);
142 // Limit free list to spans less or equal to kAllocationSize.
143 if (span->length() * base::GetPageSize() > kAllocationSize) {
144 heap_.DeleteSpan(span.Pass());
145 return;
148 heap_.MergeIntoFreeList(span.Pass());
151 scoped_ptr<base::DiscardableSharedMemory>
152 ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
153 size_t size) {
154 TRACE_EVENT1("renderer",
155 "ChildDiscardableSharedMemoryManager::"
156 "AllocateLockedDiscardableSharedMemory",
157 "size",
158 size);
160 base::SharedMemoryHandle handle = base::SharedMemory::NULLHandle();
161 sender_->Send(
162 new ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory(
163 size, &handle));
164 scoped_ptr<base::DiscardableSharedMemory> memory(
165 new base::DiscardableSharedMemory(handle));
166 CHECK(memory->Map(size));
167 return memory.Pass();
170 } // namespace content