Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Unified Diff: content/common/host_discardable_shared_memory_manager.cc

Issue 1009203004: content: Add DeletedDiscardableSharedMemory IPC. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: avoid updating trace counter and crash key unless bytes allocated changed Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/common/host_discardable_shared_memory_manager.cc
diff --git a/content/common/host_discardable_shared_memory_manager.cc b/content/common/host_discardable_shared_memory_manager.cc
index e150fc63dcf00a11da58b0b4ae912f8a94ada2e5..4e6e53aa1ad85c04aeaf34888b1317156a353a60 100644
--- a/content/common/host_discardable_shared_memory_manager.cc
+++ b/content/common/host_discardable_shared_memory_manager.cc
@@ -28,9 +28,8 @@ const int kEnforceMemoryPolicyDelayMs = 1000;
} // namespace
HostDiscardableSharedMemoryManager::MemorySegment::MemorySegment(
- linked_ptr<base::DiscardableSharedMemory> memory,
- base::ProcessHandle process_handle)
- : memory(memory), process_handle(process_handle) {
+ scoped_ptr<base::DiscardableSharedMemory> memory)
+ : memory_(memory.Pass()) {
}
HostDiscardableSharedMemoryManager::MemorySegment::~MemorySegment() {
@@ -71,6 +70,7 @@ void HostDiscardableSharedMemoryManager::
AllocateLockedDiscardableSharedMemoryForChild(
base::ProcessHandle process_handle,
size_t size,
+ DiscardableSharedMemoryId id,
base::SharedMemoryHandle* shared_memory_handle) {
// TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405
// is fixed.
@@ -79,6 +79,14 @@ void HostDiscardableSharedMemoryManager::
"466405 AllocateLockedDiscardableSharedMemoryForChild::Start"));
base::AutoLock lock(lock_);
+ // Make sure |id| is not already in use.
+ MemorySegmentMap& process_segments = processes_[process_handle];
+ if (process_segments.find(id) != process_segments.end()) {
+ LOG(ERROR) << "Invalid discardable shared memory ID";
+ *shared_memory_handle = base::SharedMemory::NULLHandle();
+ return;
+ }
+
// Memory usage must be reduced to prevent the addition of |size| from
// taking usage above the limit. Usage should be reduced to 0 in cases
// where |size| is greater than the limit.
@@ -104,7 +112,7 @@ void HostDiscardableSharedMemoryManager::
tracked_objects::ScopedTracker tracking_profile3(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"466405 AllocateLockedDiscardableSharedMemoryForChild::NewMemory"));
- linked_ptr<base::DiscardableSharedMemory> memory(
+ scoped_ptr<base::DiscardableSharedMemory> memory(
new base::DiscardableSharedMemory);
if (!memory->CreateAndMap(size)) {
*shared_memory_handle = base::SharedMemory::NULLHandle();
@@ -140,7 +148,9 @@ void HostDiscardableSharedMemoryManager::
bytes_allocated_ = checked_bytes_allocated.ValueOrDie();
BytesAllocatedChanged(bytes_allocated_);
- segments_.push_back(MemorySegment(memory, process_handle));
+ scoped_refptr<MemorySegment> segment(new MemorySegment(memory.Pass()));
+ process_segments[id] = segment.get();
+ segments_.push_back(segment.get());
std::push_heap(segments_.begin(), segments_.end(), CompareMemoryUsageTime);
// TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405
@@ -154,30 +164,45 @@ void HostDiscardableSharedMemoryManager::
ScheduleEnforceMemoryPolicy();
}
-void HostDiscardableSharedMemoryManager::ProcessRemoved(
+void HostDiscardableSharedMemoryManager::ChildDeletedDiscardableSharedMemory(
+ DiscardableSharedMemoryId id,
base::ProcessHandle process_handle) {
base::AutoLock lock(lock_);
- size_t bytes_allocated_before_purging = bytes_allocated_;
- for (auto& segment : segments_) {
- // Skip segments that belong to a different process.
- if (segment.process_handle != process_handle)
- continue;
+ MemorySegmentMap& process_segments = processes_[process_handle];
- size_t size = segment.memory->mapped_size();
- DCHECK_GE(bytes_allocated_, size);
-
- // This will unmap the memory segment and drop our reference. The result
- // is that the memory will be released to the OS if the child process is
- // no longer referencing it.
- // Note: We intentionally leave the segment in the vector to avoid
- // reconstructing the heap. The element will be removed from the heap
- // when its last usage time is older than all other segments.
- segment.memory->Close();
- bytes_allocated_ -= size;
+ MemorySegmentMap::iterator segment_it = process_segments.find(id);
+ if (segment_it == process_segments.end()) {
+ LOG(ERROR) << "Invalid discardable shared memory ID";
+ return;
}
- if (bytes_allocated_ != bytes_allocated_before_purging)
+ size_t bytes_allocated_before_releasing_memory = bytes_allocated_;
+
+ ReleaseMemory(segment_it->second->memory());
+
+ process_segments.erase(segment_it);
+
+ if (bytes_allocated_ != bytes_allocated_before_releasing_memory)
+ BytesAllocatedChanged(bytes_allocated_);
+}
+
+void HostDiscardableSharedMemoryManager::ProcessRemoved(
+ base::ProcessHandle process_handle) {
+ base::AutoLock lock(lock_);
+
+ ProcessMap::iterator process_it = processes_.find(process_handle);
+ if (process_it == processes_.end())
+ return;
+
+ size_t bytes_allocated_before_releasing_memory = bytes_allocated_;
+
+ for (auto& segment_it : process_it->second)
+ ReleaseMemory(segment_it.second->memory());
+
+ processes_.erase(process_it);
+
+ if (bytes_allocated_ != bytes_allocated_before_releasing_memory)
BytesAllocatedChanged(bytes_allocated_);
}
@@ -195,6 +220,12 @@ void HostDiscardableSharedMemoryManager::EnforceMemoryPolicy() {
ReduceMemoryUsageUntilWithinMemoryLimit();
}
+size_t HostDiscardableSharedMemoryManager::GetBytesAllocated() {
+ base::AutoLock lock(lock_);
+
+ return bytes_allocated_;
+}
+
void HostDiscardableSharedMemoryManager::OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
base::AutoLock lock(lock_);
@@ -215,6 +246,8 @@ void HostDiscardableSharedMemoryManager::OnMemoryPressure(
void
HostDiscardableSharedMemoryManager::ReduceMemoryUsageUntilWithinMemoryLimit() {
+ lock_.AssertAcquired();
+
if (bytes_allocated_ <= memory_limit_)
return;
@@ -243,11 +276,11 @@ void HostDiscardableSharedMemoryManager::ReduceMemoryUsageUntilWithinLimit(
break;
// Stop eviction attempts when the LRU segment is currently in use.
- if (segments_.front().memory->last_known_usage() >= current_time)
+ if (segments_.front()->memory()->last_known_usage() >= current_time)
break;
std::pop_heap(segments_.begin(), segments_.end(), CompareMemoryUsageTime);
- MemorySegment segment = segments_.back();
+ scoped_refptr<MemorySegment> segment = segments_.back();
segments_.pop_back();
// Attempt to purge and truncate LRU segment. When successful, as much
@@ -255,16 +288,14 @@ void HostDiscardableSharedMemoryManager::ReduceMemoryUsageUntilWithinLimit(
// released depends on the platform. The child process should perform
// periodic cleanup to ensure that all memory is release within a
// reasonable amount of time.
- if (segment.memory->PurgeAndTruncate(current_time)) {
- size_t size = segment.memory->mapped_size();
- DCHECK_GE(bytes_allocated_, size);
- bytes_allocated_ -= size;
+ if (segment->memory()->PurgeAndTruncate(current_time)) {
+ ReleaseMemory(segment->memory());
continue;
}
// Add memory segment (with updated usage timestamp) back on heap after
// failed attempt to purge it.
- segments_.push_back(segment);
+ segments_.push_back(segment.get());
std::push_heap(segments_.begin(), segments_.end(), CompareMemoryUsageTime);
}
@@ -272,6 +303,23 @@ void HostDiscardableSharedMemoryManager::ReduceMemoryUsageUntilWithinLimit(
BytesAllocatedChanged(bytes_allocated_);
}
+void HostDiscardableSharedMemoryManager::ReleaseMemory(
+ base::DiscardableSharedMemory* memory) {
+ lock_.AssertAcquired();
+
+ size_t size = memory->mapped_size();
+ DCHECK_GE(bytes_allocated_, size);
+ bytes_allocated_ -= size;
+
+ // This will unmap the memory segment and drop our reference. The result
+ // is that the memory will be released to the OS if the child process is
+ // no longer referencing it.
+ // Note: We intentionally leave the segment in the |segments| vector to
+ // avoid reconstructing the heap. The element will be removed from the heap
+ // when its last usage time is older than all other segments.
+ memory->Close();
+}
+
void HostDiscardableSharedMemoryManager::BytesAllocatedChanged(
size_t new_bytes_allocated) const {
TRACE_COUNTER_ID1("renderer_host", "TotalDiscardableMemoryUsage", this,

Powered by Google App Engine
This is Rietveld 408576698