summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/memory/discardable_shared_memory.cc36
-rw-r--r--base/memory/discardable_shared_memory.h18
-rw-r--r--base/memory/discardable_shared_memory_unittest.cc16
-rw-r--r--content/common/host_discardable_shared_memory_manager.cc17
4 files changed, 59 insertions, 28 deletions
diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc
index 49e93cd..830d6b9 100644
--- a/base/memory/discardable_shared_memory.cc
+++ b/base/memory/discardable_shared_memory.cc
@@ -325,22 +325,6 @@ bool DiscardableSharedMemory::Purge(Time current_time) {
return true;
}
-bool DiscardableSharedMemory::PurgeAndTruncate(Time current_time) {
- if (!Purge(current_time))
- return false;
-
-#if defined(OS_POSIX)
- // Truncate shared memory to size of SharedState.
- SharedMemoryHandle handle = shared_memory_.handle();
- if (SharedMemory::IsHandleValid(handle)) {
- if (HANDLE_EINTR(ftruncate(handle.fd, sizeof(SharedState))) != 0)
- DPLOG(ERROR) << "ftruncate() failed";
- }
-#endif
-
- return true;
-}
-
bool DiscardableSharedMemory::IsMemoryResident() const {
DCHECK(shared_memory_.memory());
@@ -357,6 +341,26 @@ void DiscardableSharedMemory::Close() {
mapped_size_ = 0;
}
+#if defined(DISCARDABLE_SHARED_MEMORY_SHRINKING)
+void DiscardableSharedMemory::Shrink() {
+#if defined(OS_POSIX)
+ SharedMemoryHandle handle = shared_memory_.handle();
+ if (!SharedMemory::IsHandleValid(handle))
+ return;
+
+ // Truncate shared memory to size of SharedState.
+ if (HANDLE_EINTR(
+ ftruncate(handle.fd, AlignToPageSize(sizeof(SharedState)))) != 0) {
+ DPLOG(ERROR) << "ftruncate() failed";
+ return;
+ }
+ mapped_size_ = 0;
+#else
+ NOTIMPLEMENTED();
+#endif
+}
+#endif
+
Time DiscardableSharedMemory::Now() const {
return Time::Now();
}
diff --git a/base/memory/discardable_shared_memory.h b/base/memory/discardable_shared_memory.h
index e3b437c..892d556 100644
--- a/base/memory/discardable_shared_memory.h
+++ b/base/memory/discardable_shared_memory.h
@@ -15,6 +15,12 @@
#include <set>
#endif
+// Define DISCARDABLE_SHARED_MEMORY_SHRINKING if platform supports shrinking
+// of discardable shared memory segments.
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#define DISCARDABLE_SHARED_MEMORY_SHRINKING
+#endif
+
namespace base {
// Platform abstraction for discardable shared memory.
@@ -93,12 +99,6 @@ class BASE_EXPORT DiscardableSharedMemory {
// each call.
bool Purge(Time current_time);
- // Purge and release as much memory as possible to the OS.
- // Note: The amount of memory that can be released to the OS is platform
- // specific. Best case, all but one page is released. Worst case, nothing
- // is released.
- bool PurgeAndTruncate(Time current_time);
-
// Returns true if memory is still resident.
bool IsMemoryResident() const;
@@ -116,6 +116,12 @@ class BASE_EXPORT DiscardableSharedMemory {
return shared_memory_.ShareToProcess(process_handle, new_handle);
}
+#if defined(DISCARDABLE_SHARED_MEMORY_SHRINKING)
+ // Release as much memory as possible to the OS. The change in size will
+ // be reflected by the return value of mapped_size().
+ void Shrink();
+#endif
+
private:
// Virtual for tests.
virtual Time Now() const;
diff --git a/base/memory/discardable_shared_memory_unittest.cc b/base/memory/discardable_shared_memory_unittest.cc
index 74d19a6..ae7235d 100644
--- a/base/memory/discardable_shared_memory_unittest.cc
+++ b/base/memory/discardable_shared_memory_unittest.cc
@@ -311,5 +311,21 @@ TEST(DiscardableSharedMemoryTest, MappedSize) {
EXPECT_EQ(0u, memory.mapped_size());
}
+#if defined(DISCARDABLE_SHARED_MEMORY_SHRINKING)
+TEST(DiscardableSharedMemoryTest, Shrink) {
+ const uint32 kDataSize = 1024;
+
+ TestDiscardableSharedMemory memory;
+ bool rv = memory.CreateAndMap(kDataSize);
+ ASSERT_TRUE(rv);
+
+ EXPECT_NE(0u, memory.mapped_size());
+
+ // Mapped size should be 0 after shrinking memory segment.
+ memory.Shrink();
+ EXPECT_EQ(0u, memory.mapped_size());
+}
+#endif
+
} // namespace
} // namespace base
diff --git a/content/common/host_discardable_shared_memory_manager.cc b/content/common/host_discardable_shared_memory_manager.cc
index 49c24f8..04c677e 100644
--- a/content/common/host_discardable_shared_memory_manager.cc
+++ b/content/common/host_discardable_shared_memory_manager.cc
@@ -359,12 +359,17 @@ void HostDiscardableSharedMemoryManager::ReduceMemoryUsageUntilWithinLimit(
scoped_refptr<MemorySegment> segment = segments_.back();
segments_.pop_back();
- // Attempt to purge and truncate LRU segment. When successful, as much
- // memory as possible will be released to the OS. How much memory is
- // 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)) {
+ // Attempt to purge LRU segment. When successful, released the memory.
+ if (segment->memory()->Purge(current_time)) {
+#if defined(DISCARDABLE_SHARED_MEMORY_SHRINKING)
+ size_t size = segment->memory()->mapped_size();
+ DCHECK_GE(bytes_allocated_, size);
+ bytes_allocated_ -= size;
+ // Shrink memory segment. This will immediately release the memory to
+ // the OS.
+ segment->memory()->Shrink();
+ DCHECK_EQ(segment->memory()->mapped_size(), 0u);
+#endif
ReleaseMemory(segment->memory());
continue;
}