| 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 "base/atomic_sequence_num.h" | 7 #include "base/atomic_sequence_num.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/debug/crash_logging.h" | 9 #include "base/debug/crash_logging.h" |
| 10 #include "base/memory/discardable_memory.h" | 10 #include "base/memory/discardable_memory.h" |
| 11 #include "base/memory/discardable_shared_memory.h" | 11 #include "base/memory/discardable_shared_memory.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/process/memory.h" | 13 #include "base/process/memory.h" |
| 14 #include "base/process/process_metrics.h" | 14 #include "base/process/process_metrics.h" |
| 15 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
| 16 #include "base/thread_task_runner_handle.h" |
| 17 #include "base/trace_event/memory_dump_manager.h" |
| 16 #include "base/trace_event/trace_event.h" | 18 #include "base/trace_event/trace_event.h" |
| 17 #include "content/common/child_process_messages.h" | 19 #include "content/common/child_process_messages.h" |
| 18 | 20 |
| 19 namespace content { | 21 namespace content { |
| 20 namespace { | 22 namespace { |
| 21 | 23 |
| 22 // Default allocation size. | 24 // Default allocation size. |
| 23 #if defined(OS_ANDROID) | 25 #if defined(OS_ANDROID) |
| 24 // Larger allocation size on Android to avoid reaching the FD-limit. | 26 // Larger allocation size on Android to avoid reaching the FD-limit. |
| 25 const size_t kAllocationSize = 32 * 1024 * 1024; | 27 const size_t kAllocationSize = 32 * 1024 * 1024; |
| 26 #else | 28 #else |
| 27 const size_t kAllocationSize = 4 * 1024 * 1024; | 29 const size_t kAllocationSize = 4 * 1024 * 1024; |
| 28 #endif | 30 #endif |
| 29 | 31 |
| 32 const char kMemoryDumperFriendlyName[] = "Discardable"; |
| 33 |
| 30 // Global atomic to generate unique discardable shared memory IDs. | 34 // Global atomic to generate unique discardable shared memory IDs. |
| 31 base::StaticAtomicSequenceNumber g_next_discardable_shared_memory_id; | 35 base::StaticAtomicSequenceNumber g_next_discardable_shared_memory_id; |
| 32 | 36 |
| 33 class DiscardableMemoryImpl : public base::DiscardableMemory { | 37 class DiscardableMemoryImpl : public base::DiscardableMemory { |
| 34 public: | 38 public: |
| 35 DiscardableMemoryImpl(ChildDiscardableSharedMemoryManager* manager, | 39 DiscardableMemoryImpl(ChildDiscardableSharedMemoryManager* manager, |
| 36 scoped_ptr<DiscardableSharedMemoryHeap::Span> span) | 40 scoped_ptr<DiscardableSharedMemoryHeap::Span> span) |
| 37 : manager_(manager), span_(span.Pass()), is_locked_(true) {} | 41 : manager_(manager), span_(span.Pass()), is_locked_(true) {} |
| 38 | 42 |
| 39 ~DiscardableMemoryImpl() override { | 43 ~DiscardableMemoryImpl() override { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 void SendDeletedDiscardableSharedMemoryMessage( | 79 void SendDeletedDiscardableSharedMemoryMessage( |
| 76 scoped_refptr<ThreadSafeSender> sender, | 80 scoped_refptr<ThreadSafeSender> sender, |
| 77 DiscardableSharedMemoryId id) { | 81 DiscardableSharedMemoryId id) { |
| 78 sender->Send(new ChildProcessHostMsg_DeletedDiscardableSharedMemory(id)); | 82 sender->Send(new ChildProcessHostMsg_DeletedDiscardableSharedMemory(id)); |
| 79 } | 83 } |
| 80 | 84 |
| 81 } // namespace | 85 } // namespace |
| 82 | 86 |
| 83 ChildDiscardableSharedMemoryManager::ChildDiscardableSharedMemoryManager( | 87 ChildDiscardableSharedMemoryManager::ChildDiscardableSharedMemoryManager( |
| 84 ThreadSafeSender* sender) | 88 ThreadSafeSender* sender) |
| 85 : heap_(base::GetPageSize()), sender_(sender) { | 89 : MemoryDumpProvider(base::ThreadTaskRunnerHandle::Get()), |
| 90 heap_(base::GetPageSize()), |
| 91 sender_(sender) { |
| 92 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( |
| 93 this); |
| 86 } | 94 } |
| 87 | 95 |
| 88 ChildDiscardableSharedMemoryManager::~ChildDiscardableSharedMemoryManager() { | 96 ChildDiscardableSharedMemoryManager::~ChildDiscardableSharedMemoryManager() { |
| 97 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( |
| 98 this); |
| 89 // TODO(reveman): Determine if this DCHECK can be enabled. crbug.com/430533 | 99 // TODO(reveman): Determine if this DCHECK can be enabled. crbug.com/430533 |
| 90 // DCHECK_EQ(heap_.GetSize(), heap_.GetSizeOfFreeLists()); | 100 // DCHECK_EQ(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
| 91 if (heap_.GetSize()) | 101 if (heap_.GetSize()) |
| 92 MemoryUsageChanged(0, 0); | 102 MemoryUsageChanged(0, 0); |
| 93 } | 103 } |
| 94 | 104 |
| 95 scoped_ptr<base::DiscardableMemory> | 105 scoped_ptr<base::DiscardableMemory> |
| 96 ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory( | 106 ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory( |
| 97 size_t size) { | 107 size_t size) { |
| 98 base::AutoLock lock(lock_); | 108 base::AutoLock lock(lock_); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 | 173 |
| 164 DiscardableSharedMemoryId new_id = | 174 DiscardableSharedMemoryId new_id = |
| 165 g_next_discardable_shared_memory_id.GetNext(); | 175 g_next_discardable_shared_memory_id.GetNext(); |
| 166 | 176 |
| 167 // Ask parent process to allocate a new discardable shared memory segment. | 177 // Ask parent process to allocate a new discardable shared memory segment. |
| 168 scoped_ptr<base::DiscardableSharedMemory> shared_memory( | 178 scoped_ptr<base::DiscardableSharedMemory> shared_memory( |
| 169 AllocateLockedDiscardableSharedMemory(allocation_size_in_bytes, new_id)); | 179 AllocateLockedDiscardableSharedMemory(allocation_size_in_bytes, new_id)); |
| 170 | 180 |
| 171 // Create span for allocated memory. | 181 // Create span for allocated memory. |
| 172 scoped_ptr<DiscardableSharedMemoryHeap::Span> new_span(heap_.Grow( | 182 scoped_ptr<DiscardableSharedMemoryHeap::Span> new_span(heap_.Grow( |
| 173 shared_memory.Pass(), allocation_size_in_bytes, | 183 shared_memory.Pass(), allocation_size_in_bytes, new_id, |
| 174 base::Bind(&SendDeletedDiscardableSharedMemoryMessage, sender_, new_id))); | 184 base::Bind(&SendDeletedDiscardableSharedMemoryMessage, sender_, new_id))); |
| 175 | 185 |
| 176 // Unlock and insert any left over memory into free lists. | 186 // Unlock and insert any left over memory into free lists. |
| 177 if (pages < pages_to_allocate) { | 187 if (pages < pages_to_allocate) { |
| 178 scoped_ptr<DiscardableSharedMemoryHeap::Span> leftover = | 188 scoped_ptr<DiscardableSharedMemoryHeap::Span> leftover = |
| 179 heap_.Split(new_span.get(), pages); | 189 heap_.Split(new_span.get(), pages); |
| 180 leftover->shared_memory()->Unlock( | 190 leftover->shared_memory()->Unlock( |
| 181 leftover->start() * base::GetPageSize() - | 191 leftover->start() * base::GetPageSize() - |
| 182 reinterpret_cast<size_t>(leftover->shared_memory()->memory()), | 192 reinterpret_cast<size_t>(leftover->shared_memory()->memory()), |
| 183 leftover->length() * base::GetPageSize()); | 193 leftover->length() * base::GetPageSize()); |
| 184 heap_.MergeIntoFreeLists(leftover.Pass()); | 194 heap_.MergeIntoFreeLists(leftover.Pass()); |
| 185 } | 195 } |
| 186 | 196 |
| 187 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); | 197 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
| 188 | 198 |
| 189 return make_scoped_ptr(new DiscardableMemoryImpl(this, new_span.Pass())); | 199 return make_scoped_ptr(new DiscardableMemoryImpl(this, new_span.Pass())); |
| 190 } | 200 } |
| 191 | 201 |
| 202 bool ChildDiscardableSharedMemoryManager::DumpInto( |
| 203 base::trace_event::ProcessMemoryDump* pmd) { |
| 204 return heap_.DumpInto(pmd); |
| 205 } |
| 206 |
| 207 const char* ChildDiscardableSharedMemoryManager::GetFriendlyName() const { |
| 208 return kMemoryDumperFriendlyName; |
| 209 } |
| 210 |
| 192 void ChildDiscardableSharedMemoryManager::ReleaseFreeMemory() { | 211 void ChildDiscardableSharedMemoryManager::ReleaseFreeMemory() { |
| 193 base::AutoLock lock(lock_); | 212 base::AutoLock lock(lock_); |
| 194 | 213 |
| 195 size_t heap_size_prior_to_releasing_memory = heap_.GetSize(); | 214 size_t heap_size_prior_to_releasing_memory = heap_.GetSize(); |
| 196 | 215 |
| 197 // Release both purged and free memory. | 216 // Release both purged and free memory. |
| 198 heap_.ReleasePurgedMemory(); | 217 heap_.ReleasePurgedMemory(); |
| 199 heap_.ReleaseFreeMemory(); | 218 heap_.ReleaseFreeMemory(); |
| 200 | 219 |
| 201 if (heap_.GetSize() != heap_size_prior_to_releasing_memory) | 220 if (heap_.GetSize() != heap_size_prior_to_releasing_memory) |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 "discardable-memory-allocated"; | 302 "discardable-memory-allocated"; |
| 284 base::debug::SetCrashKeyValue(kDiscardableMemoryAllocatedKey, | 303 base::debug::SetCrashKeyValue(kDiscardableMemoryAllocatedKey, |
| 285 base::Uint64ToString(new_bytes_total)); | 304 base::Uint64ToString(new_bytes_total)); |
| 286 | 305 |
| 287 static const char kDiscardableMemoryFreeKey[] = "discardable-memory-free"; | 306 static const char kDiscardableMemoryFreeKey[] = "discardable-memory-free"; |
| 288 base::debug::SetCrashKeyValue(kDiscardableMemoryFreeKey, | 307 base::debug::SetCrashKeyValue(kDiscardableMemoryFreeKey, |
| 289 base::Uint64ToString(new_bytes_free)); | 308 base::Uint64ToString(new_bytes_free)); |
| 290 } | 309 } |
| 291 | 310 |
| 292 } // namespace content | 311 } // namespace content |
| OLD | NEW |