Index: content/child/child_discardable_shared_memory_manager.cc |
diff --git a/content/child/child_discardable_shared_memory_manager.cc b/content/child/child_discardable_shared_memory_manager.cc |
deleted file mode 100644 |
index 1d1aa4c4591f0ba2aaacf3050aeb3e08ba6c4dc4..0000000000000000000000000000000000000000 |
--- a/content/child/child_discardable_shared_memory_manager.cc |
+++ /dev/null |
@@ -1,356 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "content/child/child_discardable_shared_memory_manager.h" |
- |
-#include <inttypes.h> |
- |
-#include <algorithm> |
-#include <utility> |
- |
-#include "base/atomic_sequence_num.h" |
-#include "base/bind.h" |
-#include "base/debug/crash_logging.h" |
-#include "base/macros.h" |
-#include "base/memory/discardable_memory.h" |
-#include "base/memory/discardable_shared_memory.h" |
-#include "base/memory/ptr_util.h" |
-#include "base/metrics/histogram_macros.h" |
-#include "base/process/memory.h" |
-#include "base/process/process_metrics.h" |
-#include "base/strings/string_number_conversions.h" |
-#include "base/strings/stringprintf.h" |
-#include "base/threading/thread_task_runner_handle.h" |
-#include "base/trace_event/memory_dump_manager.h" |
-#include "base/trace_event/trace_event.h" |
-#include "content/common/child_process_messages.h" |
- |
-namespace content { |
-namespace { |
- |
-// Default allocation size. |
-const size_t kAllocationSize = 4 * 1024 * 1024; |
- |
-// Global atomic to generate unique discardable shared memory IDs. |
-base::StaticAtomicSequenceNumber g_next_discardable_shared_memory_id; |
- |
-class DiscardableMemoryImpl : public base::DiscardableMemory { |
- public: |
- DiscardableMemoryImpl(ChildDiscardableSharedMemoryManager* manager, |
- std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) |
- : manager_(manager), span_(std::move(span)), is_locked_(true) {} |
- |
- ~DiscardableMemoryImpl() override { |
- if (is_locked_) |
- manager_->UnlockSpan(span_.get()); |
- |
- manager_->ReleaseSpan(std::move(span_)); |
- } |
- |
- // Overridden from base::DiscardableMemory: |
- bool Lock() override { |
- DCHECK(!is_locked_); |
- |
- if (!manager_->LockSpan(span_.get())) |
- return false; |
- |
- is_locked_ = true; |
- return true; |
- } |
- void Unlock() override { |
- DCHECK(is_locked_); |
- |
- manager_->UnlockSpan(span_.get()); |
- is_locked_ = false; |
- } |
- void* data() const override { |
- DCHECK(is_locked_); |
- return reinterpret_cast<void*>(span_->start() * base::GetPageSize()); |
- } |
- |
- base::trace_event::MemoryAllocatorDump* CreateMemoryAllocatorDump( |
- const char* name, |
- base::trace_event::ProcessMemoryDump* pmd) const override { |
- return manager_->CreateMemoryAllocatorDump(span_.get(), name, pmd); |
- } |
- |
- private: |
- ChildDiscardableSharedMemoryManager* const manager_; |
- std::unique_ptr<DiscardableSharedMemoryHeap::Span> span_; |
- bool is_locked_; |
- |
- DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryImpl); |
-}; |
- |
-void SendDeletedDiscardableSharedMemoryMessage( |
- scoped_refptr<ThreadSafeSender> sender, |
- DiscardableSharedMemoryId id) { |
- sender->Send(new ChildProcessHostMsg_DeletedDiscardableSharedMemory(id)); |
-} |
- |
-} // namespace |
- |
-ChildDiscardableSharedMemoryManager::ChildDiscardableSharedMemoryManager( |
- ThreadSafeSender* sender) |
- : heap_(base::GetPageSize()), sender_(sender) { |
- base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( |
- this, "ChildDiscardableSharedMemoryManager", |
- base::ThreadTaskRunnerHandle::Get()); |
-} |
- |
-ChildDiscardableSharedMemoryManager::~ChildDiscardableSharedMemoryManager() { |
- base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( |
- this); |
- // TODO(reveman): Determine if this DCHECK can be enabled. crbug.com/430533 |
- // DCHECK_EQ(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
- if (heap_.GetSize()) |
- MemoryUsageChanged(0, 0); |
-} |
- |
-std::unique_ptr<base::DiscardableMemory> |
-ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory( |
- size_t size) { |
- base::AutoLock lock(lock_); |
- |
- DCHECK_NE(size, 0u); |
- |
- UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.DiscardableAllocationSize", |
- size / 1024, // In KB |
- 1, |
- 4 * 1024 * 1024, // 4 GB |
- 50); |
- |
- // Round up to multiple of page size. |
- size_t pages = |
- std::max((size + base::GetPageSize() - 1) / base::GetPageSize(), |
- static_cast<size_t>(1)); |
- |
- // Default allocation size in pages. |
- size_t allocation_pages = kAllocationSize / base::GetPageSize(); |
- |
- size_t slack = 0; |
- // When searching the free lists, allow a slack between required size and |
- // free span size that is less or equal to kAllocationSize. This is to |
- // avoid segments larger then kAllocationSize unless they are a perfect |
- // fit. The result is that large allocations can be reused without reducing |
- // the ability to discard memory. |
- if (pages < allocation_pages) |
- slack = allocation_pages - pages; |
- |
- size_t heap_size_prior_to_releasing_purged_memory = heap_.GetSize(); |
- for (;;) { |
- // Search free lists for suitable span. |
- std::unique_ptr<DiscardableSharedMemoryHeap::Span> free_span = |
- heap_.SearchFreeLists(pages, slack); |
- if (!free_span.get()) |
- break; |
- |
- // Attempt to lock |free_span|. Delete span and search free lists again |
- // if locking failed. |
- if (free_span->shared_memory()->Lock( |
- free_span->start() * base::GetPageSize() - |
- reinterpret_cast<size_t>(free_span->shared_memory()->memory()), |
- free_span->length() * base::GetPageSize()) == |
- base::DiscardableSharedMemory::FAILED) { |
- DCHECK(!free_span->shared_memory()->IsMemoryResident()); |
- // We have to release purged memory before |free_span| can be destroyed. |
- heap_.ReleasePurgedMemory(); |
- DCHECK(!free_span->shared_memory()); |
- continue; |
- } |
- |
- free_span->set_is_locked(true); |
- |
- // Memory usage is guaranteed to have changed after having removed |
- // at least one span from the free lists. |
- MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
- |
- return base::MakeUnique<DiscardableMemoryImpl>(this, std::move(free_span)); |
- } |
- |
- // Release purged memory to free up the address space before we attempt to |
- // allocate more memory. |
- heap_.ReleasePurgedMemory(); |
- |
- // Make sure crash keys are up to date in case allocation fails. |
- if (heap_.GetSize() != heap_size_prior_to_releasing_purged_memory) |
- MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
- |
- size_t pages_to_allocate = |
- std::max(kAllocationSize / base::GetPageSize(), pages); |
- size_t allocation_size_in_bytes = pages_to_allocate * base::GetPageSize(); |
- |
- DiscardableSharedMemoryId new_id = |
- g_next_discardable_shared_memory_id.GetNext(); |
- |
- // Ask parent process to allocate a new discardable shared memory segment. |
- std::unique_ptr<base::DiscardableSharedMemory> shared_memory( |
- AllocateLockedDiscardableSharedMemory(allocation_size_in_bytes, new_id)); |
- |
- // Create span for allocated memory. |
- std::unique_ptr<DiscardableSharedMemoryHeap::Span> new_span(heap_.Grow( |
- std::move(shared_memory), allocation_size_in_bytes, new_id, |
- base::Bind(&SendDeletedDiscardableSharedMemoryMessage, sender_, new_id))); |
- new_span->set_is_locked(true); |
- |
- // Unlock and insert any left over memory into free lists. |
- if (pages < pages_to_allocate) { |
- std::unique_ptr<DiscardableSharedMemoryHeap::Span> leftover = |
- heap_.Split(new_span.get(), pages); |
- leftover->shared_memory()->Unlock( |
- leftover->start() * base::GetPageSize() - |
- reinterpret_cast<size_t>(leftover->shared_memory()->memory()), |
- leftover->length() * base::GetPageSize()); |
- leftover->set_is_locked(false); |
- heap_.MergeIntoFreeLists(std::move(leftover)); |
- } |
- |
- MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
- |
- return base::MakeUnique<DiscardableMemoryImpl>(this, std::move(new_span)); |
-} |
- |
-bool ChildDiscardableSharedMemoryManager::OnMemoryDump( |
- const base::trace_event::MemoryDumpArgs& args, |
- base::trace_event::ProcessMemoryDump* pmd) { |
- base::AutoLock lock(lock_); |
- if (args.level_of_detail == |
- base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) { |
- base::trace_event::MemoryAllocatorDump* total_dump = |
- pmd->CreateAllocatorDump( |
- base::StringPrintf("discardable/child_0x%" PRIXPTR, |
- reinterpret_cast<uintptr_t>(this))); |
- const size_t total_size = heap_.GetSize(); |
- const size_t freelist_size = heap_.GetSizeOfFreeLists(); |
- total_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, |
- base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
- total_size - freelist_size); |
- total_dump->AddScalar("freelist_size", |
- base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
- freelist_size); |
- return true; |
- } |
- |
- return heap_.OnMemoryDump(pmd); |
-} |
- |
-ChildDiscardableSharedMemoryManager::Statistics |
-ChildDiscardableSharedMemoryManager::GetStatistics() const { |
- base::AutoLock lock(lock_); |
- Statistics stats; |
- stats.total_size = heap_.GetSize(); |
- stats.freelist_size = heap_.GetSizeOfFreeLists(); |
- return stats; |
-} |
- |
-void ChildDiscardableSharedMemoryManager::ReleaseFreeMemory() { |
- base::AutoLock lock(lock_); |
- |
- size_t heap_size_prior_to_releasing_memory = heap_.GetSize(); |
- |
- // Release both purged and free memory. |
- heap_.ReleasePurgedMemory(); |
- heap_.ReleaseFreeMemory(); |
- |
- if (heap_.GetSize() != heap_size_prior_to_releasing_memory) |
- MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
-} |
- |
-bool ChildDiscardableSharedMemoryManager::LockSpan( |
- DiscardableSharedMemoryHeap::Span* span) { |
- base::AutoLock lock(lock_); |
- |
- if (!span->shared_memory()) |
- return false; |
- |
- size_t offset = span->start() * base::GetPageSize() - |
- reinterpret_cast<size_t>(span->shared_memory()->memory()); |
- size_t length = span->length() * base::GetPageSize(); |
- |
- switch (span->shared_memory()->Lock(offset, length)) { |
- case base::DiscardableSharedMemory::SUCCESS: |
- span->set_is_locked(true); |
- return true; |
- case base::DiscardableSharedMemory::PURGED: |
- span->shared_memory()->Unlock(offset, length); |
- span->set_is_locked(false); |
- return false; |
- case base::DiscardableSharedMemory::FAILED: |
- return false; |
- } |
- |
- NOTREACHED(); |
- return false; |
-} |
- |
-void ChildDiscardableSharedMemoryManager::UnlockSpan( |
- DiscardableSharedMemoryHeap::Span* span) { |
- base::AutoLock lock(lock_); |
- |
- DCHECK(span->shared_memory()); |
- size_t offset = span->start() * base::GetPageSize() - |
- reinterpret_cast<size_t>(span->shared_memory()->memory()); |
- size_t length = span->length() * base::GetPageSize(); |
- |
- span->set_is_locked(false); |
- return span->shared_memory()->Unlock(offset, length); |
-} |
- |
-void ChildDiscardableSharedMemoryManager::ReleaseSpan( |
- std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) { |
- base::AutoLock lock(lock_); |
- |
- // Delete span instead of merging it into free lists if memory is gone. |
- if (!span->shared_memory()) |
- return; |
- |
- heap_.MergeIntoFreeLists(std::move(span)); |
- |
- // Bytes of free memory changed. |
- MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
-} |
- |
-base::trace_event::MemoryAllocatorDump* |
-ChildDiscardableSharedMemoryManager::CreateMemoryAllocatorDump( |
- DiscardableSharedMemoryHeap::Span* span, |
- const char* name, |
- base::trace_event::ProcessMemoryDump* pmd) const { |
- base::AutoLock lock(lock_); |
- return heap_.CreateMemoryAllocatorDump(span, name, pmd); |
-} |
- |
-std::unique_ptr<base::DiscardableSharedMemory> |
-ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory( |
- size_t size, |
- DiscardableSharedMemoryId id) { |
- TRACE_EVENT2("renderer", |
- "ChildDiscardableSharedMemoryManager::" |
- "AllocateLockedDiscardableSharedMemory", |
- "size", size, "id", id); |
- |
- base::SharedMemoryHandle handle = base::SharedMemory::NULLHandle(); |
- sender_->Send( |
- new ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory( |
- size, id, &handle)); |
- std::unique_ptr<base::DiscardableSharedMemory> memory( |
- new base::DiscardableSharedMemory(handle)); |
- if (!memory->Map(size)) |
- base::TerminateBecauseOutOfMemory(size); |
- return memory; |
-} |
- |
-void ChildDiscardableSharedMemoryManager::MemoryUsageChanged( |
- size_t new_bytes_total, |
- size_t new_bytes_free) const { |
- static const char kDiscardableMemoryAllocatedKey[] = |
- "discardable-memory-allocated"; |
- base::debug::SetCrashKeyValue(kDiscardableMemoryAllocatedKey, |
- base::Uint64ToString(new_bytes_total)); |
- |
- static const char kDiscardableMemoryFreeKey[] = "discardable-memory-free"; |
- base::debug::SetCrashKeyValue(kDiscardableMemoryFreeKey, |
- base::Uint64ToString(new_bytes_free)); |
-} |
- |
-} // namespace content |