Commit ae5e45c0 authored by Alexandr Ilin's avatar Alexandr Ilin Committed by Commit Bot

Convert discardable shared memory to the new shared memory API

Bug: 826213
Change-Id: Ifa1d7e3fd3625ef0161073d594f3f48aada7b7c8
Reviewed-on: https://chromium-review.googlesource.com/1019448Reviewed-by: default avatarDavid Reveman <reveman@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Commit-Queue: Alexandr Ilin <alexilin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#553472}
parent 5b0d48d5
...@@ -97,8 +97,9 @@ struct SharedState { ...@@ -97,8 +97,9 @@ struct SharedState {
}; };
// Shared state is stored at offset 0 in shared memory segments. // Shared state is stored at offset 0 in shared memory segments.
SharedState* SharedStateFromSharedMemory(const SharedMemory& shared_memory) { SharedState* SharedStateFromSharedMemory(
DCHECK(shared_memory.memory()); const WritableSharedMemoryMapping& shared_memory) {
DCHECK(shared_memory.IsValid());
return static_cast<SharedState*>(shared_memory.memory()); return static_cast<SharedState*>(shared_memory.memory());
} }
...@@ -107,39 +108,6 @@ size_t AlignToPageSize(size_t size) { ...@@ -107,39 +108,6 @@ size_t AlignToPageSize(size_t size) {
return bits::Align(size, base::GetPageSize()); 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.
#if defined(OS_ANDROID)
// Returns SUCCESS on platforms which do not support discardable pages.
DiscardableSharedMemory::LockResult LockPages(const SharedMemory& memory,
size_t offset,
size_t length) {
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;
}
return DiscardableSharedMemory::SUCCESS;
}
#endif
// 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 } // namespace
DiscardableSharedMemory::DiscardableSharedMemory() DiscardableSharedMemory::DiscardableSharedMemory()
...@@ -147,11 +115,10 @@ DiscardableSharedMemory::DiscardableSharedMemory() ...@@ -147,11 +115,10 @@ DiscardableSharedMemory::DiscardableSharedMemory()
} }
DiscardableSharedMemory::DiscardableSharedMemory( DiscardableSharedMemory::DiscardableSharedMemory(
SharedMemoryHandle shared_memory_handle) UnsafeSharedMemoryRegion shared_memory_region)
: shared_memory_(shared_memory_handle, false), : shared_memory_region_(std::move(shared_memory_region)),
mapped_size_(0), mapped_size_(0),
locked_page_count_(0) { locked_page_count_(0) {}
}
DiscardableSharedMemory::~DiscardableSharedMemory() = default; DiscardableSharedMemory::~DiscardableSharedMemory() = default;
...@@ -161,11 +128,18 @@ bool DiscardableSharedMemory::CreateAndMap(size_t size) { ...@@ -161,11 +128,18 @@ bool DiscardableSharedMemory::CreateAndMap(size_t size) {
if (!checked_size.IsValid()) if (!checked_size.IsValid())
return false; return false;
if (!shared_memory_.CreateAndMapAnonymous(checked_size.ValueOrDie())) shared_memory_region_ =
UnsafeSharedMemoryRegion::Create(checked_size.ValueOrDie());
if (!shared_memory_region_.IsValid())
return false; return false;
mapped_size_ = shared_memory_mapping_ = shared_memory_region_.Map();
shared_memory_.mapped_size() - AlignToPageSize(sizeof(SharedState)); if (!shared_memory_mapping_.IsValid())
return false;
mapped_size_ = shared_memory_mapping_.mapped_size() -
AlignToPageSize(sizeof(SharedState));
locked_page_count_ = AlignToPageSize(mapped_size_) / base::GetPageSize(); locked_page_count_ = AlignToPageSize(mapped_size_) / base::GetPageSize();
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
...@@ -175,17 +149,24 @@ bool DiscardableSharedMemory::CreateAndMap(size_t size) { ...@@ -175,17 +149,24 @@ bool DiscardableSharedMemory::CreateAndMap(size_t size) {
DCHECK(last_known_usage_.is_null()); DCHECK(last_known_usage_.is_null());
SharedState new_state(SharedState::LOCKED, Time()); SharedState new_state(SharedState::LOCKED, Time());
subtle::Release_Store(&SharedStateFromSharedMemory(shared_memory_)->value.i, subtle::Release_Store(
&SharedStateFromSharedMemory(shared_memory_mapping_)->value.i,
new_state.value.i); new_state.value.i);
return true; return true;
} }
bool DiscardableSharedMemory::Map(size_t size) { bool DiscardableSharedMemory::Map(size_t size) {
if (!shared_memory_.Map(AlignToPageSize(sizeof(SharedState)) + size)) DCHECK(!shared_memory_mapping_.IsValid());
if (shared_memory_mapping_.IsValid())
return false; return false;
mapped_size_ = shared_memory_mapping_ = shared_memory_region_.MapAt(
shared_memory_.mapped_size() - AlignToPageSize(sizeof(SharedState)); 0, AlignToPageSize(sizeof(SharedState)) + size);
if (!shared_memory_mapping_.IsValid())
return false;
mapped_size_ = shared_memory_mapping_.mapped_size() -
AlignToPageSize(sizeof(SharedState));
locked_page_count_ = AlignToPageSize(mapped_size_) / base::GetPageSize(); locked_page_count_ = AlignToPageSize(mapped_size_) / base::GetPageSize();
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
...@@ -197,9 +178,10 @@ bool DiscardableSharedMemory::Map(size_t size) { ...@@ -197,9 +178,10 @@ bool DiscardableSharedMemory::Map(size_t size) {
} }
bool DiscardableSharedMemory::Unmap() { bool DiscardableSharedMemory::Unmap() {
if (!shared_memory_.Unmap()) if (!shared_memory_mapping_.IsValid())
return false; return false;
shared_memory_mapping_ = WritableSharedMemoryMapping();
locked_page_count_ = 0; locked_page_count_ = 0;
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
locked_pages_.clear(); locked_pages_.clear();
...@@ -216,7 +198,7 @@ DiscardableSharedMemory::LockResult DiscardableSharedMemory::Lock( ...@@ -216,7 +198,7 @@ DiscardableSharedMemory::LockResult DiscardableSharedMemory::Lock(
// Calls to this function must be synchronized properly. // Calls to this function must be synchronized properly.
DFAKE_SCOPED_LOCK(thread_collision_warner_); DFAKE_SCOPED_LOCK(thread_collision_warner_);
DCHECK(shared_memory_.memory()); DCHECK(shared_memory_mapping_.IsValid());
// We need to successfully acquire the platform independent lock before // We need to successfully acquire the platform independent lock before
// individual pages can be locked. // individual pages can be locked.
...@@ -229,9 +211,8 @@ DiscardableSharedMemory::LockResult DiscardableSharedMemory::Lock( ...@@ -229,9 +211,8 @@ DiscardableSharedMemory::LockResult DiscardableSharedMemory::Lock(
SharedState old_state(SharedState::UNLOCKED, last_known_usage_); SharedState old_state(SharedState::UNLOCKED, last_known_usage_);
SharedState new_state(SharedState::LOCKED, Time()); SharedState new_state(SharedState::LOCKED, Time());
SharedState result(subtle::Acquire_CompareAndSwap( SharedState result(subtle::Acquire_CompareAndSwap(
&SharedStateFromSharedMemory(shared_memory_)->value.i, &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i,
old_state.value.i, old_state.value.i, new_state.value.i));
new_state.value.i));
if (result.value.u != old_state.value.u) { if (result.value.u != old_state.value.u) {
// Update |last_known_usage_| in case the above CAS failed because of // Update |last_known_usage_| in case the above CAS failed because of
// an incorrect timestamp. // an incorrect timestamp.
...@@ -267,7 +248,7 @@ DiscardableSharedMemory::LockResult DiscardableSharedMemory::Lock( ...@@ -267,7 +248,7 @@ DiscardableSharedMemory::LockResult DiscardableSharedMemory::Lock(
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
// Ensure that the platform won't discard the required pages. // Ensure that the platform won't discard the required pages.
return LockPages(shared_memory_, return LockPages(shared_memory_region_,
AlignToPageSize(sizeof(SharedState)) + offset, length); AlignToPageSize(sizeof(SharedState)) + offset, length);
#elif defined(OS_MACOSX) #elif defined(OS_MACOSX)
// On macOS, there is no mechanism to lock pages. However, we do need to call // On macOS, there is no mechanism to lock pages. However, we do need to call
...@@ -283,7 +264,7 @@ DiscardableSharedMemory::LockResult DiscardableSharedMemory::Lock( ...@@ -283,7 +264,7 @@ DiscardableSharedMemory::LockResult DiscardableSharedMemory::Lock(
// //
// For more information, see // For more information, see
// https://bugs.chromium.org/p/chromium/issues/detail?id=823915. // https://bugs.chromium.org/p/chromium/issues/detail?id=823915.
if (madvise(reinterpret_cast<char*>(shared_memory_.memory()) + if (madvise(reinterpret_cast<char*>(shared_memory_mapping_.memory()) +
AlignToPageSize(sizeof(SharedState)), AlignToPageSize(sizeof(SharedState)),
AlignToPageSize(mapped_size_), MADV_FREE_REUSE)) AlignToPageSize(mapped_size_), MADV_FREE_REUSE))
; ;
...@@ -305,11 +286,11 @@ void DiscardableSharedMemory::Unlock(size_t offset, size_t length) { ...@@ -305,11 +286,11 @@ void DiscardableSharedMemory::Unlock(size_t offset, size_t length) {
if (!length) if (!length)
length = AlignToPageSize(mapped_size_) - offset; length = AlignToPageSize(mapped_size_) - offset;
DCHECK(shared_memory_.memory()); DCHECK(shared_memory_mapping_.IsValid());
// Allow the pages to be discarded by the platform, if supported. // Allow the pages to be discarded by the platform, if supported.
UnlockPages(shared_memory_, AlignToPageSize(sizeof(SharedState)) + offset, UnlockPages(shared_memory_region_,
length); AlignToPageSize(sizeof(SharedState)) + offset, length);
size_t start = offset / base::GetPageSize(); size_t start = offset / base::GetPageSize();
size_t end = start + length / base::GetPageSize(); size_t end = start + length / base::GetPageSize();
...@@ -346,9 +327,8 @@ void DiscardableSharedMemory::Unlock(size_t offset, size_t length) { ...@@ -346,9 +327,8 @@ void DiscardableSharedMemory::Unlock(size_t offset, size_t length) {
DCHECK_EQ((new_state.GetTimestamp() - Time::UnixEpoch()).InSeconds(), DCHECK_EQ((new_state.GetTimestamp() - Time::UnixEpoch()).InSeconds(),
(current_time - Time::UnixEpoch()).InSeconds()); (current_time - Time::UnixEpoch()).InSeconds());
SharedState result(subtle::Release_CompareAndSwap( SharedState result(subtle::Release_CompareAndSwap(
&SharedStateFromSharedMemory(shared_memory_)->value.i, &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i,
old_state.value.i, old_state.value.i, new_state.value.i));
new_state.value.i));
DCHECK_EQ(old_state.value.u, result.value.u); DCHECK_EQ(old_state.value.u, result.value.u);
...@@ -356,21 +336,20 @@ void DiscardableSharedMemory::Unlock(size_t offset, size_t length) { ...@@ -356,21 +336,20 @@ void DiscardableSharedMemory::Unlock(size_t offset, size_t length) {
} }
void* DiscardableSharedMemory::memory() const { void* DiscardableSharedMemory::memory() const {
return reinterpret_cast<uint8_t*>(shared_memory_.memory()) + return reinterpret_cast<uint8_t*>(shared_memory_mapping_.memory()) +
AlignToPageSize(sizeof(SharedState)); AlignToPageSize(sizeof(SharedState));
} }
bool DiscardableSharedMemory::Purge(Time current_time) { bool DiscardableSharedMemory::Purge(Time current_time) {
// Calls to this function must be synchronized properly. // Calls to this function must be synchronized properly.
DFAKE_SCOPED_LOCK(thread_collision_warner_); DFAKE_SCOPED_LOCK(thread_collision_warner_);
DCHECK(shared_memory_.memory()); DCHECK(shared_memory_mapping_.IsValid());
SharedState old_state(SharedState::UNLOCKED, last_known_usage_); SharedState old_state(SharedState::UNLOCKED, last_known_usage_);
SharedState new_state(SharedState::UNLOCKED, Time()); SharedState new_state(SharedState::UNLOCKED, Time());
SharedState result(subtle::Acquire_CompareAndSwap( SharedState result(subtle::Acquire_CompareAndSwap(
&SharedStateFromSharedMemory(shared_memory_)->value.i, &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i,
old_state.value.i, old_state.value.i, new_state.value.i));
new_state.value.i));
// Update |last_known_usage_| to |current_time| if the memory is locked. This // Update |last_known_usage_| to |current_time| if the memory is locked. This
// allows the caller to determine if purging failed because last known usage // allows the caller to determine if purging failed because last known usage
...@@ -407,7 +386,7 @@ bool DiscardableSharedMemory::Purge(Time current_time) { ...@@ -407,7 +386,7 @@ bool DiscardableSharedMemory::Purge(Time current_time) {
// Advise the kernel to remove resources associated with purged pages. // Advise the kernel to remove resources associated with purged pages.
// Subsequent accesses of memory pages will succeed, but might result in // Subsequent accesses of memory pages will succeed, but might result in
// zero-fill-on-demand pages. // zero-fill-on-demand pages.
if (madvise(reinterpret_cast<char*>(shared_memory_.memory()) + if (madvise(reinterpret_cast<char*>(shared_memory_mapping_.memory()) +
AlignToPageSize(sizeof(SharedState)), AlignToPageSize(sizeof(SharedState)),
AlignToPageSize(mapped_size_), MADV_PURGE_ARGUMENT)) { AlignToPageSize(mapped_size_), MADV_PURGE_ARGUMENT)) {
DPLOG(ERROR) << "madvise() failed"; DPLOG(ERROR) << "madvise() failed";
...@@ -423,7 +402,7 @@ bool DiscardableSharedMemory::Purge(Time current_time) { ...@@ -423,7 +402,7 @@ bool DiscardableSharedMemory::Purge(Time current_time) {
GetModuleHandle(L"kernel32.dll"), "DiscardVirtualMemory")); GetModuleHandle(L"kernel32.dll"), "DiscardVirtualMemory"));
if (discard_virtual_memory) { if (discard_virtual_memory) {
DWORD discard_result = discard_virtual_memory( DWORD discard_result = discard_virtual_memory(
reinterpret_cast<char*>(shared_memory_.memory()) + reinterpret_cast<char*>(shared_memory_mapping_.memory()) +
AlignToPageSize(sizeof(SharedState)), AlignToPageSize(sizeof(SharedState)),
AlignToPageSize(mapped_size_)); AlignToPageSize(mapped_size_));
if (discard_result != ERROR_SUCCESS) { if (discard_result != ERROR_SUCCESS) {
...@@ -439,34 +418,34 @@ bool DiscardableSharedMemory::Purge(Time current_time) { ...@@ -439,34 +418,34 @@ bool DiscardableSharedMemory::Purge(Time current_time) {
} }
bool DiscardableSharedMemory::IsMemoryResident() const { bool DiscardableSharedMemory::IsMemoryResident() const {
DCHECK(shared_memory_.memory()); DCHECK(shared_memory_mapping_.IsValid());
SharedState result(subtle::NoBarrier_Load( SharedState result(subtle::NoBarrier_Load(
&SharedStateFromSharedMemory(shared_memory_)->value.i)); &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i));
return result.GetLockState() == SharedState::LOCKED || return result.GetLockState() == SharedState::LOCKED ||
!result.GetTimestamp().is_null(); !result.GetTimestamp().is_null();
} }
bool DiscardableSharedMemory::IsMemoryLocked() const { bool DiscardableSharedMemory::IsMemoryLocked() const {
DCHECK(shared_memory_.memory()); DCHECK(shared_memory_mapping_.IsValid());
SharedState result(subtle::NoBarrier_Load( SharedState result(subtle::NoBarrier_Load(
&SharedStateFromSharedMemory(shared_memory_)->value.i)); &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i));
return result.GetLockState() == SharedState::LOCKED; return result.GetLockState() == SharedState::LOCKED;
} }
void DiscardableSharedMemory::Close() { void DiscardableSharedMemory::Close() {
shared_memory_.Close(); shared_memory_region_ = UnsafeSharedMemoryRegion();
} }
void DiscardableSharedMemory::CreateSharedMemoryOwnershipEdge( void DiscardableSharedMemory::CreateSharedMemoryOwnershipEdge(
trace_event::MemoryAllocatorDump* local_segment_dump, trace_event::MemoryAllocatorDump* local_segment_dump,
trace_event::ProcessMemoryDump* pmd, trace_event::ProcessMemoryDump* pmd,
bool is_owned) const { bool is_owned) const {
auto* shared_memory_dump = auto* shared_memory_dump = SharedMemoryTracker::GetOrCreateSharedMemoryDump(
SharedMemoryTracker::GetOrCreateSharedMemoryDump(&shared_memory_, pmd); shared_memory_mapping_, pmd);
// TODO(ssid): Clean this by a new api to inherit size of parent dump once the // TODO(ssid): Clean this by a new api to inherit size of parent dump once the
// we send the full PMD and calculate sizes inside chrome, crbug.com/704203. // we send the full PMD and calculate sizes inside chrome, crbug.com/704203.
size_t resident_size = shared_memory_dump->GetSizeInternal(); size_t resident_size = shared_memory_dump->GetSizeInternal();
...@@ -480,7 +459,7 @@ void DiscardableSharedMemory::CreateSharedMemoryOwnershipEdge( ...@@ -480,7 +459,7 @@ void DiscardableSharedMemory::CreateSharedMemoryOwnershipEdge(
// TODO(ssid): Define better constants in MemoryAllocatorDump for importance // TODO(ssid): Define better constants in MemoryAllocatorDump for importance
// values, crbug.com/754793. // values, crbug.com/754793.
const int kImportance = is_owned ? 2 : 0; const int kImportance = is_owned ? 2 : 0;
auto shared_memory_guid = shared_memory_.mapped_id(); auto shared_memory_guid = shared_memory_mapping_.guid();
local_segment_dump->AddString("id", "hash", shared_memory_guid.ToString()); local_segment_dump->AddString("id", "hash", shared_memory_guid.ToString());
// Owned discardable segments which are allocated by client process, could // Owned discardable segments which are allocated by client process, could
...@@ -496,6 +475,38 @@ void DiscardableSharedMemory::CreateSharedMemoryOwnershipEdge( ...@@ -496,6 +475,38 @@ void DiscardableSharedMemory::CreateSharedMemoryOwnershipEdge(
} }
} }
// static
DiscardableSharedMemory::LockResult DiscardableSharedMemory::LockPages(
const UnsafeSharedMemoryRegion& region,
size_t offset,
size_t length) {
#if defined(OS_ANDROID)
if (region.IsValid()) {
int pin_result =
ashmem_pin_region(region.GetPlatformHandle(), offset, length);
if (pin_result == ASHMEM_WAS_PURGED)
return PURGED;
if (pin_result < 0)
return FAILED;
}
#endif
return SUCCESS;
}
// static
void DiscardableSharedMemory::UnlockPages(
const UnsafeSharedMemoryRegion& region,
size_t offset,
size_t length) {
#if defined(OS_ANDROID)
if (region.IsValid()) {
int unpin_result =
ashmem_unpin_region(region.GetPlatformHandle(), offset, length);
DCHECK_EQ(0, unpin_result);
}
#endif
}
Time DiscardableSharedMemory::Now() const { Time DiscardableSharedMemory::Now() const {
return Time::Now(); return Time::Now();
} }
......
...@@ -10,7 +10,8 @@ ...@@ -10,7 +10,8 @@
#include "base/base_export.h" #include "base/base_export.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/shared_memory.h" #include "base/memory/shared_memory_mapping.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/threading/thread_collision_warner.h" #include "base/threading/thread_collision_warner.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -49,7 +50,7 @@ class BASE_EXPORT DiscardableSharedMemory { ...@@ -49,7 +50,7 @@ class BASE_EXPORT DiscardableSharedMemory {
// Create a new DiscardableSharedMemory object from an existing, open shared // Create a new DiscardableSharedMemory object from an existing, open shared
// memory file. Memory must be locked. // memory file. Memory must be locked.
explicit DiscardableSharedMemory(SharedMemoryHandle handle); explicit DiscardableSharedMemory(UnsafeSharedMemoryRegion region);
// Closes any open files. // Closes any open files.
virtual ~DiscardableSharedMemory(); virtual ~DiscardableSharedMemory();
...@@ -71,14 +72,17 @@ class BASE_EXPORT DiscardableSharedMemory { ...@@ -71,14 +72,17 @@ class BASE_EXPORT DiscardableSharedMemory {
// The actual size of the mapped memory (may be larger than requested). // The actual size of the mapped memory (may be larger than requested).
size_t mapped_size() const { return mapped_size_; } size_t mapped_size() const { return mapped_size_; }
// Returns a shared memory handle for this DiscardableSharedMemory object. // Returns a duplicated shared memory region for this DiscardableSharedMemory
SharedMemoryHandle handle() const { return shared_memory_.handle(); } // object.
UnsafeSharedMemoryRegion DuplicateRegion() const {
return shared_memory_region_.Duplicate();
}
// Returns an ID for the shared memory region. This is ID of the mapped region // Returns an ID for the shared memory region. This is ID of the mapped region
// consistent across all processes and is valid as long as the region is not // consistent across all processes and is valid as long as the region is not
// unmapped. // unmapped.
const UnguessableToken& mapped_id() const { const UnguessableToken& mapped_id() const {
return shared_memory_.mapped_id(); return shared_memory_mapping_.guid();
} }
// Locks a range of memory so that it will not be purged by the system. // Locks a range of memory so that it will not be purged by the system.
...@@ -147,10 +151,24 @@ class BASE_EXPORT DiscardableSharedMemory { ...@@ -147,10 +151,24 @@ class BASE_EXPORT DiscardableSharedMemory {
bool is_owned) const; bool is_owned) const;
private: private:
// 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.
static LockResult LockPages(const UnsafeSharedMemoryRegion& region,
size_t offset,
size_t length);
// UnlockPages() is a no-op on platforms not supporting discardable pages.
static void UnlockPages(const UnsafeSharedMemoryRegion& region,
size_t offset,
size_t length);
// Virtual for tests. // Virtual for tests.
virtual Time Now() const; virtual Time Now() const;
SharedMemory shared_memory_; UnsafeSharedMemoryRegion shared_memory_region_;
WritableSharedMemoryMapping shared_memory_mapping_;
size_t mapped_size_; size_t mapped_size_;
size_t locked_page_count_; size_t locked_page_count_;
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
......
...@@ -15,14 +15,13 @@ ...@@ -15,14 +15,13 @@
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace base { namespace base {
namespace {
class TestDiscardableSharedMemory : public DiscardableSharedMemory { class TestDiscardableSharedMemory : public DiscardableSharedMemory {
public: public:
TestDiscardableSharedMemory() = default; TestDiscardableSharedMemory() = default;
explicit TestDiscardableSharedMemory(SharedMemoryHandle handle) explicit TestDiscardableSharedMemory(UnsafeSharedMemoryRegion region)
: DiscardableSharedMemory(handle) {} : DiscardableSharedMemory(std::move(region)) {}
void SetNow(Time now) { now_ = now; } void SetNow(Time now) { now_ = now; }
...@@ -50,10 +49,10 @@ TEST(DiscardableSharedMemoryTest, CreateFromHandle) { ...@@ -50,10 +49,10 @@ TEST(DiscardableSharedMemoryTest, CreateFromHandle) {
bool rv = memory1.CreateAndMap(kDataSize); bool rv = memory1.CreateAndMap(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
SharedMemoryHandle shared_handle = memory1.handle().Duplicate(); UnsafeSharedMemoryRegion shared_region = memory1.DuplicateRegion();
ASSERT_TRUE(shared_handle.IsValid()); ASSERT_TRUE(shared_region.IsValid());
TestDiscardableSharedMemory memory2(shared_handle); TestDiscardableSharedMemory memory2(std::move(shared_region));
rv = memory2.Map(kDataSize); rv = memory2.Map(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
EXPECT_TRUE(memory2.IsMemoryLocked()); EXPECT_TRUE(memory2.IsMemoryLocked());
...@@ -82,10 +81,10 @@ TEST(DiscardableSharedMemoryTest, LockAndUnlock) { ...@@ -82,10 +81,10 @@ TEST(DiscardableSharedMemoryTest, LockAndUnlock) {
EXPECT_EQ(DiscardableSharedMemory::SUCCESS, lock_rv); EXPECT_EQ(DiscardableSharedMemory::SUCCESS, lock_rv);
EXPECT_TRUE(memory1.IsMemoryLocked()); EXPECT_TRUE(memory1.IsMemoryLocked());
SharedMemoryHandle shared_handle = memory1.handle().Duplicate(); UnsafeSharedMemoryRegion shared_region = memory1.DuplicateRegion();
ASSERT_TRUE(shared_handle.IsValid()); ASSERT_TRUE(shared_region.IsValid());
TestDiscardableSharedMemory memory2(shared_handle); TestDiscardableSharedMemory memory2(std::move(shared_region));
rv = memory2.Map(kDataSize); rv = memory2.Map(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
...@@ -118,10 +117,10 @@ TEST(DiscardableSharedMemoryTest, Purge) { ...@@ -118,10 +117,10 @@ TEST(DiscardableSharedMemoryTest, Purge) {
bool rv = memory1.CreateAndMap(kDataSize); bool rv = memory1.CreateAndMap(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
SharedMemoryHandle shared_handle = memory1.handle().Duplicate(); UnsafeSharedMemoryRegion shared_region = memory1.DuplicateRegion();
ASSERT_TRUE(shared_handle.IsValid()); ASSERT_TRUE(shared_region.IsValid());
TestDiscardableSharedMemory memory2(shared_handle); TestDiscardableSharedMemory memory2(std::move(shared_region));
rv = memory2.Map(kDataSize); rv = memory2.Map(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
...@@ -158,10 +157,10 @@ TEST(DiscardableSharedMemoryTest, LastUsed) { ...@@ -158,10 +157,10 @@ TEST(DiscardableSharedMemoryTest, LastUsed) {
bool rv = memory1.CreateAndMap(kDataSize); bool rv = memory1.CreateAndMap(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
SharedMemoryHandle shared_handle = memory1.handle().Duplicate(); UnsafeSharedMemoryRegion shared_region = memory1.DuplicateRegion();
ASSERT_TRUE(shared_handle.IsValid()); ASSERT_TRUE(shared_region.IsValid());
TestDiscardableSharedMemory memory2(shared_handle); TestDiscardableSharedMemory memory2(std::move(shared_region));
rv = memory2.Map(kDataSize); rv = memory2.Map(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
...@@ -224,10 +223,10 @@ TEST(DiscardableSharedMemoryTest, LockShouldAlwaysFailAfterSuccessfulPurge) { ...@@ -224,10 +223,10 @@ TEST(DiscardableSharedMemoryTest, LockShouldAlwaysFailAfterSuccessfulPurge) {
bool rv = memory1.CreateAndMap(kDataSize); bool rv = memory1.CreateAndMap(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
SharedMemoryHandle shared_handle = memory1.handle().Duplicate(); UnsafeSharedMemoryRegion shared_region = memory1.DuplicateRegion();
ASSERT_TRUE(shared_handle.IsValid()); ASSERT_TRUE(shared_region.IsValid());
TestDiscardableSharedMemory memory2(shared_handle); TestDiscardableSharedMemory memory2(std::move(shared_region));
rv = memory2.Map(kDataSize); rv = memory2.Map(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
...@@ -242,16 +241,22 @@ TEST(DiscardableSharedMemoryTest, LockShouldAlwaysFailAfterSuccessfulPurge) { ...@@ -242,16 +241,22 @@ TEST(DiscardableSharedMemoryTest, LockShouldAlwaysFailAfterSuccessfulPurge) {
EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv); EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv);
} }
#if defined(OS_ANDROID)
TEST(DiscardableSharedMemoryTest, LockShouldFailIfPlatformLockPagesFails) { TEST(DiscardableSharedMemoryTest, LockShouldFailIfPlatformLockPagesFails) {
const uint32_t kDataSize = 1024; const uint32_t kDataSize = 1024;
DiscardableSharedMemory memory; DiscardableSharedMemory memory1;
bool rv = memory.CreateAndMap(kDataSize); bool rv1 = memory1.CreateAndMap(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv1);
base::UnsafeSharedMemoryRegion region = memory1.DuplicateRegion();
int fd = region.GetPlatformHandle();
DiscardableSharedMemory memory2(std::move(region));
bool rv2 = memory2.Map(kDataSize);
ASSERT_TRUE(rv2);
// Unlock() the first page of memory, so we can test Lock()ing it. // Unlock() the first page of memory, so we can test Lock()ing it.
memory.Unlock(0, base::GetPageSize()); memory2.Unlock(0, base::GetPageSize());
#if defined(OS_ANDROID)
// To cause ashmem_pin_region() to fail, we arrange for it to be called with // To cause ashmem_pin_region() to fail, we arrange for it to be called with
// an invalid file-descriptor, which requires a valid-looking fd (i.e. we // an invalid file-descriptor, which requires a valid-looking fd (i.e. we
// can't just Close() |memory|), but one on which the operation is invalid. // can't just Close() |memory|), but one on which the operation is invalid.
...@@ -260,15 +265,14 @@ TEST(DiscardableSharedMemoryTest, LockShouldFailIfPlatformLockPagesFails) { ...@@ -260,15 +265,14 @@ TEST(DiscardableSharedMemoryTest, LockShouldFailIfPlatformLockPagesFails) {
// that it can close, etc without errors, but on which ashmem_pin_region() // that it can close, etc without errors, but on which ashmem_pin_region()
// will fail. // will fail.
base::ScopedFD null(open("/dev/null", O_RDONLY)); base::ScopedFD null(open("/dev/null", O_RDONLY));
ASSERT_EQ(memory.handle().GetHandle(), ASSERT_EQ(fd, dup2(null.get(), fd));
dup2(null.get(), memory.handle().GetHandle()));
// Now re-Lock()ing the first page should fail. // Now re-Lock()ing the first page should fail.
DiscardableSharedMemory::LockResult lock_rv = DiscardableSharedMemory::LockResult lock_rv =
memory.Lock(0, base::GetPageSize()); memory2.Lock(0, base::GetPageSize());
EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv); EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv);
#endif // defined(OS_ANDROID)
} }
#endif // defined(OS_ANDROID)
TEST(DiscardableSharedMemoryTest, LockAndUnlockRange) { TEST(DiscardableSharedMemoryTest, LockAndUnlockRange) {
const uint32_t kDataSize = 32; const uint32_t kDataSize = 32;
...@@ -279,10 +283,10 @@ TEST(DiscardableSharedMemoryTest, LockAndUnlockRange) { ...@@ -279,10 +283,10 @@ TEST(DiscardableSharedMemoryTest, LockAndUnlockRange) {
bool rv = memory1.CreateAndMap(data_size_in_bytes); bool rv = memory1.CreateAndMap(data_size_in_bytes);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
SharedMemoryHandle shared_handle = memory1.handle().Duplicate(); UnsafeSharedMemoryRegion shared_region = memory1.DuplicateRegion();
ASSERT_TRUE(shared_handle.IsValid()); ASSERT_TRUE(shared_region.IsValid());
TestDiscardableSharedMemory memory2(shared_handle); TestDiscardableSharedMemory memory2(std::move(shared_region));
rv = memory2.Map(data_size_in_bytes); rv = memory2.Map(data_size_in_bytes);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
...@@ -396,10 +400,10 @@ TEST(DiscardableSharedMemoryTest, ZeroFilledPagesAfterPurge) { ...@@ -396,10 +400,10 @@ TEST(DiscardableSharedMemoryTest, ZeroFilledPagesAfterPurge) {
bool rv = memory1.CreateAndMap(kDataSize); bool rv = memory1.CreateAndMap(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
SharedMemoryHandle shared_handle = memory1.handle().Duplicate(); UnsafeSharedMemoryRegion shared_region = memory1.DuplicateRegion();
ASSERT_TRUE(shared_handle.IsValid()); ASSERT_TRUE(shared_region.IsValid());
TestDiscardableSharedMemory memory2(shared_handle); TestDiscardableSharedMemory memory2(std::move(shared_region));
rv = memory2.Map(kDataSize); rv = memory2.Map(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
...@@ -449,5 +453,4 @@ TEST(DiscardableSharedMemoryTest, TracingOwnershipEdges) { ...@@ -449,5 +453,4 @@ TEST(DiscardableSharedMemoryTest, TracingOwnershipEdges) {
// CreateWeakSharedMemoryOwnershipEdge() is fixed, crbug.com/661257. // CreateWeakSharedMemoryOwnershipEdge() is fixed, crbug.com/661257.
} }
} // namespace
} // namespace base } // namespace base
...@@ -44,6 +44,15 @@ SharedMemoryTracker::GetOrCreateSharedMemoryDump( ...@@ -44,6 +44,15 @@ SharedMemoryTracker::GetOrCreateSharedMemoryDump(
shared_memory->mapped_id(), pmd); shared_memory->mapped_id(), pmd);
} }
const trace_event::MemoryAllocatorDump*
SharedMemoryTracker::GetOrCreateSharedMemoryDump(
const SharedMemoryMapping& shared_memory,
trace_event::ProcessMemoryDump* pmd) {
return GetOrCreateSharedMemoryDumpInternal(shared_memory.raw_memory_ptr(),
shared_memory.mapped_size(),
shared_memory.guid(), pmd);
}
void SharedMemoryTracker::IncrementMemoryUsage( void SharedMemoryTracker::IncrementMemoryUsage(
const SharedMemory& shared_memory) { const SharedMemory& shared_memory) {
AutoLock hold(usages_lock_); AutoLock hold(usages_lock_);
......
...@@ -38,11 +38,14 @@ class BASE_EXPORT SharedMemoryTracker : public trace_event::MemoryDumpProvider { ...@@ -38,11 +38,14 @@ class BASE_EXPORT SharedMemoryTracker : public trace_event::MemoryDumpProvider {
static const trace_event::MemoryAllocatorDump* GetOrCreateSharedMemoryDump( static const trace_event::MemoryAllocatorDump* GetOrCreateSharedMemoryDump(
const SharedMemory* shared_memory, const SharedMemory* shared_memory,
trace_event::ProcessMemoryDump* pmd); trace_event::ProcessMemoryDump* pmd);
// We're in the middle of a refactor https://crbug.com/795291. Eventually, the
// first call will go away.
static const trace_event::MemoryAllocatorDump* GetOrCreateSharedMemoryDump(
const SharedMemoryMapping& shared_memory,
trace_event::ProcessMemoryDump* pmd);
// Records shared memory usage on valid mapping. // Records shared memory usage on valid mapping.
void IncrementMemoryUsage(const SharedMemory& shared_memory); void IncrementMemoryUsage(const SharedMemory& shared_memory);
// We're in the middle of a refactor https://crbug.com/795291. Eventually, the
// first call will go away.
void IncrementMemoryUsage(const SharedMemoryMapping& mapping); void IncrementMemoryUsage(const SharedMemoryMapping& mapping);
// Records shared memory usage on unmapping. // Records shared memory usage on unmapping.
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef BASE_MEMORY_UNSAFE_SHARED_MEMORY_REGION_H_ #ifndef BASE_MEMORY_UNSAFE_SHARED_MEMORY_REGION_H_
#define BASE_MEMORY_UNSAFE_SHARED_MEMORY_REGION_H_ #define BASE_MEMORY_UNSAFE_SHARED_MEMORY_REGION_H_
#include "base/gtest_prod_util.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/platform_shared_memory_region.h" #include "base/memory/platform_shared_memory_region.h"
#include "base/memory/shared_memory_mapping.h" #include "base/memory/shared_memory_mapping.h"
...@@ -88,8 +89,19 @@ class BASE_EXPORT UnsafeSharedMemoryRegion { ...@@ -88,8 +89,19 @@ class BASE_EXPORT UnsafeSharedMemoryRegion {
} }
private: private:
FRIEND_TEST_ALL_PREFIXES(DiscardableSharedMemoryTest,
LockShouldFailIfPlatformLockPagesFails);
friend class DiscardableSharedMemory;
explicit UnsafeSharedMemoryRegion(subtle::PlatformSharedMemoryRegion handle); explicit UnsafeSharedMemoryRegion(subtle::PlatformSharedMemoryRegion handle);
// Returns a platform shared memory handle. |this| remains the owner of the
// handle.
subtle::PlatformSharedMemoryRegion::PlatformHandle GetPlatformHandle() const {
DCHECK(IsValid());
return handle_.GetPlatformHandle();
}
subtle::PlatformSharedMemoryRegion handle_; subtle::PlatformSharedMemoryRegion handle_;
DISALLOW_COPY_AND_ASSIGN(UnsafeSharedMemoryRegion); DISALLOW_COPY_AND_ASSIGN(UnsafeSharedMemoryRegion);
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "components/crash/core/common/crash_key.h" #include "components/crash/core/common/crash_key.h"
#include "mojo/public/cpp/system/platform_handle.h"
namespace discardable_memory { namespace discardable_memory {
namespace { namespace {
...@@ -357,7 +356,7 @@ ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory( ...@@ -357,7 +356,7 @@ ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
"ClientDiscardableSharedMemoryManager::" "ClientDiscardableSharedMemoryManager::"
"AllocateLockedDiscardableSharedMemory", "AllocateLockedDiscardableSharedMemory",
"size", size, "id", id); "size", size, "id", id);
base::SharedMemoryHandle handle; base::UnsafeSharedMemoryRegion region;
base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED); base::WaitableEvent::InitialState::NOT_SIGNALED);
base::ScopedClosureRunner event_signal_runner( base::ScopedClosureRunner event_signal_runner(
...@@ -365,11 +364,12 @@ ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory( ...@@ -365,11 +364,12 @@ ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
io_task_runner_->PostTask( io_task_runner_->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&ClientDiscardableSharedMemoryManager::AllocateOnIO, base::BindOnce(&ClientDiscardableSharedMemoryManager::AllocateOnIO,
base::Unretained(this), size, id, &handle, base::Unretained(this), size, id, &region,
std::move(event_signal_runner))); std::move(event_signal_runner)));
// Waiting until IPC has finished on the IO thread. // Waiting until IPC has finished on the IO thread.
event.Wait(); event.Wait();
auto memory = std::make_unique<base::DiscardableSharedMemory>(handle); auto memory =
std::make_unique<base::DiscardableSharedMemory>(std::move(region));
if (!memory->Map(size)) if (!memory->Map(size))
base::TerminateBecauseOutOfMemory(size); base::TerminateBecauseOutOfMemory(size);
return memory; return memory;
...@@ -378,25 +378,21 @@ ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory( ...@@ -378,25 +378,21 @@ ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
void ClientDiscardableSharedMemoryManager::AllocateOnIO( void ClientDiscardableSharedMemoryManager::AllocateOnIO(
size_t size, size_t size,
int32_t id, int32_t id,
base::SharedMemoryHandle* handle, base::UnsafeSharedMemoryRegion* region,
base::ScopedClosureRunner closure_runner) { base::ScopedClosureRunner closure_runner) {
(*manager_mojo_) (*manager_mojo_)
->AllocateLockedDiscardableSharedMemory( ->AllocateLockedDiscardableSharedMemory(
static_cast<uint32_t>(size), id, static_cast<uint32_t>(size), id,
base::BindOnce( base::BindOnce(
&ClientDiscardableSharedMemoryManager::AllocateCompletedOnIO, &ClientDiscardableSharedMemoryManager::AllocateCompletedOnIO,
base::Unretained(this), handle, std::move(closure_runner))); base::Unretained(this), region, std::move(closure_runner)));
} }
void ClientDiscardableSharedMemoryManager::AllocateCompletedOnIO( void ClientDiscardableSharedMemoryManager::AllocateCompletedOnIO(
base::SharedMemoryHandle* handle, base::UnsafeSharedMemoryRegion* region,
base::ScopedClosureRunner closure_runner, base::ScopedClosureRunner closure_runner,
mojo::ScopedSharedBufferHandle mojo_handle) { base::UnsafeSharedMemoryRegion ret_region) {
if (!mojo_handle.is_valid()) *region = std::move(ret_region);
return;
auto result = mojo::UnwrapSharedMemoryHandle(std::move(mojo_handle), handle,
nullptr, nullptr);
DCHECK_EQ(result, MOJO_RESULT_OK);
} }
void ClientDiscardableSharedMemoryManager::DeletedDiscardableSharedMemory( void ClientDiscardableSharedMemoryManager::DeletedDiscardableSharedMemory(
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/discardable_memory_allocator.h" #include "base/memory/discardable_memory_allocator.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/shared_memory_handle.h" #include "base/memory/unsafe_shared_memory_region.h"
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
#include "base/trace_event/memory_dump_provider.h" #include "base/trace_event/memory_dump_provider.h"
#include "components/discardable_memory/common/discardable_memory_export.h" #include "components/discardable_memory/common/discardable_memory_export.h"
...@@ -67,11 +67,11 @@ class DISCARDABLE_MEMORY_EXPORT ClientDiscardableSharedMemoryManager ...@@ -67,11 +67,11 @@ class DISCARDABLE_MEMORY_EXPORT ClientDiscardableSharedMemoryManager
AllocateLockedDiscardableSharedMemory(size_t size, int32_t id); AllocateLockedDiscardableSharedMemory(size_t size, int32_t id);
void AllocateOnIO(size_t size, void AllocateOnIO(size_t size,
int32_t id, int32_t id,
base::SharedMemoryHandle* handle, base::UnsafeSharedMemoryRegion* region,
base::ScopedClosureRunner closure_runner); base::ScopedClosureRunner closure_runner);
void AllocateCompletedOnIO(base::SharedMemoryHandle* handle, void AllocateCompletedOnIO(base::UnsafeSharedMemoryRegion* region,
base::ScopedClosureRunner closure_runner, base::ScopedClosureRunner closure_runner,
mojo::ScopedSharedBufferHandle mojo_handle); base::UnsafeSharedMemoryRegion ret_region);
void DeletedDiscardableSharedMemory(int32_t id); void DeletedDiscardableSharedMemory(int32_t id);
void MemoryUsageChanged(size_t new_bytes_allocated, void MemoryUsageChanged(size_t new_bytes_allocated,
......
...@@ -14,4 +14,8 @@ mojom("interfaces") { ...@@ -14,4 +14,8 @@ mojom("interfaces") {
get_path_info("../../../..", "abspath"), get_path_info("../../../..", "abspath"),
"//mojo/services", "//mojo/services",
] ]
public_deps = [
"//mojo/public/mojom/base",
]
} }
...@@ -4,13 +4,15 @@ ...@@ -4,13 +4,15 @@
module discardable_memory.mojom; module discardable_memory.mojom;
import "mojo/public/mojom/base/shared_memory.mojom";
// This interface is used for allocating discardable shared memory from browser // This interface is used for allocating discardable shared memory from browser
// process. For mus+ash, this service will live in mus process. // process. For mus+ash, this service will live in mus process.
interface DiscardableSharedMemoryManager { interface DiscardableSharedMemoryManager {
// Allocate a locked discardable shared memory segment. // Allocate a locked discardable shared memory segment.
AllocateLockedDiscardableSharedMemory( AllocateLockedDiscardableSharedMemory(
uint32 size, uint32 size,
int32 id) => (handle<shared_buffer>? memory); int32 id) => (mojo_base.mojom.UnsafeSharedMemoryRegion region);
// Notify manager that a memory segment has been deleted. // Notify manager that a memory segment has been deleted.
DeletedDiscardableSharedMemory(int32 id); DeletedDiscardableSharedMemory(int32 id);
}; };
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include "components/crash/core/common/crash_key.h" #include "components/crash/core/common/crash_key.h"
#include "components/discardable_memory/common/discardable_shared_memory_heap.h" #include "components/discardable_memory/common/discardable_shared_memory_heap.h"
#include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/platform_handle.h"
#if defined(OS_LINUX) #if defined(OS_LINUX)
#include "base/files/file_path.h" #include "base/files/file_path.h"
...@@ -69,16 +68,12 @@ class MojoDiscardableSharedMemoryManagerImpl ...@@ -69,16 +68,12 @@ class MojoDiscardableSharedMemoryManagerImpl
uint32_t size, uint32_t size,
int32_t id, int32_t id,
AllocateLockedDiscardableSharedMemoryCallback callback) override { AllocateLockedDiscardableSharedMemoryCallback callback) override {
base::SharedMemoryHandle handle; base::UnsafeSharedMemoryRegion region;
mojo::ScopedSharedBufferHandle memory;
if (manager_) { if (manager_) {
manager_->AllocateLockedDiscardableSharedMemoryForClient(client_id_, size, manager_->AllocateLockedDiscardableSharedMemoryForClient(client_id_, size,
id, &handle); id, &region);
memory = mojo::WrapSharedMemoryHandle(
handle, size,
mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
} }
std::move(callback).Run(std::move(memory)); std::move(callback).Run(std::move(region));
} }
void DeletedDiscardableSharedMemory(int32_t id) override { void DeletedDiscardableSharedMemory(int32_t id) override {
...@@ -288,11 +283,11 @@ DiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(size_t size) { ...@@ -288,11 +283,11 @@ DiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(size_t size) {
// Note: Use DiscardableSharedMemoryHeap for in-process allocation // Note: Use DiscardableSharedMemoryHeap for in-process allocation
// of discardable memory if the cost of each allocation is too high. // of discardable memory if the cost of each allocation is too high.
base::SharedMemoryHandle handle; base::UnsafeSharedMemoryRegion region;
AllocateLockedDiscardableSharedMemory(kInvalidUniqueClientID, size, new_id, AllocateLockedDiscardableSharedMemory(kInvalidUniqueClientID, size, new_id,
&handle); &region);
std::unique_ptr<base::DiscardableSharedMemory> memory( std::unique_ptr<base::DiscardableSharedMemory> memory(
new base::DiscardableSharedMemory(handle)); new base::DiscardableSharedMemory(std::move(region)));
if (!memory->Map(size)) if (!memory->Map(size))
base::TerminateBecauseOutOfMemory(size); base::TerminateBecauseOutOfMemory(size);
// Close file descriptor to avoid running out. // Close file descriptor to avoid running out.
...@@ -354,9 +349,9 @@ void DiscardableSharedMemoryManager:: ...@@ -354,9 +349,9 @@ void DiscardableSharedMemoryManager::
int client_id, int client_id,
size_t size, size_t size,
int32_t id, int32_t id,
base::SharedMemoryHandle* shared_memory_handle) { base::UnsafeSharedMemoryRegion* shared_memory_region) {
AllocateLockedDiscardableSharedMemory(client_id, size, id, AllocateLockedDiscardableSharedMemory(client_id, size, id,
shared_memory_handle); shared_memory_region);
} }
void DiscardableSharedMemoryManager::ClientDeletedDiscardableSharedMemory( void DiscardableSharedMemoryManager::ClientDeletedDiscardableSharedMemory(
...@@ -443,14 +438,14 @@ void DiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory( ...@@ -443,14 +438,14 @@ void DiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
int client_id, int client_id,
size_t size, size_t size,
int32_t id, int32_t id,
base::SharedMemoryHandle* shared_memory_handle) { base::UnsafeSharedMemoryRegion* shared_memory_region) {
base::AutoLock lock(lock_); base::AutoLock lock(lock_);
// Make sure |id| is not already in use. // Make sure |id| is not already in use.
MemorySegmentMap& client_segments = clients_[client_id]; MemorySegmentMap& client_segments = clients_[client_id];
if (client_segments.find(id) != client_segments.end()) { if (client_segments.find(id) != client_segments.end()) {
LOG(ERROR) << "Invalid discardable shared memory ID"; LOG(ERROR) << "Invalid discardable shared memory ID";
*shared_memory_handle = base::SharedMemoryHandle(); *shared_memory_region = base::UnsafeSharedMemoryRegion();
return; return;
} }
...@@ -471,21 +466,21 @@ void DiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory( ...@@ -471,21 +466,21 @@ void DiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
std::unique_ptr<base::DiscardableSharedMemory> memory( std::unique_ptr<base::DiscardableSharedMemory> memory(
new base::DiscardableSharedMemory); new base::DiscardableSharedMemory);
if (!memory->CreateAndMap(size)) { if (!memory->CreateAndMap(size)) {
*shared_memory_handle = base::SharedMemoryHandle(); *shared_memory_region = base::UnsafeSharedMemoryRegion();
return; return;
} }
base::CheckedNumeric<size_t> checked_bytes_allocated = bytes_allocated_; base::CheckedNumeric<size_t> checked_bytes_allocated = bytes_allocated_;
checked_bytes_allocated += memory->mapped_size(); checked_bytes_allocated += memory->mapped_size();
if (!checked_bytes_allocated.IsValid()) { if (!checked_bytes_allocated.IsValid()) {
*shared_memory_handle = base::SharedMemoryHandle(); *shared_memory_region = base::UnsafeSharedMemoryRegion();
return; return;
} }
bytes_allocated_ = checked_bytes_allocated.ValueOrDie(); bytes_allocated_ = checked_bytes_allocated.ValueOrDie();
BytesAllocatedChanged(bytes_allocated_); BytesAllocatedChanged(bytes_allocated_);
*shared_memory_handle = base::SharedMemory::DuplicateHandle(memory->handle()); *shared_memory_region = memory->DuplicateRegion();
// Close file descriptor to avoid running out. // Close file descriptor to avoid running out.
memory->Close(); memory->Close();
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include "base/memory/memory_coordinator_client.h" #include "base/memory/memory_coordinator_client.h"
#include "base/memory/memory_pressure_listener.h" #include "base/memory/memory_pressure_listener.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h" #include "base/memory/unsafe_shared_memory_region.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_current.h" #include "base/message_loop/message_loop_current.h"
...@@ -68,12 +68,12 @@ class DISCARDABLE_MEMORY_EXPORT DiscardableSharedMemoryManager ...@@ -68,12 +68,12 @@ class DISCARDABLE_MEMORY_EXPORT DiscardableSharedMemoryManager
base::trace_event::ProcessMemoryDump* pmd) override; base::trace_event::ProcessMemoryDump* pmd) override;
// This allocates a discardable memory segment for |process_handle|. // This allocates a discardable memory segment for |process_handle|.
// A valid shared memory handle is returned on success. // A valid shared memory region is returned on success.
void AllocateLockedDiscardableSharedMemoryForClient( void AllocateLockedDiscardableSharedMemoryForClient(
int client_id, int client_id,
size_t size, size_t size,
int32_t id, int32_t id,
base::SharedMemoryHandle* shared_memory_handle); base::UnsafeSharedMemoryRegion* shared_memory_region);
// Call this to notify the manager that client process associated with // Call this to notify the manager that client process associated with
// |client_id| has deleted discardable memory segment with |id|. // |client_id| has deleted discardable memory segment with |id|.
...@@ -128,7 +128,7 @@ class DISCARDABLE_MEMORY_EXPORT DiscardableSharedMemoryManager ...@@ -128,7 +128,7 @@ class DISCARDABLE_MEMORY_EXPORT DiscardableSharedMemoryManager
int client_id, int client_id,
size_t size, size_t size,
int32_t id, int32_t id,
base::SharedMemoryHandle* shared_memory_handle); base::UnsafeSharedMemoryRegion* shared_memory_region);
void DeletedDiscardableSharedMemory(int32_t id, int client_id); void DeletedDiscardableSharedMemory(int32_t id, int client_id);
void OnMemoryPressure( void OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
......
...@@ -20,8 +20,8 @@ class TestDiscardableSharedMemory : public base::DiscardableSharedMemory { ...@@ -20,8 +20,8 @@ class TestDiscardableSharedMemory : public base::DiscardableSharedMemory {
public: public:
TestDiscardableSharedMemory() {} TestDiscardableSharedMemory() {}
explicit TestDiscardableSharedMemory(base::SharedMemoryHandle handle) explicit TestDiscardableSharedMemory(base::UnsafeSharedMemoryRegion region)
: DiscardableSharedMemory(handle) {} : DiscardableSharedMemory(std::move(region)) {}
void SetNow(base::Time now) { now_ = now; } void SetNow(base::Time now) { now_ = now; }
...@@ -75,12 +75,12 @@ TEST_F(DiscardableSharedMemoryManagerTest, AllocateForClient) { ...@@ -75,12 +75,12 @@ TEST_F(DiscardableSharedMemoryManagerTest, AllocateForClient) {
uint8_t data[kDataSize]; uint8_t data[kDataSize];
memset(data, 0x80, kDataSize); memset(data, 0x80, kDataSize);
base::SharedMemoryHandle shared_handle; base::UnsafeSharedMemoryRegion shared_region;
manager_->AllocateLockedDiscardableSharedMemoryForClient( manager_->AllocateLockedDiscardableSharedMemoryForClient(
kInvalidUniqueID, kDataSize, 0, &shared_handle); kInvalidUniqueID, kDataSize, 0, &shared_region);
ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle)); ASSERT_TRUE(shared_region.IsValid());
TestDiscardableSharedMemory memory(shared_handle); TestDiscardableSharedMemory memory(std::move(shared_region));
bool rv = memory.Map(kDataSize); bool rv = memory.Map(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
...@@ -96,21 +96,21 @@ TEST_F(DiscardableSharedMemoryManagerTest, AllocateForClient) { ...@@ -96,21 +96,21 @@ TEST_F(DiscardableSharedMemoryManagerTest, AllocateForClient) {
TEST_F(DiscardableSharedMemoryManagerTest, Purge) { TEST_F(DiscardableSharedMemoryManagerTest, Purge) {
const int kDataSize = 1024; const int kDataSize = 1024;
base::SharedMemoryHandle shared_handle1; base::UnsafeSharedMemoryRegion shared_region1;
manager_->AllocateLockedDiscardableSharedMemoryForClient( manager_->AllocateLockedDiscardableSharedMemoryForClient(
kInvalidUniqueID, kDataSize, 1, &shared_handle1); kInvalidUniqueID, kDataSize, 1, &shared_region1);
ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle1)); ASSERT_TRUE(shared_region1.IsValid());
TestDiscardableSharedMemory memory1(shared_handle1); TestDiscardableSharedMemory memory1(std::move(shared_region1));
bool rv = memory1.Map(kDataSize); bool rv = memory1.Map(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
base::SharedMemoryHandle shared_handle2; base::UnsafeSharedMemoryRegion shared_region2;
manager_->AllocateLockedDiscardableSharedMemoryForClient( manager_->AllocateLockedDiscardableSharedMemoryForClient(
kInvalidUniqueID, kDataSize, 2, &shared_handle2); kInvalidUniqueID, kDataSize, 2, &shared_region2);
ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle2)); ASSERT_TRUE(shared_region2.IsValid());
TestDiscardableSharedMemory memory2(shared_handle2); TestDiscardableSharedMemory memory2(std::move(shared_region2));
rv = memory2.Map(kDataSize); rv = memory2.Map(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
...@@ -160,12 +160,12 @@ TEST_F(DiscardableSharedMemoryManagerTest, Purge) { ...@@ -160,12 +160,12 @@ TEST_F(DiscardableSharedMemoryManagerTest, Purge) {
TEST_F(DiscardableSharedMemoryManagerTest, EnforceMemoryPolicy) { TEST_F(DiscardableSharedMemoryManagerTest, EnforceMemoryPolicy) {
const int kDataSize = 1024; const int kDataSize = 1024;
base::SharedMemoryHandle shared_handle; base::UnsafeSharedMemoryRegion shared_region;
manager_->AllocateLockedDiscardableSharedMemoryForClient( manager_->AllocateLockedDiscardableSharedMemoryForClient(
kInvalidUniqueID, kDataSize, 0, &shared_handle); kInvalidUniqueID, kDataSize, 0, &shared_region);
ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle)); ASSERT_TRUE(shared_region.IsValid());
TestDiscardableSharedMemory memory(shared_handle); TestDiscardableSharedMemory memory(std::move(shared_region));
bool rv = memory.Map(kDataSize); bool rv = memory.Map(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
...@@ -198,21 +198,21 @@ TEST_F(DiscardableSharedMemoryManagerTest, ...@@ -198,21 +198,21 @@ TEST_F(DiscardableSharedMemoryManagerTest,
ReduceMemoryAfterSegmentHasBeenDeleted) { ReduceMemoryAfterSegmentHasBeenDeleted) {
const int kDataSize = 1024; const int kDataSize = 1024;
base::SharedMemoryHandle shared_handle1; base::UnsafeSharedMemoryRegion shared_region1;
manager_->AllocateLockedDiscardableSharedMemoryForClient( manager_->AllocateLockedDiscardableSharedMemoryForClient(
kInvalidUniqueID, kDataSize, 1, &shared_handle1); kInvalidUniqueID, kDataSize, 1, &shared_region1);
ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle1)); ASSERT_TRUE(shared_region1.IsValid());
TestDiscardableSharedMemory memory1(shared_handle1); TestDiscardableSharedMemory memory1(std::move(shared_region1));
bool rv = memory1.Map(kDataSize); bool rv = memory1.Map(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
base::SharedMemoryHandle shared_handle2; base::UnsafeSharedMemoryRegion shared_region2;
manager_->AllocateLockedDiscardableSharedMemoryForClient( manager_->AllocateLockedDiscardableSharedMemoryForClient(
kInvalidUniqueID, kDataSize, 2, &shared_handle2); kInvalidUniqueID, kDataSize, 2, &shared_region2);
ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle2)); ASSERT_TRUE(shared_region2.IsValid());
TestDiscardableSharedMemory memory2(shared_handle2); TestDiscardableSharedMemory memory2(std::move(shared_region2));
rv = memory2.Map(kDataSize); rv = memory2.Map(kDataSize);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
...@@ -261,10 +261,10 @@ TEST_F(DiscardableSharedMemoryManagerScheduleEnforceMemoryPolicyTest, ...@@ -261,10 +261,10 @@ TEST_F(DiscardableSharedMemoryManagerScheduleEnforceMemoryPolicyTest,
SetMemoryLimitOnSimpleThread) { SetMemoryLimitOnSimpleThread) {
const int kDataSize = 1024; const int kDataSize = 1024;
base::SharedMemoryHandle shared_handle; base::UnsafeSharedMemoryRegion shared_region;
manager_->AllocateLockedDiscardableSharedMemoryForClient( manager_->AllocateLockedDiscardableSharedMemoryForClient(
kInvalidUniqueID, kDataSize, 0, &shared_handle); kInvalidUniqueID, kDataSize, 0, &shared_region);
ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle)); ASSERT_TRUE(shared_region.IsValid());
// Set the memory limit to a value that will require EnforceMemoryPolicy() // Set the memory limit to a value that will require EnforceMemoryPolicy()
// to be schedule on a thread without a message loop. // to be schedule on a thread without a message loop.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment