| 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 |