Chromium Code Reviews| Index: base/memory/discardable_shared_memory.cc |
| diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc |
| index d0eaca1a66219eafee72db30d3e91170e4055e98..8427e6e19a847f4cdd945ff22372eedfe0d4592c 100644 |
| --- a/base/memory/discardable_shared_memory.cc |
| +++ b/base/memory/discardable_shared_memory.cc |
| @@ -4,8 +4,9 @@ |
| #include "base/memory/discardable_shared_memory.h" |
| -#if defined(OS_POSIX) |
| -#include <unistd.h> |
| +#if defined(OS_POSIX) && !defined(OS_NACL) |
| +// For madvise() which is available on all POSIX compatible systems. |
| +#include <sys/mman.h> |
| #endif |
| #include <algorithm> |
| @@ -20,6 +21,14 @@ |
| #include "third_party/ashmem/ashmem.h" |
| #endif |
| +// Linux and Android provide MADV_REMOVE which is preferred as it has a |
| +// behavior that can be verified in tests. Other supported POSIX platforms, |
| +// MacOSX to be specific, provide MADV_FREE instead. MADV_FREE has the |
| +// same result but memory is purged lazily which makes it hard to test. |
| +#if !defined(DISCARDABLE_SHARED_MEMORY_REMOVE) |
| +#define MADV_REMOVE MADV_FREE |
|
danakj
2015/10/21 18:34:25
Rather than defining MADV_REMOVE ourselves, can yo
|
| +#endif |
| + |
| namespace base { |
| namespace { |
| @@ -301,11 +310,7 @@ void* DiscardableSharedMemory::memory() const { |
| bool DiscardableSharedMemory::Purge(Time current_time) { |
| // Calls to this function must be synchronized properly. |
| DFAKE_SCOPED_LOCK(thread_collision_warner_); |
| - |
| - // Early out if not mapped. This can happen if the segment was previously |
| - // unmapped using a call to Close(). |
| - if (!shared_memory_.memory()) |
| - return true; |
| + DCHECK(shared_memory_.memory()); |
| SharedState old_state(SharedState::UNLOCKED, last_known_usage_); |
| SharedState new_state(SharedState::UNLOCKED, Time()); |
| @@ -326,6 +331,17 @@ bool DiscardableSharedMemory::Purge(Time current_time) { |
| return false; |
| } |
| +#if defined(OS_POSIX) && !defined(OS_NACL) |
| + // Advise the kernel to remove resources associated with purged pages. |
| + // Subsequent accesses of memory pages will succeed, but will result in |
| + // zero-fill-on-demand pages. |
| + if (madvise(reinterpret_cast<char*>(shared_memory_.memory()) + |
| + AlignToPageSize(sizeof(SharedState)), |
| + AlignToPageSize(mapped_size_), MADV_REMOVE)) { |
|
danakj
2015/10/21 18:34:25
Then this doesn't read like it's doing MADV_REMOVE
|
| + DPLOG(ERROR) << "madvise() failed"; |
| + } |
| +#endif |
| + |
| last_known_usage_ = Time(); |
| return true; |
| } |
| @@ -353,26 +369,6 @@ void DiscardableSharedMemory::Close() { |
| shared_memory_.Close(); |
| } |
| -#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(SharedMemory::GetFdFromSharedMemoryHandle(handle), |
| - AlignToPageSize(sizeof(SharedState)))) != 0) { |
| - DPLOG(ERROR) << "ftruncate() failed"; |
| - return; |
| - } |
| - mapped_size_ = 0; |
| -#else |
| - NOTIMPLEMENTED(); |
| -#endif |
| -} |
| -#endif |
| - |
| Time DiscardableSharedMemory::Now() const { |
| return Time::Now(); |
| } |