| 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 "components/discardable_memory/client/child_discardable_shared_memory_m
anager.h" |
| 6 | 6 |
| 7 #include <inttypes.h> | 7 #include <inttypes.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/atomic_sequence_num.h" | 12 #include "base/atomic_sequence_num.h" |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/debug/crash_logging.h" | 14 #include "base/debug/crash_logging.h" |
| 15 #include "base/macros.h" | 15 #include "base/macros.h" |
| 16 #include "base/memory/discardable_memory.h" | 16 #include "base/memory/discardable_memory.h" |
| 17 #include "base/memory/discardable_shared_memory.h" | 17 #include "base/memory/discardable_shared_memory.h" |
| 18 #include "base/memory/ptr_util.h" | 18 #include "base/memory/ptr_util.h" |
| 19 #include "base/metrics/histogram_macros.h" | 19 #include "base/metrics/histogram_macros.h" |
| 20 #include "base/process/memory.h" | 20 #include "base/process/memory.h" |
| 21 #include "base/process/process_metrics.h" | 21 #include "base/process/process_metrics.h" |
| 22 #include "base/strings/string_number_conversions.h" | 22 #include "base/strings/string_number_conversions.h" |
| 23 #include "base/strings/stringprintf.h" | 23 #include "base/strings/stringprintf.h" |
| 24 #include "base/threading/thread_task_runner_handle.h" | 24 #include "base/threading/thread_task_runner_handle.h" |
| 25 #include "base/trace_event/memory_dump_manager.h" | 25 #include "base/trace_event/memory_dump_manager.h" |
| 26 #include "base/trace_event/trace_event.h" | 26 #include "base/trace_event/trace_event.h" |
| 27 #include "content/common/child_process_messages.h" | |
| 28 | 27 |
| 29 namespace content { | 28 namespace discardable_memory { |
| 30 namespace { | 29 namespace { |
| 31 | 30 |
| 32 // Default allocation size. | 31 // Default allocation size. |
| 33 const size_t kAllocationSize = 4 * 1024 * 1024; | 32 const size_t kAllocationSize = 4 * 1024 * 1024; |
| 34 | 33 |
| 35 // Global atomic to generate unique discardable shared memory IDs. | 34 // Global atomic to generate unique discardable shared memory IDs. |
| 36 base::StaticAtomicSequenceNumber g_next_discardable_shared_memory_id; | 35 base::StaticAtomicSequenceNumber g_next_discardable_shared_memory_id; |
| 37 | 36 |
| 38 class DiscardableMemoryImpl : public base::DiscardableMemory { | 37 class DiscardableMemoryImpl : public base::DiscardableMemory { |
| 39 public: | 38 public: |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 | 76 |
| 78 private: | 77 private: |
| 79 ChildDiscardableSharedMemoryManager* const manager_; | 78 ChildDiscardableSharedMemoryManager* const manager_; |
| 80 std::unique_ptr<DiscardableSharedMemoryHeap::Span> span_; | 79 std::unique_ptr<DiscardableSharedMemoryHeap::Span> span_; |
| 81 bool is_locked_; | 80 bool is_locked_; |
| 82 | 81 |
| 83 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryImpl); | 82 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryImpl); |
| 84 }; | 83 }; |
| 85 | 84 |
| 86 void SendDeletedDiscardableSharedMemoryMessage( | 85 void SendDeletedDiscardableSharedMemoryMessage( |
| 87 scoped_refptr<ThreadSafeSender> sender, | 86 ChildDiscardableSharedMemoryManager::Delegate* delegate, |
| 88 DiscardableSharedMemoryId id) { | 87 DiscardableSharedMemoryId id) { |
| 89 sender->Send(new ChildProcessHostMsg_DeletedDiscardableSharedMemory(id)); | 88 delegate->DeletedDiscardableSharedMemory(id); |
| 90 } | 89 } |
| 91 | 90 |
| 92 } // namespace | 91 } // namespace |
| 93 | 92 |
| 94 ChildDiscardableSharedMemoryManager::ChildDiscardableSharedMemoryManager( | 93 ChildDiscardableSharedMemoryManager::ChildDiscardableSharedMemoryManager( |
| 95 ThreadSafeSender* sender) | 94 Delegate* delegate) |
| 96 : heap_(base::GetPageSize()), sender_(sender) { | 95 : heap_(base::GetPageSize()), delegate_(delegate) { |
| 97 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( | 96 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( |
| 98 this, "ChildDiscardableSharedMemoryManager", | 97 this, "ChildDiscardableSharedMemoryManager", |
| 99 base::ThreadTaskRunnerHandle::Get()); | 98 base::ThreadTaskRunnerHandle::Get()); |
| 100 } | 99 } |
| 101 | 100 |
| 102 ChildDiscardableSharedMemoryManager::~ChildDiscardableSharedMemoryManager() { | 101 ChildDiscardableSharedMemoryManager::~ChildDiscardableSharedMemoryManager() { |
| 103 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( | 102 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( |
| 104 this); | 103 this); |
| 105 // TODO(reveman): Determine if this DCHECK can be enabled. crbug.com/430533 | 104 // TODO(reveman): Determine if this DCHECK can be enabled. crbug.com/430533 |
| 106 // DCHECK_EQ(heap_.GetSize(), heap_.GetSizeOfFreeLists()); | 105 // DCHECK_EQ(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
| 107 if (heap_.GetSize()) | 106 if (heap_.GetSize()) |
| 108 MemoryUsageChanged(0, 0); | 107 MemoryUsageChanged(0, 0); |
| 109 } | 108 } |
| 110 | 109 |
| 111 std::unique_ptr<base::DiscardableMemory> | 110 std::unique_ptr<base::DiscardableMemory> |
| 112 ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory( | 111 ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory( |
| 113 size_t size) { | 112 size_t size) { |
| 114 base::AutoLock lock(lock_); | 113 base::AutoLock lock(lock_); |
| 115 | 114 |
| 116 DCHECK_NE(size, 0u); | 115 DCHECK_NE(size, 0u); |
| 117 | 116 |
| 117 auto size_in_kb = static_cast<base::HistogramBase::Sample>(size / 1024); |
| 118 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.DiscardableAllocationSize", | 118 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.DiscardableAllocationSize", |
| 119 size / 1024, // In KB | 119 size_in_kb, // In KB |
| 120 1, | 120 1, |
| 121 4 * 1024 * 1024, // 4 GB | 121 4 * 1024 * 1024, // 4 GB |
| 122 50); | 122 50); |
| 123 | 123 |
| 124 // Round up to multiple of page size. | 124 // Round up to multiple of page size. |
| 125 size_t pages = | 125 size_t pages = |
| 126 std::max((size + base::GetPageSize() - 1) / base::GetPageSize(), | 126 std::max((size + base::GetPageSize() - 1) / base::GetPageSize(), |
| 127 static_cast<size_t>(1)); | 127 static_cast<size_t>(1)); |
| 128 | 128 |
| 129 // Default allocation size in pages. | 129 // Default allocation size in pages. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 size_t allocation_size_in_bytes = pages_to_allocate * base::GetPageSize(); | 182 size_t allocation_size_in_bytes = pages_to_allocate * base::GetPageSize(); |
| 183 | 183 |
| 184 DiscardableSharedMemoryId new_id = | 184 DiscardableSharedMemoryId new_id = |
| 185 g_next_discardable_shared_memory_id.GetNext(); | 185 g_next_discardable_shared_memory_id.GetNext(); |
| 186 | 186 |
| 187 // Ask parent process to allocate a new discardable shared memory segment. | 187 // Ask parent process to allocate a new discardable shared memory segment. |
| 188 std::unique_ptr<base::DiscardableSharedMemory> shared_memory( | 188 std::unique_ptr<base::DiscardableSharedMemory> shared_memory( |
| 189 AllocateLockedDiscardableSharedMemory(allocation_size_in_bytes, new_id)); | 189 AllocateLockedDiscardableSharedMemory(allocation_size_in_bytes, new_id)); |
| 190 | 190 |
| 191 // Create span for allocated memory. | 191 // Create span for allocated memory. |
| 192 std::unique_ptr<DiscardableSharedMemoryHeap::Span> new_span(heap_.Grow( | 192 std::unique_ptr<DiscardableSharedMemoryHeap::Span> new_span( |
| 193 std::move(shared_memory), allocation_size_in_bytes, new_id, | 193 heap_.Grow(std::move(shared_memory), allocation_size_in_bytes, new_id, |
| 194 base::Bind(&SendDeletedDiscardableSharedMemoryMessage, sender_, new_id))); | 194 base::Bind(&SendDeletedDiscardableSharedMemoryMessage, |
| 195 delegate_, new_id))); |
| 195 new_span->set_is_locked(true); | 196 new_span->set_is_locked(true); |
| 196 | 197 |
| 197 // Unlock and insert any left over memory into free lists. | 198 // Unlock and insert any left over memory into free lists. |
| 198 if (pages < pages_to_allocate) { | 199 if (pages < pages_to_allocate) { |
| 199 std::unique_ptr<DiscardableSharedMemoryHeap::Span> leftover = | 200 std::unique_ptr<DiscardableSharedMemoryHeap::Span> leftover = |
| 200 heap_.Split(new_span.get(), pages); | 201 heap_.Split(new_span.get(), pages); |
| 201 leftover->shared_memory()->Unlock( | 202 leftover->shared_memory()->Unlock( |
| 202 leftover->start() * base::GetPageSize() - | 203 leftover->start() * base::GetPageSize() - |
| 203 reinterpret_cast<size_t>(leftover->shared_memory()->memory()), | 204 reinterpret_cast<size_t>(leftover->shared_memory()->memory()), |
| 204 leftover->length() * base::GetPageSize()); | 205 leftover->length() * base::GetPageSize()); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 } | 259 } |
| 259 | 260 |
| 260 bool ChildDiscardableSharedMemoryManager::LockSpan( | 261 bool ChildDiscardableSharedMemoryManager::LockSpan( |
| 261 DiscardableSharedMemoryHeap::Span* span) { | 262 DiscardableSharedMemoryHeap::Span* span) { |
| 262 base::AutoLock lock(lock_); | 263 base::AutoLock lock(lock_); |
| 263 | 264 |
| 264 if (!span->shared_memory()) | 265 if (!span->shared_memory()) |
| 265 return false; | 266 return false; |
| 266 | 267 |
| 267 size_t offset = span->start() * base::GetPageSize() - | 268 size_t offset = span->start() * base::GetPageSize() - |
| 268 reinterpret_cast<size_t>(span->shared_memory()->memory()); | 269 reinterpret_cast<size_t>(span->shared_memory()->memory()); |
| 269 size_t length = span->length() * base::GetPageSize(); | 270 size_t length = span->length() * base::GetPageSize(); |
| 270 | 271 |
| 271 switch (span->shared_memory()->Lock(offset, length)) { | 272 switch (span->shared_memory()->Lock(offset, length)) { |
| 272 case base::DiscardableSharedMemory::SUCCESS: | 273 case base::DiscardableSharedMemory::SUCCESS: |
| 273 span->set_is_locked(true); | 274 span->set_is_locked(true); |
| 274 return true; | 275 return true; |
| 275 case base::DiscardableSharedMemory::PURGED: | 276 case base::DiscardableSharedMemory::PURGED: |
| 276 span->shared_memory()->Unlock(offset, length); | 277 span->shared_memory()->Unlock(offset, length); |
| 277 span->set_is_locked(false); | 278 span->set_is_locked(false); |
| 278 return false; | 279 return false; |
| 279 case base::DiscardableSharedMemory::FAILED: | 280 case base::DiscardableSharedMemory::FAILED: |
| 280 return false; | 281 return false; |
| 281 } | 282 } |
| 282 | 283 |
| 283 NOTREACHED(); | 284 NOTREACHED(); |
| 284 return false; | 285 return false; |
| 285 } | 286 } |
| 286 | 287 |
| 287 void ChildDiscardableSharedMemoryManager::UnlockSpan( | 288 void ChildDiscardableSharedMemoryManager::UnlockSpan( |
| 288 DiscardableSharedMemoryHeap::Span* span) { | 289 DiscardableSharedMemoryHeap::Span* span) { |
| 289 base::AutoLock lock(lock_); | 290 base::AutoLock lock(lock_); |
| 290 | 291 |
| 291 DCHECK(span->shared_memory()); | 292 DCHECK(span->shared_memory()); |
| 292 size_t offset = span->start() * base::GetPageSize() - | 293 size_t offset = span->start() * base::GetPageSize() - |
| 293 reinterpret_cast<size_t>(span->shared_memory()->memory()); | 294 reinterpret_cast<size_t>(span->shared_memory()->memory()); |
| 294 size_t length = span->length() * base::GetPageSize(); | 295 size_t length = span->length() * base::GetPageSize(); |
| 295 | 296 |
| 296 span->set_is_locked(false); | 297 span->set_is_locked(false); |
| 297 return span->shared_memory()->Unlock(offset, length); | 298 return span->shared_memory()->Unlock(offset, length); |
| 298 } | 299 } |
| 299 | 300 |
| 300 void ChildDiscardableSharedMemoryManager::ReleaseSpan( | 301 void ChildDiscardableSharedMemoryManager::ReleaseSpan( |
| 301 std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) { | 302 std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) { |
| 302 base::AutoLock lock(lock_); | 303 base::AutoLock lock(lock_); |
| 303 | 304 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 323 std::unique_ptr<base::DiscardableSharedMemory> | 324 std::unique_ptr<base::DiscardableSharedMemory> |
| 324 ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory( | 325 ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory( |
| 325 size_t size, | 326 size_t size, |
| 326 DiscardableSharedMemoryId id) { | 327 DiscardableSharedMemoryId id) { |
| 327 TRACE_EVENT2("renderer", | 328 TRACE_EVENT2("renderer", |
| 328 "ChildDiscardableSharedMemoryManager::" | 329 "ChildDiscardableSharedMemoryManager::" |
| 329 "AllocateLockedDiscardableSharedMemory", | 330 "AllocateLockedDiscardableSharedMemory", |
| 330 "size", size, "id", id); | 331 "size", size, "id", id); |
| 331 | 332 |
| 332 base::SharedMemoryHandle handle = base::SharedMemory::NULLHandle(); | 333 base::SharedMemoryHandle handle = base::SharedMemory::NULLHandle(); |
| 333 sender_->Send( | 334 delegate_->AllocateLockedDiscardableSharedMemory(size, id, &handle); |
| 334 new ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory( | |
| 335 size, id, &handle)); | |
| 336 std::unique_ptr<base::DiscardableSharedMemory> memory( | 335 std::unique_ptr<base::DiscardableSharedMemory> memory( |
| 337 new base::DiscardableSharedMemory(handle)); | 336 new base::DiscardableSharedMemory(handle)); |
| 338 if (!memory->Map(size)) | 337 if (!memory->Map(size)) |
| 339 base::TerminateBecauseOutOfMemory(size); | 338 base::TerminateBecauseOutOfMemory(size); |
| 340 return memory; | 339 return memory; |
| 341 } | 340 } |
| 342 | 341 |
| 343 void ChildDiscardableSharedMemoryManager::MemoryUsageChanged( | 342 void ChildDiscardableSharedMemoryManager::MemoryUsageChanged( |
| 344 size_t new_bytes_total, | 343 size_t new_bytes_total, |
| 345 size_t new_bytes_free) const { | 344 size_t new_bytes_free) const { |
| 346 static const char kDiscardableMemoryAllocatedKey[] = | 345 static const char kDiscardableMemoryAllocatedKey[] = |
| 347 "discardable-memory-allocated"; | 346 "discardable-memory-allocated"; |
| 348 base::debug::SetCrashKeyValue(kDiscardableMemoryAllocatedKey, | 347 base::debug::SetCrashKeyValue(kDiscardableMemoryAllocatedKey, |
| 349 base::Uint64ToString(new_bytes_total)); | 348 base::Uint64ToString(new_bytes_total)); |
| 350 | 349 |
| 351 static const char kDiscardableMemoryFreeKey[] = "discardable-memory-free"; | 350 static const char kDiscardableMemoryFreeKey[] = "discardable-memory-free"; |
| 352 base::debug::SetCrashKeyValue(kDiscardableMemoryFreeKey, | 351 base::debug::SetCrashKeyValue(kDiscardableMemoryFreeKey, |
| 353 base::Uint64ToString(new_bytes_free)); | 352 base::Uint64ToString(new_bytes_free)); |
| 354 } | 353 } |
| 355 | 354 |
| 356 } // namespace content | 355 } // namespace discardable_memory |
| OLD | NEW |