OLD | NEW |
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 <utility> |
| 8 |
7 #include "base/atomic_sequence_num.h" | 9 #include "base/atomic_sequence_num.h" |
8 #include "base/bind.h" | 10 #include "base/bind.h" |
9 #include "base/debug/crash_logging.h" | 11 #include "base/debug/crash_logging.h" |
10 #include "base/macros.h" | 12 #include "base/macros.h" |
11 #include "base/memory/discardable_memory.h" | 13 #include "base/memory/discardable_memory.h" |
12 #include "base/memory/discardable_shared_memory.h" | 14 #include "base/memory/discardable_shared_memory.h" |
13 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
14 #include "base/process/memory.h" | 16 #include "base/process/memory.h" |
15 #include "base/process/process_metrics.h" | 17 #include "base/process/process_metrics.h" |
16 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
17 #include "base/thread_task_runner_handle.h" | 19 #include "base/thread_task_runner_handle.h" |
18 #include "base/trace_event/memory_dump_manager.h" | 20 #include "base/trace_event/memory_dump_manager.h" |
19 #include "base/trace_event/trace_event.h" | 21 #include "base/trace_event/trace_event.h" |
20 #include "content/common/child_process_messages.h" | 22 #include "content/common/child_process_messages.h" |
21 | 23 |
22 namespace content { | 24 namespace content { |
23 namespace { | 25 namespace { |
24 | 26 |
25 // Default allocation size. | 27 // Default allocation size. |
26 const size_t kAllocationSize = 4 * 1024 * 1024; | 28 const size_t kAllocationSize = 4 * 1024 * 1024; |
27 | 29 |
28 // Global atomic to generate unique discardable shared memory IDs. | 30 // Global atomic to generate unique discardable shared memory IDs. |
29 base::StaticAtomicSequenceNumber g_next_discardable_shared_memory_id; | 31 base::StaticAtomicSequenceNumber g_next_discardable_shared_memory_id; |
30 | 32 |
31 class DiscardableMemoryImpl : public base::DiscardableMemory { | 33 class DiscardableMemoryImpl : public base::DiscardableMemory { |
32 public: | 34 public: |
33 DiscardableMemoryImpl(ChildDiscardableSharedMemoryManager* manager, | 35 DiscardableMemoryImpl(ChildDiscardableSharedMemoryManager* manager, |
34 scoped_ptr<DiscardableSharedMemoryHeap::Span> span) | 36 scoped_ptr<DiscardableSharedMemoryHeap::Span> span) |
35 : manager_(manager), span_(span.Pass()), is_locked_(true) {} | 37 : manager_(manager), span_(std::move(span)), is_locked_(true) {} |
36 | 38 |
37 ~DiscardableMemoryImpl() override { | 39 ~DiscardableMemoryImpl() override { |
38 if (is_locked_) | 40 if (is_locked_) |
39 manager_->UnlockSpan(span_.get()); | 41 manager_->UnlockSpan(span_.get()); |
40 | 42 |
41 manager_->ReleaseSpan(span_.Pass()); | 43 manager_->ReleaseSpan(std::move(span_)); |
42 } | 44 } |
43 | 45 |
44 // Overridden from base::DiscardableMemory: | 46 // Overridden from base::DiscardableMemory: |
45 bool Lock() override { | 47 bool Lock() override { |
46 DCHECK(!is_locked_); | 48 DCHECK(!is_locked_); |
47 | 49 |
48 if (!manager_->LockSpan(span_.get())) | 50 if (!manager_->LockSpan(span_.get())) |
49 return false; | 51 return false; |
50 | 52 |
51 is_locked_ = true; | 53 is_locked_ = true; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 DCHECK(!free_span->shared_memory()); | 152 DCHECK(!free_span->shared_memory()); |
151 continue; | 153 continue; |
152 } | 154 } |
153 | 155 |
154 free_span->set_is_locked(true); | 156 free_span->set_is_locked(true); |
155 | 157 |
156 // Memory usage is guaranteed to have changed after having removed | 158 // Memory usage is guaranteed to have changed after having removed |
157 // at least one span from the free lists. | 159 // at least one span from the free lists. |
158 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); | 160 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
159 | 161 |
160 return make_scoped_ptr(new DiscardableMemoryImpl(this, free_span.Pass())); | 162 return make_scoped_ptr( |
| 163 new DiscardableMemoryImpl(this, std::move(free_span))); |
161 } | 164 } |
162 | 165 |
163 // Release purged memory to free up the address space before we attempt to | 166 // Release purged memory to free up the address space before we attempt to |
164 // allocate more memory. | 167 // allocate more memory. |
165 heap_.ReleasePurgedMemory(); | 168 heap_.ReleasePurgedMemory(); |
166 | 169 |
167 // Make sure crash keys are up to date in case allocation fails. | 170 // Make sure crash keys are up to date in case allocation fails. |
168 if (heap_.GetSize() != heap_size_prior_to_releasing_purged_memory) | 171 if (heap_.GetSize() != heap_size_prior_to_releasing_purged_memory) |
169 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); | 172 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
170 | 173 |
171 size_t pages_to_allocate = | 174 size_t pages_to_allocate = |
172 std::max(kAllocationSize / base::GetPageSize(), pages); | 175 std::max(kAllocationSize / base::GetPageSize(), pages); |
173 size_t allocation_size_in_bytes = pages_to_allocate * base::GetPageSize(); | 176 size_t allocation_size_in_bytes = pages_to_allocate * base::GetPageSize(); |
174 | 177 |
175 DiscardableSharedMemoryId new_id = | 178 DiscardableSharedMemoryId new_id = |
176 g_next_discardable_shared_memory_id.GetNext(); | 179 g_next_discardable_shared_memory_id.GetNext(); |
177 | 180 |
178 // Ask parent process to allocate a new discardable shared memory segment. | 181 // Ask parent process to allocate a new discardable shared memory segment. |
179 scoped_ptr<base::DiscardableSharedMemory> shared_memory( | 182 scoped_ptr<base::DiscardableSharedMemory> shared_memory( |
180 AllocateLockedDiscardableSharedMemory(allocation_size_in_bytes, new_id)); | 183 AllocateLockedDiscardableSharedMemory(allocation_size_in_bytes, new_id)); |
181 | 184 |
182 // Create span for allocated memory. | 185 // Create span for allocated memory. |
183 scoped_ptr<DiscardableSharedMemoryHeap::Span> new_span(heap_.Grow( | 186 scoped_ptr<DiscardableSharedMemoryHeap::Span> new_span(heap_.Grow( |
184 shared_memory.Pass(), allocation_size_in_bytes, new_id, | 187 std::move(shared_memory), allocation_size_in_bytes, new_id, |
185 base::Bind(&SendDeletedDiscardableSharedMemoryMessage, sender_, new_id))); | 188 base::Bind(&SendDeletedDiscardableSharedMemoryMessage, sender_, new_id))); |
186 new_span->set_is_locked(true); | 189 new_span->set_is_locked(true); |
187 | 190 |
188 // Unlock and insert any left over memory into free lists. | 191 // Unlock and insert any left over memory into free lists. |
189 if (pages < pages_to_allocate) { | 192 if (pages < pages_to_allocate) { |
190 scoped_ptr<DiscardableSharedMemoryHeap::Span> leftover = | 193 scoped_ptr<DiscardableSharedMemoryHeap::Span> leftover = |
191 heap_.Split(new_span.get(), pages); | 194 heap_.Split(new_span.get(), pages); |
192 leftover->shared_memory()->Unlock( | 195 leftover->shared_memory()->Unlock( |
193 leftover->start() * base::GetPageSize() - | 196 leftover->start() * base::GetPageSize() - |
194 reinterpret_cast<size_t>(leftover->shared_memory()->memory()), | 197 reinterpret_cast<size_t>(leftover->shared_memory()->memory()), |
195 leftover->length() * base::GetPageSize()); | 198 leftover->length() * base::GetPageSize()); |
196 leftover->set_is_locked(false); | 199 leftover->set_is_locked(false); |
197 heap_.MergeIntoFreeLists(leftover.Pass()); | 200 heap_.MergeIntoFreeLists(std::move(leftover)); |
198 } | 201 } |
199 | 202 |
200 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); | 203 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
201 | 204 |
202 return make_scoped_ptr(new DiscardableMemoryImpl(this, new_span.Pass())); | 205 return make_scoped_ptr(new DiscardableMemoryImpl(this, std::move(new_span))); |
203 } | 206 } |
204 | 207 |
205 bool ChildDiscardableSharedMemoryManager::OnMemoryDump( | 208 bool ChildDiscardableSharedMemoryManager::OnMemoryDump( |
206 const base::trace_event::MemoryDumpArgs& args, | 209 const base::trace_event::MemoryDumpArgs& args, |
207 base::trace_event::ProcessMemoryDump* pmd) { | 210 base::trace_event::ProcessMemoryDump* pmd) { |
208 base::AutoLock lock(lock_); | 211 base::AutoLock lock(lock_); |
209 return heap_.OnMemoryDump(pmd); | 212 return heap_.OnMemoryDump(pmd); |
210 } | 213 } |
211 | 214 |
212 void ChildDiscardableSharedMemoryManager::ReleaseFreeMemory() { | 215 void ChildDiscardableSharedMemoryManager::ReleaseFreeMemory() { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 } | 266 } |
264 | 267 |
265 void ChildDiscardableSharedMemoryManager::ReleaseSpan( | 268 void ChildDiscardableSharedMemoryManager::ReleaseSpan( |
266 scoped_ptr<DiscardableSharedMemoryHeap::Span> span) { | 269 scoped_ptr<DiscardableSharedMemoryHeap::Span> span) { |
267 base::AutoLock lock(lock_); | 270 base::AutoLock lock(lock_); |
268 | 271 |
269 // Delete span instead of merging it into free lists if memory is gone. | 272 // Delete span instead of merging it into free lists if memory is gone. |
270 if (!span->shared_memory()) | 273 if (!span->shared_memory()) |
271 return; | 274 return; |
272 | 275 |
273 heap_.MergeIntoFreeLists(span.Pass()); | 276 heap_.MergeIntoFreeLists(std::move(span)); |
274 | 277 |
275 // Bytes of free memory changed. | 278 // Bytes of free memory changed. |
276 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); | 279 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
277 } | 280 } |
278 | 281 |
279 base::trace_event::MemoryAllocatorDump* | 282 base::trace_event::MemoryAllocatorDump* |
280 ChildDiscardableSharedMemoryManager::CreateMemoryAllocatorDump( | 283 ChildDiscardableSharedMemoryManager::CreateMemoryAllocatorDump( |
281 DiscardableSharedMemoryHeap::Span* span, | 284 DiscardableSharedMemoryHeap::Span* span, |
282 const char* name, | 285 const char* name, |
283 base::trace_event::ProcessMemoryDump* pmd) const { | 286 base::trace_event::ProcessMemoryDump* pmd) const { |
(...skipping 11 matching lines...) Expand all Loading... |
295 "size", size, "id", id); | 298 "size", size, "id", id); |
296 | 299 |
297 base::SharedMemoryHandle handle = base::SharedMemory::NULLHandle(); | 300 base::SharedMemoryHandle handle = base::SharedMemory::NULLHandle(); |
298 sender_->Send( | 301 sender_->Send( |
299 new ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory( | 302 new ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory( |
300 size, id, &handle)); | 303 size, id, &handle)); |
301 scoped_ptr<base::DiscardableSharedMemory> memory( | 304 scoped_ptr<base::DiscardableSharedMemory> memory( |
302 new base::DiscardableSharedMemory(handle)); | 305 new base::DiscardableSharedMemory(handle)); |
303 if (!memory->Map(size)) | 306 if (!memory->Map(size)) |
304 base::TerminateBecauseOutOfMemory(size); | 307 base::TerminateBecauseOutOfMemory(size); |
305 return memory.Pass(); | 308 return memory; |
306 } | 309 } |
307 | 310 |
308 void ChildDiscardableSharedMemoryManager::MemoryUsageChanged( | 311 void ChildDiscardableSharedMemoryManager::MemoryUsageChanged( |
309 size_t new_bytes_total, | 312 size_t new_bytes_total, |
310 size_t new_bytes_free) const { | 313 size_t new_bytes_free) const { |
311 static const char kDiscardableMemoryAllocatedKey[] = | 314 static const char kDiscardableMemoryAllocatedKey[] = |
312 "discardable-memory-allocated"; | 315 "discardable-memory-allocated"; |
313 base::debug::SetCrashKeyValue(kDiscardableMemoryAllocatedKey, | 316 base::debug::SetCrashKeyValue(kDiscardableMemoryAllocatedKey, |
314 base::Uint64ToString(new_bytes_total)); | 317 base::Uint64ToString(new_bytes_total)); |
315 | 318 |
316 static const char kDiscardableMemoryFreeKey[] = "discardable-memory-free"; | 319 static const char kDiscardableMemoryFreeKey[] = "discardable-memory-free"; |
317 base::debug::SetCrashKeyValue(kDiscardableMemoryFreeKey, | 320 base::debug::SetCrashKeyValue(kDiscardableMemoryFreeKey, |
318 base::Uint64ToString(new_bytes_free)); | 321 base::Uint64ToString(new_bytes_free)); |
319 } | 322 } |
320 | 323 |
321 } // namespace content | 324 } // namespace content |
OLD | NEW |