diff options
-rw-r--r-- | base/memory/discardable_shared_memory.cc | 36 | ||||
-rw-r--r-- | base/memory/discardable_shared_memory.h | 18 | ||||
-rw-r--r-- | base/memory/discardable_shared_memory_unittest.cc | 16 | ||||
-rw-r--r-- | content/common/host_discardable_shared_memory_manager.cc | 17 |
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; } |