| 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_shared_memory.h" | 11 #include "base/memory/discardable_shared_memory.h" |
| 11 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 12 #include "base/process/process_metrics.h" | 13 #include "base/process/process_metrics.h" |
| 13 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
| 15 #include "content/common/child_process_messages.h" | 16 #include "content/common/child_process_messages.h" |
| 16 | 17 |
| 17 namespace content { | 18 namespace content { |
| 18 namespace { | 19 namespace { |
| 19 | 20 |
| 20 // Default allocation size. | 21 // Default allocation size. |
| 21 #if defined(OS_ANDROID) | 22 #if defined(OS_ANDROID) |
| 22 // Larger allocation size on Android to avoid reaching the FD-limit. | 23 // Larger allocation size on Android to avoid reaching the FD-limit. |
| 23 const size_t kAllocationSize = 32 * 1024 * 1024; | 24 const size_t kAllocationSize = 32 * 1024 * 1024; |
| 24 #else | 25 #else |
| 25 const size_t kAllocationSize = 4 * 1024 * 1024; | 26 const size_t kAllocationSize = 4 * 1024 * 1024; |
| 26 #endif | 27 #endif |
| 27 | 28 |
| 28 // Global atomic to generate unique discardable shared memory IDs. | 29 // Global atomic to generate unique discardable shared memory IDs. |
| 29 base::StaticAtomicSequenceNumber g_next_discardable_shared_memory_id; | 30 base::StaticAtomicSequenceNumber g_next_discardable_shared_memory_id; |
| 30 | 31 |
| 31 class DiscardableMemoryShmemChunkImpl | 32 class DiscardableMemoryImpl : public base::DiscardableMemory { |
| 32 : public base::DiscardableMemoryShmemChunk { | |
| 33 public: | 33 public: |
| 34 DiscardableMemoryShmemChunkImpl( | 34 DiscardableMemoryImpl(ChildDiscardableSharedMemoryManager* manager, |
| 35 ChildDiscardableSharedMemoryManager* manager, | 35 scoped_ptr<DiscardableSharedMemoryHeap::Span> span) |
| 36 scoped_ptr<DiscardableSharedMemoryHeap::Span> span) | 36 : manager_(manager), span_(span.Pass()), is_locked_(true) {} |
| 37 : manager_(manager), span_(span.Pass()) {} | 37 |
| 38 ~DiscardableMemoryShmemChunkImpl() override { | 38 ~DiscardableMemoryImpl() override { |
| 39 if (is_locked_) |
| 40 manager_->UnlockSpan(span_.get()); |
| 41 |
| 39 manager_->ReleaseSpan(span_.Pass()); | 42 manager_->ReleaseSpan(span_.Pass()); |
| 40 } | 43 } |
| 41 | 44 |
| 42 // Overridden from DiscardableMemoryShmemChunk: | 45 // Overridden from base::DiscardableMemory: |
| 43 bool Lock() override { return manager_->LockSpan(span_.get()); } | 46 bool Lock() override { |
| 44 void Unlock() override { manager_->UnlockSpan(span_.get()); } | 47 DCHECK(!is_locked_); |
| 48 |
| 49 if (!manager_->LockSpan(span_.get())) |
| 50 return false; |
| 51 |
| 52 is_locked_ = true; |
| 53 return true; |
| 54 } |
| 55 void Unlock() override { |
| 56 DCHECK(is_locked_); |
| 57 |
| 58 manager_->UnlockSpan(span_.get()); |
| 59 is_locked_ = false; |
| 60 } |
| 45 void* Memory() const override { | 61 void* Memory() const override { |
| 62 DCHECK(is_locked_); |
| 46 return reinterpret_cast<void*>(span_->start() * base::GetPageSize()); | 63 return reinterpret_cast<void*>(span_->start() * base::GetPageSize()); |
| 47 } | 64 } |
| 48 | 65 |
| 49 private: | 66 private: |
| 50 ChildDiscardableSharedMemoryManager* manager_; | 67 ChildDiscardableSharedMemoryManager* const manager_; |
| 51 scoped_ptr<DiscardableSharedMemoryHeap::Span> span_; | 68 scoped_ptr<DiscardableSharedMemoryHeap::Span> span_; |
| 69 bool is_locked_; |
| 52 | 70 |
| 53 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryShmemChunkImpl); | 71 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryImpl); |
| 54 }; | 72 }; |
| 55 | 73 |
| 56 void DeletedDiscardableSharedMemory(scoped_refptr<ThreadSafeSender> sender, | 74 void DeletedDiscardableSharedMemory(scoped_refptr<ThreadSafeSender> sender, |
| 57 DiscardableSharedMemoryId id) { | 75 DiscardableSharedMemoryId id) { |
| 58 sender->Send(new ChildProcessHostMsg_DeletedDiscardableSharedMemory(id)); | 76 sender->Send(new ChildProcessHostMsg_DeletedDiscardableSharedMemory(id)); |
| 59 } | 77 } |
| 60 | 78 |
| 61 } // namespace | 79 } // namespace |
| 62 | 80 |
| 63 ChildDiscardableSharedMemoryManager::ChildDiscardableSharedMemoryManager( | 81 ChildDiscardableSharedMemoryManager::ChildDiscardableSharedMemoryManager( |
| 64 ThreadSafeSender* sender) | 82 ThreadSafeSender* sender) |
| 65 : heap_(base::GetPageSize()), sender_(sender) { | 83 : heap_(base::GetPageSize()), sender_(sender) { |
| 66 } | 84 } |
| 67 | 85 |
| 68 ChildDiscardableSharedMemoryManager::~ChildDiscardableSharedMemoryManager() { | 86 ChildDiscardableSharedMemoryManager::~ChildDiscardableSharedMemoryManager() { |
| 69 // TODO(reveman): Determine if this DCHECK can be enabled. crbug.com/430533 | 87 // TODO(reveman): Determine if this DCHECK can be enabled. crbug.com/430533 |
| 70 // DCHECK_EQ(heap_.GetSize(), heap_.GetSizeOfFreeLists()); | 88 // DCHECK_EQ(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
| 71 if (heap_.GetSize()) | 89 if (heap_.GetSize()) |
| 72 MemoryUsageChanged(0, 0); | 90 MemoryUsageChanged(0, 0); |
| 73 } | 91 } |
| 74 | 92 |
| 75 scoped_ptr<base::DiscardableMemoryShmemChunk> | 93 scoped_ptr<base::DiscardableMemory> |
| 76 ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory( | 94 ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory( |
| 77 size_t size) { | 95 size_t size) { |
| 78 base::AutoLock lock(lock_); | 96 base::AutoLock lock(lock_); |
| 79 | 97 |
| 80 DCHECK_NE(size, 0u); | 98 DCHECK_NE(size, 0u); |
| 81 | 99 |
| 82 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.DiscardableAllocationSize", | 100 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.DiscardableAllocationSize", |
| 83 size / 1024, // In KB | 101 size / 1024, // In KB |
| 84 1, | 102 1, |
| 85 4 * 1024 * 1024, // 4 GB | 103 4 * 1024 * 1024, // 4 GB |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 // We have to release purged memory before |free_span| can be destroyed. | 137 // We have to release purged memory before |free_span| can be destroyed. |
| 120 heap_.ReleasePurgedMemory(); | 138 heap_.ReleasePurgedMemory(); |
| 121 DCHECK(!free_span->shared_memory()); | 139 DCHECK(!free_span->shared_memory()); |
| 122 continue; | 140 continue; |
| 123 } | 141 } |
| 124 | 142 |
| 125 // Memory usage is guaranteed to have changed after having removed | 143 // Memory usage is guaranteed to have changed after having removed |
| 126 // at least one span from the free lists. | 144 // at least one span from the free lists. |
| 127 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); | 145 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
| 128 | 146 |
| 129 return make_scoped_ptr( | 147 return make_scoped_ptr(new DiscardableMemoryImpl(this, free_span.Pass())); |
| 130 new DiscardableMemoryShmemChunkImpl(this, free_span.Pass())); | |
| 131 } | 148 } |
| 132 | 149 |
| 133 // Release purged memory to free up the address space before we attempt to | 150 // Release purged memory to free up the address space before we attempt to |
| 134 // allocate more memory. | 151 // allocate more memory. |
| 135 heap_.ReleasePurgedMemory(); | 152 heap_.ReleasePurgedMemory(); |
| 136 | 153 |
| 137 // Make sure crash keys are up to date in case allocation fails. | 154 // Make sure crash keys are up to date in case allocation fails. |
| 138 if (heap_.GetSize() != heap_size_prior_to_releasing_purged_memory) | 155 if (heap_.GetSize() != heap_size_prior_to_releasing_purged_memory) |
| 139 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); | 156 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
| 140 | 157 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 160 heap_.Split(new_span.get(), pages); | 177 heap_.Split(new_span.get(), pages); |
| 161 leftover->shared_memory()->Unlock( | 178 leftover->shared_memory()->Unlock( |
| 162 leftover->start() * base::GetPageSize() - | 179 leftover->start() * base::GetPageSize() - |
| 163 reinterpret_cast<size_t>(leftover->shared_memory()->memory()), | 180 reinterpret_cast<size_t>(leftover->shared_memory()->memory()), |
| 164 leftover->length() * base::GetPageSize()); | 181 leftover->length() * base::GetPageSize()); |
| 165 heap_.MergeIntoFreeLists(leftover.Pass()); | 182 heap_.MergeIntoFreeLists(leftover.Pass()); |
| 166 } | 183 } |
| 167 | 184 |
| 168 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); | 185 MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists()); |
| 169 | 186 |
| 170 return make_scoped_ptr( | 187 return make_scoped_ptr(new DiscardableMemoryImpl(this, new_span.Pass())); |
| 171 new DiscardableMemoryShmemChunkImpl(this, new_span.Pass())); | |
| 172 } | 188 } |
| 173 | 189 |
| 174 void ChildDiscardableSharedMemoryManager::ReleaseFreeMemory() { | 190 void ChildDiscardableSharedMemoryManager::ReleaseFreeMemory() { |
| 175 base::AutoLock lock(lock_); | 191 base::AutoLock lock(lock_); |
| 176 | 192 |
| 177 size_t heap_size_prior_to_releasing_memory = heap_.GetSize(); | 193 size_t heap_size_prior_to_releasing_memory = heap_.GetSize(); |
| 178 | 194 |
| 179 // Release both purged and free memory. | 195 // Release both purged and free memory. |
| 180 heap_.ReleasePurgedMemory(); | 196 heap_.ReleasePurgedMemory(); |
| 181 heap_.ReleaseFreeMemory(); | 197 heap_.ReleaseFreeMemory(); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 static const char kDiscardableMemoryUsageKey[] = "dm-usage"; | 280 static const char kDiscardableMemoryUsageKey[] = "dm-usage"; |
| 265 base::debug::SetCrashKeyValue(kDiscardableMemoryUsageKey, | 281 base::debug::SetCrashKeyValue(kDiscardableMemoryUsageKey, |
| 266 base::Uint64ToString(new_bytes_total)); | 282 base::Uint64ToString(new_bytes_total)); |
| 267 | 283 |
| 268 static const char kDiscardableMemoryUsageFreeKey[] = "dm-usage-free"; | 284 static const char kDiscardableMemoryUsageFreeKey[] = "dm-usage-free"; |
| 269 base::debug::SetCrashKeyValue(kDiscardableMemoryUsageFreeKey, | 285 base::debug::SetCrashKeyValue(kDiscardableMemoryUsageFreeKey, |
| 270 base::Uint64ToString(new_bytes_free)); | 286 base::Uint64ToString(new_bytes_free)); |
| 271 } | 287 } |
| 272 | 288 |
| 273 } // namespace content | 289 } // namespace content |
| OLD | NEW |