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..3d2be9d22c1e32bcad935e4cc8694b60e1282df7 100644 |
--- a/content/common/host_discardable_shared_memory_manager.cc |
+++ b/content/common/host_discardable_shared_memory_manager.cc |
@@ -18,6 +18,46 @@ |
namespace content { |
namespace { |
+class DiscardableMemoryShmemChunkImpl |
+ : public base::DiscardableMemoryShmemChunk { |
+ public: |
+ explicit DiscardableMemoryShmemChunkImpl( |
+ scoped_ptr<base::DiscardableSharedMemory> shared_memory) |
+ : shared_memory_(shared_memory.Pass()), is_locked_(true) {} |
+ ~DiscardableMemoryShmemChunkImpl() override { |
+ if (is_locked_) |
+ shared_memory_->Unlock(0, 0); |
+ shared_memory_->Purge(base::Time::Now()); |
+ } |
+ |
+ // Overridden from base::DiscardableMemoryShmemChunk: |
+ bool Lock() override { |
+ DCHECK(!is_locked_); |
+ |
+ if (shared_memory_->Lock(0, 0) != base::DiscardableSharedMemory::SUCCESS) |
+ return false; |
+ |
+ is_locked_ = true; |
+ return true; |
+ } |
+ void Unlock() override { |
+ DCHECK(is_locked_); |
+ |
+ shared_memory_->Unlock(0, 0); |
+ is_locked_ = false; |
+ } |
+ void* Memory() const override { |
+ DCHECK(is_locked_); |
+ return shared_memory_->memory(); |
+ } |
+ |
+ private: |
+ scoped_ptr<base::DiscardableSharedMemory> shared_memory_; |
+ bool is_locked_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryShmemChunkImpl); |
+}; |
+ |
base::LazyInstance<HostDiscardableSharedMemoryManager> |
g_discardable_shared_memory_manager = LAZY_INSTANCE_INITIALIZER; |
@@ -61,10 +101,16 @@ HostDiscardableSharedMemoryManager::current() { |
scoped_ptr<base::DiscardableMemoryShmemChunk> |
HostDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory( |
size_t size) { |
- // TODO(reveman): Need to implement this for discardable memory support in |
- // the browser process. |
- NOTIMPLEMENTED(); |
- return nullptr; |
+ // Note: Use DiscardableSharedMemoryHeap for in-process allocation |
+ // of discardable memory if the cost of each allocation is too high. |
+ base::SharedMemoryHandle handle; |
+ AllocateLockedDiscardableSharedMemory(base::GetCurrentProcessHandle(), size, |
+ &handle); |
+ CHECK(base::SharedMemory::IsHandleValid(handle)); |
+ scoped_ptr<base::DiscardableSharedMemory> memory( |
+ new base::DiscardableSharedMemory(handle)); |
+ CHECK(memory->Map(size)); |
+ return make_scoped_ptr(new DiscardableMemoryShmemChunkImpl(memory.Pass())); |
} |
void HostDiscardableSharedMemoryManager:: |
@@ -72,11 +118,60 @@ void HostDiscardableSharedMemoryManager:: |
base::ProcessHandle process_handle, |
size_t size, |
base::SharedMemoryHandle* shared_memory_handle) { |
+ AllocateLockedDiscardableSharedMemory(process_handle, size, |
+ shared_memory_handle); |
+} |
+ |
+void HostDiscardableSharedMemoryManager::ProcessRemoved( |
+ 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; |
+ |
+ 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; |
+ } |
+ |
+ if (bytes_allocated_ != bytes_allocated_before_purging) |
+ BytesAllocatedChanged(bytes_allocated_); |
+} |
+ |
+void HostDiscardableSharedMemoryManager::SetMemoryLimit(size_t limit) { |
+ base::AutoLock lock(lock_); |
+ |
+ memory_limit_ = limit; |
+ ReduceMemoryUsageUntilWithinMemoryLimit(); |
+} |
+ |
+void HostDiscardableSharedMemoryManager::EnforceMemoryPolicy() { |
+ base::AutoLock lock(lock_); |
+ |
+ enforce_memory_policy_pending_ = false; |
+ ReduceMemoryUsageUntilWithinMemoryLimit(); |
+} |
+ |
+void HostDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory( |
+ base::ProcessHandle process_handle, |
+ size_t size, |
+ base::SharedMemoryHandle* shared_memory_handle) { |
// TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405 |
// is fixed. |
tracked_objects::ScopedTracker tracking_profile1( |
FROM_HERE_WITH_EXPLICIT_FUNCTION( |
- "466405 AllocateLockedDiscardableSharedMemoryForChild::Start")); |
+ "466405 AllocateLockedDiscardableSharedMemory::Start")); |
base::AutoLock lock(lock_); |
// Memory usage must be reduced to prevent the addition of |size| from |
@@ -94,8 +189,7 @@ void HostDiscardableSharedMemoryManager:: |
// is fixed. |
tracked_objects::ScopedTracker tracking_profile2( |
FROM_HERE_WITH_EXPLICIT_FUNCTION( |
- "466405 " |
- "AllocateLockedDiscardableSharedMemoryForChild::ReduceMemoryUsage")); |
+ "466405 AllocateLockedDiscardableSharedMemory::ReduceMemoryUsage")); |
if (bytes_allocated_ > limit) |
ReduceMemoryUsageUntilWithinLimit(limit); |
@@ -103,7 +197,7 @@ void HostDiscardableSharedMemoryManager:: |
// is fixed. |
tracked_objects::ScopedTracker tracking_profile3( |
FROM_HERE_WITH_EXPLICIT_FUNCTION( |
- "466405 AllocateLockedDiscardableSharedMemoryForChild::NewMemory")); |
+ "466405 AllocateLockedDiscardableSharedMemory::NewMemory")); |
linked_ptr<base::DiscardableSharedMemory> memory( |
new base::DiscardableSharedMemory); |
if (!memory->CreateAndMap(size)) { |
@@ -115,8 +209,7 @@ void HostDiscardableSharedMemoryManager:: |
// is fixed. |
tracked_objects::ScopedTracker tracking_profile4( |
FROM_HERE_WITH_EXPLICIT_FUNCTION( |
- "466405 " |
- "AllocateLockedDiscardableSharedMemoryForChild::ShareToProcess")); |
+ "466405 AllocateLockedDiscardableSharedMemory::ShareToProcess")); |
if (!memory->ShareToProcess(process_handle, shared_memory_handle)) { |
LOG(ERROR) << "Cannot share discardable memory segment"; |
*shared_memory_handle = base::SharedMemory::NULLHandle(); |
@@ -135,8 +228,7 @@ void HostDiscardableSharedMemoryManager:: |
tracked_objects::ScopedTracker tracking_profile5( |
FROM_HERE_WITH_EXPLICIT_FUNCTION( |
"466405 " |
- "AllocateLockedDiscardableSharedMemoryForChild::" |
- "BytesAllocatedChanged")); |
+ "AllocateLockedDiscardableSharedMemory::BytesAllocatedChanged")); |
bytes_allocated_ = checked_bytes_allocated.ValueOrDie(); |
BytesAllocatedChanged(bytes_allocated_); |
@@ -148,53 +240,12 @@ void HostDiscardableSharedMemoryManager:: |
tracked_objects::ScopedTracker tracking_profile6( |
FROM_HERE_WITH_EXPLICIT_FUNCTION( |
"466405 " |
- "AllocateLockedDiscardableSharedMemoryForChild::" |
+ "AllocateLockedDiscardableSharedMemory::" |
"ScheduleEnforceMemoryPolicy")); |
if (bytes_allocated_ > memory_limit_) |
ScheduleEnforceMemoryPolicy(); |
} |
-void HostDiscardableSharedMemoryManager::ProcessRemoved( |
- 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; |
- |
- 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; |
- } |
- |
- if (bytes_allocated_ != bytes_allocated_before_purging) |
- BytesAllocatedChanged(bytes_allocated_); |
-} |
- |
-void HostDiscardableSharedMemoryManager::SetMemoryLimit(size_t limit) { |
- base::AutoLock lock(lock_); |
- |
- memory_limit_ = limit; |
- ReduceMemoryUsageUntilWithinMemoryLimit(); |
-} |
- |
-void HostDiscardableSharedMemoryManager::EnforceMemoryPolicy() { |
- base::AutoLock lock(lock_); |
- |
- enforce_memory_policy_pending_ = false; |
- ReduceMemoryUsageUntilWithinMemoryLimit(); |
-} |
- |
void HostDiscardableSharedMemoryManager::OnMemoryPressure( |
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { |
base::AutoLock lock(lock_); |