Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(622)

Side by Side Diff: content/child/child_discardable_shared_memory_manager.cc

Issue 807303002: base: Add free list implementation to browser-wide discardable memory system. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@discardable-shared-memory-ashmem
Patch Set: fix nits Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/child/child_discardable_shared_memory_manager.h" 5 #include "content/child/child_discardable_shared_memory_manager.h"
6 6
7 #include "base/memory/discardable_shared_memory.h" 7 #include "base/memory/discardable_shared_memory.h"
8 #include "base/process/process_metrics.h"
8 #include "content/child/child_thread.h" 9 #include "content/child/child_thread.h"
9 #include "content/common/child_process_messages.h" 10 #include "content/common/child_process_messages.h"
10 11
11 namespace content { 12 namespace content {
13 namespace {
14
15 // Default allocation size.
16 const size_t kAllocationSize = 4 * 1024 * 1024;
17
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());
27 }
28
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());
34 }
35 bool IsMemoryResident() const override {
36 return manager_->IsSpanResident(span_.get());
37 }
38
39 private:
40 ChildDiscardableSharedMemoryManager* manager_;
41 scoped_ptr<DiscardableSharedMemoryHeap::Span> span_;
42
43 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryShmemChunkImpl);
44 };
45
46 } // namespace
12 47
13 ChildDiscardableSharedMemoryManager::ChildDiscardableSharedMemoryManager( 48 ChildDiscardableSharedMemoryManager::ChildDiscardableSharedMemoryManager(
14 ThreadSafeSender* sender) 49 ThreadSafeSender* sender)
15 : sender_(sender) { 50 : heap_(base::GetPageSize()), sender_(sender) {
16 } 51 }
17 52
18 ChildDiscardableSharedMemoryManager::~ChildDiscardableSharedMemoryManager() { 53 ChildDiscardableSharedMemoryManager::~ChildDiscardableSharedMemoryManager() {
19 } 54 }
20 55
56 scoped_ptr<base::DiscardableMemoryShmemChunk>
57 ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
58 size_t size) {
59 base::AutoLock lock(lock_);
60
61 DCHECK_NE(size, 0u);
62
63 // Round up to multiple of page size.
64 size_t pages = (size + base::GetPageSize() - 1) / base::GetPageSize();
65
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;
72
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;
81 }
82
83 return make_scoped_ptr(
84 new DiscardableMemoryShmemChunkImpl(this, free_span.Pass()));
85 }
86
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();
90
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));
94
95 // Create span for allocated memory.
96 scoped_ptr<DiscardableSharedMemoryHeap::Span> new_span(
97 heap_.Grow(shared_memory.Pass(), allocation_size_in_bytes));
98
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());
108 }
109
110 return make_scoped_ptr(
111 new DiscardableMemoryShmemChunkImpl(this, new_span.Pass()));
112 }
113
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());
121 }
122
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());
130 }
131
132 bool ChildDiscardableSharedMemoryManager::IsSpanResident(
133 DiscardableSharedMemoryHeap::Span* span) const {
134 base::AutoLock lock(lock_);
135 return span->shared_memory()->IsMemoryResident();
136 }
137
138 void ChildDiscardableSharedMemoryManager::ReleaseSpan(
139 scoped_ptr<DiscardableSharedMemoryHeap::Span> span) {
140 base::AutoLock lock(lock_);
141
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;
146 }
147
148 heap_.MergeIntoFreeList(span.Pass());
149 }
150
21 scoped_ptr<base::DiscardableSharedMemory> 151 scoped_ptr<base::DiscardableSharedMemory>
22 ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory( 152 ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
23 size_t size) { 153 size_t size) {
24 TRACE_EVENT1("renderer", 154 TRACE_EVENT1("renderer",
25 "ChildDiscardableSharedMemoryManager::" 155 "ChildDiscardableSharedMemoryManager::"
26 "AllocateLockedDiscardableSharedMemory", 156 "AllocateLockedDiscardableSharedMemory",
27 "size", 157 "size",
28 size); 158 size);
29 159
30 base::SharedMemoryHandle handle = base::SharedMemory::NULLHandle(); 160 base::SharedMemoryHandle handle = base::SharedMemory::NULLHandle();
31 sender_->Send( 161 sender_->Send(
32 new ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory( 162 new ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory(
33 size, &handle)); 163 size, &handle));
34 scoped_ptr<base::DiscardableSharedMemory> memory( 164 scoped_ptr<base::DiscardableSharedMemory> memory(
35 new base::DiscardableSharedMemory(handle)); 165 new base::DiscardableSharedMemory(handle));
36 CHECK(memory->Map(size)); 166 CHECK(memory->Map(size));
37 return memory.Pass(); 167 return memory.Pass();
38 } 168 }
39 169
40 } // namespace content 170 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698