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 |