Skip to content

Commit

Permalink
Break out platform-specific discardable paging into Lock/UnlockPages.
Browse files Browse the repository at this point in the history
Refactor the DiscardableSharedMemory implementation to put platform-
native discardable page management in separate LockPages/UnlockPages
functions.

This isolates the platform-specific calls from internal details of the
DiscardableSharedMemory implementation, in particular the need to allow
for the space occupied by the SharedState structure.

Also corrects "lock page" platform API errors to return FAILED rather
than PURGED result, and adds some DCHECKing for "unlock page" API
errors.

Bug: 716205
Change-Id: I572d65a0304816305053669ec81c78a3461d8325
Reviewed-on: https://chromium-review.googlesource.com/574901
Commit-Queue: Wez <wez@chromium.org>
Reviewed-by: David Reveman <reveman@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#488027}
  • Loading branch information
Wez authored and Commit Bot committed Jul 19, 2017
1 parent 024c77e commit 42e65bf
Showing 1 changed file with 41 additions and 25 deletions.
66 changes: 41 additions & 25 deletions base/memory/discardable_shared_memory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,39 @@ size_t AlignToPageSize(size_t size) {
return bits::Align(size, base::GetPageSize());
}

// LockPages/UnlockPages are platform-native discardable page management
// helper functions. Both expect |offset| to be specified relative to the
// base address at which |memory| is mapped, and that |offset| and |length|
// are page-aligned by the caller.

// Returns SUCCESS on platforms which do not support discardable pages.
DiscardableSharedMemory::LockResult LockPages(const SharedMemory& memory,
size_t offset,
size_t length) {
#if defined(OS_ANDROID)
SharedMemoryHandle handle = memory.handle();
if (handle.IsValid()) {
int pin_result = ashmem_pin_region(handle.GetHandle(), offset, length);
if (pin_result == ASHMEM_WAS_PURGED)
return DiscardableSharedMemory::PURGED;
if (pin_result < 0)
return DiscardableSharedMemory::FAILED;
}
#endif
return DiscardableSharedMemory::SUCCESS;
}

// UnlockPages() is a no-op on platforms not supporting discardable pages.
void UnlockPages(const SharedMemory& memory, size_t offset, size_t length) {
#if defined(OS_ANDROID)
SharedMemoryHandle handle = memory.handle();
if (handle.IsValid()) {
int unpin_result = ashmem_unpin_region(handle.GetHandle(), offset, length);
DCHECK_EQ(0, unpin_result);
}
#endif
}

} // namespace

DiscardableSharedMemory::DiscardableSharedMemory()
Expand Down Expand Up @@ -221,19 +254,9 @@ DiscardableSharedMemory::LockResult DiscardableSharedMemory::Lock(
if (!length)
return PURGED;

// Pin pages if supported.
#if defined(OS_ANDROID)
SharedMemoryHandle handle = shared_memory_.handle();
if (handle.IsValid()) {
if (ashmem_pin_region(handle.GetHandle(),
AlignToPageSize(sizeof(SharedState)) + offset,
length)) {
return PURGED;
}
}
#endif

return SUCCESS;
// Ensure that the platform won't discard the required pages.
return LockPages(shared_memory_,
AlignToPageSize(sizeof(SharedState)) + offset, length);
}

void DiscardableSharedMemory::Unlock(size_t offset, size_t length) {
Expand All @@ -243,23 +266,16 @@ void DiscardableSharedMemory::Unlock(size_t offset, size_t length) {
// Calls to this function must be synchronized properly.
DFAKE_SCOPED_LOCK(thread_collision_warner_);

// Zero for length means "everything onward".
// Passing zero for |length| means "everything onward". Note that |length| may
// still be zero after this calculation, e.g. if |mapped_size_| is zero.
if (!length)
length = AlignToPageSize(mapped_size_) - offset;

DCHECK(shared_memory_.memory());

// Unpin pages if supported.
#if defined(OS_ANDROID)
SharedMemoryHandle handle = shared_memory_.handle();
if (handle.IsValid()) {
if (ashmem_unpin_region(handle.GetHandle(),
AlignToPageSize(sizeof(SharedState)) + offset,
length)) {
DPLOG(ERROR) << "ashmem_unpin_region() failed";
}
}
#endif
// Allow the pages to be discarded by the platform, if supported.
UnlockPages(shared_memory_, AlignToPageSize(sizeof(SharedState)) + offset,
length);

size_t start = offset / base::GetPageSize();
size_t end = start + length / base::GetPageSize();
Expand Down

0 comments on commit 42e65bf

Please sign in to comment.