Remove most of base/memory Change-Id: I877807f4d8bfe8b162baa71f159f74340f562c23 Reviewed-on: https://gn-review.googlesource.com/1480 Commit-Queue: Scott Graham <scottmg@chromium.org> Reviewed-by: Brett Wilson <brettw@chromium.org>
diff --git a/base/memory/OWNERS b/base/memory/OWNERS deleted file mode 100644 index 9b7cbb1..0000000 --- a/base/memory/OWNERS +++ /dev/null
@@ -1,4 +0,0 @@ -per-file *chromeos*=skuhne@chromium.org -per-file *chromeos*=oshima@chromium.org -per-file *shared_memory*=set noparent -per-file *shared_memory*=file://ipc/SECURITY_OWNERS
diff --git a/base/memory/aligned_memory.cc b/base/memory/aligned_memory.cc deleted file mode 100644 index 861ea50..0000000 --- a/base/memory/aligned_memory.cc +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/aligned_memory.h" - -#include "base/logging.h" -#include "build_config.h" - -#if defined(OS_ANDROID) -#include <malloc.h> -#endif - -namespace base { - -void* AlignedAlloc(size_t size, size_t alignment) { - DCHECK_GT(size, 0U); - DCHECK_EQ(alignment & (alignment - 1), 0U); - DCHECK_EQ(alignment % sizeof(void*), 0U); - void* ptr = nullptr; -#if defined(COMPILER_MSVC) - ptr = _aligned_malloc(size, alignment); -// Android technically supports posix_memalign(), but does not expose it in -// the current version of the library headers used by Chrome. Luckily, -// memalign() on Android returns pointers which can safely be used with -// free(), so we can use it instead. Issue filed to document this: -// http://code.google.com/p/android/issues/detail?id=35391 -#elif defined(OS_ANDROID) - ptr = memalign(alignment, size); -#else - if (posix_memalign(&ptr, alignment, size)) - ptr = nullptr; -#endif - // Since aligned allocations may fail for non-memory related reasons, force a - // crash if we encounter a failed allocation; maintaining consistent behavior - // with a normal allocation failure in Chrome. - if (!ptr) { - DLOG(ERROR) << "If you crashed here, your aligned allocation is incorrect: " - << "size=" << size << ", alignment=" << alignment; - CHECK(false); - } - // Sanity check alignment just to be safe. - DCHECK_EQ(reinterpret_cast<uintptr_t>(ptr) & (alignment - 1), 0U); - return ptr; -} - -} // namespace base
diff --git a/base/memory/aligned_memory.h b/base/memory/aligned_memory.h deleted file mode 100644 index e0dd7f5..0000000 --- a/base/memory/aligned_memory.h +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_ALIGNED_MEMORY_H_ -#define BASE_MEMORY_ALIGNED_MEMORY_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <type_traits> - -#include "base/base_export.h" -#include "base/compiler_specific.h" -#include "build_config.h" - -#if defined(COMPILER_MSVC) -#include <malloc.h> -#else -#include <stdlib.h> -#endif - -// A runtime sized aligned allocation can be created: -// -// float* my_array = static_cast<float*>(AlignedAlloc(size, alignment)); -// -// // ... later, to release the memory: -// AlignedFree(my_array); -// -// Or using unique_ptr: -// -// std::unique_ptr<float, AlignedFreeDeleter> my_array( -// static_cast<float*>(AlignedAlloc(size, alignment))); - -namespace base { - -// This can be replaced with std::aligned_malloc when we have C++17. -BASE_EXPORT void* AlignedAlloc(size_t size, size_t alignment); - -inline void AlignedFree(void* ptr) { -#if defined(COMPILER_MSVC) - _aligned_free(ptr); -#else - free(ptr); -#endif -} - -// Deleter for use with unique_ptr. E.g., use as -// std::unique_ptr<Foo, base::AlignedFreeDeleter> foo; -struct AlignedFreeDeleter { - inline void operator()(void* ptr) const { - AlignedFree(ptr); - } -}; - -} // namespace base - -#endif // BASE_MEMORY_ALIGNED_MEMORY_H_
diff --git a/base/memory/discardable_memory.cc b/base/memory/discardable_memory.cc deleted file mode 100644 index f0730aa..0000000 --- a/base/memory/discardable_memory.cc +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory.h" - -namespace base { - -DiscardableMemory::DiscardableMemory() = default; - -DiscardableMemory::~DiscardableMemory() = default; - -} // namespace base
diff --git a/base/memory/discardable_memory.h b/base/memory/discardable_memory.h deleted file mode 100644 index 5c632d1..0000000 --- a/base/memory/discardable_memory.h +++ /dev/null
@@ -1,78 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_H_ -#define BASE_MEMORY_DISCARDABLE_MEMORY_H_ - -#include "base/base_export.h" -#include "base/compiler_specific.h" - -namespace base { - -namespace trace_event { -class MemoryAllocatorDump; -class ProcessMemoryDump; -} - -// Discardable memory is used to cache large objects without worrying about -// blowing out memory, both on mobile devices where there is no swap, and -// desktop devices where unused free memory should be used to help the user -// experience. This is preferable to releasing memory in response to an OOM -// signal because it is simpler and provides system-wide management of -// purgable memory, though it has less flexibility as to which objects get -// discarded. -// -// Discardable memory has two states: locked and unlocked. While the memory is -// locked, it will not be discarded. Unlocking the memory allows the -// discardable memory system and the OS to reclaim it if needed. Locks do not -// nest. -// -// Notes: -// - The paging behavior of memory while it is locked is not specified. While -// mobile platforms will not swap it out, it may qualify for swapping -// on desktop platforms. It is not expected that this will matter, as the -// preferred pattern of usage for DiscardableMemory is to lock down the -// memory, use it as quickly as possible, and then unlock it. -// - Because of memory alignment, the amount of memory allocated can be -// larger than the requested memory size. It is not very efficient for -// small allocations. -// - A discardable memory instance is not thread safe. It is the -// responsibility of users of discardable memory to ensure there are no -// races. -// -class BASE_EXPORT DiscardableMemory { - public: - DiscardableMemory(); - virtual ~DiscardableMemory(); - - // Locks the memory so that it will not be purged by the system. Returns - // true on success. If the return value is false then this object should be - // discarded and a new one should be created. - virtual bool Lock() WARN_UNUSED_RESULT = 0; - - // Unlocks the memory so that it can be purged by the system. Must be called - // after every successful lock call. - virtual void Unlock() = 0; - - // Returns the memory address held by this object. The object must be locked - // before calling this. - virtual void* data() const = 0; - - // Handy method to simplify calling data() with a reinterpret_cast. - template<typename T> T* data_as() const { - return reinterpret_cast<T*>(data()); - } - - // Used for dumping the statistics of discardable memory allocated in tracing. - // Returns a new MemoryAllocatorDump in the |pmd| with the size of the - // discardable memory. The MemoryAllocatorDump created is owned by |pmd|. See - // ProcessMemoryDump::CreateAllocatorDump. - virtual trace_event::MemoryAllocatorDump* CreateMemoryAllocatorDump( - const char* name, - trace_event::ProcessMemoryDump* pmd) const = 0; -}; - -} // namespace base - -#endif // BASE_MEMORY_DISCARDABLE_MEMORY_H_
diff --git a/base/memory/discardable_memory_allocator.cc b/base/memory/discardable_memory_allocator.cc deleted file mode 100644 index 3dbb276..0000000 --- a/base/memory/discardable_memory_allocator.cc +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory_allocator.h" - -#include "base/logging.h" - -namespace base { -namespace { - -DiscardableMemoryAllocator* g_discardable_allocator = nullptr; - -} // namespace - -// static -void DiscardableMemoryAllocator::SetInstance( - DiscardableMemoryAllocator* allocator) { - DCHECK(!allocator || !g_discardable_allocator); - g_discardable_allocator = allocator; -} - -// static -DiscardableMemoryAllocator* DiscardableMemoryAllocator::GetInstance() { - DCHECK(g_discardable_allocator); - return g_discardable_allocator; -} - -} // namespace base
diff --git a/base/memory/discardable_memory_allocator.h b/base/memory/discardable_memory_allocator.h deleted file mode 100644 index 8d74b16..0000000 --- a/base/memory/discardable_memory_allocator.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_ALLOCATOR_H_ -#define BASE_MEMORY_DISCARDABLE_MEMORY_ALLOCATOR_H_ - -#include <stddef.h> - -#include <memory> - -#include "base/base_export.h" - -namespace base { -class DiscardableMemory; - -class BASE_EXPORT DiscardableMemoryAllocator { - public: - // Returns the allocator instance. - static DiscardableMemoryAllocator* GetInstance(); - - // Sets the allocator instance. Can only be called once, e.g. on startup. - // Ownership of |instance| remains with the caller. - static void SetInstance(DiscardableMemoryAllocator* allocator); - - // Giant WARNING: Discardable[Shared]Memory is only implemented on Android. On - // non-Android platforms, it behaves exactly the same as SharedMemory. - // See LockPages() in discardable_shared_memory.cc. - virtual std::unique_ptr<DiscardableMemory> AllocateLockedDiscardableMemory( - size_t size) = 0; - - protected: - virtual ~DiscardableMemoryAllocator() = default; -}; - -} // namespace base - -#endif // BASE_MEMORY_DISCARDABLE_MEMORY_ALLOCATOR_H_
diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc deleted file mode 100644 index 8601e21..0000000 --- a/base/memory/discardable_shared_memory.cc +++ /dev/null
@@ -1,514 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_shared_memory.h" - -#include <stdint.h> - -#include <algorithm> - -#include "base/atomicops.h" -#include "base/bits.h" -#include "base/logging.h" -#include "base/memory/shared_memory_tracker.h" -#include "base/numerics/safe_math.h" -#include "base/process/process_metrics.h" -#include "base/trace_event/memory_allocator_dump.h" -#include "base/trace_event/process_memory_dump.h" -#include "build_config.h" - -#if defined(OS_POSIX) && !defined(OS_NACL) -// For madvise() which is available on all POSIX compatible systems. -#include <sys/mman.h> -#endif - -#if defined(OS_ANDROID) -#include "third_party/ashmem/ashmem.h" -#endif - -#if defined(OS_WIN) -#include <windows.h> -#include "base/win/windows_version.h" -#endif - -namespace base { -namespace { - -// Use a machine-sized pointer as atomic type. It will use the Atomic32 or -// Atomic64 routines, depending on the architecture. -typedef intptr_t AtomicType; -typedef uintptr_t UAtomicType; - -// Template specialization for timestamp serialization/deserialization. This -// is used to serialize timestamps using Unix time on systems where AtomicType -// does not have enough precision to contain a timestamp in the standard -// serialized format. -template <int> -Time TimeFromWireFormat(int64_t value); -template <int> -int64_t TimeToWireFormat(Time time); - -// Serialize to Unix time when using 4-byte wire format. -// Note: 19 January 2038, this will cease to work. -template <> -Time ALLOW_UNUSED_TYPE TimeFromWireFormat<4>(int64_t value) { - return value ? Time::UnixEpoch() + TimeDelta::FromSeconds(value) : Time(); -} -template <> -int64_t ALLOW_UNUSED_TYPE TimeToWireFormat<4>(Time time) { - return time > Time::UnixEpoch() ? (time - Time::UnixEpoch()).InSeconds() : 0; -} - -// Standard serialization format when using 8-byte wire format. -template <> -Time ALLOW_UNUSED_TYPE TimeFromWireFormat<8>(int64_t value) { - return Time::FromInternalValue(value); -} -template <> -int64_t ALLOW_UNUSED_TYPE TimeToWireFormat<8>(Time time) { - return time.ToInternalValue(); -} - -struct SharedState { - enum LockState { UNLOCKED = 0, LOCKED = 1 }; - - explicit SharedState(AtomicType ivalue) { value.i = ivalue; } - SharedState(LockState lock_state, Time timestamp) { - int64_t wire_timestamp = TimeToWireFormat<sizeof(AtomicType)>(timestamp); - DCHECK_GE(wire_timestamp, 0); - DCHECK_EQ(lock_state & ~1, 0); - value.u = (static_cast<UAtomicType>(wire_timestamp) << 1) | lock_state; - } - - LockState GetLockState() const { return static_cast<LockState>(value.u & 1); } - - Time GetTimestamp() const { - return TimeFromWireFormat<sizeof(AtomicType)>(value.u >> 1); - } - - // Bit 1: Lock state. Bit is set when locked. - // Bit 2..sizeof(AtomicType)*8: Usage timestamp. NULL time when locked or - // purged. - union { - AtomicType i; - UAtomicType u; - } value; -}; - -// Shared state is stored at offset 0 in shared memory segments. -SharedState* SharedStateFromSharedMemory( - const WritableSharedMemoryMapping& shared_memory) { - DCHECK(shared_memory.IsValid()); - return static_cast<SharedState*>(shared_memory.memory()); -} - -// Round up |size| to a multiple of page size. -size_t AlignToPageSize(size_t size) { - return bits::Align(size, base::GetPageSize()); -} - -} // namespace - -DiscardableSharedMemory::DiscardableSharedMemory() - : mapped_size_(0), locked_page_count_(0) { -} - -DiscardableSharedMemory::DiscardableSharedMemory( - UnsafeSharedMemoryRegion shared_memory_region) - : shared_memory_region_(std::move(shared_memory_region)), - mapped_size_(0), - locked_page_count_(0) {} - -DiscardableSharedMemory::~DiscardableSharedMemory() = default; - -bool DiscardableSharedMemory::CreateAndMap(size_t size) { - CheckedNumeric<size_t> checked_size = size; - checked_size += AlignToPageSize(sizeof(SharedState)); - if (!checked_size.IsValid()) - return false; - - shared_memory_region_ = - UnsafeSharedMemoryRegion::Create(checked_size.ValueOrDie()); - - if (!shared_memory_region_.IsValid()) - return false; - - shared_memory_mapping_ = shared_memory_region_.Map(); - 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(); -#if DCHECK_IS_ON() - for (size_t page = 0; page < locked_page_count_; ++page) - locked_pages_.insert(page); -#endif - - DCHECK(last_known_usage_.is_null()); - SharedState new_state(SharedState::LOCKED, Time()); - subtle::Release_Store( - &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i, - new_state.value.i); - return true; -} - -bool DiscardableSharedMemory::Map(size_t size) { - DCHECK(!shared_memory_mapping_.IsValid()); - if (shared_memory_mapping_.IsValid()) - return false; - - shared_memory_mapping_ = shared_memory_region_.MapAt( - 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(); -#if DCHECK_IS_ON() - for (size_t page = 0; page < locked_page_count_; ++page) - locked_pages_.insert(page); -#endif - - return true; -} - -bool DiscardableSharedMemory::Unmap() { - if (!shared_memory_mapping_.IsValid()) - return false; - - shared_memory_mapping_ = WritableSharedMemoryMapping(); - locked_page_count_ = 0; -#if DCHECK_IS_ON() - locked_pages_.clear(); -#endif - mapped_size_ = 0; - return true; -} - -DiscardableSharedMemory::LockResult DiscardableSharedMemory::Lock( - size_t offset, size_t length) { - DCHECK_EQ(AlignToPageSize(offset), offset); - DCHECK_EQ(AlignToPageSize(length), length); - - // Calls to this function must be synchronized properly. - DFAKE_SCOPED_LOCK(thread_collision_warner_); - - DCHECK(shared_memory_mapping_.IsValid()); - - // We need to successfully acquire the platform independent lock before - // individual pages can be locked. - if (!locked_page_count_) { - // Return false when instance has been purged or not initialized properly - // by checking if |last_known_usage_| is NULL. - if (last_known_usage_.is_null()) - return FAILED; - - SharedState old_state(SharedState::UNLOCKED, last_known_usage_); - SharedState new_state(SharedState::LOCKED, Time()); - SharedState result(subtle::Acquire_CompareAndSwap( - &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i, - old_state.value.i, new_state.value.i)); - if (result.value.u != old_state.value.u) { - // Update |last_known_usage_| in case the above CAS failed because of - // an incorrect timestamp. - last_known_usage_ = result.GetTimestamp(); - return FAILED; - } - } - - // Zero for length means "everything onward". - if (!length) - length = AlignToPageSize(mapped_size_) - offset; - - size_t start = offset / base::GetPageSize(); - size_t end = start + length / base::GetPageSize(); - DCHECK_LE(start, end); - DCHECK_LE(end, AlignToPageSize(mapped_size_) / base::GetPageSize()); - - // Add pages to |locked_page_count_|. - // Note: Locking a page that is already locked is an error. - locked_page_count_ += end - start; -#if DCHECK_IS_ON() - // Detect incorrect usage by keeping track of exactly what pages are locked. - for (auto page = start; page < end; ++page) { - auto result = locked_pages_.insert(page); - DCHECK(result.second); - } - DCHECK_EQ(locked_pages_.size(), locked_page_count_); -#endif - - // Always behave as if memory was purged when trying to lock a 0 byte segment. - if (!length) - return PURGED; - -#if defined(OS_ANDROID) - // Ensure that the platform won't discard the required pages. - return LockPages(shared_memory_region_, - AlignToPageSize(sizeof(SharedState)) + offset, length); -#elif defined(OS_MACOSX) - // On macOS, there is no mechanism to lock pages. However, we do need to call - // madvise(MADV_FREE_REUSE) in order to correctly update accounting for memory - // footprint via task_info(). - // - // Note that calling madvise(MADV_FREE_REUSE) on regions that haven't had - // madvise(MADV_FREE_REUSABLE) called on them has no effect. - // - // Note that the corresponding call to MADV_FREE_REUSABLE is in Purge(), since - // that's where the memory is actually released, rather than Unlock(), which - // is a no-op on macOS. - // - // For more information, see - // https://bugs.chromium.org/p/chromium/issues/detail?id=823915. - if (madvise(reinterpret_cast<char*>(shared_memory_mapping_.memory()) + - AlignToPageSize(sizeof(SharedState)), - AlignToPageSize(mapped_size_), MADV_FREE_REUSE)) - ; - return DiscardableSharedMemory::SUCCESS; -#else - return DiscardableSharedMemory::SUCCESS; -#endif -} - -void DiscardableSharedMemory::Unlock(size_t offset, size_t length) { - DCHECK_EQ(AlignToPageSize(offset), offset); - DCHECK_EQ(AlignToPageSize(length), length); - - // Calls to this function must be synchronized properly. - DFAKE_SCOPED_LOCK(thread_collision_warner_); - - // 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_mapping_.IsValid()); - - // Allow the pages to be discarded by the platform, if supported. - UnlockPages(shared_memory_region_, - AlignToPageSize(sizeof(SharedState)) + offset, length); - - size_t start = offset / base::GetPageSize(); - size_t end = start + length / base::GetPageSize(); - DCHECK_LE(start, end); - DCHECK_LE(end, AlignToPageSize(mapped_size_) / base::GetPageSize()); - - // Remove pages from |locked_page_count_|. - // Note: Unlocking a page that is not locked is an error. - DCHECK_GE(locked_page_count_, end - start); - locked_page_count_ -= end - start; -#if DCHECK_IS_ON() - // Detect incorrect usage by keeping track of exactly what pages are locked. - for (auto page = start; page < end; ++page) { - auto erased_count = locked_pages_.erase(page); - DCHECK_EQ(1u, erased_count); - } - DCHECK_EQ(locked_pages_.size(), locked_page_count_); -#endif - - // Early out and avoid releasing the platform independent lock if some pages - // are still locked. - if (locked_page_count_) - return; - - Time current_time = Now(); - DCHECK(!current_time.is_null()); - - SharedState old_state(SharedState::LOCKED, Time()); - SharedState new_state(SharedState::UNLOCKED, current_time); - // Note: timestamp cannot be NULL as that is a unique value used when - // locked or purged. - DCHECK(!new_state.GetTimestamp().is_null()); - // Timestamp precision should at least be accurate to the second. - DCHECK_EQ((new_state.GetTimestamp() - Time::UnixEpoch()).InSeconds(), - (current_time - Time::UnixEpoch()).InSeconds()); - SharedState result(subtle::Release_CompareAndSwap( - &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i, - old_state.value.i, new_state.value.i)); - - DCHECK_EQ(old_state.value.u, result.value.u); - - last_known_usage_ = current_time; -} - -void* DiscardableSharedMemory::memory() const { - return reinterpret_cast<uint8_t*>(shared_memory_mapping_.memory()) + - AlignToPageSize(sizeof(SharedState)); -} - -bool DiscardableSharedMemory::Purge(Time current_time) { - // Calls to this function must be synchronized properly. - DFAKE_SCOPED_LOCK(thread_collision_warner_); - DCHECK(shared_memory_mapping_.IsValid()); - - SharedState old_state(SharedState::UNLOCKED, last_known_usage_); - SharedState new_state(SharedState::UNLOCKED, Time()); - SharedState result(subtle::Acquire_CompareAndSwap( - &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i, - old_state.value.i, new_state.value.i)); - - // 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 - // was incorrect or memory was locked. In the second case, the caller should - // most likely wait for some amount of time before attempting to purge the - // the memory again. - if (result.value.u != old_state.value.u) { - last_known_usage_ = result.GetLockState() == SharedState::LOCKED - ? current_time - : result.GetTimestamp(); - return false; - } - -// The next section will release as much resource as can be done -// from the purging process, until the client process notices the -// purge and releases its own references. -// Note: this memory will not be accessed again. The segment will be -// freed asynchronously at a later time, so just do the best -// immediately. -#if defined(OS_POSIX) && !defined(OS_NACL) -// Linux and Android provide MADV_REMOVE which is preferred as it has a -// behavior that can be verified in tests. Other POSIX flavors (MacOSX, BSDs), -// provide MADV_FREE which has the same result but memory is purged lazily. -#if defined(OS_LINUX) || defined(OS_ANDROID) -#define MADV_PURGE_ARGUMENT MADV_REMOVE -#elif defined(OS_MACOSX) -// MADV_FREE_REUSABLE is similar to MADV_FREE, but also marks the pages with the -// reusable bit, which allows both Activity Monitor and memory-infra to -// correctly track the pages. -#define MADV_PURGE_ARGUMENT MADV_FREE_REUSABLE -#else -#define MADV_PURGE_ARGUMENT MADV_FREE -#endif - // Advise the kernel to remove resources associated with purged pages. - // Subsequent accesses of memory pages will succeed, but might result in - // zero-fill-on-demand pages. - if (madvise(reinterpret_cast<char*>(shared_memory_mapping_.memory()) + - AlignToPageSize(sizeof(SharedState)), - AlignToPageSize(mapped_size_), MADV_PURGE_ARGUMENT)) { - DPLOG(ERROR) << "madvise() failed"; - } -#elif defined(OS_WIN) - if (base::win::GetVersion() >= base::win::VERSION_WIN8_1) { - // Discard the purged pages, which releases the physical storage (resident - // memory, compressed or swapped), but leaves them reserved & committed. - // This does not free commit for use by other applications, but allows the - // system to avoid compressing/swapping these pages to free physical memory. - static const auto discard_virtual_memory = - reinterpret_cast<decltype(&::DiscardVirtualMemory)>(GetProcAddress( - GetModuleHandle(L"kernel32.dll"), "DiscardVirtualMemory")); - if (discard_virtual_memory) { - DWORD discard_result = discard_virtual_memory( - reinterpret_cast<char*>(shared_memory_mapping_.memory()) + - AlignToPageSize(sizeof(SharedState)), - AlignToPageSize(mapped_size_)); - if (discard_result != ERROR_SUCCESS) { - DLOG(DCHECK) << "DiscardVirtualMemory() failed in Purge(): " - << logging::SystemErrorCodeToString(discard_result); - } - } - } -#endif - - last_known_usage_ = Time(); - return true; -} - -bool DiscardableSharedMemory::IsMemoryResident() const { - DCHECK(shared_memory_mapping_.IsValid()); - - SharedState result(subtle::NoBarrier_Load( - &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i)); - - return result.GetLockState() == SharedState::LOCKED || - !result.GetTimestamp().is_null(); -} - -bool DiscardableSharedMemory::IsMemoryLocked() const { - DCHECK(shared_memory_mapping_.IsValid()); - - SharedState result(subtle::NoBarrier_Load( - &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i)); - - return result.GetLockState() == SharedState::LOCKED; -} - -void DiscardableSharedMemory::Close() { - shared_memory_region_ = UnsafeSharedMemoryRegion(); -} - -void DiscardableSharedMemory::CreateSharedMemoryOwnershipEdge( - trace_event::MemoryAllocatorDump* local_segment_dump, - trace_event::ProcessMemoryDump* pmd, - bool is_owned) const { - auto* shared_memory_dump = SharedMemoryTracker::GetOrCreateSharedMemoryDump( - shared_memory_mapping_, pmd); - // 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. - size_t resident_size = shared_memory_dump->GetSizeInternal(); - local_segment_dump->AddScalar(trace_event::MemoryAllocatorDump::kNameSize, - trace_event::MemoryAllocatorDump::kUnitsBytes, - resident_size); - - // By creating an edge with a higher |importance| (w.r.t non-owned dumps) - // the tracing UI will account the effective size of the segment to the - // client instead of manager. - // TODO(ssid): Define better constants in MemoryAllocatorDump for importance - // values, crbug.com/754793. - const int kImportance = is_owned ? 2 : 0; - auto shared_memory_guid = shared_memory_mapping_.guid(); - local_segment_dump->AddString("id", "hash", shared_memory_guid.ToString()); - - // Owned discardable segments which are allocated by client process, could - // have been cleared by the discardable manager. So, the segment need not - // exist in memory and weak dumps are created to indicate the UI that the dump - // should exist only if the manager also created the global dump edge. - if (is_owned) { - pmd->CreateWeakSharedMemoryOwnershipEdge(local_segment_dump->guid(), - shared_memory_guid, kImportance); - } else { - pmd->CreateSharedMemoryOwnershipEdge(local_segment_dump->guid(), - shared_memory_guid, kImportance); - } -} - -// 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 { - return Time::Now(); -} - -} // namespace base
diff --git a/base/memory/discardable_shared_memory.h b/base/memory/discardable_shared_memory.h deleted file mode 100644 index 55e99d9..0000000 --- a/base/memory/discardable_shared_memory.h +++ /dev/null
@@ -1,187 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_DISCARDABLE_SHARED_MEMORY_H_ -#define BASE_MEMORY_DISCARDABLE_SHARED_MEMORY_H_ - -#include <stddef.h> - -#include "base/base_export.h" -#include "base/logging.h" -#include "base/macros.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/time/time.h" -#include "build_config.h" - -#if DCHECK_IS_ON() -#include <set> -#endif - -// Linux (including Android) support the MADV_REMOVE argument with madvise() -// which has the behavior of reliably causing zero-fill-on-demand pages to -// be returned after a call. Here we define -// DISCARDABLE_SHARED_MEMORY_ZERO_FILL_ON_DEMAND_PAGES_AFTER_PURGE on Linux -// and Android to indicate that this type of behavior can be expected on -// those platforms. Note that madvise() will still be used on other POSIX -// platforms but doesn't provide the zero-fill-on-demand pages guarantee. -#if defined(OS_LINUX) || defined(OS_ANDROID) -#define DISCARDABLE_SHARED_MEMORY_ZERO_FILL_ON_DEMAND_PAGES_AFTER_PURGE -#endif - -namespace base { - -namespace trace_event { -class MemoryAllocatorDump; -class ProcessMemoryDump; -} // namespace trace_event - -// Platform abstraction for discardable shared memory. -// -// This class is not thread-safe. Clients are responsible for synchronizing -// access to an instance of this class. -class BASE_EXPORT DiscardableSharedMemory { - public: - enum LockResult { SUCCESS, PURGED, FAILED }; - - DiscardableSharedMemory(); - - // Create a new DiscardableSharedMemory object from an existing, open shared - // memory file. Memory must be locked. - explicit DiscardableSharedMemory(UnsafeSharedMemoryRegion region); - - // Closes any open files. - virtual ~DiscardableSharedMemory(); - - // Creates and maps a locked DiscardableSharedMemory object with |size|. - // Returns true on success and false on failure. - bool CreateAndMap(size_t size); - - // Maps the locked discardable memory into the caller's address space. - // Returns true on success, false otherwise. - bool Map(size_t size); - - // Unmaps the discardable shared memory from the caller's address space. - // Unmapping won't unlock previously locked range. - // Returns true if successful; returns false on error or if the memory is - // not mapped. - bool Unmap(); - - // The actual size of the mapped memory (may be larger than requested). - size_t mapped_size() const { return mapped_size_; } - - // Returns a duplicated shared memory region for this DiscardableSharedMemory - // object. - UnsafeSharedMemoryRegion DuplicateRegion() const { - return shared_memory_region_.Duplicate(); - } - - // 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 - // unmapped. - const UnguessableToken& mapped_id() const { - return shared_memory_mapping_.guid(); - } - - // Locks a range of memory so that it will not be purged by the system. - // The range of memory must be unlocked. The result of trying to lock an - // already locked range is undefined. |offset| and |length| must both be - // a multiple of the page size as returned by GetPageSize(). - // Passing 0 for |length| means "everything onward". - // Returns SUCCESS if range was successfully locked and the memory is still - // resident, PURGED if range was successfully locked but has been purged - // since last time it was locked and FAILED if range could not be locked. - // Locking can fail for two reasons; object might have been purged, our - // last known usage timestamp might be out of date. Last known usage time - // is updated to the actual last usage timestamp if memory is still resident - // or 0 if not. - LockResult Lock(size_t offset, size_t length); - - // Unlock a previously successfully locked range of memory. The range of - // memory must be locked. The result of trying to unlock a not - // previously locked range is undefined. - // |offset| and |length| must both be a multiple of the page size as returned - // by GetPageSize(). - // Passing 0 for |length| means "everything onward". - void Unlock(size_t offset, size_t length); - - // Gets a pointer to the opened discardable memory space. Discardable memory - // must have been mapped via Map(). - void* memory() const; - - // Returns the last known usage time for DiscardableSharedMemory object. This - // may be earlier than the "true" usage time when memory has been used by a - // different process. Returns NULL time if purged. - Time last_known_usage() const { return last_known_usage_; } - - // This returns true and sets |last_known_usage_| to 0 if - // DiscardableSharedMemory object was successfully purged. Purging can fail - // for two reasons; object might be locked or our last known usage timestamp - // might be out of date. Last known usage time is updated to |current_time| - // if locked or the actual last usage timestamp if unlocked. It is often - // necessary to call this function twice for the object to successfully be - // purged. First call, updates |last_known_usage_|. Second call, successfully - // purges the object using the updated |last_known_usage_|. - // Note: there is no guarantee that multiple calls to this function will - // successfully purge object. DiscardableSharedMemory object might be locked - // or another thread/process might be able to lock and unlock it in between - // each call. - bool Purge(Time current_time); - - // Returns true if memory is still resident. - bool IsMemoryResident() const; - - // Returns true if memory is locked. - bool IsMemoryLocked() const; - - // Closes the open discardable memory segment. - // It is safe to call Close repeatedly. - void Close(); - - // For tracing: Creates ownership edge to the underlying shared memory dump - // which is cross process in the given |pmd|. |local_segment_dump| is the dump - // associated with the local discardable shared memory segment and |is_owned| - // is true when the current process owns the segment and the effective memory - // is assigned to the current process. - void CreateSharedMemoryOwnershipEdge( - trace_event::MemoryAllocatorDump* local_segment_dump, - trace_event::ProcessMemoryDump* pmd, - bool is_owned) const; - - 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 Time Now() const; - - UnsafeSharedMemoryRegion shared_memory_region_; - WritableSharedMemoryMapping shared_memory_mapping_; - size_t mapped_size_; - size_t locked_page_count_; -#if DCHECK_IS_ON() - std::set<size_t> locked_pages_; -#endif - // Implementation is not thread-safe but still usable if clients are - // synchronized somehow. Use a collision warner to detect incorrect usage. - DFAKE_MUTEX(thread_collision_warner_); - Time last_known_usage_; - - DISALLOW_COPY_AND_ASSIGN(DiscardableSharedMemory); -}; - -} // namespace base - -#endif // BASE_MEMORY_DISCARDABLE_SHARED_MEMORY_H_
diff --git a/base/memory/linked_ptr.h b/base/memory/linked_ptr.h deleted file mode 100644 index 6851286..0000000 --- a/base/memory/linked_ptr.h +++ /dev/null
@@ -1,179 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// A "smart" pointer type with reference tracking. Every pointer to a -// particular object is kept on a circular linked list. When the last pointer -// to an object is destroyed or reassigned, the object is deleted. -// -// Used properly, this deletes the object when the last reference goes away. -// There are several caveats: -// - Like all reference counting schemes, cycles lead to leaks. -// - Each smart pointer is actually two pointers (8 bytes instead of 4). -// - Every time a pointer is released, the entire list of pointers to that -// object is traversed. This class is therefore NOT SUITABLE when there -// will often be more than two or three pointers to a particular object. -// - References are only tracked as long as linked_ptr<> objects are copied. -// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS -// will happen (double deletion). -// -// Note: If you use an incomplete type with linked_ptr<>, the class -// *containing* linked_ptr<> must have a constructor and destructor (even -// if they do nothing!). -// -// Thread Safety: -// A linked_ptr is NOT thread safe. Copying a linked_ptr object is -// effectively a read-write operation. -// -// Alternative: to linked_ptr is shared_ptr, which -// - is also two pointers in size (8 bytes for 32 bit addresses) -// - is thread safe for copying and deletion -// - supports weak_ptrs - -#ifndef BASE_MEMORY_LINKED_PTR_H_ -#define BASE_MEMORY_LINKED_PTR_H_ - -#include "base/logging.h" // for CHECK macros - -// This is used internally by all instances of linked_ptr<>. It needs to be -// a non-template class because different types of linked_ptr<> can refer to -// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)). -// So, it needs to be possible for different types of linked_ptr to participate -// in the same circular linked list, so we need a single class type here. -// -// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr<T>. -class linked_ptr_internal { - public: - // Create a new circle that includes only this instance. - void join_new() { - next_ = this; - } - - // Join an existing circle. - void join(linked_ptr_internal const* ptr) { - next_ = ptr->next_; - ptr->next_ = this; - } - - // Leave whatever circle we're part of. Returns true iff we were the - // last member of the circle. Once this is done, you can join() another. - bool depart() { - if (next_ == this) return true; - linked_ptr_internal const* p = next_; - while (p->next_ != this) p = p->next_; - p->next_ = next_; - return false; - } - - private: - mutable linked_ptr_internal const* next_; -}; - -// TODO(http://crbug.com/556939): DEPRECATED: Use unique_ptr instead (now that -// we have support for moveable types inside STL containers). -template <typename T> -class linked_ptr { - public: - typedef T element_type; - - // Take over ownership of a raw pointer. This should happen as soon as - // possible after the object is created. - explicit linked_ptr(T* ptr = NULL) { capture(ptr); } - ~linked_ptr() { depart(); } - - // Copy an existing linked_ptr<>, adding ourselves to the list of references. - template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); } - - linked_ptr(linked_ptr const& ptr) { - DCHECK_NE(&ptr, this); - copy(&ptr); - } - - // Assignment releases the old value and acquires the new. - template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) { - depart(); - copy(&ptr); - return *this; - } - - linked_ptr& operator=(linked_ptr const& ptr) { - if (&ptr != this) { - depart(); - copy(&ptr); - } - return *this; - } - - // Smart pointer members. - void reset(T* ptr = NULL) { - depart(); - capture(ptr); - } - T* get() const { return value_; } - T* operator->() const { return value_; } - T& operator*() const { return *value_; } - // Release ownership of the pointed object and returns it. - // Sole ownership by this linked_ptr object is required. - T* release() { - bool last = link_.depart(); - CHECK(last); - T* v = value_; - value_ = NULL; - return v; - } - - bool operator==(const T* p) const { return value_ == p; } - bool operator!=(const T* p) const { return value_ != p; } - template <typename U> - bool operator==(linked_ptr<U> const& ptr) const { - return value_ == ptr.get(); - } - template <typename U> - bool operator!=(linked_ptr<U> const& ptr) const { - return value_ != ptr.get(); - } - - private: - template <typename U> - friend class linked_ptr; - - T* value_; - linked_ptr_internal link_; - - void depart() { - if (link_.depart()) delete value_; - } - - void capture(T* ptr) { - value_ = ptr; - link_.join_new(); - } - - template <typename U> void copy(linked_ptr<U> const* ptr) { - value_ = ptr->get(); - if (value_) - link_.join(&ptr->link_); - else - link_.join_new(); - } -}; - -template<typename T> inline -bool operator==(T* ptr, const linked_ptr<T>& x) { - return ptr == x.get(); -} - -template<typename T> inline -bool operator!=(T* ptr, const linked_ptr<T>& x) { - return ptr != x.get(); -} - -// A function to convert T* into linked_ptr<T> -// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation -// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg)) -template <typename T> -linked_ptr<T> make_linked_ptr(T* ptr) { - return linked_ptr<T>(ptr); -} - -#endif // BASE_MEMORY_LINKED_PTR_H_
diff --git a/base/memory/memory_coordinator_client.cc b/base/memory/memory_coordinator_client.cc deleted file mode 100644 index 7fa6232..0000000 --- a/base/memory/memory_coordinator_client.cc +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/memory_coordinator_client.h" - -#include "base/logging.h" - -namespace base { - -const char* MemoryStateToString(MemoryState state) { - switch (state) { - case MemoryState::UNKNOWN: - return "unknown"; - case MemoryState::NORMAL: - return "normal"; - case MemoryState::THROTTLED: - return "throttled"; - case MemoryState::SUSPENDED: - return "suspended"; - default: - NOTREACHED(); - } - return ""; -} - -} // namespace base
diff --git a/base/memory/memory_coordinator_client.h b/base/memory/memory_coordinator_client.h deleted file mode 100644 index 804f0a6..0000000 --- a/base/memory/memory_coordinator_client.h +++ /dev/null
@@ -1,79 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_MEMORY_COORDINATOR_CLIENT_H_ -#define BASE_MEMORY_MEMORY_COORDINATOR_CLIENT_H_ - -#include "base/base_export.h" - -namespace base { - -// OVERVIEW: -// -// MemoryCoordinatorClient is an interface which a component can implement to -// adjust "future allocation" and "existing allocation". For "future allocation" -// it provides a callback to observe memory state changes, and for "existing -// allocation" it provides a callback to purge memory. -// -// Unlike MemoryPressureListener, memory state changes are stateful. State -// transitions are throttled to avoid thrashing; the exact throttling period is -// platform dependent, but will be at least 5-10 seconds. When a state change -// notification is dispatched, clients are expected to update their allocation -// policies (e.g. setting cache limit) that persist for the duration of the -// memory state. Note that clients aren't expected to free up memory on memory -// state changes. Clients should wait for a separate purge request to free up -// memory. Purging requests will be throttled as well. - -// MemoryState is an indicator that processes can use to guide their memory -// allocation policies. For example, a process that receives the throttled -// state can use that as as signal to decrease memory cache limits. -// NOTE: This enum is used to back an UMA histogram, and therefore should be -// treated as append-only. -enum class MemoryState : int { - // The state is unknown. - UNKNOWN = -1, - // No memory constraints. - NORMAL = 0, - // Running and interactive but memory allocation should be throttled. - // Clients should set lower budget for any memory that is used as an - // optimization but that is not necessary for the process to run. - // (e.g. caches) - THROTTLED = 1, - // Still resident in memory but core processing logic has been suspended. - // In most cases, OnPurgeMemory() will be called before entering this state. - SUSPENDED = 2, -}; - -const int kMemoryStateMax = static_cast<int>(MemoryState::SUSPENDED) + 1; - -// Returns a string representation of MemoryState. -BASE_EXPORT const char* MemoryStateToString(MemoryState state); - -// This is an interface for components which can respond to memory status -// changes. An initial state is NORMAL. See MemoryCoordinatorClientRegistry for -// threading guarantees and ownership management. -class BASE_EXPORT MemoryCoordinatorClient { - public: - // Called when memory state has changed. Any transition can occur except for - // UNKNOWN. General guidelines are: - // * NORMAL: Restore the default settings for memory allocation/usage if - // it has changed. - // * THROTTLED: Use smaller limits for future memory allocations. You don't - // need to take any action on existing allocations. - // * SUSPENDED: Use much smaller limits for future memory allocations. You - // don't need to take any action on existing allocations. - virtual void OnMemoryStateChange(MemoryState state) {} - - // Called to purge memory. - // This callback should free up any memory that is used as an optimization, or - // any memory whose contents can be reproduced. - virtual void OnPurgeMemory() {} - - protected: - virtual ~MemoryCoordinatorClient() = default; -}; - -} // namespace base - -#endif // BASE_MEMORY_MEMORY_COORDINATOR_CLIENT_H_
diff --git a/base/memory/memory_coordinator_client_registry.cc b/base/memory/memory_coordinator_client_registry.cc deleted file mode 100644 index 45b4a7f..0000000 --- a/base/memory/memory_coordinator_client_registry.cc +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/memory_coordinator_client_registry.h" - -namespace base { - -// static -MemoryCoordinatorClientRegistry* -MemoryCoordinatorClientRegistry::GetInstance() { - return Singleton< - MemoryCoordinatorClientRegistry, - LeakySingletonTraits<MemoryCoordinatorClientRegistry>>::get(); -} - -MemoryCoordinatorClientRegistry::MemoryCoordinatorClientRegistry() - : clients_(new ClientList) {} - -MemoryCoordinatorClientRegistry::~MemoryCoordinatorClientRegistry() = default; - -void MemoryCoordinatorClientRegistry::Register( - MemoryCoordinatorClient* client) { - clients_->AddObserver(client); -} - -void MemoryCoordinatorClientRegistry::Unregister( - MemoryCoordinatorClient* client) { - clients_->RemoveObserver(client); -} - -void MemoryCoordinatorClientRegistry::Notify(MemoryState state) { - clients_->Notify(FROM_HERE, - &base::MemoryCoordinatorClient::OnMemoryStateChange, state); -} - -void MemoryCoordinatorClientRegistry::PurgeMemory() { - clients_->Notify(FROM_HERE, &base::MemoryCoordinatorClient::OnPurgeMemory); -} - -} // namespace base
diff --git a/base/memory/memory_coordinator_client_registry.h b/base/memory/memory_coordinator_client_registry.h deleted file mode 100644 index e2c81b7..0000000 --- a/base/memory/memory_coordinator_client_registry.h +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_MEMORY_CLIENT_REGISTRY_H_ -#define BASE_MEMORY_MEMORY_CLIENT_REGISTRY_H_ - -#include "base/base_export.h" -#include "base/memory/memory_coordinator_client.h" -#include "base/memory/singleton.h" -#include "base/observer_list_threadsafe.h" - -namespace base { - -// MemoryCoordinatorClientRegistry is the registry of MemoryCoordinatorClients. -// This class manages clients and provides a way to notify memory state changes -// to clients, but this isn't responsible to determine how/when to change -// memory states. -// -// Threading guarantees: -// This class uses ObserverListThreadsafe internally, which means that -// * Registering/unregistering callbacks are thread-safe. -// * Callbacks are invoked on the same thread on which they are registered. -// See base/observer_list_threadsafe.h for reference. -// -// Ownership management: -// This class doesn't take the ownership of clients. Clients must be -// unregistered before they are destroyed. -class BASE_EXPORT MemoryCoordinatorClientRegistry { - public: - static MemoryCoordinatorClientRegistry* GetInstance(); - - ~MemoryCoordinatorClientRegistry(); - - // Registers/unregisters a client. Does not take ownership of client. - void Register(MemoryCoordinatorClient* client); - void Unregister(MemoryCoordinatorClient* client); - - // Notify clients of a memory state change. - void Notify(MemoryState state); - - // Requests purging memory. - void PurgeMemory(); - - private: - friend struct DefaultSingletonTraits<MemoryCoordinatorClientRegistry>; - - MemoryCoordinatorClientRegistry(); - - using ClientList = ObserverListThreadSafe<MemoryCoordinatorClient>; - scoped_refptr<ClientList> clients_; -}; - -} // namespace base - -#endif // BASE_MEMORY_MEMORY_CLIENT_REGISTRY_H_
diff --git a/base/memory/memory_coordinator_proxy.cc b/base/memory/memory_coordinator_proxy.cc deleted file mode 100644 index 4e22fe0..0000000 --- a/base/memory/memory_coordinator_proxy.cc +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/memory_coordinator_proxy.h" - -namespace base { - -namespace { - -MemoryCoordinator* g_memory_coordinator = nullptr; - -} // namespace - -MemoryCoordinatorProxy::MemoryCoordinatorProxy() = default; - -MemoryCoordinatorProxy::~MemoryCoordinatorProxy() = default; - -// static -MemoryCoordinatorProxy* MemoryCoordinatorProxy::GetInstance() { - return Singleton<base::MemoryCoordinatorProxy>::get(); -} - -// static -void MemoryCoordinatorProxy::SetMemoryCoordinator( - MemoryCoordinator* coordinator) { - DCHECK(!g_memory_coordinator || !coordinator); - g_memory_coordinator = coordinator; -} - -MemoryState MemoryCoordinatorProxy::GetCurrentMemoryState() const { - if (!g_memory_coordinator) - return MemoryState::NORMAL; - return g_memory_coordinator->GetCurrentMemoryState(); -} - -} // namespace base
diff --git a/base/memory/memory_coordinator_proxy.h b/base/memory/memory_coordinator_proxy.h deleted file mode 100644 index b6e7b3f..0000000 --- a/base/memory/memory_coordinator_proxy.h +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_MEMORY_COORDINATOR_PROXY_H_ -#define BASE_MEMORY_MEMORY_COORDINATOR_PROXY_H_ - -#include "base/base_export.h" -#include "base/callback.h" -#include "base/memory/memory_coordinator_client.h" -#include "base/memory/singleton.h" - -namespace base { - -// The MemoryCoordinator interface. See comments in MemoryCoordinatorProxy for -// method descriptions. -class BASE_EXPORT MemoryCoordinator { - public: - virtual ~MemoryCoordinator() = default; - - virtual MemoryState GetCurrentMemoryState() const = 0; -}; - -// The proxy of MemoryCoordinator to be accessed from components that are not -// in content/browser e.g. net. -class BASE_EXPORT MemoryCoordinatorProxy { - public: - static MemoryCoordinatorProxy* GetInstance(); - - // Sets an implementation of MemoryCoordinator. MemoryCoordinatorProxy doesn't - // take the ownership of |coordinator|. It must outlive this proxy. - // This should be called before any components starts using this proxy. - static void SetMemoryCoordinator(MemoryCoordinator* coordinator); - - // Returns the current memory state. - MemoryState GetCurrentMemoryState() const; - - private: - friend struct base::DefaultSingletonTraits<MemoryCoordinatorProxy>; - - MemoryCoordinatorProxy(); - virtual ~MemoryCoordinatorProxy(); - - DISALLOW_COPY_AND_ASSIGN(MemoryCoordinatorProxy); -}; - -} // namespace base - -#endif // BASE_MEMORY_MEMORY_COORDINATOR_PROXY_H_
diff --git a/base/memory/memory_pressure_listener.cc b/base/memory/memory_pressure_listener.cc deleted file mode 100644 index 3768283..0000000 --- a/base/memory/memory_pressure_listener.cc +++ /dev/null
@@ -1,128 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/memory_pressure_listener.h" - -#include "base/observer_list_threadsafe.h" - -namespace base { - -namespace { - -// This class is thread safe and internally synchronized. -class MemoryPressureObserver { - public: - // There is at most one MemoryPressureObserver and it is never deleted. - ~MemoryPressureObserver() = delete; - - void AddObserver(MemoryPressureListener* listener, bool sync) { - async_observers_->AddObserver(listener); - if (sync) { - AutoLock lock(sync_observers_lock_); - sync_observers_.AddObserver(listener); - } - } - - void RemoveObserver(MemoryPressureListener* listener) { - async_observers_->RemoveObserver(listener); - AutoLock lock(sync_observers_lock_); - sync_observers_.RemoveObserver(listener); - } - - void Notify( - MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { - async_observers_->Notify(FROM_HERE, &MemoryPressureListener::Notify, - memory_pressure_level); - AutoLock lock(sync_observers_lock_); - for (auto& observer : sync_observers_) - observer.SyncNotify(memory_pressure_level); - } - - private: - const scoped_refptr<ObserverListThreadSafe<MemoryPressureListener>> - async_observers_ = base::MakeRefCounted< - ObserverListThreadSafe<MemoryPressureListener>>(); - ObserverList<MemoryPressureListener> sync_observers_; - Lock sync_observers_lock_; -}; - -// Gets the shared MemoryPressureObserver singleton instance. -MemoryPressureObserver* GetMemoryPressureObserver() { - static auto* const observer = new MemoryPressureObserver(); - return observer; -} - -subtle::Atomic32 g_notifications_suppressed = 0; - -} // namespace - -MemoryPressureListener::MemoryPressureListener( - const MemoryPressureListener::MemoryPressureCallback& callback) - : callback_(callback) { - GetMemoryPressureObserver()->AddObserver(this, false); -} - -MemoryPressureListener::MemoryPressureListener( - const MemoryPressureListener::MemoryPressureCallback& callback, - const MemoryPressureListener::SyncMemoryPressureCallback& - sync_memory_pressure_callback) - : callback_(callback), - sync_memory_pressure_callback_(sync_memory_pressure_callback) { - GetMemoryPressureObserver()->AddObserver(this, true); -} - -MemoryPressureListener::~MemoryPressureListener() { - GetMemoryPressureObserver()->RemoveObserver(this); -} - -void MemoryPressureListener::Notify(MemoryPressureLevel memory_pressure_level) { - callback_.Run(memory_pressure_level); -} - -void MemoryPressureListener::SyncNotify( - MemoryPressureLevel memory_pressure_level) { - if (!sync_memory_pressure_callback_.is_null()) { - sync_memory_pressure_callback_.Run(memory_pressure_level); - } -} - -// static -void MemoryPressureListener::NotifyMemoryPressure( - MemoryPressureLevel memory_pressure_level) { - DCHECK_NE(memory_pressure_level, MEMORY_PRESSURE_LEVEL_NONE); - TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("memory-infra"), - "MemoryPressureListener::NotifyMemoryPressure", - TRACE_EVENT_SCOPE_THREAD, "level", - memory_pressure_level); - if (AreNotificationsSuppressed()) - return; - DoNotifyMemoryPressure(memory_pressure_level); -} - -// static -bool MemoryPressureListener::AreNotificationsSuppressed() { - return subtle::Acquire_Load(&g_notifications_suppressed) == 1; -} - -// static -void MemoryPressureListener::SetNotificationsSuppressed(bool suppress) { - subtle::Release_Store(&g_notifications_suppressed, suppress ? 1 : 0); -} - -// static -void MemoryPressureListener::SimulatePressureNotification( - MemoryPressureLevel memory_pressure_level) { - // Notify all listeners even if regular pressure notifications are suppressed. - DoNotifyMemoryPressure(memory_pressure_level); -} - -// static -void MemoryPressureListener::DoNotifyMemoryPressure( - MemoryPressureLevel memory_pressure_level) { - DCHECK_NE(memory_pressure_level, MEMORY_PRESSURE_LEVEL_NONE); - - GetMemoryPressureObserver()->Notify(memory_pressure_level); -} - -} // namespace base
diff --git a/base/memory/memory_pressure_listener.h b/base/memory/memory_pressure_listener.h deleted file mode 100644 index 7e97010..0000000 --- a/base/memory/memory_pressure_listener.h +++ /dev/null
@@ -1,102 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// MemoryPressure provides static APIs for handling memory pressure on -// platforms that have such signals, such as Android and ChromeOS. -// The app will try to discard buffers that aren't deemed essential (individual -// modules will implement their own policy). - -#ifndef BASE_MEMORY_MEMORY_PRESSURE_LISTENER_H_ -#define BASE_MEMORY_MEMORY_PRESSURE_LISTENER_H_ - -#include "base/base_export.h" -#include "base/callback.h" -#include "base/macros.h" - -namespace base { - -// To start listening, create a new instance, passing a callback to a -// function that takes a MemoryPressureLevel parameter. To stop listening, -// simply delete the listener object. The implementation guarantees -// that the callback will always be called on the thread that created -// the listener. -// Note that even on the same thread, the callback is not guaranteed to be -// called synchronously within the system memory pressure broadcast. -// Please see notes in MemoryPressureLevel enum below: some levels are -// absolutely critical, and if not enough memory is returned to the system, -// it'll potentially kill the app, and then later the app will have to be -// cold-started. -// -// Example: -// -// void OnMemoryPressure(MemoryPressureLevel memory_pressure_level) { -// ... -// } -// -// // Start listening. -// MemoryPressureListener* my_listener = -// new MemoryPressureListener(base::Bind(&OnMemoryPressure)); -// -// ... -// -// // Stop listening. -// delete my_listener; -// -class BASE_EXPORT MemoryPressureListener { - public: - // A Java counterpart will be generated for this enum. - // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base - enum MemoryPressureLevel { - // No problems, there is enough memory to use. This event is not sent via - // callback, but the enum is used in other places to find out the current - // state of the system. - MEMORY_PRESSURE_LEVEL_NONE, - - // Modules are advised to free buffers that are cheap to re-allocate and not - // immediately needed. - MEMORY_PRESSURE_LEVEL_MODERATE, - - // At this level, modules are advised to free all possible memory. The - // alternative is to be killed by the system, which means all memory will - // have to be re-created, plus the cost of a cold start. - MEMORY_PRESSURE_LEVEL_CRITICAL, - }; - - typedef Callback<void(MemoryPressureLevel)> MemoryPressureCallback; - typedef Callback<void(MemoryPressureLevel)> SyncMemoryPressureCallback; - - explicit MemoryPressureListener( - const MemoryPressureCallback& memory_pressure_callback); - MemoryPressureListener( - const MemoryPressureCallback& memory_pressure_callback, - const SyncMemoryPressureCallback& sync_memory_pressure_callback); - - ~MemoryPressureListener(); - - // Intended for use by the platform specific implementation. - static void NotifyMemoryPressure(MemoryPressureLevel memory_pressure_level); - - // These methods should not be used anywhere else but in memory measurement - // code, where they are intended to maintain stable conditions across - // measurements. - static bool AreNotificationsSuppressed(); - static void SetNotificationsSuppressed(bool suppressed); - static void SimulatePressureNotification( - MemoryPressureLevel memory_pressure_level); - - void Notify(MemoryPressureLevel memory_pressure_level); - void SyncNotify(MemoryPressureLevel memory_pressure_level); - - private: - static void DoNotifyMemoryPressure(MemoryPressureLevel memory_pressure_level); - - MemoryPressureCallback callback_; - SyncMemoryPressureCallback sync_memory_pressure_callback_; - - DISALLOW_COPY_AND_ASSIGN(MemoryPressureListener); -}; - -} // namespace base - -#endif // BASE_MEMORY_MEMORY_PRESSURE_LISTENER_H_
diff --git a/base/memory/memory_pressure_monitor.cc b/base/memory/memory_pressure_monitor.cc deleted file mode 100644 index ed350b8..0000000 --- a/base/memory/memory_pressure_monitor.cc +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/memory_pressure_monitor.h" - -#include "base/logging.h" -#include "base/metrics/histogram_macros.h" - -namespace base { -namespace { - -MemoryPressureMonitor* g_monitor = nullptr; - -// Enumeration of UMA memory pressure levels. This needs to be kept in sync with -// histograms.xml and the memory pressure levels defined in -// MemoryPressureListener. -enum MemoryPressureLevelUMA { - UMA_MEMORY_PRESSURE_LEVEL_NONE = 0, - UMA_MEMORY_PRESSURE_LEVEL_MODERATE = 1, - UMA_MEMORY_PRESSURE_LEVEL_CRITICAL = 2, - // This must be the last value in the enum. - UMA_MEMORY_PRESSURE_LEVEL_COUNT, -}; - -// Converts a memory pressure level to an UMA enumeration value. -MemoryPressureLevelUMA MemoryPressureLevelToUmaEnumValue( - base::MemoryPressureListener::MemoryPressureLevel level) { - switch (level) { - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: - return UMA_MEMORY_PRESSURE_LEVEL_NONE; - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: - return UMA_MEMORY_PRESSURE_LEVEL_MODERATE; - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: - return UMA_MEMORY_PRESSURE_LEVEL_CRITICAL; - } - NOTREACHED(); - return UMA_MEMORY_PRESSURE_LEVEL_NONE; -} - -} // namespace - -MemoryPressureMonitor::MemoryPressureMonitor() { - DCHECK(!g_monitor); - g_monitor = this; -} - -MemoryPressureMonitor::~MemoryPressureMonitor() { - DCHECK(g_monitor); - g_monitor = nullptr; -} - -// static -MemoryPressureMonitor* MemoryPressureMonitor::Get() { - return g_monitor; -} -void MemoryPressureMonitor::RecordMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel level, - int ticks) { - // Use the more primitive STATIC_HISTOGRAM_POINTER_BLOCK macro because the - // simple UMA_HISTOGRAM macros don't expose 'AddCount' functionality. - STATIC_HISTOGRAM_POINTER_BLOCK( - "Memory.PressureLevel", - AddCount(MemoryPressureLevelToUmaEnumValue(level), ticks), - base::LinearHistogram::FactoryGet( - "Memory.PressureLevel", 1, UMA_MEMORY_PRESSURE_LEVEL_COUNT, - UMA_MEMORY_PRESSURE_LEVEL_COUNT + 1, - base::HistogramBase::kUmaTargetedHistogramFlag)); -} - -} // namespace base
diff --git a/base/memory/memory_pressure_monitor.h b/base/memory/memory_pressure_monitor.h deleted file mode 100644 index e48244b..0000000 --- a/base/memory/memory_pressure_monitor.h +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_MEMORY_PRESSURE_MONITOR_H_ -#define BASE_MEMORY_MEMORY_PRESSURE_MONITOR_H_ - -#include "base/base_export.h" -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/memory_pressure_listener.h" - -namespace base { - -// TODO(chrisha): Make this a concrete class with per-OS implementations rather -// than an abstract base class. - -// Declares the interface for a MemoryPressureMonitor. There are multiple -// OS specific implementations of this class. An instance of the memory -// pressure observer is created at the process level, tracks memory usage, and -// pushes memory state change notifications to the static function -// base::MemoryPressureListener::NotifyMemoryPressure. This is turn notifies -// all MemoryPressureListener instances via a callback. -class BASE_EXPORT MemoryPressureMonitor { - public: - using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel; - using DispatchCallback = base::Callback<void(MemoryPressureLevel level)>; - - virtual ~MemoryPressureMonitor(); - - // Return the singleton MemoryPressureMonitor. - static MemoryPressureMonitor* Get(); - - // Record memory pressure UMA statistic. A tick is 5 seconds. - static void RecordMemoryPressure(MemoryPressureLevel level, int ticks); - - // Returns the currently observed memory pressure. - virtual MemoryPressureLevel GetCurrentPressureLevel() = 0; - - // Sets a notification callback. The default callback invokes - // base::MemoryPressureListener::NotifyMemoryPressure. - virtual void SetDispatchCallback(const DispatchCallback& callback) = 0; - - protected: - MemoryPressureMonitor(); - - private: - DISALLOW_COPY_AND_ASSIGN(MemoryPressureMonitor); -}; - -} // namespace base - -#endif // BASE_MEMORY_MEMORY_PRESSURE_MONITOR_H_
diff --git a/base/memory/memory_pressure_monitor_chromeos.cc b/base/memory/memory_pressure_monitor_chromeos.cc deleted file mode 100644 index b4e4b94..0000000 --- a/base/memory/memory_pressure_monitor_chromeos.cc +++ /dev/null
@@ -1,288 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/memory_pressure_monitor_chromeos.h" - -#include <fcntl.h> -#include <sys/select.h> - -#include "base/metrics/histogram_macros.h" -#include "base/posix/eintr_wrapper.h" -#include "base/process/process_metrics.h" -#include "base/single_thread_task_runner.h" -#include "base/sys_info.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" - -namespace base { -namespace chromeos { - -namespace { - -// The time between memory pressure checks. While under critical pressure, this -// is also the timer to repeat cleanup attempts. -const int kMemoryPressureIntervalMs = 1000; - -// The time which should pass between two moderate memory pressure calls. -const int kModerateMemoryPressureCooldownMs = 10000; - -// Number of event polls before the next moderate pressure event can be sent. -const int kModerateMemoryPressureCooldown = - kModerateMemoryPressureCooldownMs / kMemoryPressureIntervalMs; - -// Threshold constants to emit pressure events. -const int kNormalMemoryPressureModerateThresholdPercent = 60; -const int kNormalMemoryPressureCriticalThresholdPercent = 95; -const int kAggressiveMemoryPressureModerateThresholdPercent = 35; -const int kAggressiveMemoryPressureCriticalThresholdPercent = 70; - -// The possible state for memory pressure level. The values should be in line -// with values in MemoryPressureListener::MemoryPressureLevel and should be -// updated if more memory pressure levels are introduced. -enum MemoryPressureLevelUMA { - MEMORY_PRESSURE_LEVEL_NONE = 0, - MEMORY_PRESSURE_LEVEL_MODERATE, - MEMORY_PRESSURE_LEVEL_CRITICAL, - NUM_MEMORY_PRESSURE_LEVELS -}; - -// This is the file that will exist if low memory notification is available -// on the device. Whenever it becomes readable, it signals a low memory -// condition. -const char kLowMemFile[] = "/dev/chromeos-low-mem"; - -// Converts a |MemoryPressureThreshold| value into a used memory percentage for -// the moderate pressure event. -int GetModerateMemoryThresholdInPercent( - MemoryPressureMonitor::MemoryPressureThresholds thresholds) { - return thresholds == MemoryPressureMonitor:: - THRESHOLD_AGGRESSIVE_CACHE_DISCARD || - thresholds == MemoryPressureMonitor::THRESHOLD_AGGRESSIVE - ? kAggressiveMemoryPressureModerateThresholdPercent - : kNormalMemoryPressureModerateThresholdPercent; -} - -// Converts a |MemoryPressureThreshold| value into a used memory percentage for -// the critical pressure event. -int GetCriticalMemoryThresholdInPercent( - MemoryPressureMonitor::MemoryPressureThresholds thresholds) { - return thresholds == MemoryPressureMonitor:: - THRESHOLD_AGGRESSIVE_TAB_DISCARD || - thresholds == MemoryPressureMonitor::THRESHOLD_AGGRESSIVE - ? kAggressiveMemoryPressureCriticalThresholdPercent - : kNormalMemoryPressureCriticalThresholdPercent; -} - -// Converts free percent of memory into a memory pressure value. -MemoryPressureListener::MemoryPressureLevel GetMemoryPressureLevelFromFillLevel( - int actual_fill_level, - int moderate_threshold, - int critical_threshold) { - if (actual_fill_level < moderate_threshold) - return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; - return actual_fill_level < critical_threshold - ? MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE - : MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; -} - -// This function will be called less than once a second. It will check if -// the kernel has detected a low memory situation. -bool IsLowMemoryCondition(int file_descriptor) { - fd_set fds; - struct timeval tv; - - FD_ZERO(&fds); - FD_SET(file_descriptor, &fds); - - tv.tv_sec = 0; - tv.tv_usec = 0; - - return HANDLE_EINTR(select(file_descriptor + 1, &fds, NULL, NULL, &tv)) > 0; -} - -} // namespace - -MemoryPressureMonitor::MemoryPressureMonitor( - MemoryPressureThresholds thresholds) - : current_memory_pressure_level_( - MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), - moderate_pressure_repeat_count_(0), - seconds_since_reporting_(0), - moderate_pressure_threshold_percent_( - GetModerateMemoryThresholdInPercent(thresholds)), - critical_pressure_threshold_percent_( - GetCriticalMemoryThresholdInPercent(thresholds)), - low_mem_file_(HANDLE_EINTR(::open(kLowMemFile, O_RDONLY))), - dispatch_callback_( - base::Bind(&MemoryPressureListener::NotifyMemoryPressure)), - weak_ptr_factory_(this) { - StartObserving(); - LOG_IF(ERROR, - base::SysInfo::IsRunningOnChromeOS() && !low_mem_file_.is_valid()) - << "Cannot open kernel listener"; -} - -MemoryPressureMonitor::~MemoryPressureMonitor() { - StopObserving(); -} - -void MemoryPressureMonitor::ScheduleEarlyCheck() { - ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, BindOnce(&MemoryPressureMonitor::CheckMemoryPressure, - weak_ptr_factory_.GetWeakPtr())); -} - -MemoryPressureListener::MemoryPressureLevel -MemoryPressureMonitor::GetCurrentPressureLevel() { - return current_memory_pressure_level_; -} - -// static -MemoryPressureMonitor* MemoryPressureMonitor::Get() { - return static_cast<MemoryPressureMonitor*>( - base::MemoryPressureMonitor::Get()); -} - -void MemoryPressureMonitor::StartObserving() { - timer_.Start(FROM_HERE, - TimeDelta::FromMilliseconds(kMemoryPressureIntervalMs), - Bind(&MemoryPressureMonitor:: - CheckMemoryPressureAndRecordStatistics, - weak_ptr_factory_.GetWeakPtr())); -} - -void MemoryPressureMonitor::StopObserving() { - // If StartObserving failed, StopObserving will still get called. - timer_.Stop(); -} - -void MemoryPressureMonitor::CheckMemoryPressureAndRecordStatistics() { - CheckMemoryPressure(); - if (seconds_since_reporting_++ == 5) { - seconds_since_reporting_ = 0; - RecordMemoryPressure(current_memory_pressure_level_, 1); - } - // Record UMA histogram statistics for the current memory pressure level. - // TODO(lgrey): Remove this once there's a usable history for the - // "Memory.PressureLevel" statistic - MemoryPressureLevelUMA memory_pressure_level_uma(MEMORY_PRESSURE_LEVEL_NONE); - switch (current_memory_pressure_level_) { - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: - memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_NONE; - break; - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: - memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_MODERATE; - break; - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: - memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_CRITICAL; - break; - } - - UMA_HISTOGRAM_ENUMERATION("ChromeOS.MemoryPressureLevel", - memory_pressure_level_uma, - NUM_MEMORY_PRESSURE_LEVELS); -} - -void MemoryPressureMonitor::CheckMemoryPressure() { - MemoryPressureListener::MemoryPressureLevel old_pressure = - current_memory_pressure_level_; - - // If we have the kernel low memory observer, we use it's flag instead of our - // own computation (for now). Note that in "simulation mode" it can be null. - // TODO(skuhne): We need to add code which makes sure that the kernel and this - // computation come to similar results and then remove this override again. - // TODO(skuhne): Add some testing framework here to see how close the kernel - // and the internal functions are. - if (low_mem_file_.is_valid() && IsLowMemoryCondition(low_mem_file_.get())) { - current_memory_pressure_level_ = - MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; - } else { - current_memory_pressure_level_ = GetMemoryPressureLevelFromFillLevel( - GetUsedMemoryInPercent(), - moderate_pressure_threshold_percent_, - critical_pressure_threshold_percent_); - - // When listening to the kernel, we ignore the reported memory pressure - // level from our own computation and reduce critical to moderate. - if (low_mem_file_.is_valid() && - current_memory_pressure_level_ == - MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) { - current_memory_pressure_level_ = - MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; - } - } - - // In case there is no memory pressure we do not notify. - if (current_memory_pressure_level_ == - MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) { - return; - } - if (old_pressure == current_memory_pressure_level_) { - // If the memory pressure is still at the same level, we notify again for a - // critical level. In case of a moderate level repeat however, we only send - // a notification after a certain time has passed. - if (current_memory_pressure_level_ == - MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE && - ++moderate_pressure_repeat_count_ < - kModerateMemoryPressureCooldown) { - return; - } - } else if (current_memory_pressure_level_ == - MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE && - old_pressure == - MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) { - // When we reducing the pressure level from critical to moderate, we - // restart the timeout and do not send another notification. - moderate_pressure_repeat_count_ = 0; - return; - } - moderate_pressure_repeat_count_ = 0; - dispatch_callback_.Run(current_memory_pressure_level_); -} - -// Gets the used ChromeOS memory in percent. -int MemoryPressureMonitor::GetUsedMemoryInPercent() { - base::SystemMemoryInfoKB info; - if (!base::GetSystemMemoryInfo(&info)) { - VLOG(1) << "Cannot determine the free memory of the system."; - return 0; - } - // TODO(skuhne): Instead of adding the kernel memory pressure calculation - // logic here, we should have a kernel mechanism similar to the low memory - // notifier in ChromeOS which offers multiple pressure states. - // To track this, we have crbug.com/381196. - - // The available memory consists of "real" and virtual (z)ram memory. - // Since swappable memory uses a non pre-deterministic compression and - // the compression creates its own "dynamic" in the system, it gets - // de-emphasized by the |kSwapWeight| factor. - const int kSwapWeight = 4; - - // The total memory we have is the "real memory" plus the virtual (z)ram. - int total_memory = info.total + info.swap_total / kSwapWeight; - - // The kernel internally uses 50MB. - const int kMinFileMemory = 50 * 1024; - - // Most file memory can be easily reclaimed. - int file_memory = info.active_file + info.inactive_file; - // unless it is dirty or it's a minimal portion which is required. - file_memory -= info.dirty + kMinFileMemory; - - // Available memory is the sum of free, swap and easy reclaimable memory. - int available_memory = - info.free + info.swap_free / kSwapWeight + file_memory; - - DCHECK(available_memory < total_memory); - int percentage = ((total_memory - available_memory) * 100) / total_memory; - return percentage; -} - -void MemoryPressureMonitor::SetDispatchCallback( - const DispatchCallback& callback) { - dispatch_callback_ = callback; -} - -} // namespace chromeos -} // namespace base
diff --git a/base/memory/memory_pressure_monitor_chromeos.h b/base/memory/memory_pressure_monitor_chromeos.h deleted file mode 100644 index 563ba85..0000000 --- a/base/memory/memory_pressure_monitor_chromeos.h +++ /dev/null
@@ -1,128 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_MEMORY_PRESSURE_MONITOR_CHROMEOS_H_ -#define BASE_MEMORY_MEMORY_PRESSURE_MONITOR_CHROMEOS_H_ - -#include "base/base_export.h" -#include "base/files/scoped_file.h" -#include "base/macros.h" -#include "base/memory/memory_pressure_listener.h" -#include "base/memory/memory_pressure_monitor.h" -#include "base/memory/weak_ptr.h" -#include "base/timer/timer.h" - -namespace base { -namespace chromeos { - -class TestMemoryPressureMonitor; - -//////////////////////////////////////////////////////////////////////////////// -// MemoryPressureMonitor -// -// A class to handle the observation of our free memory. It notifies the -// MemoryPressureListener of memory fill level changes, so that it can take -// action to reduce memory resources accordingly. -// -class BASE_EXPORT MemoryPressureMonitor : public base::MemoryPressureMonitor { - public: - using GetUsedMemoryInPercentCallback = int (*)(); - - // There are two memory pressure events: - // MODERATE - which will mainly release caches. - // CRITICAL - which will discard tabs. - // The |MemoryPressureThresholds| enum selects the strategy of firing these - // events: A conservative strategy will keep as much content in memory as - // possible (causing the system to swap to zram) and an aggressive strategy - // will release memory earlier to avoid swapping. - enum MemoryPressureThresholds { - // Use the system default. - THRESHOLD_DEFAULT = 0, - // Try to keep as much content in memory as possible. - THRESHOLD_CONSERVATIVE = 1, - // Discard caches earlier, allowing to keep more tabs in memory. - THRESHOLD_AGGRESSIVE_CACHE_DISCARD = 2, - // Discard tabs earlier, allowing the system to get faster. - THRESHOLD_AGGRESSIVE_TAB_DISCARD = 3, - // Discard caches and tabs earlier to allow the system to be faster. - THRESHOLD_AGGRESSIVE = 4 - }; - - explicit MemoryPressureMonitor(MemoryPressureThresholds thresholds); - ~MemoryPressureMonitor() override; - - // Redo the memory pressure calculation soon and call again if a critical - // memory pressure prevails. Note that this call will trigger an asynchronous - // action which gives the system time to release memory back into the pool. - void ScheduleEarlyCheck(); - - // Get the current memory pressure level. - MemoryPressureListener::MemoryPressureLevel GetCurrentPressureLevel() - override; - void SetDispatchCallback(const DispatchCallback& callback) override; - - // Returns a type-casted version of the current memory pressure monitor. A - // simple wrapper to base::MemoryPressureMonitor::Get. - static MemoryPressureMonitor* Get(); - - private: - friend TestMemoryPressureMonitor; - // Starts observing the memory fill level. - // Calls to StartObserving should always be matched with calls to - // StopObserving. - void StartObserving(); - - // Stop observing the memory fill level. - // May be safely called if StartObserving has not been called. - void StopObserving(); - - // The function which gets periodically called to check any changes in the - // memory pressure. It will report pressure changes as well as continuous - // critical pressure levels. - void CheckMemoryPressure(); - - // The function periodically checks the memory pressure changes and records - // the UMA histogram statistics for the current memory pressure level. - void CheckMemoryPressureAndRecordStatistics(); - - // Get the memory pressure in percent (virtual for testing). - virtual int GetUsedMemoryInPercent(); - - // The current memory pressure. - base::MemoryPressureListener::MemoryPressureLevel - current_memory_pressure_level_; - - // A periodic timer to check for resource pressure changes. This will get - // replaced by a kernel triggered event system (see crbug.com/381196). - base::RepeatingTimer timer_; - - // To slow down the amount of moderate pressure event calls, this counter - // gets used to count the number of events since the last event occured. - int moderate_pressure_repeat_count_; - - // The "Memory.PressureLevel" statistic is recorded every - // 5 seconds, but the timer to report "ChromeOS.MemoryPressureLevel" - // fires every second. This counter is used to allow reporting - // "Memory.PressureLevel" correctly without adding another - // timer. - int seconds_since_reporting_; - - // The thresholds for moderate and critical pressure. - const int moderate_pressure_threshold_percent_; - const int critical_pressure_threshold_percent_; - - // File descriptor used to detect low memory condition. - ScopedFD low_mem_file_; - - DispatchCallback dispatch_callback_; - - base::WeakPtrFactory<MemoryPressureMonitor> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(MemoryPressureMonitor); -}; - -} // namespace chromeos -} // namespace base - -#endif // BASE_MEMORY_MEMORY_PRESSURE_MONITOR_CHROMEOS_H_
diff --git a/base/memory/memory_pressure_monitor_mac.cc b/base/memory/memory_pressure_monitor_mac.cc deleted file mode 100644 index 678c276..0000000 --- a/base/memory/memory_pressure_monitor_mac.cc +++ /dev/null
@@ -1,190 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/memory_pressure_monitor_mac.h" - -#include <CoreFoundation/CoreFoundation.h> - -#include <dlfcn.h> -#include <stddef.h> -#include <sys/sysctl.h> - -#include <cmath> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/mac/mac_util.h" - -// Redeclare for partial 10.9 availability. -DISPATCH_EXPORT const struct dispatch_source_type_s - _dispatch_source_type_memorypressure; - -namespace { -static const int kUMATickSize = 5; -} // namespace - -namespace base { -namespace mac { - -MemoryPressureListener::MemoryPressureLevel -MemoryPressureMonitor::MemoryPressureLevelForMacMemoryPressureLevel( - int mac_memory_pressure_level) { - switch (mac_memory_pressure_level) { - case DISPATCH_MEMORYPRESSURE_NORMAL: - return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; - case DISPATCH_MEMORYPRESSURE_WARN: - return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; - case DISPATCH_MEMORYPRESSURE_CRITICAL: - return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; - } - return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; -} - -void MemoryPressureMonitor::OnRunLoopExit(CFRunLoopObserverRef observer, - CFRunLoopActivity activity, - void* info) { - MemoryPressureMonitor* self = static_cast<MemoryPressureMonitor*>(info); - self->UpdatePressureLevelOnRunLoopExit(); -} - -MemoryPressureMonitor::MemoryPressureMonitor() - : memory_level_event_source_(dispatch_source_create( - DISPATCH_SOURCE_TYPE_MEMORYPRESSURE, - 0, - DISPATCH_MEMORYPRESSURE_WARN | DISPATCH_MEMORYPRESSURE_CRITICAL | - DISPATCH_MEMORYPRESSURE_NORMAL, - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))), - dispatch_callback_( - base::Bind(&MemoryPressureListener::NotifyMemoryPressure)), - last_statistic_report_time_(CFAbsoluteTimeGetCurrent()), - last_pressure_level_(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), - subtick_seconds_(0) { - // Attach an event handler to the memory pressure event source. - if (memory_level_event_source_.get()) { - dispatch_source_set_event_handler(memory_level_event_source_, ^{ - OnMemoryPressureChanged(memory_level_event_source_.get(), - dispatch_callback_); - }); - - // Start monitoring the event source. - dispatch_resume(memory_level_event_source_); - } - - // Create a CFRunLoopObserver to check the memory pressure at the end of - // every pass through the event loop (modulo kUMATickSize). - CFRunLoopObserverContext observer_context = {0, this, NULL, NULL, NULL}; - - exit_observer_.reset( - CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopExit, true, 0, - OnRunLoopExit, &observer_context)); - - CFRunLoopRef run_loop = CFRunLoopGetCurrent(); - CFRunLoopAddObserver(run_loop, exit_observer_, kCFRunLoopCommonModes); - CFRunLoopAddObserver(run_loop, exit_observer_, - kMessageLoopExclusiveRunLoopMode); -} - -MemoryPressureMonitor::~MemoryPressureMonitor() { - // Detach from the run loop. - CFRunLoopRef run_loop = CFRunLoopGetCurrent(); - CFRunLoopRemoveObserver(run_loop, exit_observer_, kCFRunLoopCommonModes); - CFRunLoopRemoveObserver(run_loop, exit_observer_, - kMessageLoopExclusiveRunLoopMode); - - // Remove the memory pressure event source. - if (memory_level_event_source_.get()) { - dispatch_source_cancel(memory_level_event_source_); - } -} - -int MemoryPressureMonitor::GetMacMemoryPressureLevel() { - // Get the raw memory pressure level from macOS. - int mac_memory_pressure_level; - size_t length = sizeof(int); - sysctlbyname("kern.memorystatus_vm_pressure_level", - &mac_memory_pressure_level, &length, nullptr, 0); - - return mac_memory_pressure_level; -} - -void MemoryPressureMonitor::UpdatePressureLevel() { - // Get the current macOS pressure level and convert to the corresponding - // Chrome pressure level. - int mac_memory_pressure_level = GetMacMemoryPressureLevel(); - MemoryPressureListener::MemoryPressureLevel new_pressure_level = - MemoryPressureLevelForMacMemoryPressureLevel(mac_memory_pressure_level); - - // Compute the number of "ticks" spent at |last_pressure_level_| (since the - // last report sent to UMA). - CFTimeInterval now = CFAbsoluteTimeGetCurrent(); - CFTimeInterval time_since_last_report = now - last_statistic_report_time_; - last_statistic_report_time_ = now; - - double accumulated_time = time_since_last_report + subtick_seconds_; - int ticks_to_report = static_cast<int>(accumulated_time / kUMATickSize); - // Save for later the seconds that didn't make it into a full tick. - subtick_seconds_ = std::fmod(accumulated_time, kUMATickSize); - - // Round the tick count up on a pressure level change to ensure we capture it. - bool pressure_level_changed = (new_pressure_level != last_pressure_level_); - if (pressure_level_changed && ticks_to_report < 1) { - ticks_to_report = 1; - subtick_seconds_ = 0; - } - - // Send elapsed ticks to UMA. - if (ticks_to_report >= 1) { - RecordMemoryPressure(last_pressure_level_, ticks_to_report); - } - - // Save the now-current memory pressure level. - last_pressure_level_ = new_pressure_level; -} - -void MemoryPressureMonitor::UpdatePressureLevelOnRunLoopExit() { - // Wait until it's time to check the pressure level. - CFTimeInterval now = CFAbsoluteTimeGetCurrent(); - if (now >= next_run_loop_update_time_) { - UpdatePressureLevel(); - - // Update again in kUMATickSize seconds. We can update at any frequency, - // but because we're only checking memory pressure levels for UMA there's - // no need to update more frequently than we're keeping statistics on. - next_run_loop_update_time_ = now + kUMATickSize - subtick_seconds_; - } -} - -// Static. -int MemoryPressureMonitor::GetSecondsPerUMATick() { - return kUMATickSize; -} - -MemoryPressureListener::MemoryPressureLevel -MemoryPressureMonitor::GetCurrentPressureLevel() { - return last_pressure_level_; -} - -void MemoryPressureMonitor::OnMemoryPressureChanged( - dispatch_source_s* event_source, - const MemoryPressureMonitor::DispatchCallback& dispatch_callback) { - // The OS has sent a notification that the memory pressure level has changed. - // Go through the normal memory pressure level checking mechanism so that - // last_pressure_level_ and UMA get updated to the current value. - UpdatePressureLevel(); - - // Run the callback that's waiting on memory pressure change notifications. - // The convention is to not send notifiations on memory pressure returning to - // normal. - if (last_pressure_level_ != - MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) - dispatch_callback.Run(last_pressure_level_); -} - -void MemoryPressureMonitor::SetDispatchCallback( - const DispatchCallback& callback) { - dispatch_callback_ = callback; -} - -} // namespace mac -} // namespace base
diff --git a/base/memory/memory_pressure_monitor_mac.h b/base/memory/memory_pressure_monitor_mac.h deleted file mode 100644 index b85b6c9..0000000 --- a/base/memory/memory_pressure_monitor_mac.h +++ /dev/null
@@ -1,91 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_MEMORY_PRESSURE_MONITOR_MAC_H_ -#define BASE_MEMORY_MEMORY_PRESSURE_MONITOR_MAC_H_ - -#include <CoreFoundation/CFDate.h> -#include <dispatch/dispatch.h> - -#include "base/base_export.h" -#include "base/mac/scoped_cftyperef.h" -#include "base/mac/scoped_dispatch_object.h" -#include "base/macros.h" -#include "base/memory/memory_pressure_listener.h" -#include "base/memory/memory_pressure_monitor.h" -#include "base/message_loop/message_pump_mac.h" - -namespace base { -namespace mac { - -class TestMemoryPressureMonitor; - -// Declares the interface for the Mac MemoryPressureMonitor, which reports -// memory pressure events and status. -class BASE_EXPORT MemoryPressureMonitor : public base::MemoryPressureMonitor { - public: - MemoryPressureMonitor(); - ~MemoryPressureMonitor() override; - - // Returns the currently-observed memory pressure. - MemoryPressureLevel GetCurrentPressureLevel() override; - - void SetDispatchCallback(const DispatchCallback& callback) override; - - private: - friend TestMemoryPressureMonitor; - - static MemoryPressureLevel MemoryPressureLevelForMacMemoryPressureLevel( - int mac_memory_pressure_level); - static void OnRunLoopExit(CFRunLoopObserverRef observer, - CFRunLoopActivity activity, - void* info); - // Returns the raw memory pressure level from the macOS. Exposed for - // unit testing. - virtual int GetMacMemoryPressureLevel(); - - // Updates |last_pressure_level_| with the current memory pressure level. - void UpdatePressureLevel(); - - // Updates |last_pressure_level_| at the end of every run loop pass (modulo - // some number of seconds). - void UpdatePressureLevelOnRunLoopExit(); - - // Run |dispatch_callback| on memory pressure notifications from the OS. - void OnMemoryPressureChanged(dispatch_source_s* event_source, - const DispatchCallback& dispatch_callback); - - // Returns the number of seconds per UMA tick (for statistics recording). - // Exposed for testing. - static int GetSecondsPerUMATick(); - - // The dispatch source that generates memory pressure change notifications. - ScopedDispatchObject<dispatch_source_t> memory_level_event_source_; - - // The callback to call upon receiving a memory pressure change notification. - DispatchCallback dispatch_callback_; - - // Last UMA report time. - CFTimeInterval last_statistic_report_time_; - - // Most-recent memory pressure level. - MemoryPressureLevel last_pressure_level_; - - // Observer that tracks exits from the main run loop. - ScopedCFTypeRef<CFRunLoopObserverRef> exit_observer_; - - // Next time to update the memory pressure level when exiting the run loop. - CFTimeInterval next_run_loop_update_time_; - - // Seconds left over from the last UMA tick calculation (to be added to the - // next calculation). - CFTimeInterval subtick_seconds_; - - DISALLOW_COPY_AND_ASSIGN(MemoryPressureMonitor); -}; - -} // namespace mac -} // namespace base - -#endif // BASE_MEMORY_MEMORY_PRESSURE_MONITOR_MAC_H_
diff --git a/base/memory/memory_pressure_monitor_win.cc b/base/memory/memory_pressure_monitor_win.cc deleted file mode 100644 index 3effe2c..0000000 --- a/base/memory/memory_pressure_monitor_win.cc +++ /dev/null
@@ -1,233 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/memory_pressure_monitor_win.h" - -#include <windows.h> - -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" - -namespace base { -namespace win { - -namespace { - -static const DWORDLONG kMBBytes = 1024 * 1024; - -} // namespace - -// The following constants have been lifted from similar values in the ChromeOS -// memory pressure monitor. The values were determined experimentally to ensure -// sufficient responsiveness of the memory pressure subsystem, and minimal -// overhead. -const int MemoryPressureMonitor::kPollingIntervalMs = 5000; -const int MemoryPressureMonitor::kModeratePressureCooldownMs = 10000; -const int MemoryPressureMonitor::kModeratePressureCooldownCycles = - kModeratePressureCooldownMs / kPollingIntervalMs; - -// TODO(chrisha): Explore the following constants further with an experiment. - -// A system is considered 'high memory' if it has more than 1.5GB of system -// memory available for use by the memory manager (not reserved for hardware -// and drivers). This is a fuzzy version of the ~2GB discussed below. -const int MemoryPressureMonitor::kLargeMemoryThresholdMb = 1536; - -// These are the default thresholds used for systems with < ~2GB of physical -// memory. Such systems have been observed to always maintain ~100MB of -// available memory, paging until that is the case. To try to avoid paging a -// threshold slightly above this is chosen. The moderate threshold is slightly -// less grounded in reality and chosen as 2.5x critical. -const int MemoryPressureMonitor::kSmallMemoryDefaultModerateThresholdMb = 500; -const int MemoryPressureMonitor::kSmallMemoryDefaultCriticalThresholdMb = 200; - -// These are the default thresholds used for systems with >= ~2GB of physical -// memory. Such systems have been observed to always maintain ~300MB of -// available memory, paging until that is the case. -const int MemoryPressureMonitor::kLargeMemoryDefaultModerateThresholdMb = 1000; -const int MemoryPressureMonitor::kLargeMemoryDefaultCriticalThresholdMb = 400; - -MemoryPressureMonitor::MemoryPressureMonitor() - : moderate_threshold_mb_(0), - critical_threshold_mb_(0), - current_memory_pressure_level_( - MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), - moderate_pressure_repeat_count_(0), - dispatch_callback_( - base::Bind(&MemoryPressureListener::NotifyMemoryPressure)), - weak_ptr_factory_(this) { - InferThresholds(); - StartObserving(); -} - -MemoryPressureMonitor::MemoryPressureMonitor(int moderate_threshold_mb, - int critical_threshold_mb) - : moderate_threshold_mb_(moderate_threshold_mb), - critical_threshold_mb_(critical_threshold_mb), - current_memory_pressure_level_( - MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), - moderate_pressure_repeat_count_(0), - dispatch_callback_( - base::Bind(&MemoryPressureListener::NotifyMemoryPressure)), - weak_ptr_factory_(this) { - DCHECK_GE(moderate_threshold_mb_, critical_threshold_mb_); - DCHECK_LE(0, critical_threshold_mb_); - StartObserving(); -} - -MemoryPressureMonitor::~MemoryPressureMonitor() { - StopObserving(); -} - -void MemoryPressureMonitor::CheckMemoryPressureSoon() { - DCHECK(thread_checker_.CalledOnValidThread()); - - ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, Bind(&MemoryPressureMonitor::CheckMemoryPressure, - weak_ptr_factory_.GetWeakPtr())); -} - -MemoryPressureListener::MemoryPressureLevel -MemoryPressureMonitor::GetCurrentPressureLevel() { - return current_memory_pressure_level_; -} - -void MemoryPressureMonitor::InferThresholds() { - // Default to a 'high' memory situation, which uses more conservative - // thresholds. - bool high_memory = true; - MEMORYSTATUSEX mem_status = {}; - if (GetSystemMemoryStatus(&mem_status)) { - static const DWORDLONG kLargeMemoryThresholdBytes = - static_cast<DWORDLONG>(kLargeMemoryThresholdMb) * kMBBytes; - high_memory = mem_status.ullTotalPhys >= kLargeMemoryThresholdBytes; - } - - if (high_memory) { - moderate_threshold_mb_ = kLargeMemoryDefaultModerateThresholdMb; - critical_threshold_mb_ = kLargeMemoryDefaultCriticalThresholdMb; - } else { - moderate_threshold_mb_ = kSmallMemoryDefaultModerateThresholdMb; - critical_threshold_mb_ = kSmallMemoryDefaultCriticalThresholdMb; - } -} - -void MemoryPressureMonitor::StartObserving() { - DCHECK(thread_checker_.CalledOnValidThread()); - - timer_.Start(FROM_HERE, - TimeDelta::FromMilliseconds(kPollingIntervalMs), - Bind(&MemoryPressureMonitor:: - CheckMemoryPressureAndRecordStatistics, - weak_ptr_factory_.GetWeakPtr())); -} - -void MemoryPressureMonitor::StopObserving() { - DCHECK(thread_checker_.CalledOnValidThread()); - - // If StartObserving failed, StopObserving will still get called. - timer_.Stop(); - weak_ptr_factory_.InvalidateWeakPtrs(); -} - -void MemoryPressureMonitor::CheckMemoryPressure() { - DCHECK(thread_checker_.CalledOnValidThread()); - - // Get the previous pressure level and update the current one. - MemoryPressureLevel old_pressure = current_memory_pressure_level_; - current_memory_pressure_level_ = CalculateCurrentPressureLevel(); - - // |notify| will be set to true if MemoryPressureListeners need to be - // notified of a memory pressure level state change. - bool notify = false; - switch (current_memory_pressure_level_) { - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: - break; - - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: - if (old_pressure != current_memory_pressure_level_) { - // This is a new transition to moderate pressure so notify. - moderate_pressure_repeat_count_ = 0; - notify = true; - } else { - // Already in moderate pressure, only notify if sustained over the - // cooldown period. - if (++moderate_pressure_repeat_count_ == - kModeratePressureCooldownCycles) { - moderate_pressure_repeat_count_ = 0; - notify = true; - } - } - break; - - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: - // Always notify of critical pressure levels. - notify = true; - break; - } - - if (!notify) - return; - - // Emit a notification of the current memory pressure level. This can only - // happen for moderate and critical pressure levels. - DCHECK_NE(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, - current_memory_pressure_level_); - dispatch_callback_.Run(current_memory_pressure_level_); -} - -void MemoryPressureMonitor::CheckMemoryPressureAndRecordStatistics() { - DCHECK(thread_checker_.CalledOnValidThread()); - - CheckMemoryPressure(); - - RecordMemoryPressure(current_memory_pressure_level_, 1); -} - -MemoryPressureListener::MemoryPressureLevel -MemoryPressureMonitor::CalculateCurrentPressureLevel() { - MEMORYSTATUSEX mem_status = {}; - if (!GetSystemMemoryStatus(&mem_status)) - return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; - - // How much system memory is actively available for use right now, in MBs. - int phys_free = static_cast<int>(mem_status.ullAvailPhys / kMBBytes); - - // TODO(chrisha): This should eventually care about address space pressure, - // but the browser process (where this is running) effectively never runs out - // of address space. Renderers occasionally do, but it does them no good to - // have the browser process monitor address space pressure. Long term, - // renderers should run their own address space pressure monitors and act - // accordingly, with the browser making cross-process decisions based on - // system memory pressure. - - // Determine if the physical memory is under critical memory pressure. - if (phys_free <= critical_threshold_mb_) - return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; - - // Determine if the physical memory is under moderate memory pressure. - if (phys_free <= moderate_threshold_mb_) - return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; - - // No memory pressure was detected. - return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; -} - -bool MemoryPressureMonitor::GetSystemMemoryStatus( - MEMORYSTATUSEX* mem_status) { - DCHECK(mem_status != nullptr); - mem_status->dwLength = sizeof(*mem_status); - if (!::GlobalMemoryStatusEx(mem_status)) - return false; - return true; -} - -void MemoryPressureMonitor::SetDispatchCallback( - const DispatchCallback& callback) { - dispatch_callback_ = callback; -} - -} // namespace win -} // namespace base
diff --git a/base/memory/memory_pressure_monitor_win.h b/base/memory/memory_pressure_monitor_win.h deleted file mode 100644 index a65c191..0000000 --- a/base/memory/memory_pressure_monitor_win.h +++ /dev/null
@@ -1,148 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_MEMORY_PRESSURE_MONITOR_WIN_H_ -#define BASE_MEMORY_MEMORY_PRESSURE_MONITOR_WIN_H_ - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/memory/memory_pressure_listener.h" -#include "base/memory/memory_pressure_monitor.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/thread_checker.h" -#include "base/timer/timer.h" - -// To not pull in windows.h. -typedef struct _MEMORYSTATUSEX MEMORYSTATUSEX; - -namespace base { -namespace win { - -// Windows memory pressure monitor. Because there is no OS provided signal this -// polls at a low frequency (once per second), and applies internal hysteresis. -class BASE_EXPORT MemoryPressureMonitor : public base::MemoryPressureMonitor { - public: - // Constants governing the polling and hysteresis behaviour of the observer. - - // The polling interval, in milliseconds. While under critical pressure, this - // is also the timer to repeat cleanup attempts. - static const int kPollingIntervalMs; - // The time which should pass between 2 successive moderate memory pressure - // signals, in milliseconds. - static const int kModeratePressureCooldownMs; - // The number of cycles that should pass between 2 successive moderate memory - // pressure signals. - static const int kModeratePressureCooldownCycles; - - // Constants governing the memory pressure level detection. - - // The amount of total system memory beyond which a system is considered to be - // a large-memory system. - static const int kLargeMemoryThresholdMb; - // Default minimum free memory thresholds for small-memory systems, in MB. - static const int kSmallMemoryDefaultModerateThresholdMb; - static const int kSmallMemoryDefaultCriticalThresholdMb; - // Default minimum free memory thresholds for large-memory systems, in MB. - static const int kLargeMemoryDefaultModerateThresholdMb; - static const int kLargeMemoryDefaultCriticalThresholdMb; - - // Default constructor. Will choose thresholds automatically basd on the - // actual amount of system memory. - MemoryPressureMonitor(); - - // Constructor with explicit memory thresholds. These represent the amount of - // free memory below which the applicable memory pressure state engages. - MemoryPressureMonitor(int moderate_threshold_mb, int critical_threshold_mb); - - ~MemoryPressureMonitor() override; - - // Schedules a memory pressure check to run soon. This must be called on the - // same thread where the monitor was instantiated. - void CheckMemoryPressureSoon(); - - // Get the current memory pressure level. This can be called from any thread. - MemoryPressureLevel GetCurrentPressureLevel() override; - void SetDispatchCallback(const DispatchCallback& callback) override; - - // Returns the moderate pressure level free memory threshold, in MB. - int moderate_threshold_mb() const { return moderate_threshold_mb_; } - - // Returns the critical pressure level free memory threshold, in MB. - int critical_threshold_mb() const { return critical_threshold_mb_; } - - protected: - // Internals are exposed for unittests. - - // Automatically infers threshold values based on system memory. This invokes - // GetMemoryStatus so it can be mocked in unittests. - void InferThresholds(); - - // Starts observing the memory fill level. Calls to StartObserving should - // always be matched with calls to StopObserving. - void StartObserving(); - - // Stop observing the memory fill level. May be safely called if - // StartObserving has not been called. Must be called from the same thread on - // which the monitor was instantiated. - void StopObserving(); - - // Checks memory pressure, storing the current level, applying any hysteresis - // and emitting memory pressure level change signals as necessary. This - // function is called periodically while the monitor is observing memory - // pressure. This is split out from CheckMemoryPressureAndRecordStatistics so - // that it may be called by CheckMemoryPressureSoon and not invoke UMA - // logging. Must be called from the same thread on which the monitor was - // instantiated. - void CheckMemoryPressure(); - - // Wrapper to CheckMemoryPressure that also records the observed memory - // pressure level via an UMA enumeration. This is the function that is called - // periodically by the timer. Must be called from the same thread on which the - // monitor was instantiated. - void CheckMemoryPressureAndRecordStatistics(); - - // Calculates the current instantaneous memory pressure level. This does not - // use any hysteresis and simply returns the result at the current moment. Can - // be called on any thread. - MemoryPressureLevel CalculateCurrentPressureLevel(); - - // Gets system memory status. This is virtual as a unittesting hook. Returns - // true if the system call succeeds, false otherwise. Can be called on any - // thread. - virtual bool GetSystemMemoryStatus(MEMORYSTATUSEX* mem_status); - - private: - // Threshold amounts of available memory that trigger pressure levels. See - // memory_pressure_monitor.cc for a discussion of reasonable values for these. - int moderate_threshold_mb_; - int critical_threshold_mb_; - - // A periodic timer to check for memory pressure changes. - base::RepeatingTimer timer_; - - // The current memory pressure. - MemoryPressureLevel current_memory_pressure_level_; - - // To slow down the amount of moderate pressure event calls, this gets used to - // count the number of events since the last event occured. This is used by - // |CheckMemoryPressure| to apply hysteresis on the raw results of - // |CalculateCurrentPressureLevel|. - int moderate_pressure_repeat_count_; - - // Ensures that this object is used from a single thread. - base::ThreadChecker thread_checker_; - - DispatchCallback dispatch_callback_; - - // Weak pointer factory to ourself used for scheduling calls to - // CheckMemoryPressure/CheckMemoryPressureAndRecordStatistics via |timer_|. - base::WeakPtrFactory<MemoryPressureMonitor> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(MemoryPressureMonitor); -}; - -} // namespace win -} // namespace base - -#endif // BASE_MEMORY_MEMORY_PRESSURE_MONITOR_WIN_H_
diff --git a/base/memory/platform_shared_memory_region.cc b/base/memory/platform_shared_memory_region.cc deleted file mode 100644 index c145336..0000000 --- a/base/memory/platform_shared_memory_region.cc +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/platform_shared_memory_region.h" - -#include "base/memory/shared_memory_mapping.h" - -namespace base { -namespace subtle { - -// static -PlatformSharedMemoryRegion PlatformSharedMemoryRegion::CreateWritable( - size_t size) { - return Create(Mode::kWritable, size); -} - -// static -PlatformSharedMemoryRegion PlatformSharedMemoryRegion::CreateUnsafe( - size_t size) { - return Create(Mode::kUnsafe, size); -} - -PlatformSharedMemoryRegion::PlatformSharedMemoryRegion() = default; -PlatformSharedMemoryRegion::PlatformSharedMemoryRegion( - PlatformSharedMemoryRegion&& other) = default; -PlatformSharedMemoryRegion& PlatformSharedMemoryRegion::operator=( - PlatformSharedMemoryRegion&& other) = default; -PlatformSharedMemoryRegion::~PlatformSharedMemoryRegion() = default; - -PlatformSharedMemoryRegion::ScopedPlatformHandle -PlatformSharedMemoryRegion::PassPlatformHandle() { - return std::move(handle_); -} - -} // namespace subtle -} // namespace base
diff --git a/base/memory/platform_shared_memory_region.h b/base/memory/platform_shared_memory_region.h deleted file mode 100644 index df4cc4d..0000000 --- a/base/memory/platform_shared_memory_region.h +++ /dev/null
@@ -1,223 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_PLATFORM_SHARED_MEMORY_REGION_H_ -#define BASE_MEMORY_PLATFORM_SHARED_MEMORY_REGION_H_ - -#include <utility> - -#include "base/compiler_specific.h" -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/unguessable_token.h" -#include "build_config.h" - -#if defined(OS_MACOSX) && !defined(OS_IOS) -#include <mach/mach.h> -#include "base/mac/scoped_mach_port.h" -#elif defined(OS_FUCHSIA) -#include "base/fuchsia/scoped_zx_handle.h" -#elif defined(OS_WIN) -#include "base/win/scoped_handle.h" -#include "base/win/windows_types.h" -#elif defined(OS_POSIX) -#include <sys/types.h> -#include "base/file_descriptor_posix.h" -#include "base/files/scoped_file.h" -#endif - -namespace base { -namespace subtle { - -#if defined(OS_POSIX) && (!defined(OS_MACOSX) || defined(OS_IOS)) && \ - !defined(OS_FUCHSIA) && !defined(OS_ANDROID) -// Helper structs to keep two descriptors on POSIX. It's needed to support -// ConvertToReadOnly(). -struct BASE_EXPORT FDPair { - int fd; - int readonly_fd; -}; - -struct BASE_EXPORT ScopedFDPair { - ScopedFDPair(); - ScopedFDPair(ScopedFD in_fd, ScopedFD in_readonly_fd); - ScopedFDPair(ScopedFDPair&&); - ScopedFDPair& operator=(ScopedFDPair&&); - ~ScopedFDPair(); - - FDPair get() const; - - ScopedFD fd; - ScopedFD readonly_fd; -}; -#endif - -// Implementation class for shared memory regions. -// -// This class does the following: -// -// - Wraps and owns a shared memory region platform handle. -// - Provides a way to allocate a new region of platform shared memory of given -// size. -// - Provides a way to create mapping of the region in the current process' -// address space, under special access-control constraints (see Mode). -// - Provides methods to help transferring the handle across process boundaries. -// - Holds a 128-bit unique identifier used to uniquely identify the same -// kernel region resource across processes (used for memory tracking). -// - Has a method to retrieve the region's size in bytes. -// -// IMPORTANT NOTE: Users should never use this directly, but -// ReadOnlySharedMemoryRegion, WritableSharedMemoryRegion or -// UnsafeSharedMemoryRegion since this is an implementation class. -class BASE_EXPORT PlatformSharedMemoryRegion { - public: - // Permission mode of the platform handle. Each mode corresponds to one of the - // typed shared memory classes: - // - // * ReadOnlySharedMemoryRegion: A region that can only create read-only - // mappings. - // - // * WritableSharedMemoryRegion: A region that can only create writable - // mappings. The region can be demoted to ReadOnlySharedMemoryRegion without - // the possibility of promoting back to writable. - // - // * UnsafeSharedMemoryRegion: A region that can only create writable - // mappings. The region cannot be demoted to ReadOnlySharedMemoryRegion. - enum class Mode { - kReadOnly, // ReadOnlySharedMemoryRegion - kWritable, // WritableSharedMemoryRegion - kUnsafe, // UnsafeSharedMemoryRegion - kMaxValue = kUnsafe - }; - -// Platform-specific shared memory type used by this class. -#if defined(OS_MACOSX) && !defined(OS_IOS) - using PlatformHandle = mach_port_t; - using ScopedPlatformHandle = mac::ScopedMachSendRight; -#elif defined(OS_FUCHSIA) - using PlatformHandle = zx_handle_t; - using ScopedPlatformHandle = ScopedZxHandle; -#elif defined(OS_WIN) - using PlatformHandle = HANDLE; - using ScopedPlatformHandle = win::ScopedHandle; -#elif defined(OS_ANDROID) - using PlatformHandle = int; - using ScopedPlatformHandle = ScopedFD; -#else - using PlatformHandle = FDPair; - using ScopedPlatformHandle = ScopedFDPair; -#endif - - // The minimum alignment in bytes that any mapped address produced by Map() - // and MapAt() is guaranteed to have. - enum { kMapMinimumAlignment = 32 }; - - // Creates a new PlatformSharedMemoryRegion with corresponding mode and size. - // Creating in kReadOnly mode isn't supported because then there will be no - // way to modify memory content. - static PlatformSharedMemoryRegion CreateWritable(size_t size); - static PlatformSharedMemoryRegion CreateUnsafe(size_t size); - - // Returns a new PlatformSharedMemoryRegion that takes ownership of the - // |handle|. All parameters must be taken from another valid - // PlatformSharedMemoryRegion instance, e.g. |size| must be equal to the - // actual region size as allocated by the kernel. - // Closes the |handle| and returns an invalid instance if passed parameters - // are invalid. - static PlatformSharedMemoryRegion Take(ScopedPlatformHandle handle, - Mode mode, - size_t size, - const UnguessableToken& guid); - - // Default constructor initializes an invalid instance, i.e. an instance that - // doesn't wrap any valid platform handle. - PlatformSharedMemoryRegion(); - - // Move operations are allowed. - PlatformSharedMemoryRegion(PlatformSharedMemoryRegion&&); - PlatformSharedMemoryRegion& operator=(PlatformSharedMemoryRegion&&); - - // Destructor closes the platform handle. Does nothing if the handle is - // invalid. - ~PlatformSharedMemoryRegion(); - - // Passes ownership of the platform handle to the caller. The current instance - // becomes invalid. It's the responsibility of the caller to close the handle. - ScopedPlatformHandle PassPlatformHandle() WARN_UNUSED_RESULT; - - // Returns the platform handle. The current instance keeps ownership of this - // handle. - PlatformHandle GetPlatformHandle() const; - - // Whether the platform handle is valid. - bool IsValid() const; - - // Duplicates the platform handle and creates a new PlatformSharedMemoryRegion - // with the same |mode_|, |size_| and |guid_| that owns this handle. Returns - // invalid region on failure, the current instance remains valid. - // Can be called only in kReadOnly and kUnsafe modes, CHECK-fails if is - // called in kWritable mode. - PlatformSharedMemoryRegion Duplicate() const; - - // Converts the region to read-only. Returns whether the operation succeeded. - // Makes the current instance invalid on failure. Can be called only in - // kWritable mode, all other modes will CHECK-fail. The object will have - // kReadOnly mode after this call on success. - bool ConvertToReadOnly(); -#if defined(OS_MACOSX) && !defined(OS_IOS) - // Same as above, but |mapped_addr| is used as a hint to avoid additional - // mapping of the memory object. - // |mapped_addr| must be mapped location of |memory_object_|. If the location - // is unknown, |mapped_addr| should be |nullptr|. - bool ConvertToReadOnly(void* mapped_addr); -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - - // Maps |size| bytes of the shared memory region starting with the given - // |offset| into the caller's address space. |offset| must be aligned to value - // of |SysInfo::VMAllocationGranularity()|. Fails if requested bytes are out - // of the region limits. - // Returns true and sets |memory| and |mapped_size| on success, returns false - // and leaves output parameters in unspecified state otherwise. The mapped - // address is guaranteed to have an alignment of at least - // |kMapMinimumAlignment|. - bool MapAt(off_t offset, - size_t size, - void** memory, - size_t* mapped_size) const; - - const UnguessableToken& GetGUID() const { return guid_; } - - size_t GetSize() const { return size_; } - - Mode GetMode() const { return mode_; } - - private: - FRIEND_TEST_ALL_PREFIXES(PlatformSharedMemoryRegionTest, - CreateReadOnlyRegionDeathTest); - FRIEND_TEST_ALL_PREFIXES(PlatformSharedMemoryRegionTest, - CheckPlatformHandlePermissionsCorrespondToMode); - static PlatformSharedMemoryRegion Create(Mode mode, size_t size); - - static bool CheckPlatformHandlePermissionsCorrespondToMode( - PlatformHandle handle, - Mode mode, - size_t size); - - PlatformSharedMemoryRegion(ScopedPlatformHandle handle, - Mode mode, - size_t size, - const UnguessableToken& guid); - - ScopedPlatformHandle handle_; - Mode mode_ = Mode::kReadOnly; - size_t size_ = 0; - UnguessableToken guid_; - - DISALLOW_COPY_AND_ASSIGN(PlatformSharedMemoryRegion); -}; - -} // namespace subtle -} // namespace base - -#endif // BASE_MEMORY_PLATFORM_SHARED_MEMORY_REGION_H_
diff --git a/base/memory/platform_shared_memory_region_fuchsia.cc b/base/memory/platform_shared_memory_region_fuchsia.cc deleted file mode 100644 index 5a75845..0000000 --- a/base/memory/platform_shared_memory_region_fuchsia.cc +++ /dev/null
@@ -1,190 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/platform_shared_memory_region.h" - -#include <zircon/process.h> -#include <zircon/rights.h> -#include <zircon/syscalls.h> - -#include "base/bits.h" -#include "base/fuchsia/fuchsia_logging.h" -#include "base/numerics/checked_math.h" -#include "base/process/process_metrics.h" - -namespace base { -namespace subtle { - -static constexpr int kNoWriteOrExec = - ZX_DEFAULT_VMO_RIGHTS & - ~(ZX_RIGHT_WRITE | ZX_RIGHT_EXECUTE | ZX_RIGHT_SET_PROPERTY); - -// static -PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Take( - ScopedZxHandle handle, - Mode mode, - size_t size, - const UnguessableToken& guid) { - if (!handle.is_valid()) - return {}; - - if (size == 0) - return {}; - - if (size > static_cast<size_t>(std::numeric_limits<int>::max())) - return {}; - - CHECK( - CheckPlatformHandlePermissionsCorrespondToMode(handle.get(), mode, size)); - - return PlatformSharedMemoryRegion(std::move(handle), mode, size, guid); -} - -zx_handle_t PlatformSharedMemoryRegion::GetPlatformHandle() const { - return handle_.get(); -} - -bool PlatformSharedMemoryRegion::IsValid() const { - return handle_.is_valid(); -} - -PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Duplicate() const { - if (!IsValid()) - return {}; - - CHECK_NE(mode_, Mode::kWritable) - << "Duplicating a writable shared memory region is prohibited"; - - ScopedZxHandle duped_handle; - zx_status_t status = zx_handle_duplicate(handle_.get(), ZX_RIGHT_SAME_RIGHTS, - duped_handle.receive()); - if (status != ZX_OK) { - ZX_DLOG(ERROR, status) << "zx_handle_duplicate"; - return {}; - } - - return PlatformSharedMemoryRegion(std::move(duped_handle), mode_, size_, - guid_); -} - -bool PlatformSharedMemoryRegion::ConvertToReadOnly() { - if (!IsValid()) - return false; - - CHECK_EQ(mode_, Mode::kWritable) - << "Only writable shared memory region can be converted to read-only"; - - ScopedZxHandle old_handle(handle_.release()); - ScopedZxHandle new_handle; - zx_status_t status = - zx_handle_replace(old_handle.get(), kNoWriteOrExec, new_handle.receive()); - if (status != ZX_OK) { - ZX_DLOG(ERROR, status) << "zx_handle_replace"; - return false; - } - ignore_result(old_handle.release()); - - handle_ = std::move(new_handle); - mode_ = Mode::kReadOnly; - return true; -} - -bool PlatformSharedMemoryRegion::MapAt(off_t offset, - size_t size, - void** memory, - size_t* mapped_size) const { - if (!IsValid()) - return false; - - size_t end_byte; - if (!CheckAdd(offset, size).AssignIfValid(&end_byte) || end_byte > size_) { - return false; - } - - bool write_allowed = mode_ != Mode::kReadOnly; - uintptr_t addr; - zx_status_t status = zx_vmar_map( - zx_vmar_root_self(), 0, handle_.get(), offset, size, - ZX_VM_FLAG_PERM_READ | (write_allowed ? ZX_VM_FLAG_PERM_WRITE : 0), - &addr); - if (status != ZX_OK) { - ZX_DLOG(ERROR, status) << "zx_vmar_map"; - return false; - } - - *memory = reinterpret_cast<void*>(addr); - *mapped_size = size; - DCHECK_EQ(0U, - reinterpret_cast<uintptr_t>(*memory) & (kMapMinimumAlignment - 1)); - return true; -} - -// static -PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Create(Mode mode, - size_t size) { - if (size == 0) - return {}; - - size_t rounded_size = bits::Align(size, GetPageSize()); - if (rounded_size > static_cast<size_t>(std::numeric_limits<int>::max())) - return {}; - - CHECK_NE(mode, Mode::kReadOnly) << "Creating a region in read-only mode will " - "lead to this region being non-modifiable"; - - ScopedZxHandle vmo; - zx_status_t status = zx_vmo_create(rounded_size, 0, vmo.receive()); - if (status != ZX_OK) { - ZX_DLOG(ERROR, status) << "zx_vmo_create"; - return {}; - } - - const int kNoExecFlags = ZX_DEFAULT_VMO_RIGHTS & ~ZX_RIGHT_EXECUTE; - ScopedZxHandle old_vmo(std::move(vmo)); - status = zx_handle_replace(old_vmo.get(), kNoExecFlags, vmo.receive()); - if (status != ZX_OK) { - ZX_DLOG(ERROR, status) << "zx_handle_replace"; - return {}; - } - ignore_result(old_vmo.release()); - - return PlatformSharedMemoryRegion(std::move(vmo), mode, size, - UnguessableToken::Create()); -} - -// static -bool PlatformSharedMemoryRegion::CheckPlatformHandlePermissionsCorrespondToMode( - PlatformHandle handle, - Mode mode, - size_t size) { - zx_info_handle_basic_t basic = {}; - zx_status_t status = zx_object_get_info(handle, ZX_INFO_HANDLE_BASIC, &basic, - sizeof(basic), nullptr, nullptr); - if (status != ZX_OK) { - ZX_DLOG(ERROR, status) << "zx_object_get_info"; - return false; - } - - bool is_read_only = (basic.rights & kNoWriteOrExec) == basic.rights; - bool expected_read_only = mode == Mode::kReadOnly; - - if (is_read_only != expected_read_only) { - DLOG(ERROR) << "VMO object has wrong access rights: it is" - << (is_read_only ? " " : " not ") << "read-only but it should" - << (expected_read_only ? " " : " not ") << "be"; - return false; - } - - return true; -} - -PlatformSharedMemoryRegion::PlatformSharedMemoryRegion( - ScopedZxHandle handle, - Mode mode, - size_t size, - const UnguessableToken& guid) - : handle_(std::move(handle)), mode_(mode), size_(size), guid_(guid) {} - -} // namespace subtle -} // namespace base
diff --git a/base/memory/platform_shared_memory_region_mac.cc b/base/memory/platform_shared_memory_region_mac.cc deleted file mode 100644 index 9cbe92e..0000000 --- a/base/memory/platform_shared_memory_region_mac.cc +++ /dev/null
@@ -1,222 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/platform_shared_memory_region.h" - -#include <mach/mach_vm.h> - -#include "base/mac/mach_logging.h" -#include "base/mac/scoped_mach_vm.h" -#include "base/numerics/checked_math.h" -#include "build_config.h" - -#if defined(OS_IOS) -#error "MacOS only - iOS uses platform_shared_memory_region_posix.cc" -#endif - -namespace base { -namespace subtle { - -// static -PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Take( - mac::ScopedMachSendRight handle, - Mode mode, - size_t size, - const UnguessableToken& guid) { - if (!handle.is_valid()) - return {}; - - if (size == 0) - return {}; - - if (size > static_cast<size_t>(std::numeric_limits<int>::max())) - return {}; - - CHECK( - CheckPlatformHandlePermissionsCorrespondToMode(handle.get(), mode, size)); - - return PlatformSharedMemoryRegion(std::move(handle), mode, size, guid); -} - -mach_port_t PlatformSharedMemoryRegion::GetPlatformHandle() const { - return handle_.get(); -} - -bool PlatformSharedMemoryRegion::IsValid() const { - return handle_.is_valid(); -} - -PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Duplicate() const { - if (!IsValid()) - return {}; - - CHECK_NE(mode_, Mode::kWritable) - << "Duplicating a writable shared memory region is prohibited"; - - // Increment the ref count. - kern_return_t kr = mach_port_mod_refs(mach_task_self(), handle_.get(), - MACH_PORT_RIGHT_SEND, 1); - if (kr != KERN_SUCCESS) { - MACH_DLOG(ERROR, kr) << "mach_port_mod_refs"; - return {}; - } - - return PlatformSharedMemoryRegion(mac::ScopedMachSendRight(handle_.get()), - mode_, size_, guid_); -} - -bool PlatformSharedMemoryRegion::ConvertToReadOnly() { - return ConvertToReadOnly(nullptr); -} - -bool PlatformSharedMemoryRegion::ConvertToReadOnly(void* mapped_addr) { - if (!IsValid()) - return false; - - CHECK_EQ(mode_, Mode::kWritable) - << "Only writable shared memory region can be converted to read-only"; - - mac::ScopedMachSendRight handle_copy(handle_.release()); - - void* temp_addr = mapped_addr; - mac::ScopedMachVM scoped_memory; - if (!temp_addr) { - // Intentionally lower current prot and max prot to |VM_PROT_READ|. - kern_return_t kr = mach_vm_map( - mach_task_self(), reinterpret_cast<mach_vm_address_t*>(&temp_addr), - size_, 0, VM_FLAGS_ANYWHERE, handle_copy.get(), 0, FALSE, VM_PROT_READ, - VM_PROT_READ, VM_INHERIT_NONE); - if (kr != KERN_SUCCESS) { - MACH_DLOG(ERROR, kr) << "mach_vm_map"; - return false; - } - scoped_memory.reset(reinterpret_cast<vm_address_t>(temp_addr), - mach_vm_round_page(size_)); - } - - // Make new memory object. - memory_object_size_t allocation_size = size_; - mac::ScopedMachSendRight named_right; - kern_return_t kr = mach_make_memory_entry_64( - mach_task_self(), &allocation_size, - reinterpret_cast<memory_object_offset_t>(temp_addr), VM_PROT_READ, - named_right.receive(), MACH_PORT_NULL); - if (kr != KERN_SUCCESS) { - MACH_DLOG(ERROR, kr) << "mach_make_memory_entry_64"; - return false; - } - DCHECK_GE(allocation_size, size_); - - handle_ = std::move(named_right); - mode_ = Mode::kReadOnly; - return true; -} - -bool PlatformSharedMemoryRegion::MapAt(off_t offset, - size_t size, - void** memory, - size_t* mapped_size) const { - if (!IsValid()) - return false; - - size_t end_byte; - if (!CheckAdd(offset, size).AssignIfValid(&end_byte) || end_byte > size_) { - return false; - } - - bool write_allowed = mode_ != Mode::kReadOnly; - vm_prot_t vm_prot_write = write_allowed ? VM_PROT_WRITE : 0; - kern_return_t kr = mach_vm_map( - mach_task_self(), - reinterpret_cast<mach_vm_address_t*>(memory), // Output parameter - size, - 0, // Alignment mask - VM_FLAGS_ANYWHERE, handle_.get(), offset, - FALSE, // Copy - VM_PROT_READ | vm_prot_write, // Current protection - VM_PROT_READ | vm_prot_write, // Maximum protection - VM_INHERIT_NONE); - if (kr != KERN_SUCCESS) { - MACH_DLOG(ERROR, kr) << "mach_vm_map"; - return false; - } - - *mapped_size = size; - DCHECK_EQ(0U, - reinterpret_cast<uintptr_t>(*memory) & (kMapMinimumAlignment - 1)); - return true; -} - -// static -PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Create(Mode mode, - size_t size) { - if (size == 0) - return {}; - - if (size > static_cast<size_t>(std::numeric_limits<int>::max())) - return {}; - - CHECK_NE(mode, Mode::kReadOnly) << "Creating a region in read-only mode will " - "lead to this region being non-modifiable"; - - mach_vm_size_t vm_size = size; - mac::ScopedMachSendRight named_right; - kern_return_t kr = mach_make_memory_entry_64( - mach_task_self(), &vm_size, - 0, // Address. - MAP_MEM_NAMED_CREATE | VM_PROT_READ | VM_PROT_WRITE, - named_right.receive(), - MACH_PORT_NULL); // Parent handle. - if (kr != KERN_SUCCESS) { - MACH_DLOG(ERROR, kr) << "mach_make_memory_entry_64"; - return {}; - } - DCHECK_GE(vm_size, size); - - return PlatformSharedMemoryRegion(std::move(named_right), mode, size, - UnguessableToken::Create()); -} - -// static -bool PlatformSharedMemoryRegion::CheckPlatformHandlePermissionsCorrespondToMode( - PlatformHandle handle, - Mode mode, - size_t size) { - mach_vm_address_t temp_addr = 0; - kern_return_t kr = - mach_vm_map(mach_task_self(), &temp_addr, size, 0, VM_FLAGS_ANYWHERE, - handle, 0, FALSE, VM_PROT_READ | VM_PROT_WRITE, - VM_PROT_READ | VM_PROT_WRITE, VM_INHERIT_NONE); - if (kr == KERN_SUCCESS) { - kern_return_t kr_deallocate = - mach_vm_deallocate(mach_task_self(), temp_addr, size); - MACH_DLOG_IF(ERROR, kr_deallocate != KERN_SUCCESS, kr_deallocate) - << "mach_vm_deallocate"; - } else if (kr != KERN_INVALID_RIGHT) { - MACH_DLOG(ERROR, kr) << "mach_vm_map"; - return false; - } - - bool is_read_only = kr == KERN_INVALID_RIGHT; - bool expected_read_only = mode == Mode::kReadOnly; - - if (is_read_only != expected_read_only) { - DLOG(ERROR) << "VM region has a wrong protection mask: it is" - << (is_read_only ? " " : " not ") << "read-only but it should" - << (expected_read_only ? " " : " not ") << "be"; - return false; - } - - return true; -} - -PlatformSharedMemoryRegion::PlatformSharedMemoryRegion( - mac::ScopedMachSendRight handle, - Mode mode, - size_t size, - const UnguessableToken& guid) - : handle_(std::move(handle)), mode_(mode), size_(size), guid_(guid) {} - -} // namespace subtle -} // namespace base
diff --git a/base/memory/platform_shared_memory_region_posix.cc b/base/memory/platform_shared_memory_region_posix.cc deleted file mode 100644 index 422cec5..0000000 --- a/base/memory/platform_shared_memory_region_posix.cc +++ /dev/null
@@ -1,291 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/platform_shared_memory_region.h" - -#include <fcntl.h> -#include <sys/mman.h> -#include <sys/stat.h> - -#include "base/files/file_util.h" -#include "base/numerics/checked_math.h" -#include "base/threading/thread_restrictions.h" -#include "build_config.h" - -namespace base { -namespace subtle { - -namespace { - -struct ScopedPathUnlinkerTraits { - static const FilePath* InvalidValue() { return nullptr; } - - static void Free(const FilePath* path) { - if (unlink(path->value().c_str())) - PLOG(WARNING) << "unlink"; - } -}; - -// Unlinks the FilePath when the object is destroyed. -using ScopedPathUnlinker = - ScopedGeneric<const FilePath*, ScopedPathUnlinkerTraits>; - -bool CheckFDAccessMode(int fd, int expected_mode) { - int fd_status = fcntl(fd, F_GETFL); - if (fd_status == -1) { - DPLOG(ERROR) << "fcntl(" << fd << ", F_GETFL) failed"; - return false; - } - - int mode = fd_status & O_ACCMODE; - if (mode != expected_mode) { - DLOG(ERROR) << "Descriptor access mode (" << mode - << ") differs from expected (" << expected_mode << ")"; - return false; - } - - return true; -} - -} // namespace - -ScopedFDPair::ScopedFDPair() = default; - -ScopedFDPair::ScopedFDPair(ScopedFDPair&&) = default; - -ScopedFDPair& ScopedFDPair::operator=(ScopedFDPair&&) = default; - -ScopedFDPair::~ScopedFDPair() = default; - -ScopedFDPair::ScopedFDPair(ScopedFD in_fd, ScopedFD in_readonly_fd) - : fd(std::move(in_fd)), readonly_fd(std::move(in_readonly_fd)) {} - -FDPair ScopedFDPair::get() const { - return {fd.get(), readonly_fd.get()}; -} - -// static -PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Take( - ScopedFDPair handle, - Mode mode, - size_t size, - const UnguessableToken& guid) { - if (!handle.fd.is_valid()) - return {}; - - if (size == 0) - return {}; - - if (size > static_cast<size_t>(std::numeric_limits<int>::max())) - return {}; - - CHECK( - CheckPlatformHandlePermissionsCorrespondToMode(handle.get(), mode, size)); - - switch (mode) { - case Mode::kReadOnly: - case Mode::kUnsafe: - if (handle.readonly_fd.is_valid()) { - handle.readonly_fd.reset(); - DLOG(WARNING) << "Readonly handle shouldn't be valid for a " - "non-writable memory region; closing"; - } - break; - case Mode::kWritable: - if (!handle.readonly_fd.is_valid()) { - DLOG(ERROR) - << "Readonly handle must be valid for writable memory region"; - return {}; - } - break; - default: - DLOG(ERROR) << "Invalid permission mode: " << static_cast<int>(mode); - return {}; - } - - return PlatformSharedMemoryRegion(std::move(handle), mode, size, guid); -} - -FDPair PlatformSharedMemoryRegion::GetPlatformHandle() const { - return handle_.get(); -} - -bool PlatformSharedMemoryRegion::IsValid() const { - return handle_.fd.is_valid() && - (mode_ == Mode::kWritable ? handle_.readonly_fd.is_valid() : true); -} - -PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Duplicate() const { - if (!IsValid()) - return {}; - - CHECK_NE(mode_, Mode::kWritable) - << "Duplicating a writable shared memory region is prohibited"; - - ScopedFD duped_fd(HANDLE_EINTR(dup(handle_.fd.get()))); - if (!duped_fd.is_valid()) { - DPLOG(ERROR) << "dup(" << handle_.fd.get() << ") failed"; - return {}; - } - - return PlatformSharedMemoryRegion({std::move(duped_fd), ScopedFD()}, mode_, - size_, guid_); -} - -bool PlatformSharedMemoryRegion::ConvertToReadOnly() { - if (!IsValid()) - return false; - - CHECK_EQ(mode_, Mode::kWritable) - << "Only writable shared memory region can be converted to read-only"; - - handle_.fd.reset(handle_.readonly_fd.release()); - mode_ = Mode::kReadOnly; - return true; -} - -bool PlatformSharedMemoryRegion::MapAt(off_t offset, - size_t size, - void** memory, - size_t* mapped_size) const { - if (!IsValid()) - return false; - - size_t end_byte; - if (!CheckAdd(offset, size).AssignIfValid(&end_byte) || end_byte > size_) { - return false; - } - - bool write_allowed = mode_ != Mode::kReadOnly; - *memory = mmap(nullptr, size, PROT_READ | (write_allowed ? PROT_WRITE : 0), - MAP_SHARED, handle_.fd.get(), offset); - - bool mmap_succeeded = *memory && *memory != reinterpret_cast<void*>(-1); - if (!mmap_succeeded) { - DPLOG(ERROR) << "mmap " << handle_.fd.get() << " failed"; - return false; - } - - *mapped_size = size; - DCHECK_EQ(0U, - reinterpret_cast<uintptr_t>(*memory) & (kMapMinimumAlignment - 1)); - return true; -} - -// static -PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Create(Mode mode, - size_t size) { -#if defined(OS_NACL) - // Untrusted code can't create descriptors or handles. - return {}; -#else - if (size == 0) - return {}; - - if (size > static_cast<size_t>(std::numeric_limits<int>::max())) - return {}; - - CHECK_NE(mode, Mode::kReadOnly) << "Creating a region in read-only mode will " - "lead to this region being non-modifiable"; - - // This function theoretically can block on the disk, but realistically - // the temporary files we create will just go into the buffer cache - // and be deleted before they ever make it out to disk. - ThreadRestrictions::ScopedAllowIO allow_io; - - // We don't use shm_open() API in order to support the --disable-dev-shm-usage - // flag. - FilePath directory; - if (!GetShmemTempDir(false /* executable */, &directory)) - return {}; - - ScopedFD fd; - FilePath path; - fd.reset(CreateAndOpenFdForTemporaryFileInDir(directory, &path)); - - if (!fd.is_valid()) { - PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed"; - FilePath dir = path.DirName(); - if (access(dir.value().c_str(), W_OK | X_OK) < 0) { - PLOG(ERROR) << "Unable to access(W_OK|X_OK) " << dir.value(); - if (dir.value() == "/dev/shm") { - LOG(FATAL) << "This is frequently caused by incorrect permissions on " - << "/dev/shm. Try 'sudo chmod 1777 /dev/shm' to fix."; - } - } - return {}; - } - - // Deleting the file prevents anyone else from mapping it in (making it - // private), and prevents the need for cleanup (once the last fd is - // closed, it is truly freed). - ScopedPathUnlinker path_unlinker(&path); - - ScopedFD readonly_fd; - if (mode == Mode::kWritable) { - // Also open as readonly so that we can ConvertToReadOnly(). - readonly_fd.reset(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY))); - if (!readonly_fd.is_valid()) { - DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed"; - return {}; - } - } - - // Get current size. - struct stat stat = {}; - if (fstat(fd.get(), &stat) != 0) - return {}; - const size_t current_size = stat.st_size; - if (current_size != size) { - if (HANDLE_EINTR(ftruncate(fd.get(), size)) != 0) - return {}; - } - - if (readonly_fd.is_valid()) { - struct stat readonly_stat = {}; - if (fstat(readonly_fd.get(), &readonly_stat)) - NOTREACHED(); - - if (stat.st_dev != readonly_stat.st_dev || - stat.st_ino != readonly_stat.st_ino) { - LOG(ERROR) << "Writable and read-only inodes don't match; bailing"; - return {}; - } - } - - return PlatformSharedMemoryRegion({std::move(fd), std::move(readonly_fd)}, - mode, size, UnguessableToken::Create()); -#endif // !defined(OS_NACL) -} - -bool PlatformSharedMemoryRegion::CheckPlatformHandlePermissionsCorrespondToMode( - PlatformHandle handle, - Mode mode, - size_t size) { - if (!CheckFDAccessMode(handle.fd, - mode == Mode::kReadOnly ? O_RDONLY : O_RDWR)) { - return false; - } - - if (mode == Mode::kWritable) - return CheckFDAccessMode(handle.readonly_fd, O_RDONLY); - - // The second descriptor must be invalid in kReadOnly and kUnsafe modes. - if (handle.readonly_fd != -1) { - DLOG(ERROR) << "The second descriptor must be invalid"; - return false; - } - - return true; -} - -PlatformSharedMemoryRegion::PlatformSharedMemoryRegion( - ScopedFDPair handle, - Mode mode, - size_t size, - const UnguessableToken& guid) - : handle_(std::move(handle)), mode_(mode), size_(size), guid_(guid) {} - -} // namespace subtle -} // namespace base
diff --git a/base/memory/platform_shared_memory_region_win.cc b/base/memory/platform_shared_memory_region_win.cc deleted file mode 100644 index b6608da..0000000 --- a/base/memory/platform_shared_memory_region_win.cc +++ /dev/null
@@ -1,345 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/platform_shared_memory_region.h" - -#include <aclapi.h> -#include <stddef.h> -#include <stdint.h> - -#include "base/allocator/partition_allocator/page_allocator.h" -#include "base/bits.h" -#include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros.h" -#include "base/numerics/checked_math.h" -#include "base/process/process_handle.h" -#include "base/rand_util.h" -#include "base/strings/stringprintf.h" - -namespace base { -namespace subtle { - -namespace { - -// Errors that can occur during Shared Memory construction. -// These match tools/metrics/histograms/histograms.xml. -// This enum is append-only. -enum CreateError { - SUCCESS = 0, - SIZE_ZERO = 1, - SIZE_TOO_LARGE = 2, - INITIALIZE_ACL_FAILURE = 3, - INITIALIZE_SECURITY_DESC_FAILURE = 4, - SET_SECURITY_DESC_FAILURE = 5, - CREATE_FILE_MAPPING_FAILURE = 6, - REDUCE_PERMISSIONS_FAILURE = 7, - ALREADY_EXISTS = 8, - CREATE_ERROR_LAST = ALREADY_EXISTS -}; - -// Emits UMA metrics about encountered errors. Pass zero (0) for |winerror| -// if there is no associated Windows error. -void LogError(CreateError error, DWORD winerror) { - UMA_HISTOGRAM_ENUMERATION("SharedMemory.CreateError", error, - CREATE_ERROR_LAST + 1); - static_assert(ERROR_SUCCESS == 0, "Windows error code changed!"); - if (winerror != ERROR_SUCCESS) - UmaHistogramSparse("SharedMemory.CreateWinError", winerror); -} - -typedef enum _SECTION_INFORMATION_CLASS { - SectionBasicInformation, -} SECTION_INFORMATION_CLASS; - -typedef struct _SECTION_BASIC_INFORMATION { - PVOID BaseAddress; - ULONG Attributes; - LARGE_INTEGER Size; -} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION; - -typedef ULONG(__stdcall* NtQuerySectionType)( - HANDLE SectionHandle, - SECTION_INFORMATION_CLASS SectionInformationClass, - PVOID SectionInformation, - ULONG SectionInformationLength, - PULONG ResultLength); - -// Returns the length of the memory section starting at the supplied address. -size_t GetMemorySectionSize(void* address) { - MEMORY_BASIC_INFORMATION memory_info; - if (!::VirtualQuery(address, &memory_info, sizeof(memory_info))) - return 0; - return memory_info.RegionSize - - (static_cast<char*>(address) - - static_cast<char*>(memory_info.AllocationBase)); -} - -// Checks if the section object is safe to map. At the moment this just means -// it's not an image section. -bool IsSectionSafeToMap(HANDLE handle) { - static NtQuerySectionType nt_query_section_func = - reinterpret_cast<NtQuerySectionType>( - ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), "NtQuerySection")); - DCHECK(nt_query_section_func); - - // The handle must have SECTION_QUERY access for this to succeed. - SECTION_BASIC_INFORMATION basic_information = {}; - ULONG status = - nt_query_section_func(handle, SectionBasicInformation, &basic_information, - sizeof(basic_information), nullptr); - if (status) - return false; - return (basic_information.Attributes & SEC_IMAGE) != SEC_IMAGE; -} - -// Returns a HANDLE on success and |nullptr| on failure. -// This function is similar to CreateFileMapping, but removes the permissions -// WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE. -// -// A newly created file mapping has two sets of permissions. It has access -// control permissions (WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE) and -// file permissions (FILE_MAP_READ, FILE_MAP_WRITE, etc.). The Chrome sandbox -// prevents HANDLEs with the WRITE_DAC permission from being duplicated into -// unprivileged processes. -// -// In order to remove the access control permissions, after being created the -// handle is duplicated with only the file access permissions. -HANDLE CreateFileMappingWithReducedPermissions(SECURITY_ATTRIBUTES* sa, - size_t rounded_size, - LPCWSTR name) { - HANDLE h = CreateFileMapping(INVALID_HANDLE_VALUE, sa, PAGE_READWRITE, 0, - static_cast<DWORD>(rounded_size), name); - if (!h) { - LogError(CREATE_FILE_MAPPING_FAILURE, GetLastError()); - return nullptr; - } - - HANDLE h2; - ProcessHandle process = GetCurrentProcess(); - BOOL success = ::DuplicateHandle( - process, h, process, &h2, FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY, - FALSE, 0); - BOOL rv = ::CloseHandle(h); - DCHECK(rv); - - if (!success) { - LogError(REDUCE_PERMISSIONS_FAILURE, GetLastError()); - return nullptr; - } - - return h2; -} - -} // namespace - -// static -PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Take( - win::ScopedHandle handle, - Mode mode, - size_t size, - const UnguessableToken& guid) { - if (!handle.IsValid()) - return {}; - - if (size == 0) - return {}; - - if (size > static_cast<size_t>(std::numeric_limits<int>::max())) - return {}; - - if (!IsSectionSafeToMap(handle.Get())) - return {}; - - CHECK( - CheckPlatformHandlePermissionsCorrespondToMode(handle.Get(), mode, size)); - - return PlatformSharedMemoryRegion(std::move(handle), mode, size, guid); -} - -HANDLE PlatformSharedMemoryRegion::GetPlatformHandle() const { - return handle_.Get(); -} - -bool PlatformSharedMemoryRegion::IsValid() const { - return handle_.IsValid(); -} - -PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Duplicate() const { - if (!IsValid()) - return {}; - - CHECK_NE(mode_, Mode::kWritable) - << "Duplicating a writable shared memory region is prohibited"; - - HANDLE duped_handle; - ProcessHandle process = GetCurrentProcess(); - BOOL success = - ::DuplicateHandle(process, handle_.Get(), process, &duped_handle, 0, - FALSE, DUPLICATE_SAME_ACCESS); - if (!success) - return {}; - - return PlatformSharedMemoryRegion(win::ScopedHandle(duped_handle), mode_, - size_, guid_); -} - -bool PlatformSharedMemoryRegion::ConvertToReadOnly() { - if (!IsValid()) - return false; - - CHECK_EQ(mode_, Mode::kWritable) - << "Only writable shared memory region can be converted to read-only"; - - win::ScopedHandle handle_copy(handle_.Take()); - - HANDLE duped_handle; - ProcessHandle process = GetCurrentProcess(); - BOOL success = - ::DuplicateHandle(process, handle_copy.Get(), process, &duped_handle, - FILE_MAP_READ | SECTION_QUERY, FALSE, 0); - if (!success) - return false; - - handle_.Set(duped_handle); - mode_ = Mode::kReadOnly; - return true; -} - -bool PlatformSharedMemoryRegion::MapAt(off_t offset, - size_t size, - void** memory, - size_t* mapped_size) const { - if (!IsValid()) - return false; - - size_t end_byte; - if (!CheckAdd(offset, size).AssignIfValid(&end_byte) || end_byte > size_) { - return false; - } - - bool write_allowed = mode_ != Mode::kReadOnly; - // Try to map the shared memory. On the first failure, release any reserved - // address space for a single entry. - for (int i = 0; i < 2; ++i) { - *memory = MapViewOfFile( - handle_.Get(), FILE_MAP_READ | (write_allowed ? FILE_MAP_WRITE : 0), - static_cast<uint64_t>(offset) >> 32, static_cast<DWORD>(offset), size); - if (*memory) - break; - ReleaseReservation(); - } - if (!*memory) { - DPLOG(ERROR) << "Failed executing MapViewOfFile"; - return false; - } - - *mapped_size = GetMemorySectionSize(*memory); - DCHECK_EQ(0U, - reinterpret_cast<uintptr_t>(*memory) & (kMapMinimumAlignment - 1)); - return true; -} - -// static -PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Create(Mode mode, - size_t size) { - // TODO(crbug.com/210609): NaCl forces us to round up 64k here, wasting 32k - // per mapping on average. - static const size_t kSectionSize = 65536; - if (size == 0) { - LogError(SIZE_ZERO, 0); - return {}; - } - - size_t rounded_size = bits::Align(size, kSectionSize); - if (rounded_size > static_cast<size_t>(std::numeric_limits<int>::max())) { - LogError(SIZE_TOO_LARGE, 0); - return {}; - } - - CHECK_NE(mode, Mode::kReadOnly) << "Creating a region in read-only mode will " - "lead to this region being non-modifiable"; - - // Add an empty DACL to enforce anonymous read-only sections. - ACL dacl; - SECURITY_DESCRIPTOR sd; - if (!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION)) { - LogError(INITIALIZE_ACL_FAILURE, GetLastError()); - return {}; - } - if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { - LogError(INITIALIZE_SECURITY_DESC_FAILURE, GetLastError()); - return {}; - } - if (!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE)) { - LogError(SET_SECURITY_DESC_FAILURE, GetLastError()); - return {}; - } - - // Windows ignores DACLs on unnamed shared section. Generate a random name in - // order to be able to enforce read-only. - uint64_t rand_values[4]; - RandBytes(&rand_values, sizeof(rand_values)); - string16 name = - StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", rand_values[0], - rand_values[1], rand_values[2], rand_values[3]); - - SECURITY_ATTRIBUTES sa = {sizeof(sa), &sd, FALSE}; - // Ask for the file mapping with reduced permisions to avoid passing the - // access control permissions granted by default into unpriviledged process. - HANDLE h = - CreateFileMappingWithReducedPermissions(&sa, rounded_size, name.c_str()); - if (h == nullptr) { - // The error is logged within CreateFileMappingWithReducedPermissions(). - return {}; - } - - win::ScopedHandle scoped_h(h); - // Check if the shared memory pre-exists. - if (GetLastError() == ERROR_ALREADY_EXISTS) { - LogError(ALREADY_EXISTS, ERROR_ALREADY_EXISTS); - return {}; - } - - return PlatformSharedMemoryRegion(std::move(scoped_h), mode, size, - UnguessableToken::Create()); -} - -// static -bool PlatformSharedMemoryRegion::CheckPlatformHandlePermissionsCorrespondToMode( - PlatformHandle handle, - Mode mode, - size_t size) { - // Call ::DuplicateHandle() with FILE_MAP_WRITE as a desired access to check - // if the |handle| has a write access. - ProcessHandle process = GetCurrentProcess(); - HANDLE duped_handle; - BOOL success = ::DuplicateHandle(process, handle, process, &duped_handle, - FILE_MAP_WRITE, FALSE, 0); - if (success) { - BOOL rv = ::CloseHandle(duped_handle); - DCHECK(rv); - } - - bool is_read_only = !success; - bool expected_read_only = mode == Mode::kReadOnly; - - if (is_read_only != expected_read_only) { - DLOG(ERROR) << "File mapping handle has wrong access rights: it is" - << (is_read_only ? " " : " not ") << "read-only but it should" - << (expected_read_only ? " " : " not ") << "be"; - return false; - } - - return true; -} - -PlatformSharedMemoryRegion::PlatformSharedMemoryRegion( - win::ScopedHandle handle, - Mode mode, - size_t size, - const UnguessableToken& guid) - : handle_(std::move(handle)), mode_(mode), size_(size), guid_(guid) {} - -} // namespace subtle -} // namespace base
diff --git a/base/memory/protected_memory.cc b/base/memory/protected_memory.cc deleted file mode 100644 index 157a677..0000000 --- a/base/memory/protected_memory.cc +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/protected_memory.h" -#include "base/synchronization/lock.h" - -namespace base { - -#if !defined(COMPONENT_BUILD) -PROTECTED_MEMORY_SECTION int AutoWritableMemory::writers = 0; -#endif // !defined(COMPONENT_BUILD) - -base::LazyInstance<Lock>::Leaky AutoWritableMemory::writers_lock = - LAZY_INSTANCE_INITIALIZER; - -} // namespace base
diff --git a/base/memory/protected_memory.h b/base/memory/protected_memory.h deleted file mode 100644 index 9f372ca..0000000 --- a/base/memory/protected_memory.h +++ /dev/null
@@ -1,261 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Protected memory is memory holding security-sensitive data intended to be -// left read-only for the majority of its lifetime to avoid being overwritten -// by attackers. ProtectedMemory is a simple wrapper around platform-specific -// APIs to set memory read-write and read-only when required. Protected memory -// should be set read-write for the minimum amount of time required. - -// Normally mutable variables are held in read-write memory and constant data -// is held in read-only memory to ensure it is not accidentally overwritten. -// In some cases we want to hold mutable variables in read-only memory, except -// when they are being written to, to ensure that they are not tampered with. -// -// ProtectedMemory is a container class intended to hold a single variable in -// read-only memory, except when explicitly set read-write. The variable can be -// set read-write by creating a scoped AutoWritableMemory object by calling -// AutoWritableMemory::Create(), the memory stays writable until the returned -// object goes out of scope and is destructed. The wrapped variable can be -// accessed using operator* and operator->. -// -// Instances of ProtectedMemory must be declared in the PROTECTED_MEMORY_SECTION -// and as global variables. Because protected memory variables are globals, the -// the same rules apply disallowing non-trivial constructors and destructors. -// Global definitions are required to avoid the linker placing statics in -// inlinable functions into a comdat section and setting the protected memory -// section read-write when they are merged. -// -// EXAMPLE: -// -// struct Items { void* item1; }; -// static PROTECTED_MEMORY_SECTION base::ProtectedMemory<Items> items; -// void InitializeItems() { -// // Explicitly set items read-write before writing to it. -// auto writer = base::AutoWritableMemory::Create(items); -// items->item1 = /* ... */; -// assert(items->item1 != nullptr); -// // items is set back to read-only on the destruction of writer -// } -// -// using FnPtr = void (*)(void); -// PROTECTED_MEMORY_SECTION base::ProtectedMemory<FnPtr> fnPtr; -// FnPtr ResolveFnPtr(void) { -// // The Initializer nested class is a helper class for creating a static -// // initializer for a ProtectedMemory variable. It implicitly sets the -// // variable read-write during initialization. -// static base::ProtectedMemory<FnPtr>::Initializer I(&fnPtr, -// reinterpret_cast<FnPtr>(dlsym(/* ... */))); -// return *fnPtr; -// } - -#ifndef BASE_MEMORY_PROTECTED_MEMORY_H_ -#define BASE_MEMORY_PROTECTED_MEMORY_H_ - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/synchronization/lock.h" -#include "build_config.h" - -#define PROTECTED_MEMORY_ENABLED 1 - -#if defined(OS_MACOSX) && !defined(OS_IOS) -// The segment the section is in is defined read-only with a linker flag in -// build/config/mac/BUILD.gn -#define PROTECTED_MEMORY_SECTION \ - __attribute__((section("PROTECTED_MEMORY, protected_memory"))) -extern char __start_protected_memory __asm( - "section$start$PROTECTED_MEMORY$protected_memory"); -extern char __stop_protected_memory __asm( - "section$end$PROTECTED_MEMORY$protected_memory"); - -#elif defined(OS_WIN) -// Define a read-write prot section. The $a, $mem, and $z 'sub-sections' are -// merged alphabetically so $a and $z are used to define the start and end of -// the protected memory section, and $mem holds protected variables. -// (Note: Sections in Portable Executables are equivalent to segments in other -// executable formats, so this section is mapped into its own pages.) -#pragma section("prot$a", read, write) -#pragma section("prot$mem", read, write) -#pragma section("prot$z", read, write) - -// We want the protected memory section to be read-only, not read-write so we -// instruct the linker to set the section read-only at link time. We do this -// at link time instead of compile time, because defining the prot section -// read-only would cause mis-compiles due to optimizations assuming that the -// section contents are constant. -#pragma comment(linker, "/SECTION:prot,R") - -__declspec(allocate("prot$a")) __declspec(selectany) -char __start_protected_memory; -__declspec(allocate("prot$z")) __declspec(selectany) -char __stop_protected_memory; - -#define PROTECTED_MEMORY_SECTION __declspec(allocate("prot$mem")) - -#else -#undef PROTECTED_MEMORY_ENABLED -#define PROTECTED_MEMORY_ENABLED 0 -#define PROTECTED_MEMORY_SECTION -#endif - -namespace base { - -template <typename T> -class ProtectedMemory { - public: - ProtectedMemory() = default; - - // Expose direct access to the encapsulated variable - T& operator*() { return data; } - const T& operator*() const { return data; } - T* operator->() { return &data; } - const T* operator->() const { return &data; } - - // Helper class for creating simple ProtectedMemory static initializers. - class Initializer { - public: - // Defined out-of-line below to break circular definition dependency between - // ProtectedMemory and AutoWritableMemory. - Initializer(ProtectedMemory<T>* PM, const T& Init); - - DISALLOW_IMPLICIT_CONSTRUCTORS(Initializer); - }; - - private: - T data; - - DISALLOW_COPY_AND_ASSIGN(ProtectedMemory); -}; - -// DCHECK that the byte at |ptr| is read-only. -BASE_EXPORT void AssertMemoryIsReadOnly(const void* ptr); - -// Abstract out platform-specific methods to get the beginning and end of the -// PROTECTED_MEMORY_SECTION. ProtectedMemoryEnd returns a pointer to the byte -// past the end of the PROTECTED_MEMORY_SECTION. -#if PROTECTED_MEMORY_ENABLED -constexpr void* ProtectedMemoryStart = &__start_protected_memory; -constexpr void* ProtectedMemoryEnd = &__stop_protected_memory; -#endif - -#if defined(COMPONENT_BUILD) -namespace internal { - -// For component builds we want to define a separate global writers variable -// (explained below) in every DSO that includes this header. To do that we use -// this template to define a global without duplicate symbol errors. -template <typename T> -struct DsoSpecific { - static T value; -}; -template <typename T> -T DsoSpecific<T>::value = 0; - -} // namespace internal -#endif // defined(COMPONENT_BUILD) - -// A class that sets a given ProtectedMemory variable writable while the -// AutoWritableMemory is in scope. This class implements the logic for setting -// the protected memory region read-only/read-write in a thread-safe manner. -class AutoWritableMemory { - private: - // 'writers' is a global holding the number of ProtectedMemory instances set - // writable, used to avoid races setting protected memory readable/writable. - // When this reaches zero the protected memory region is set read only. - // Access is controlled by writers_lock. -#if defined(COMPONENT_BUILD) - // For component builds writers is a reference to an int defined separately in - // every DSO. - static constexpr int& writers = internal::DsoSpecific<int>::value; -#else - // Otherwise, we declare writers in the protected memory section to avoid the - // scenario where an attacker could overwrite it with a large value and invoke - // code that constructs and destructs an AutoWritableMemory. After such a call - // protected memory would still be set writable because writers > 0. - static int writers; -#endif // defined(COMPONENT_BUILD) - - // Synchronizes access to the writers variable and the simultaneous actions - // that need to happen alongside writers changes, e.g. setting the protected - // memory region readable when writers is decremented to 0. - static BASE_EXPORT base::LazyInstance<Lock>::Leaky writers_lock; - - // Abstract out platform-specific memory APIs. |end| points to the byte past - // the end of the region of memory having its memory protections changed. - BASE_EXPORT bool SetMemoryReadWrite(void* start, void* end); - BASE_EXPORT bool SetMemoryReadOnly(void* start, void* end); - - // If this is the first writer (e.g. writers == 0) set the writers variable - // read-write. Next, increment writers and set the requested memory writable. - AutoWritableMemory(void* ptr, void* ptr_end) { -#if PROTECTED_MEMORY_ENABLED - DCHECK(ptr >= ProtectedMemoryStart && ptr_end <= ProtectedMemoryEnd); - - { - base::AutoLock auto_lock(writers_lock.Get()); - if (writers == 0) { - AssertMemoryIsReadOnly(ptr); -#if !defined(COMPONENT_BUILD) - AssertMemoryIsReadOnly(&writers); - CHECK(SetMemoryReadWrite(&writers, &writers + 1)); -#endif // !defined(COMPONENT_BUILD) - } - - writers++; - } - - CHECK(SetMemoryReadWrite(ptr, ptr_end)); -#endif // PROTECTED_MEMORY_ENABLED - } - - public: - // Wrap the private constructor to create an easy-to-use interface to - // construct AutoWritableMemory objects. - template <typename T> - static AutoWritableMemory Create(ProtectedMemory<T>& PM) { - T* ptr = &*PM; - return AutoWritableMemory(ptr, ptr + 1); - } - - // Move constructor just increments writers - AutoWritableMemory(AutoWritableMemory&& original) { -#if PROTECTED_MEMORY_ENABLED - base::AutoLock auto_lock(writers_lock.Get()); - CHECK_GT(writers, 0); - writers++; -#endif // PROTECTED_MEMORY_ENABLED - } - - // On destruction decrement writers, and if no other writers exist, set the - // entire protected memory region read-only. - ~AutoWritableMemory() { -#if PROTECTED_MEMORY_ENABLED - base::AutoLock auto_lock(writers_lock.Get()); - CHECK_GT(writers, 0); - writers--; - - if (writers == 0) { - CHECK(SetMemoryReadOnly(ProtectedMemoryStart, ProtectedMemoryEnd)); -#if !defined(COMPONENT_BUILD) - AssertMemoryIsReadOnly(&writers); -#endif // !defined(COMPONENT_BUILD) - } -#endif // PROTECTED_MEMORY_ENABLED - } - - DISALLOW_IMPLICIT_CONSTRUCTORS(AutoWritableMemory); -}; - -template <typename T> -ProtectedMemory<T>::Initializer::Initializer(ProtectedMemory<T>* PM, - const T& Init) { - AutoWritableMemory writer = AutoWritableMemory::Create(*PM); - **PM = Init; -} - -} // namespace base - -#endif // BASE_MEMORY_PROTECTED_MEMORY_H_
diff --git a/base/memory/protected_memory_cfi.h b/base/memory/protected_memory_cfi.h deleted file mode 100644 index f5b0121..0000000 --- a/base/memory/protected_memory_cfi.h +++ /dev/null
@@ -1,81 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Helper routines to call function pointers stored in protected memory with -// Control Flow Integrity indirect call checking disabled. Some indirect calls, -// e.g. dynamically resolved symbols in another DSO, can not be accounted for by -// CFI-icall. These routines allow those symbols to be called without CFI-icall -// checking safely by ensuring that they are placed in protected memory. - -#ifndef BASE_MEMORY_PROTECTED_MEMORY_CFI_H_ -#define BASE_MEMORY_PROTECTED_MEMORY_CFI_H_ - -#include <utility> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/memory/protected_memory.h" -#include "build_config.h" - -namespace base { -namespace internal { - -// This class is used to exempt calls to function pointers stored in -// ProtectedMemory from cfi-icall checking. It's not secure to use directly, it -// should only be used by the UnsanitizedCfiCall() functions below. Given an -// UnsanitizedCfiCall object, you can use operator() to call the encapsulated -// function pointer without cfi-icall checking. -template <typename FunctionType> -class UnsanitizedCfiCall { - public: - explicit UnsanitizedCfiCall(FunctionType function) : function_(function) {} - UnsanitizedCfiCall(UnsanitizedCfiCall&&) = default; - - template <typename... Args> - NO_SANITIZE("cfi-icall") - auto operator()(Args&&... args) { - return function_(std::forward<Args>(args)...); - } - - private: - FunctionType function_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(UnsanitizedCfiCall); -}; - -} // namespace internal - -// These functions can be used to call function pointers in ProtectedMemory -// without cfi-icall checking. They are intended to be used to create an -// UnsanitizedCfiCall object and immediately call it. UnsanitizedCfiCall objects -// should not initialized directly or stored because they hold a function -// pointer that will be called without CFI-icall checking in mutable memory. The -// functions can be used as shown below: - -// ProtectedMemory<void (*)(int)> p; -// UnsanitizedCfiCall(p)(5); /* In place of (*p)(5); */ - -template <typename T> -auto UnsanitizedCfiCall(const ProtectedMemory<T>& PM) { -#if PROTECTED_MEMORY_ENABLED - DCHECK(&PM >= ProtectedMemoryStart && &PM < ProtectedMemoryEnd); -#endif // PROTECTED_MEMORY_ENABLED - return internal::UnsanitizedCfiCall<T>(*PM); -} - -// struct S { void (*fp)(int); } s; -// ProtectedMemory<S> p; -// UnsanitizedCfiCall(p, &S::fp)(5); /* In place of p->fp(5); */ - -template <typename T, typename Member> -auto UnsanitizedCfiCall(const ProtectedMemory<T>& PM, Member member) { -#if PROTECTED_MEMORY_ENABLED - DCHECK(&PM >= ProtectedMemoryStart && &PM < ProtectedMemoryEnd); -#endif // PROTECTED_MEMORY_ENABLED - return internal::UnsanitizedCfiCall<decltype(*PM.*member)>(*PM.*member); -} - -} // namespace base - -#endif // BASE_MEMORY_PROTECTED_MEMORY_CFI_H_
diff --git a/base/memory/protected_memory_posix.cc b/base/memory/protected_memory_posix.cc deleted file mode 100644 index 1839e3e..0000000 --- a/base/memory/protected_memory_posix.cc +++ /dev/null
@@ -1,79 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/protected_memory.h" - -#include <stdint.h> -#include <sys/mman.h> -#include <unistd.h> - -#if defined(OS_LINUX) -#include <sys/resource.h> -#endif // defined(OS_LINUX) - -#if defined(OS_MACOSX) && !defined(OS_IOS) -#include <mach/mach.h> -#include <mach/mach_vm.h> -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - -#include "base/posix/eintr_wrapper.h" -#include "base/process/process_metrics.h" -#include "base/synchronization/lock.h" -#include "build_config.h" - -namespace base { - -namespace { - -bool SetMemory(void* start, void* end, int prot) { - DCHECK(end > start); - const uintptr_t page_mask = ~(base::GetPageSize() - 1); - const uintptr_t page_start = reinterpret_cast<uintptr_t>(start) & page_mask; - return mprotect(reinterpret_cast<void*>(page_start), - reinterpret_cast<uintptr_t>(end) - page_start, prot) == 0; -} - -} // namespace - -bool AutoWritableMemory::SetMemoryReadWrite(void* start, void* end) { - return SetMemory(start, end, PROT_READ | PROT_WRITE); -} - -bool AutoWritableMemory::SetMemoryReadOnly(void* start, void* end) { - return SetMemory(start, end, PROT_READ); -} - -#if defined(OS_LINUX) -void AssertMemoryIsReadOnly(const void* ptr) { -#if DCHECK_IS_ON() - const uintptr_t page_mask = ~(base::GetPageSize() - 1); - const uintptr_t page_start = reinterpret_cast<uintptr_t>(ptr) & page_mask; - - // Note: We've casted away const here, which should not be meaningful since - // if the memory is written to we will abort immediately. - int result = - getrlimit(RLIMIT_NPROC, reinterpret_cast<struct rlimit*>(page_start)); - DCHECK_EQ(result, -1); - DCHECK_EQ(errno, EFAULT); -#endif // DCHECK_IS_ON() -} -#elif defined(OS_MACOSX) && !defined(OS_IOS) -void AssertMemoryIsReadOnly(const void* ptr) { -#if DCHECK_IS_ON() - mach_port_t object_name; - vm_region_basic_info_64 region_info; - mach_vm_size_t size = 1; - mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64; - - kern_return_t kr = mach_vm_region( - mach_task_self(), reinterpret_cast<mach_vm_address_t*>(&ptr), &size, - VM_REGION_BASIC_INFO_64, reinterpret_cast<vm_region_info_t>(®ion_info), - &count, &object_name); - DCHECK_EQ(kr, KERN_SUCCESS); - DCHECK_EQ(region_info.protection, VM_PROT_READ); -#endif // DCHECK_IS_ON() -} -#endif // defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS)) - -} // namespace base
diff --git a/base/memory/protected_memory_win.cc b/base/memory/protected_memory_win.cc deleted file mode 100644 index 43ad8ba..0000000 --- a/base/memory/protected_memory_win.cc +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/protected_memory.h" - -#include <windows.h> - -#include <stdint.h> - -#include "base/process/process_metrics.h" -#include "base/synchronization/lock.h" -#include "build_config.h" - -namespace base { - -namespace { - -bool SetMemory(void* start, void* end, DWORD prot) { - DCHECK(end > start); - const uintptr_t page_mask = ~(base::GetPageSize() - 1); - const uintptr_t page_start = reinterpret_cast<uintptr_t>(start) & page_mask; - DWORD old_prot; - return VirtualProtect(reinterpret_cast<void*>(page_start), - reinterpret_cast<uintptr_t>(end) - page_start, prot, - &old_prot) != 0; -} - -} // namespace - -bool AutoWritableMemory::SetMemoryReadWrite(void* start, void* end) { - return SetMemory(start, end, PAGE_READWRITE); -} - -bool AutoWritableMemory::SetMemoryReadOnly(void* start, void* end) { - return SetMemory(start, end, PAGE_READONLY); -} - -void AssertMemoryIsReadOnly(const void* ptr) { -#if DCHECK_IS_ON() - const uintptr_t page_mask = ~(base::GetPageSize() - 1); - const uintptr_t page_start = reinterpret_cast<uintptr_t>(ptr) & page_mask; - - MEMORY_BASIC_INFORMATION info; - SIZE_T result = - VirtualQuery(reinterpret_cast<LPCVOID>(page_start), &info, sizeof(info)); - DCHECK_GT(result, 0U); - DCHECK(info.Protect == PAGE_READONLY); -#endif // DCHECK_IS_ON() -} - -} // namespace base
diff --git a/base/memory/read_only_shared_memory_region.cc b/base/memory/read_only_shared_memory_region.cc deleted file mode 100644 index 0a5f900..0000000 --- a/base/memory/read_only_shared_memory_region.cc +++ /dev/null
@@ -1,97 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/read_only_shared_memory_region.h" - -#include <utility> - -#include "base/memory/shared_memory.h" -#include "build_config.h" - -namespace base { - -// static -MappedReadOnlyRegion ReadOnlySharedMemoryRegion::Create(size_t size) { - subtle::PlatformSharedMemoryRegion handle = - subtle::PlatformSharedMemoryRegion::CreateWritable(size); - if (!handle.IsValid()) - return {}; - - void* memory_ptr = nullptr; - size_t mapped_size = 0; - if (!handle.MapAt(0, handle.GetSize(), &memory_ptr, &mapped_size)) - return {}; - - WritableSharedMemoryMapping mapping(memory_ptr, size, mapped_size, - handle.GetGUID()); -#if defined(OS_MACOSX) && !defined(OS_IOS) - handle.ConvertToReadOnly(memory_ptr); -#else - handle.ConvertToReadOnly(); -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - ReadOnlySharedMemoryRegion region(std::move(handle)); - - if (!region.IsValid() || !mapping.IsValid()) - return {}; - - return {std::move(region), std::move(mapping)}; -} - -// static -ReadOnlySharedMemoryRegion ReadOnlySharedMemoryRegion::Deserialize( - subtle::PlatformSharedMemoryRegion handle) { - return ReadOnlySharedMemoryRegion(std::move(handle)); -} - -// static -subtle::PlatformSharedMemoryRegion -ReadOnlySharedMemoryRegion::TakeHandleForSerialization( - ReadOnlySharedMemoryRegion region) { - return std::move(region.handle_); -} - -ReadOnlySharedMemoryRegion::ReadOnlySharedMemoryRegion() = default; -ReadOnlySharedMemoryRegion::ReadOnlySharedMemoryRegion( - ReadOnlySharedMemoryRegion&& region) = default; -ReadOnlySharedMemoryRegion& ReadOnlySharedMemoryRegion::operator=( - ReadOnlySharedMemoryRegion&& region) = default; -ReadOnlySharedMemoryRegion::~ReadOnlySharedMemoryRegion() = default; - -ReadOnlySharedMemoryRegion ReadOnlySharedMemoryRegion::Duplicate() const { - return ReadOnlySharedMemoryRegion(handle_.Duplicate()); -} - -ReadOnlySharedMemoryMapping ReadOnlySharedMemoryRegion::Map() const { - return MapAt(0, handle_.GetSize()); -} - -ReadOnlySharedMemoryMapping ReadOnlySharedMemoryRegion::MapAt( - off_t offset, - size_t size) const { - if (!IsValid()) - return {}; - - void* memory = nullptr; - size_t mapped_size = 0; - if (!handle_.MapAt(offset, size, &memory, &mapped_size)) - return {}; - - return ReadOnlySharedMemoryMapping(memory, size, mapped_size, - handle_.GetGUID()); -} - -bool ReadOnlySharedMemoryRegion::IsValid() const { - return handle_.IsValid(); -} - -ReadOnlySharedMemoryRegion::ReadOnlySharedMemoryRegion( - subtle::PlatformSharedMemoryRegion handle) - : handle_(std::move(handle)) { - if (handle_.IsValid()) { - CHECK_EQ(handle_.GetMode(), - subtle::PlatformSharedMemoryRegion::Mode::kReadOnly); - } -} - -} // namespace base
diff --git a/base/memory/read_only_shared_memory_region.h b/base/memory/read_only_shared_memory_region.h deleted file mode 100644 index 54e73ed..0000000 --- a/base/memory/read_only_shared_memory_region.h +++ /dev/null
@@ -1,116 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_READ_ONLY_SHARED_MEMORY_REGION_H_ -#define BASE_MEMORY_READ_ONLY_SHARED_MEMORY_REGION_H_ - -#include <utility> - -#include "base/macros.h" -#include "base/memory/platform_shared_memory_region.h" -#include "base/memory/shared_memory_mapping.h" - -namespace base { - -struct MappedReadOnlyRegion; - -// Scoped move-only handle to a region of platform shared memory. The instance -// owns the platform handle it wraps. Mappings created by this region are -// read-only. These mappings remain valid even after the region handle is moved -// or destroyed. -class BASE_EXPORT ReadOnlySharedMemoryRegion { - public: - using MappingType = ReadOnlySharedMemoryMapping; - // Creates a new ReadOnlySharedMemoryRegion instance of a given size along - // with the WritableSharedMemoryMapping which provides the only way to modify - // the content of the newly created region. The returned region and mapping - // are guaranteed to either be both valid or both invalid. Use - // |MappedReadOnlyRegion::IsValid()| as a shortcut for checking creation - // success. - // - // This means that the caller's process is the only process that can modify - // the region content. If you need to pass write access to another process, - // consider using WritableSharedMemoryRegion or UnsafeSharedMemoryRegion. - static MappedReadOnlyRegion Create(size_t size); - - // Returns a ReadOnlySharedMemoryRegion built from a platform-specific handle - // that was taken from another ReadOnlySharedMemoryRegion instance. Returns an - // invalid region iff the |handle| is invalid. CHECK-fails if the |handle| - // isn't read-only. - // This should be used only by the code passing handles across process - // boundaries. - static ReadOnlySharedMemoryRegion Deserialize( - subtle::PlatformSharedMemoryRegion handle); - - // Extracts a platform handle from the region. Ownership is transferred to the - // returned region object. - // This should be used only for sending the handle from the current process to - // another. - static subtle::PlatformSharedMemoryRegion TakeHandleForSerialization( - ReadOnlySharedMemoryRegion region); - - // Default constructor initializes an invalid instance. - ReadOnlySharedMemoryRegion(); - - // Move operations are allowed. - ReadOnlySharedMemoryRegion(ReadOnlySharedMemoryRegion&&); - ReadOnlySharedMemoryRegion& operator=(ReadOnlySharedMemoryRegion&&); - - // Destructor closes shared memory region if valid. - // All created mappings will remain valid. - ~ReadOnlySharedMemoryRegion(); - - // Duplicates the underlying platform handle and creates a new - // ReadOnlySharedMemoryRegion instance that owns this handle. Returns a valid - // ReadOnlySharedMemoryRegion on success, invalid otherwise. The current - // region instance remains valid in any case. - ReadOnlySharedMemoryRegion Duplicate() const; - - // Maps the shared memory region into the caller's address space with - // read-only access. The mapped address is guaranteed to have an alignment of - // at least |subtle::PlatformSharedMemoryRegion::kMapMinimumAlignment|. - // Returns a valid ReadOnlySharedMemoryMapping instance on success, invalid - // otherwise. - ReadOnlySharedMemoryMapping Map() const; - - // Same as above, but maps only |size| bytes of the shared memory region - // starting with the given |offset|. |offset| must be aligned to value of - // |SysInfo::VMAllocationGranularity()|. Returns an invalid mapping if - // requested bytes are out of the region limits. - ReadOnlySharedMemoryMapping MapAt(off_t offset, size_t size) const; - - // Whether the underlying platform handle is valid. - bool IsValid() const; - - // Returns the maximum mapping size that can be created from this region. - size_t GetSize() const { - DCHECK(IsValid()); - return handle_.GetSize(); - } - - private: - explicit ReadOnlySharedMemoryRegion( - subtle::PlatformSharedMemoryRegion handle); - - subtle::PlatformSharedMemoryRegion handle_; - - DISALLOW_COPY_AND_ASSIGN(ReadOnlySharedMemoryRegion); -}; - -// Helper struct for return value of ReadOnlySharedMemoryRegion::Create(). -struct MappedReadOnlyRegion { - ReadOnlySharedMemoryRegion region; - WritableSharedMemoryMapping mapping; - // Helper function to check return value of - // ReadOnlySharedMemoryRegion::Create(). |region| and |mapping| either both - // valid or invalid. - bool IsValid() { - DCHECK_EQ(region.IsValid(), mapping.IsValid()); - return region.IsValid() && mapping.IsValid(); - } -}; - -} // namespace base - -#endif // BASE_MEMORY_READ_ONLY_SHARED_MEMORY_REGION_H_
diff --git a/base/memory/ref_counted_delete_on_sequence.h b/base/memory/ref_counted_delete_on_sequence.h deleted file mode 100644 index dd30106..0000000 --- a/base/memory/ref_counted_delete_on_sequence.h +++ /dev/null
@@ -1,82 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_REF_COUNTED_DELETE_ON_SEQUENCE_H_ -#define BASE_MEMORY_REF_COUNTED_DELETE_ON_SEQUENCE_H_ - -#include <utility> - -#include "base/location.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/sequenced_task_runner.h" - -namespace base { - -// RefCountedDeleteOnSequence is similar to RefCountedThreadSafe, and ensures -// that the object will be deleted on a specified sequence. -// -// Sample usage: -// class Foo : public RefCountedDeleteOnSequence<Foo> { -// -// Foo(scoped_refptr<SequencedTaskRunner> task_runner) -// : RefCountedDeleteOnSequence<Foo>(std::move(task_runner)) {} -// ... -// private: -// friend class RefCountedDeleteOnSequence<Foo>; -// friend class DeleteHelper<Foo>; -// -// ~Foo(); -// }; -template <class T> -class RefCountedDeleteOnSequence : public subtle::RefCountedThreadSafeBase { - public: - static constexpr subtle::StartRefCountFromZeroTag kRefCountPreference = - subtle::kStartRefCountFromZeroTag; - - // A SequencedTaskRunner for the current sequence can be acquired by calling - // SequencedTaskRunnerHandle::Get(). - RefCountedDeleteOnSequence( - scoped_refptr<SequencedTaskRunner> owning_task_runner) - : subtle::RefCountedThreadSafeBase(T::kRefCountPreference), - owning_task_runner_(std::move(owning_task_runner)) { - DCHECK(owning_task_runner_); - } - - void AddRef() const { subtle::RefCountedThreadSafeBase::AddRef(); } - - void Release() const { - if (subtle::RefCountedThreadSafeBase::Release()) - DestructOnSequence(); - } - - protected: - friend class DeleteHelper<RefCountedDeleteOnSequence>; - ~RefCountedDeleteOnSequence() = default; - - SequencedTaskRunner* owning_task_runner() { - return owning_task_runner_.get(); - } - const SequencedTaskRunner* owning_task_runner() const { - return owning_task_runner_.get(); - } - - private: - void DestructOnSequence() const { - const T* t = static_cast<const T*>(this); - if (owning_task_runner_->RunsTasksInCurrentSequence()) - delete t; - else - owning_task_runner_->DeleteSoon(FROM_HERE, t); - } - - const scoped_refptr<SequencedTaskRunner> owning_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(RefCountedDeleteOnSequence); -}; - -} // namespace base - -#endif // BASE_MEMORY_REF_COUNTED_DELETE_ON_SEQUENCE_H_
diff --git a/base/memory/ref_counted_memory.cc b/base/memory/ref_counted_memory.cc deleted file mode 100644 index 23a5ffc..0000000 --- a/base/memory/ref_counted_memory.cc +++ /dev/null
@@ -1,132 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/ref_counted_memory.h" - -#include <utility> - -#include "base/logging.h" -#include "base/memory/read_only_shared_memory_region.h" - -namespace base { - -bool RefCountedMemory::Equals( - const scoped_refptr<RefCountedMemory>& other) const { - return other.get() && - size() == other->size() && - (memcmp(front(), other->front(), size()) == 0); -} - -RefCountedMemory::RefCountedMemory() = default; - -RefCountedMemory::~RefCountedMemory() = default; - -const unsigned char* RefCountedStaticMemory::front() const { - return data_; -} - -size_t RefCountedStaticMemory::size() const { - return length_; -} - -RefCountedStaticMemory::~RefCountedStaticMemory() = default; - -RefCountedBytes::RefCountedBytes() = default; - -RefCountedBytes::RefCountedBytes(const std::vector<unsigned char>& initializer) - : data_(initializer) { -} - -RefCountedBytes::RefCountedBytes(const unsigned char* p, size_t size) - : data_(p, p + size) {} - -RefCountedBytes::RefCountedBytes(size_t size) : data_(size, 0) {} - -scoped_refptr<RefCountedBytes> RefCountedBytes::TakeVector( - std::vector<unsigned char>* to_destroy) { - auto bytes = MakeRefCounted<RefCountedBytes>(); - bytes->data_.swap(*to_destroy); - return bytes; -} - -const unsigned char* RefCountedBytes::front() const { - // STL will assert if we do front() on an empty vector, but calling code - // expects a NULL. - return size() ? &data_.front() : nullptr; -} - -size_t RefCountedBytes::size() const { - return data_.size(); -} - -RefCountedBytes::~RefCountedBytes() = default; - -RefCountedString::RefCountedString() = default; - -RefCountedString::~RefCountedString() = default; - -// static -scoped_refptr<RefCountedString> RefCountedString::TakeString( - std::string* to_destroy) { - auto self = MakeRefCounted<RefCountedString>(); - to_destroy->swap(self->data_); - return self; -} - -const unsigned char* RefCountedString::front() const { - return data_.empty() ? nullptr - : reinterpret_cast<const unsigned char*>(data_.data()); -} - -size_t RefCountedString::size() const { - return data_.size(); -} - -RefCountedSharedMemory::RefCountedSharedMemory( - std::unique_ptr<SharedMemory> shm, - size_t size) - : shm_(std::move(shm)), size_(size) { - DCHECK(shm_); - DCHECK(shm_->memory()); - DCHECK_GT(size_, 0U); - DCHECK_LE(size_, shm_->mapped_size()); -} - -RefCountedSharedMemory::~RefCountedSharedMemory() = default; - -const unsigned char* RefCountedSharedMemory::front() const { - return static_cast<const unsigned char*>(shm_->memory()); -} - -size_t RefCountedSharedMemory::size() const { - return size_; -} - -RefCountedSharedMemoryMapping::RefCountedSharedMemoryMapping( - ReadOnlySharedMemoryMapping mapping) - : mapping_(std::move(mapping)), size_(mapping_.size()) { - DCHECK_GT(size_, 0U); -} - -RefCountedSharedMemoryMapping::~RefCountedSharedMemoryMapping() = default; - -const unsigned char* RefCountedSharedMemoryMapping::front() const { - return static_cast<const unsigned char*>(mapping_.memory()); -} - -size_t RefCountedSharedMemoryMapping::size() const { - return size_; -} - -// static -scoped_refptr<RefCountedSharedMemoryMapping> -RefCountedSharedMemoryMapping::CreateFromWholeRegion( - const ReadOnlySharedMemoryRegion& region) { - ReadOnlySharedMemoryMapping mapping = region.Map(); - if (!mapping.IsValid()) - return nullptr; - return MakeRefCounted<RefCountedSharedMemoryMapping>(std::move(mapping)); -} - -} // namespace base
diff --git a/base/memory/ref_counted_memory.h b/base/memory/ref_counted_memory.h deleted file mode 100644 index 92a7d7b..0000000 --- a/base/memory/ref_counted_memory.h +++ /dev/null
@@ -1,193 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_REF_COUNTED_MEMORY_H_ -#define BASE_MEMORY_REF_COUNTED_MEMORY_H_ - -#include <stddef.h> - -#include <memory> -#include <string> -#include <vector> - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/shared_memory.h" -#include "base/memory/shared_memory_mapping.h" - -namespace base { - -class ReadOnlySharedMemoryRegion; - -// A generic interface to memory. This object is reference counted because most -// of its subclasses own the data they carry, and this interface needs to -// support heterogeneous containers of these different types of memory. -class BASE_EXPORT RefCountedMemory - : public RefCountedThreadSafe<RefCountedMemory> { - public: - // Retrieves a pointer to the beginning of the data we point to. If the data - // is empty, this will return NULL. - virtual const unsigned char* front() const = 0; - - // Size of the memory pointed to. - virtual size_t size() const = 0; - - // Returns true if |other| is byte for byte equal. - bool Equals(const scoped_refptr<RefCountedMemory>& other) const; - - // Handy method to simplify calling front() with a reinterpret_cast. - template<typename T> const T* front_as() const { - return reinterpret_cast<const T*>(front()); - } - - protected: - friend class RefCountedThreadSafe<RefCountedMemory>; - RefCountedMemory(); - virtual ~RefCountedMemory(); -}; - -// An implementation of RefCountedMemory, where the ref counting does not -// matter. -class BASE_EXPORT RefCountedStaticMemory : public RefCountedMemory { - public: - RefCountedStaticMemory() : data_(nullptr), length_(0) {} - RefCountedStaticMemory(const void* data, size_t length) - : data_(static_cast<const unsigned char*>(length ? data : nullptr)), - length_(length) {} - - // RefCountedMemory: - const unsigned char* front() const override; - size_t size() const override; - - private: - ~RefCountedStaticMemory() override; - - const unsigned char* data_; - size_t length_; - - DISALLOW_COPY_AND_ASSIGN(RefCountedStaticMemory); -}; - -// An implementation of RefCountedMemory, where the data is stored in a STL -// vector. -class BASE_EXPORT RefCountedBytes : public RefCountedMemory { - public: - RefCountedBytes(); - - // Constructs a RefCountedBytes object by copying from |initializer|. - explicit RefCountedBytes(const std::vector<unsigned char>& initializer); - - // Constructs a RefCountedBytes object by copying |size| bytes from |p|. - RefCountedBytes(const unsigned char* p, size_t size); - - // Constructs a RefCountedBytes object by zero-initializing a new vector of - // |size| bytes. - explicit RefCountedBytes(size_t size); - - // Constructs a RefCountedBytes object by performing a swap. (To non - // destructively build a RefCountedBytes, use the constructor that takes a - // vector.) - static scoped_refptr<RefCountedBytes> TakeVector( - std::vector<unsigned char>* to_destroy); - - // RefCountedMemory: - const unsigned char* front() const override; - size_t size() const override; - - const std::vector<unsigned char>& data() const { return data_; } - std::vector<unsigned char>& data() { return data_; } - - // Non-const versions of front() and front_as() that are simply shorthand for - // data().data(). - unsigned char* front() { return data_.data(); } - template <typename T> - T* front_as() { - return reinterpret_cast<T*>(front()); - } - - private: - ~RefCountedBytes() override; - - std::vector<unsigned char> data_; - - DISALLOW_COPY_AND_ASSIGN(RefCountedBytes); -}; - -// An implementation of RefCountedMemory, where the bytes are stored in a STL -// string. Use this if your data naturally arrives in that format. -class BASE_EXPORT RefCountedString : public RefCountedMemory { - public: - RefCountedString(); - - // Constructs a RefCountedString object by performing a swap. (To non - // destructively build a RefCountedString, use the default constructor and - // copy into object->data()). - static scoped_refptr<RefCountedString> TakeString(std::string* to_destroy); - - // RefCountedMemory: - const unsigned char* front() const override; - size_t size() const override; - - const std::string& data() const { return data_; } - std::string& data() { return data_; } - - private: - ~RefCountedString() override; - - std::string data_; - - DISALLOW_COPY_AND_ASSIGN(RefCountedString); -}; - -// An implementation of RefCountedMemory, where the bytes are stored in -// SharedMemory. -class BASE_EXPORT RefCountedSharedMemory : public RefCountedMemory { - public: - // Constructs a RefCountedMemory object by taking ownership of an already - // mapped SharedMemory object. - RefCountedSharedMemory(std::unique_ptr<SharedMemory> shm, size_t size); - - // RefCountedMemory: - const unsigned char* front() const override; - size_t size() const override; - - private: - ~RefCountedSharedMemory() override; - - const std::unique_ptr<SharedMemory> shm_; - const size_t size_; - - DISALLOW_COPY_AND_ASSIGN(RefCountedSharedMemory); -}; - -// An implementation of RefCountedMemory, where the bytes are stored in -// ReadOnlySharedMemoryMapping. -class BASE_EXPORT RefCountedSharedMemoryMapping : public RefCountedMemory { - public: - // Constructs a RefCountedMemory object by taking ownership of an already - // mapped ReadOnlySharedMemoryMapping object. - explicit RefCountedSharedMemoryMapping(ReadOnlySharedMemoryMapping mapping); - - // Convenience method to map all of |region| and take ownership of the - // mapping. Returns an empty scoped_refptr if the map operation fails. - static scoped_refptr<RefCountedSharedMemoryMapping> CreateFromWholeRegion( - const ReadOnlySharedMemoryRegion& region); - - // RefCountedMemory: - const unsigned char* front() const override; - size_t size() const override; - - private: - ~RefCountedSharedMemoryMapping() override; - - const ReadOnlySharedMemoryMapping mapping_; - const size_t size_; - - DISALLOW_COPY_AND_ASSIGN(RefCountedSharedMemoryMapping); -}; - -} // namespace base - -#endif // BASE_MEMORY_REF_COUNTED_MEMORY_H_
diff --git a/base/memory/shared_memory.h b/base/memory/shared_memory.h deleted file mode 100644 index aa1f682..0000000 --- a/base/memory/shared_memory.h +++ /dev/null
@@ -1,254 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_SHARED_MEMORY_H_ -#define BASE_MEMORY_SHARED_MEMORY_H_ - -#include <stddef.h> - -#include <string> - -#include "base/base_export.h" -#include "base/hash.h" -#include "base/macros.h" -#include "base/memory/shared_memory_handle.h" -#include "base/process/process_handle.h" -#include "base/strings/string16.h" -#include "build_config.h" - -#if defined(OS_POSIX) || defined(OS_FUCHSIA) -#include <stdio.h> -#include <sys/types.h> -#include <semaphore.h> -#include "base/file_descriptor_posix.h" -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#endif - -#if defined(OS_WIN) -#include "base/win/scoped_handle.h" -#endif - -namespace base { - -class FilePath; - -// Options for creating a shared memory object. -struct BASE_EXPORT SharedMemoryCreateOptions { -#if defined(OS_MACOSX) && !defined(OS_IOS) - // The type of OS primitive that should back the SharedMemory object. - SharedMemoryHandle::Type type = SharedMemoryHandle::MACH; -#elif !defined(OS_FUCHSIA) - // DEPRECATED (crbug.com/345734): - // If NULL, the object is anonymous. This pointer is owned by the caller - // and must live through the call to Create(). - const std::string* name_deprecated = nullptr; - - // DEPRECATED (crbug.com/345734): - // If true, and the shared memory already exists, Create() will open the - // existing shared memory and ignore the size parameter. If false, - // shared memory must not exist. This flag is meaningless unless - // name_deprecated is non-NULL. - bool open_existing_deprecated = false; -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - - // Size of the shared memory object to be created. - // When opening an existing object, this has no effect. - size_t size = 0; - - // If true, mappings might need to be made executable later. - bool executable = false; - - // If true, the file can be shared read-only to a process. - bool share_read_only = false; -}; - -// Platform abstraction for shared memory. -// SharedMemory consumes a SharedMemoryHandle [potentially one that it created] -// to map a shared memory OS resource into the virtual address space of the -// current process. -class BASE_EXPORT SharedMemory { - public: - SharedMemory(); - -#if defined(OS_WIN) - // Similar to the default constructor, except that this allows for - // calling LockDeprecated() to acquire the named mutex before either Create or - // Open are called on Windows. - explicit SharedMemory(const string16& name); -#endif - - // Create a new SharedMemory object from an existing, open - // shared memory file. - // - // WARNING: This does not reduce the OS-level permissions on the handle; it - // only affects how the SharedMemory will be mmapped. Use - // GetReadOnlyHandle to drop permissions. TODO(jln,jyasskin): DCHECK - // that |read_only| matches the permissions of the handle. - SharedMemory(const SharedMemoryHandle& handle, bool read_only); - - // Closes any open files. - ~SharedMemory(); - - // Return true iff the given handle is valid (i.e. not the distingished - // invalid value; NULL for a HANDLE and -1 for a file descriptor) - static bool IsHandleValid(const SharedMemoryHandle& handle); - - // Closes a shared memory handle. - static void CloseHandle(const SharedMemoryHandle& handle); - - // Returns the maximum number of handles that can be open at once per process. - static size_t GetHandleLimit(); - - // Duplicates The underlying OS primitive. Returns an invalid handle on - // failure. The caller is responsible for destroying the duplicated OS - // primitive. - static SharedMemoryHandle DuplicateHandle(const SharedMemoryHandle& handle); - -#if defined(OS_POSIX) - // This method requires that the SharedMemoryHandle is backed by a POSIX fd. - static int GetFdFromSharedMemoryHandle(const SharedMemoryHandle& handle); -#endif - - // Creates a shared memory object as described by the options struct. - // Returns true on success and false on failure. - bool Create(const SharedMemoryCreateOptions& options); - - // Creates and maps an anonymous shared memory segment of size size. - // Returns true on success and false on failure. - bool CreateAndMapAnonymous(size_t size); - - // Creates an anonymous shared memory segment of size size. - // Returns true on success and false on failure. - bool CreateAnonymous(size_t size) { - SharedMemoryCreateOptions options; - options.size = size; - return Create(options); - } - -#if (!defined(OS_MACOSX) || defined(OS_IOS)) && !defined(OS_FUCHSIA) - // DEPRECATED (crbug.com/345734): - // Creates or opens a shared memory segment based on a name. - // If open_existing is true, and the shared memory already exists, - // opens the existing shared memory and ignores the size parameter. - // If open_existing is false, shared memory must not exist. - // size is the size of the block to be created. - // Returns true on success, false on failure. - bool CreateNamedDeprecated( - const std::string& name, bool open_existing, size_t size) { - SharedMemoryCreateOptions options; - options.name_deprecated = &name; - options.open_existing_deprecated = open_existing; - options.size = size; - return Create(options); - } - - // Deletes resources associated with a shared memory segment based on name. - // Not all platforms require this call. - bool Delete(const std::string& name); - - // Opens a shared memory segment based on a name. - // If read_only is true, opens for read-only access. - // Returns true on success, false on failure. - bool Open(const std::string& name, bool read_only); -#endif // !defined(OS_MACOSX) || defined(OS_IOS) - - // Maps the shared memory into the caller's address space. - // Returns true on success, false otherwise. The memory address - // is accessed via the memory() accessor. The mapped address is guaranteed to - // have an alignment of at least MAP_MINIMUM_ALIGNMENT. This method will fail - // if this object is currently mapped. - bool Map(size_t bytes) { - return MapAt(0, bytes); - } - - // Same as above, but with |offset| to specify from begining of the shared - // memory block to map. - // |offset| must be alignent to value of |SysInfo::VMAllocationGranularity()|. - bool MapAt(off_t offset, size_t bytes); - enum { MAP_MINIMUM_ALIGNMENT = 32 }; - - // Unmaps the shared memory from the caller's address space. - // Returns true if successful; returns false on error or if the - // memory is not mapped. - bool Unmap(); - - // The size requested when the map is first created. - size_t requested_size() const { return requested_size_; } - - // The actual size of the mapped memory (may be larger than requested). - size_t mapped_size() const { return mapped_size_; } - - // Gets a pointer to the opened memory space if it has been - // Mapped via Map(). Returns NULL if it is not mapped. - void* memory() const { return memory_; } - - // Returns the underlying OS handle for this segment. - // Use of this handle for anything other than an opaque - // identifier is not portable. - SharedMemoryHandle handle() const; - - // Returns the underlying OS handle for this segment. The caller takes - // ownership of the handle and memory is unmapped. This is equivalent to - // duplicating the handle and then calling Unmap() and Close() on this object, - // without the overhead of duplicating the handle. - SharedMemoryHandle TakeHandle(); - - // Closes the open shared memory segment. The memory will remain mapped if - // it was previously mapped. - // It is safe to call Close repeatedly. - void Close(); - - // Returns a read-only handle to this shared memory region. The caller takes - // ownership of the handle. For POSIX handles, CHECK-fails if the region - // wasn't Created or Opened with share_read_only=true, which is required to - // make the handle read-only. When the handle is passed to the IPC subsystem, - // that takes ownership of the handle. As such, it's not valid to pass the - // sample handle to the IPC subsystem twice. Returns an invalid handle on - // failure. - SharedMemoryHandle GetReadOnlyHandle() const; - - // Returns an ID for the mapped region. This is ID of the SharedMemoryHandle - // that was mapped. The ID is valid even after the SharedMemoryHandle is - // Closed, as long as the region is not unmapped. - const UnguessableToken& mapped_id() const { return mapped_id_; } - - private: -#if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_ANDROID) && \ - (!defined(OS_MACOSX) || defined(OS_IOS)) - bool FilePathForMemoryName(const std::string& mem_name, FilePath* path); -#endif - -#if defined(OS_WIN) - // If true indicates this came from an external source so needs extra checks - // before being mapped. - bool external_section_ = false; - string16 name_; -#elif !defined(OS_ANDROID) && !defined(OS_FUCHSIA) - // If valid, points to the same memory region as shm_, but with readonly - // permissions. - SharedMemoryHandle readonly_shm_; -#endif - -#if defined(OS_MACOSX) && !defined(OS_IOS) - // The mechanism by which the memory is mapped. Only valid if |memory_| is not - // |nullptr|. - SharedMemoryHandle::Type mapped_memory_mechanism_ = SharedMemoryHandle::MACH; -#endif - - // The OS primitive that backs the shared memory region. - SharedMemoryHandle shm_; - - size_t mapped_size_ = 0; - void* memory_ = nullptr; - bool read_only_ = false; - size_t requested_size_ = 0; - base::UnguessableToken mapped_id_; - - DISALLOW_COPY_AND_ASSIGN(SharedMemory); -}; - -} // namespace base - -#endif // BASE_MEMORY_SHARED_MEMORY_H_
diff --git a/base/memory/shared_memory_fuchsia.cc b/base/memory/shared_memory_fuchsia.cc deleted file mode 100644 index 4036bf6..0000000 --- a/base/memory/shared_memory_fuchsia.cc +++ /dev/null
@@ -1,166 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/shared_memory.h" - -#include <limits> - -#include <zircon/process.h> -#include <zircon/rights.h> -#include <zircon/syscalls.h> - -#include "base/bits.h" -#include "base/fuchsia/scoped_zx_handle.h" -#include "base/logging.h" -#include "base/memory/shared_memory_tracker.h" -#include "base/process/process_metrics.h" - -namespace base { - -SharedMemory::SharedMemory() {} - -SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) - : shm_(handle), read_only_(read_only) {} - -SharedMemory::~SharedMemory() { - Unmap(); - Close(); -} - -// static -bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { - return handle.IsValid(); -} - -// static -void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { - DCHECK(handle.IsValid()); - handle.Close(); -} - -// static -size_t SharedMemory::GetHandleLimit() { - // Duplicated from the internal Magenta kernel constant kMaxHandleCount - // (kernel/lib/zircon/zircon.cpp). - return 256 * 1024u; -} - -bool SharedMemory::CreateAndMapAnonymous(size_t size) { - return CreateAnonymous(size) && Map(size); -} - -bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { - requested_size_ = options.size; - mapped_size_ = bits::Align(requested_size_, GetPageSize()); - ScopedZxHandle vmo; - zx_status_t status = zx_vmo_create(mapped_size_, 0, vmo.receive()); - if (status != ZX_OK) { - DLOG(ERROR) << "zx_vmo_create failed, status=" << status; - return false; - } - - if (!options.executable) { - // If options.executable isn't set, drop that permission by replacement. - const int kNoExecFlags = ZX_DEFAULT_VMO_RIGHTS & ~ZX_RIGHT_EXECUTE; - ScopedZxHandle old_vmo(std::move(vmo)); - status = zx_handle_replace(old_vmo.get(), kNoExecFlags, vmo.receive()); - if (status != ZX_OK) { - DLOG(ERROR) << "zx_handle_replace() failed: " - << zx_status_get_string(status); - return false; - } - ignore_result(old_vmo.release()); - } - - shm_ = SharedMemoryHandle(vmo.release(), mapped_size_, - UnguessableToken::Create()); - return true; -} - -bool SharedMemory::MapAt(off_t offset, size_t bytes) { - if (!shm_.IsValid()) - return false; - - if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) - return false; - - if (memory_) - return false; - - int flags = ZX_VM_FLAG_PERM_READ; - if (!read_only_) - flags |= ZX_VM_FLAG_PERM_WRITE; - uintptr_t addr; - zx_status_t status = zx_vmar_map(zx_vmar_root_self(), 0, shm_.GetHandle(), - offset, bytes, flags, &addr); - if (status != ZX_OK) { - DLOG(ERROR) << "zx_vmar_map failed, status=" << status; - return false; - } - memory_ = reinterpret_cast<void*>(addr); - - mapped_size_ = bytes; - mapped_id_ = shm_.GetGUID(); - SharedMemoryTracker::GetInstance()->IncrementMemoryUsage(*this); - return true; -} - -bool SharedMemory::Unmap() { - if (!memory_) - return false; - - SharedMemoryTracker::GetInstance()->DecrementMemoryUsage(*this); - - uintptr_t addr = reinterpret_cast<uintptr_t>(memory_); - zx_status_t status = zx_vmar_unmap(zx_vmar_root_self(), addr, mapped_size_); - if (status != ZX_OK) { - DLOG(ERROR) << "zx_vmar_unmap failed, status=" << status; - return false; - } - - memory_ = nullptr; - mapped_id_ = UnguessableToken(); - return true; -} - -void SharedMemory::Close() { - if (shm_.IsValid()) { - shm_.Close(); - shm_ = SharedMemoryHandle(); - } -} - -SharedMemoryHandle SharedMemory::handle() const { - return shm_; -} - -SharedMemoryHandle SharedMemory::TakeHandle() { - SharedMemoryHandle handle(shm_); - handle.SetOwnershipPassesToIPC(true); - Unmap(); - shm_ = SharedMemoryHandle(); - return handle; -} - -SharedMemoryHandle SharedMemory::DuplicateHandle( - const SharedMemoryHandle& handle) { - return handle.Duplicate(); -} - -SharedMemoryHandle SharedMemory::GetReadOnlyHandle() const { - zx_handle_t duped_handle; - const int kNoWriteOrExec = - ZX_DEFAULT_VMO_RIGHTS & - ~(ZX_RIGHT_WRITE | ZX_RIGHT_EXECUTE | ZX_RIGHT_SET_PROPERTY); - zx_status_t status = - zx_handle_duplicate(shm_.GetHandle(), kNoWriteOrExec, &duped_handle); - if (status != ZX_OK) - return SharedMemoryHandle(); - - SharedMemoryHandle handle(duped_handle, shm_.GetSize(), shm_.GetGUID()); - handle.SetOwnershipPassesToIPC(true); - return handle; -} - -} // namespace base
diff --git a/base/memory/shared_memory_handle.cc b/base/memory/shared_memory_handle.cc deleted file mode 100644 index 085bde4..0000000 --- a/base/memory/shared_memory_handle.cc +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/shared_memory_handle.h" - -namespace base { - -SharedMemoryHandle::SharedMemoryHandle(const SharedMemoryHandle& handle) = - default; - -SharedMemoryHandle& SharedMemoryHandle::operator=( - const SharedMemoryHandle& handle) = default; - -base::UnguessableToken SharedMemoryHandle::GetGUID() const { - return guid_; -} - -size_t SharedMemoryHandle::GetSize() const { - return size_; -} - -} // namespace base
diff --git a/base/memory/shared_memory_handle.h b/base/memory/shared_memory_handle.h deleted file mode 100644 index 18aa816..0000000 --- a/base/memory/shared_memory_handle.h +++ /dev/null
@@ -1,236 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_SHARED_MEMORY_HANDLE_H_ -#define BASE_MEMORY_SHARED_MEMORY_HANDLE_H_ - -#include <stddef.h> - -#include "base/unguessable_token.h" -#include "build_config.h" - -#if defined(OS_WIN) -#include "base/process/process_handle.h" -#include "base/win/windows_types.h" -#elif defined(OS_MACOSX) && !defined(OS_IOS) -#include <mach/mach.h> -#include "base/base_export.h" -#include "base/file_descriptor_posix.h" -#include "base/macros.h" -#include "base/process/process_handle.h" -#elif defined(OS_POSIX) || defined(OS_FUCHSIA) -#include <sys/types.h> -#include "base/file_descriptor_posix.h" -#endif - -namespace base { - -// SharedMemoryHandle is the smallest possible IPC-transportable "reference" to -// a shared memory OS resource. A "reference" can be consumed exactly once [by -// base::SharedMemory] to map the shared memory OS resource into the virtual -// address space of the current process. -// TODO(erikchen): This class should have strong ownership semantics to prevent -// leaks of the underlying OS resource. https://crbug.com/640840. -class BASE_EXPORT SharedMemoryHandle { - public: - // The default constructor returns an invalid SharedMemoryHandle. - SharedMemoryHandle(); - - // Standard copy constructor. The new instance shares the underlying OS - // primitives. - SharedMemoryHandle(const SharedMemoryHandle& handle); - - // Standard assignment operator. The updated instance shares the underlying - // OS primitives. - SharedMemoryHandle& operator=(const SharedMemoryHandle& handle); - - // Closes the underlying OS resource. - // The fact that this method needs to be "const" is an artifact of the - // original interface for base::SharedMemory::CloseHandle. - // TODO(erikchen): This doesn't clear the underlying reference, which seems - // like a bug, but is how this class has always worked. Fix this: - // https://crbug.com/716072. - void Close() const; - - // Whether ownership of the underlying OS resource is implicitly passed to - // the IPC subsystem during serialization. - void SetOwnershipPassesToIPC(bool ownership_passes); - bool OwnershipPassesToIPC() const; - - // Whether the underlying OS resource is valid. - bool IsValid() const; - - // Duplicates the underlying OS resource. Using the return value as a - // parameter to an IPC message will cause the IPC subsystem to consume the OS - // resource. - SharedMemoryHandle Duplicate() const; - - // Uniques identifies the shared memory region that the underlying OS resource - // points to. Multiple SharedMemoryHandles that point to the same shared - // memory region will have the same GUID. Preserved across IPC. - base::UnguessableToken GetGUID() const; - - // Returns the size of the memory region that SharedMemoryHandle points to. - size_t GetSize() const; - -#if defined(OS_WIN) - // Takes implicit ownership of |h|. - // |guid| uniquely identifies the shared memory region pointed to by the - // underlying OS resource. If the HANDLE is associated with another - // SharedMemoryHandle, the caller must pass the |guid| of that - // SharedMemoryHandle. Otherwise, the caller should generate a new - // UnguessableToken. - // Passing the wrong |size| has no immediate consequence, but may cause errors - // when trying to map the SharedMemoryHandle at a later point in time. - SharedMemoryHandle(HANDLE h, size_t size, const base::UnguessableToken& guid); - HANDLE GetHandle() const; -#elif defined(OS_FUCHSIA) - // Takes implicit ownership of |h|. - // |guid| uniquely identifies the shared memory region pointed to by the - // underlying OS resource. If the zx_handle_t is associated with another - // SharedMemoryHandle, the caller must pass the |guid| of that - // SharedMemoryHandle. Otherwise, the caller should generate a new - // UnguessableToken. - // Passing the wrong |size| has no immediate consequence, but may cause errors - // when trying to map the SharedMemoryHandle at a later point in time. - SharedMemoryHandle(zx_handle_t h, - size_t size, - const base::UnguessableToken& guid); - zx_handle_t GetHandle() const; -#elif defined(OS_MACOSX) && !defined(OS_IOS) - enum Type { - // The SharedMemoryHandle is backed by a POSIX fd. - POSIX, - // The SharedMemoryHandle is backed by the Mach primitive "memory object". - MACH, - }; - - // Makes a Mach-based SharedMemoryHandle of the given size. On error, - // subsequent calls to IsValid() return false. - // Passing the wrong |size| has no immediate consequence, but may cause errors - // when trying to map the SharedMemoryHandle at a later point in time. - SharedMemoryHandle(mach_vm_size_t size, const base::UnguessableToken& guid); - - // Makes a Mach-based SharedMemoryHandle from |memory_object|, a named entry - // in the current task. The memory region has size |size|. - // Passing the wrong |size| has no immediate consequence, but may cause errors - // when trying to map the SharedMemoryHandle at a later point in time. - SharedMemoryHandle(mach_port_t memory_object, - mach_vm_size_t size, - const base::UnguessableToken& guid); - - // Exposed so that the SharedMemoryHandle can be transported between - // processes. - mach_port_t GetMemoryObject() const; - - // The SharedMemoryHandle must be valid. - // Returns whether the SharedMemoryHandle was successfully mapped into memory. - // On success, |memory| is an output variable that contains the start of the - // mapped memory. - bool MapAt(off_t offset, size_t bytes, void** memory, bool read_only); -#elif defined(OS_POSIX) - // Creates a SharedMemoryHandle from an |fd| supplied from an external - // service. - // Passing the wrong |size| has no immediate consequence, but may cause errors - // when trying to map the SharedMemoryHandle at a later point in time. - static SharedMemoryHandle ImportHandle(int fd, size_t size); - - // Returns the underlying OS resource. - int GetHandle() const; - - // Invalidates [but doesn't close] the underlying OS resource. This will leak - // unless the caller is careful. - int Release(); -#endif - -#if defined(OS_ANDROID) - // Marks the current file descriptor as read-only, for the purpose of - // mapping. This is independent of the region's read-only status. - void SetReadOnly() { read_only_ = true; } - - // Returns true iff the descriptor is to be used for read-only - // mappings. - bool IsReadOnly() const { return read_only_; } - - // Returns true iff the corresponding region is read-only. - bool IsRegionReadOnly() const; - - // Try to set the region read-only. This will fail any future attempt - // at read-write mapping. - bool SetRegionReadOnly() const; -#endif - -#if defined(OS_POSIX) - // Constructs a SharedMemoryHandle backed by a FileDescriptor. The newly - // created instance has the same ownership semantics as base::FileDescriptor. - // This typically means that the SharedMemoryHandle takes ownership of the - // |fd| if |auto_close| is true. Unfortunately, it's common for existing code - // to make shallow copies of SharedMemoryHandle, and the one that is finally - // passed into a base::SharedMemory is the one that "consumes" the fd. - // - // |guid| uniquely identifies the shared memory region pointed to by the - // underlying OS resource. If |file_descriptor| is associated with another - // SharedMemoryHandle, the caller must pass the |guid| of that - // SharedMemoryHandle. Otherwise, the caller should generate a new - // UnguessableToken. - // Passing the wrong |size| has no immediate consequence, but may cause errors - // when trying to map the SharedMemoryHandle at a later point in time. - SharedMemoryHandle(const base::FileDescriptor& file_descriptor, - size_t size, - const base::UnguessableToken& guid); -#endif - - private: -#if defined(OS_WIN) - HANDLE handle_ = nullptr; - - // Whether passing this object as a parameter to an IPC message passes - // ownership of |handle_| to the IPC stack. This is meant to mimic the - // behavior of the |auto_close| parameter of FileDescriptor. This member only - // affects attachment-brokered SharedMemoryHandles. - // Defaults to |false|. - bool ownership_passes_to_ipc_ = false; -#elif defined(OS_FUCHSIA) - zx_handle_t handle_ = ZX_HANDLE_INVALID; - bool ownership_passes_to_ipc_ = false; -#elif defined(OS_MACOSX) && !defined(OS_IOS) - friend class SharedMemory; - friend bool CheckReadOnlySharedMemoryHandleForTesting( - SharedMemoryHandle handle); - - Type type_ = MACH; - - // Each instance of a SharedMemoryHandle is backed either by a POSIX fd or a - // mach port. |type_| determines the backing member. - union { - FileDescriptor file_descriptor_; - - struct { - mach_port_t memory_object_ = MACH_PORT_NULL; - - // Whether passing this object as a parameter to an IPC message passes - // ownership of |memory_object_| to the IPC stack. This is meant to mimic - // the behavior of the |auto_close| parameter of FileDescriptor. - // Defaults to |false|. - bool ownership_passes_to_ipc_ = false; - }; - }; -#elif defined(OS_ANDROID) - friend class SharedMemory; - - FileDescriptor file_descriptor_; - bool read_only_ = false; -#elif defined(OS_POSIX) - FileDescriptor file_descriptor_; -#endif - - base::UnguessableToken guid_; - - // The size of the region referenced by the SharedMemoryHandle. - size_t size_ = 0; -}; - -} // namespace base - -#endif // BASE_MEMORY_SHARED_MEMORY_HANDLE_H_
diff --git a/base/memory/shared_memory_handle_fuchsia.cc b/base/memory/shared_memory_handle_fuchsia.cc deleted file mode 100644 index eab681f..0000000 --- a/base/memory/shared_memory_handle_fuchsia.cc +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/shared_memory_handle.h" - -#include <zircon/syscalls.h> - -#include "base/logging.h" -#include "base/unguessable_token.h" - -namespace base { - -SharedMemoryHandle::SharedMemoryHandle() {} - -SharedMemoryHandle::SharedMemoryHandle(zx_handle_t h, - size_t size, - const base::UnguessableToken& guid) - : handle_(h), guid_(guid), size_(size) {} - -void SharedMemoryHandle::Close() const { - DCHECK(handle_ != ZX_HANDLE_INVALID); - zx_handle_close(handle_); -} - -bool SharedMemoryHandle::IsValid() const { - return handle_ != ZX_HANDLE_INVALID; -} - -SharedMemoryHandle SharedMemoryHandle::Duplicate() const { - zx_handle_t duped_handle; - zx_status_t status = - zx_handle_duplicate(handle_, ZX_RIGHT_SAME_RIGHTS, &duped_handle); - if (status != ZX_OK) - return SharedMemoryHandle(); - - SharedMemoryHandle handle(duped_handle, GetSize(), GetGUID()); - handle.SetOwnershipPassesToIPC(true); - return handle; -} - -zx_handle_t SharedMemoryHandle::GetHandle() const { - return handle_; -} - -void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) { - ownership_passes_to_ipc_ = ownership_passes; -} - -bool SharedMemoryHandle::OwnershipPassesToIPC() const { - return ownership_passes_to_ipc_; -} - -} // namespace base
diff --git a/base/memory/shared_memory_handle_mac.cc b/base/memory/shared_memory_handle_mac.cc deleted file mode 100644 index 0e863fa..0000000 --- a/base/memory/shared_memory_handle_mac.cc +++ /dev/null
@@ -1,154 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/shared_memory_handle.h" - -#include <mach/mach_vm.h> -#include <stddef.h> -#include <sys/mman.h> -#include <unistd.h> - -#include "base/mac/mac_util.h" -#include "base/mac/mach_logging.h" -#include "base/posix/eintr_wrapper.h" -#include "base/unguessable_token.h" - -namespace base { - -SharedMemoryHandle::SharedMemoryHandle() {} - -SharedMemoryHandle::SharedMemoryHandle( - const base::FileDescriptor& file_descriptor, - size_t size, - const base::UnguessableToken& guid) - : type_(POSIX), - file_descriptor_(file_descriptor), - guid_(guid), - size_(size) {} - -SharedMemoryHandle::SharedMemoryHandle(mach_vm_size_t size, - const base::UnguessableToken& guid) { - type_ = MACH; - mach_port_t named_right; - kern_return_t kr = mach_make_memory_entry_64( - mach_task_self(), - &size, - 0, // Address. - MAP_MEM_NAMED_CREATE | VM_PROT_READ | VM_PROT_WRITE, - &named_right, - MACH_PORT_NULL); // Parent handle. - if (kr != KERN_SUCCESS) { - memory_object_ = MACH_PORT_NULL; - return; - } - - memory_object_ = named_right; - size_ = size; - ownership_passes_to_ipc_ = false; - guid_ = guid; -} - -SharedMemoryHandle::SharedMemoryHandle(mach_port_t memory_object, - mach_vm_size_t size, - const base::UnguessableToken& guid) - : type_(MACH), - memory_object_(memory_object), - ownership_passes_to_ipc_(false), - guid_(guid), - size_(size) {} - -SharedMemoryHandle SharedMemoryHandle::Duplicate() const { - switch (type_) { - case POSIX: { - if (!IsValid()) - return SharedMemoryHandle(); - int duped_fd = HANDLE_EINTR(dup(file_descriptor_.fd)); - if (duped_fd < 0) - return SharedMemoryHandle(); - return SharedMemoryHandle(FileDescriptor(duped_fd, true), size_, guid_); - } - case MACH: { - if (!IsValid()) - return SharedMemoryHandle(); - - // Increment the ref count. - kern_return_t kr = mach_port_mod_refs(mach_task_self(), memory_object_, - MACH_PORT_RIGHT_SEND, 1); - DCHECK_EQ(kr, KERN_SUCCESS); - SharedMemoryHandle handle(*this); - handle.SetOwnershipPassesToIPC(true); - return handle; - } - } -} - -bool SharedMemoryHandle::IsValid() const { - switch (type_) { - case POSIX: - return file_descriptor_.fd >= 0; - case MACH: - return memory_object_ != MACH_PORT_NULL; - } -} - -mach_port_t SharedMemoryHandle::GetMemoryObject() const { - DCHECK_EQ(type_, MACH); - return memory_object_; -} - -bool SharedMemoryHandle::MapAt(off_t offset, - size_t bytes, - void** memory, - bool read_only) { - DCHECK(IsValid()); - switch (type_) { - case SharedMemoryHandle::POSIX: - *memory = mmap(nullptr, bytes, PROT_READ | (read_only ? 0 : PROT_WRITE), - MAP_SHARED, file_descriptor_.fd, offset); - return *memory != MAP_FAILED; - case SharedMemoryHandle::MACH: - kern_return_t kr = mach_vm_map( - mach_task_self(), - reinterpret_cast<mach_vm_address_t*>(memory), // Output parameter - bytes, - 0, // Alignment mask - VM_FLAGS_ANYWHERE, - memory_object_, - offset, - FALSE, // Copy - VM_PROT_READ | (read_only ? 0 : VM_PROT_WRITE), // Current protection - VM_PROT_WRITE | VM_PROT_READ | VM_PROT_IS_MASK, // Maximum protection - VM_INHERIT_NONE); - return kr == KERN_SUCCESS; - } -} - -void SharedMemoryHandle::Close() const { - if (!IsValid()) - return; - - switch (type_) { - case POSIX: - if (IGNORE_EINTR(close(file_descriptor_.fd)) < 0) - DPLOG(ERROR) << "Error closing fd"; - break; - case MACH: - kern_return_t kr = mach_port_deallocate(mach_task_self(), memory_object_); - if (kr != KERN_SUCCESS) - MACH_DLOG(ERROR, kr) << "Error deallocating mach port"; - break; - } -} - -void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) { - DCHECK_EQ(type_, MACH); - ownership_passes_to_ipc_ = ownership_passes; -} - -bool SharedMemoryHandle::OwnershipPassesToIPC() const { - DCHECK_EQ(type_, MACH); - return ownership_passes_to_ipc_; -} - -} // namespace base
diff --git a/base/memory/shared_memory_handle_posix.cc b/base/memory/shared_memory_handle_posix.cc deleted file mode 100644 index 09dfb9c..0000000 --- a/base/memory/shared_memory_handle_posix.cc +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/shared_memory_handle.h" - -#include <unistd.h> - -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "base/unguessable_token.h" - -namespace base { - -SharedMemoryHandle::SharedMemoryHandle() = default; - -SharedMemoryHandle::SharedMemoryHandle( - const base::FileDescriptor& file_descriptor, - size_t size, - const base::UnguessableToken& guid) - : file_descriptor_(file_descriptor), guid_(guid), size_(size) {} - -// static -SharedMemoryHandle SharedMemoryHandle::ImportHandle(int fd, size_t size) { - SharedMemoryHandle handle; - handle.file_descriptor_.fd = fd; - handle.file_descriptor_.auto_close = false; - handle.guid_ = UnguessableToken::Create(); - handle.size_ = size; - return handle; -} - -int SharedMemoryHandle::GetHandle() const { - return file_descriptor_.fd; -} - -bool SharedMemoryHandle::IsValid() const { - return file_descriptor_.fd >= 0; -} - -void SharedMemoryHandle::Close() const { - if (IGNORE_EINTR(close(file_descriptor_.fd)) < 0) - PLOG(ERROR) << "close"; -} - -int SharedMemoryHandle::Release() { - int old_fd = file_descriptor_.fd; - file_descriptor_.fd = -1; - return old_fd; -} - -SharedMemoryHandle SharedMemoryHandle::Duplicate() const { - if (!IsValid()) - return SharedMemoryHandle(); - - int duped_handle = HANDLE_EINTR(dup(file_descriptor_.fd)); - if (duped_handle < 0) - return SharedMemoryHandle(); - return SharedMemoryHandle(FileDescriptor(duped_handle, true), GetSize(), - GetGUID()); -} - -void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) { - file_descriptor_.auto_close = ownership_passes; -} - -bool SharedMemoryHandle::OwnershipPassesToIPC() const { - return file_descriptor_.auto_close; -} - -} // namespace base
diff --git a/base/memory/shared_memory_handle_win.cc b/base/memory/shared_memory_handle_win.cc deleted file mode 100644 index 8c11d39..0000000 --- a/base/memory/shared_memory_handle_win.cc +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/shared_memory_handle.h" - -#include "base/logging.h" -#include "base/unguessable_token.h" - -#include <windows.h> - -namespace base { - -SharedMemoryHandle::SharedMemoryHandle() {} - -SharedMemoryHandle::SharedMemoryHandle(HANDLE h, - size_t size, - const base::UnguessableToken& guid) - : handle_(h), guid_(guid), size_(size) {} - -void SharedMemoryHandle::Close() const { - DCHECK(handle_ != nullptr); - ::CloseHandle(handle_); -} - -bool SharedMemoryHandle::IsValid() const { - return handle_ != nullptr; -} - -SharedMemoryHandle SharedMemoryHandle::Duplicate() const { - HANDLE duped_handle; - ProcessHandle process = GetCurrentProcess(); - BOOL success = ::DuplicateHandle(process, handle_, process, &duped_handle, 0, - FALSE, DUPLICATE_SAME_ACCESS); - if (!success) - return SharedMemoryHandle(); - - base::SharedMemoryHandle handle(duped_handle, GetSize(), GetGUID()); - handle.SetOwnershipPassesToIPC(true); - return handle; -} - -HANDLE SharedMemoryHandle::GetHandle() const { - return handle_; -} - -void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) { - ownership_passes_to_ipc_ = ownership_passes; -} - -bool SharedMemoryHandle::OwnershipPassesToIPC() const { - return ownership_passes_to_ipc_; -} - -} // namespace base
diff --git a/base/memory/shared_memory_helper.cc b/base/memory/shared_memory_helper.cc deleted file mode 100644 index f98b734..0000000 --- a/base/memory/shared_memory_helper.cc +++ /dev/null
@@ -1,157 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/shared_memory_helper.h" - -#if defined(OS_CHROMEOS) -#include <sys/resource.h> -#include <sys/time.h> - -#include "base/debug/alias.h" -#endif // defined(OS_CHROMEOS) - -#include "base/threading/thread_restrictions.h" - -namespace base { - -struct ScopedPathUnlinkerTraits { - static const FilePath* InvalidValue() { return nullptr; } - - static void Free(const FilePath* path) { - if (unlink(path->value().c_str())) - PLOG(WARNING) << "unlink"; - } -}; - -// Unlinks the FilePath when the object is destroyed. -using ScopedPathUnlinker = - ScopedGeneric<const FilePath*, ScopedPathUnlinkerTraits>; - -#if !defined(OS_ANDROID) -bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, - ScopedFD* fd, - ScopedFD* readonly_fd, - FilePath* path) { -#if defined(OS_LINUX) - // It doesn't make sense to have a open-existing private piece of shmem - DCHECK(!options.open_existing_deprecated); -#endif // defined(OS_LINUX) - // Q: Why not use the shm_open() etc. APIs? - // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU - FilePath directory; - ScopedPathUnlinker path_unlinker; - if (!GetShmemTempDir(options.executable, &directory)) - return false; - - fd->reset(base::CreateAndOpenFdForTemporaryFileInDir(directory, path)); - - if (!fd->is_valid()) - return false; - - // Deleting the file prevents anyone else from mapping it in (making it - // private), and prevents the need for cleanup (once the last fd is - // closed, it is truly freed). - path_unlinker.reset(path); - - if (options.share_read_only) { - // Also open as readonly so that we can GetReadOnlyHandle. - readonly_fd->reset(HANDLE_EINTR(open(path->value().c_str(), O_RDONLY))); - if (!readonly_fd->is_valid()) { - DPLOG(ERROR) << "open(\"" << path->value() << "\", O_RDONLY) failed"; - fd->reset(); - return false; - } - } - return true; -} - -bool PrepareMapFile(ScopedFD fd, - ScopedFD readonly_fd, - int* mapped_file, - int* readonly_mapped_file) { - DCHECK_EQ(-1, *mapped_file); - DCHECK_EQ(-1, *readonly_mapped_file); - if (!fd.is_valid()) - return false; - - // This function theoretically can block on the disk, but realistically - // the temporary files we create will just go into the buffer cache - // and be deleted before they ever make it out to disk. - base::ThreadRestrictions::ScopedAllowIO allow_io; - - if (readonly_fd.is_valid()) { - struct stat st = {}; - if (fstat(fd.get(), &st)) - NOTREACHED(); - - struct stat readonly_st = {}; - if (fstat(readonly_fd.get(), &readonly_st)) - NOTREACHED(); - if (st.st_dev != readonly_st.st_dev || st.st_ino != readonly_st.st_ino) { - LOG(ERROR) << "writable and read-only inodes don't match; bailing"; - return false; - } - } - - *mapped_file = HANDLE_EINTR(dup(fd.get())); - if (*mapped_file == -1) { - NOTREACHED() << "Call to dup failed, errno=" << errno; - -#if defined(OS_CHROMEOS) - if (errno == EMFILE) { - // We're out of file descriptors and are probably about to crash somewhere - // else in Chrome anyway. Let's collect what FD information we can and - // crash. - // Added for debugging crbug.com/733718 - int original_fd_limit = 16384; - struct rlimit rlim; - if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) { - original_fd_limit = rlim.rlim_cur; - if (rlim.rlim_max > rlim.rlim_cur) { - // Increase fd limit so breakpad has a chance to write a minidump. - rlim.rlim_cur = rlim.rlim_max; - if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) { - PLOG(ERROR) << "setrlimit() failed"; - } - } - } else { - PLOG(ERROR) << "getrlimit() failed"; - } - - const char kFileDataMarker[] = "FDATA"; - char buf[PATH_MAX]; - char fd_path[PATH_MAX]; - char crash_buffer[32 * 1024] = {0}; - char* crash_ptr = crash_buffer; - base::debug::Alias(crash_buffer); - - // Put a marker at the start of our data so we can confirm where it - // begins. - crash_ptr = strncpy(crash_ptr, kFileDataMarker, strlen(kFileDataMarker)); - for (int i = original_fd_limit; i >= 0; --i) { - memset(buf, 0, arraysize(buf)); - memset(fd_path, 0, arraysize(fd_path)); - snprintf(fd_path, arraysize(fd_path) - 1, "/proc/self/fd/%d", i); - ssize_t count = readlink(fd_path, buf, arraysize(buf) - 1); - if (count < 0) { - PLOG(ERROR) << "readlink failed for: " << fd_path; - continue; - } - - if (crash_ptr + count + 1 < crash_buffer + arraysize(crash_buffer)) { - crash_ptr = strncpy(crash_ptr, buf, count + 1); - } - LOG(ERROR) << i << ": " << buf; - } - LOG(FATAL) << "Logged for file descriptor exhaustion, crashing now"; - } -#endif // defined(OS_CHROMEOS) - } - *readonly_mapped_file = readonly_fd.release(); - - return true; -} -#endif // !defined(OS_ANDROID) - -} // namespace base
diff --git a/base/memory/shared_memory_helper.h b/base/memory/shared_memory_helper.h deleted file mode 100644 index 9da810e..0000000 --- a/base/memory/shared_memory_helper.h +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_SHARED_MEMORY_HELPER_H_ -#define BASE_MEMORY_SHARED_MEMORY_HELPER_H_ - -#include "base/memory/shared_memory.h" -#include "build_config.h" - -#include <fcntl.h> - -namespace base { - -#if !defined(OS_ANDROID) -// Makes a temporary file, fdopens it, and then unlinks it. |fd| is populated -// with the opened fd. |readonly_fd| is populated with the opened fd if -// options.share_read_only is true. |path| is populated with the location of -// the file before it was unlinked. -// Returns false if there's an unhandled failure. -bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, - ScopedFD* fd, - ScopedFD* readonly_fd, - FilePath* path); - -// Takes the outputs of CreateAnonymousSharedMemory and maps them properly to -// |mapped_file| or |readonly_mapped_file|, depending on which one is populated. -bool PrepareMapFile(ScopedFD fd, - ScopedFD readonly_fd, - int* mapped_file, - int* readonly_mapped_file); -#endif // !defined(OS_ANDROID) - -} // namespace base - -#endif // BASE_MEMORY_SHARED_MEMORY_HELPER_H_
diff --git a/base/memory/shared_memory_mac.cc b/base/memory/shared_memory_mac.cc deleted file mode 100644 index 5e9e8fc..0000000 --- a/base/memory/shared_memory_mac.cc +++ /dev/null
@@ -1,262 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/shared_memory.h" - -#include <errno.h> -#include <mach/mach_vm.h> -#include <stddef.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <unistd.h> - -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/logging.h" -#include "base/mac/foundation_util.h" -#include "base/mac/mac_util.h" -#include "base/mac/scoped_mach_vm.h" -#include "base/memory/shared_memory_helper.h" -#include "base/memory/shared_memory_tracker.h" -#include "base/posix/eintr_wrapper.h" -#include "base/posix/safe_strerror.h" -#include "base/process/process_metrics.h" -#include "base/scoped_generic.h" -#include "base/strings/utf_string_conversions.h" -#include "base/threading/thread_restrictions.h" -#include "base/unguessable_token.h" -#include "build_config.h" - -#if defined(OS_IOS) -#error "MacOS only - iOS uses shared_memory_posix.cc" -#endif - -namespace base { - -namespace { - -// Returns whether the operation succeeded. -// |new_handle| is an output variable, populated on success. The caller takes -// ownership of the underlying memory object. -// |handle| is the handle to copy. -// If |handle| is already mapped, |mapped_addr| is its mapped location. -// Otherwise, |mapped_addr| should be |nullptr|. -bool MakeMachSharedMemoryHandleReadOnly(SharedMemoryHandle* new_handle, - SharedMemoryHandle handle, - void* mapped_addr) { - if (!handle.IsValid()) - return false; - - size_t size = handle.GetSize(); - - // Map if necessary. - void* temp_addr = mapped_addr; - base::mac::ScopedMachVM scoper; - if (!temp_addr) { - // Intentionally lower current prot and max prot to |VM_PROT_READ|. - kern_return_t kr = mach_vm_map( - mach_task_self(), reinterpret_cast<mach_vm_address_t*>(&temp_addr), - size, 0, VM_FLAGS_ANYWHERE, handle.GetMemoryObject(), 0, FALSE, - VM_PROT_READ, VM_PROT_READ, VM_INHERIT_NONE); - if (kr != KERN_SUCCESS) - return false; - scoper.reset(reinterpret_cast<vm_address_t>(temp_addr), - mach_vm_round_page(size)); - } - - // Make new memory object. - mach_port_t named_right; - kern_return_t kr = mach_make_memory_entry_64( - mach_task_self(), reinterpret_cast<memory_object_size_t*>(&size), - reinterpret_cast<memory_object_offset_t>(temp_addr), VM_PROT_READ, - &named_right, MACH_PORT_NULL); - if (kr != KERN_SUCCESS) - return false; - - *new_handle = SharedMemoryHandle(named_right, size, handle.GetGUID()); - return true; -} - -} // namespace - -SharedMemory::SharedMemory() {} - -SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) - : mapped_memory_mechanism_(SharedMemoryHandle::POSIX), - shm_(handle), - read_only_(read_only) {} - -SharedMemory::~SharedMemory() { - Unmap(); - Close(); -} - -// static -bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { - return handle.IsValid(); -} - -// static -void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { - handle.Close(); -} - -// static -size_t SharedMemory::GetHandleLimit() { - return GetMaxFds(); -} - -// static -SharedMemoryHandle SharedMemory::DuplicateHandle( - const SharedMemoryHandle& handle) { - return handle.Duplicate(); -} - -// static -int SharedMemory::GetFdFromSharedMemoryHandle( - const SharedMemoryHandle& handle) { - return handle.file_descriptor_.fd; -} - -bool SharedMemory::CreateAndMapAnonymous(size_t size) { - return CreateAnonymous(size) && Map(size); -} - -// Chromium mostly only uses the unique/private shmem as specified by -// "name == L"". The exception is in the StatsTable. -bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { - DCHECK(!shm_.IsValid()); - if (options.size == 0) - return false; - - if (options.size > static_cast<size_t>(std::numeric_limits<int>::max())) - return false; - - if (options.type == SharedMemoryHandle::MACH) { - shm_ = SharedMemoryHandle(options.size, UnguessableToken::Create()); - requested_size_ = options.size; - return shm_.IsValid(); - } - - // This function theoretically can block on the disk. Both profiling of real - // users and local instrumentation shows that this is a real problem. - // https://code.google.com/p/chromium/issues/detail?id=466437 - ThreadRestrictions::ScopedAllowIO allow_io; - - ScopedFD fd; - ScopedFD readonly_fd; - - FilePath path; - bool result = CreateAnonymousSharedMemory(options, &fd, &readonly_fd, &path); - if (!result) - return false; - // Should be guaranteed by CreateAnonymousSharedMemory(). - DCHECK(fd.is_valid()); - - // Get current size. - struct stat stat; - if (fstat(fd.get(), &stat) != 0) - return false; - const size_t current_size = stat.st_size; - if (current_size != options.size) { - if (HANDLE_EINTR(ftruncate(fd.get(), options.size)) != 0) - return false; - } - requested_size_ = options.size; - - int mapped_file = -1; - int readonly_mapped_file = -1; - result = PrepareMapFile(std::move(fd), std::move(readonly_fd), &mapped_file, - &readonly_mapped_file); - shm_ = SharedMemoryHandle(FileDescriptor(mapped_file, false), options.size, - UnguessableToken::Create()); - readonly_shm_ = - SharedMemoryHandle(FileDescriptor(readonly_mapped_file, false), - options.size, shm_.GetGUID()); - return result; -} - -bool SharedMemory::MapAt(off_t offset, size_t bytes) { - if (!shm_.IsValid()) - return false; - if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) - return false; - if (memory_) - return false; - - bool success = shm_.MapAt(offset, bytes, &memory_, read_only_); - if (success) { - mapped_size_ = bytes; - DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) & - (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); - mapped_memory_mechanism_ = shm_.type_; - mapped_id_ = shm_.GetGUID(); - SharedMemoryTracker::GetInstance()->IncrementMemoryUsage(*this); - } else { - memory_ = nullptr; - } - - return success; -} - -bool SharedMemory::Unmap() { - if (!memory_) - return false; - - SharedMemoryTracker::GetInstance()->DecrementMemoryUsage(*this); - switch (mapped_memory_mechanism_) { - case SharedMemoryHandle::POSIX: - munmap(memory_, mapped_size_); - break; - case SharedMemoryHandle::MACH: - mach_vm_deallocate(mach_task_self(), - reinterpret_cast<mach_vm_address_t>(memory_), - mapped_size_); - break; - } - memory_ = nullptr; - mapped_size_ = 0; - mapped_id_ = UnguessableToken(); - return true; -} - -SharedMemoryHandle SharedMemory::handle() const { - return shm_; -} - -SharedMemoryHandle SharedMemory::TakeHandle() { - SharedMemoryHandle dup = DuplicateHandle(handle()); - Unmap(); - Close(); - return dup; -} - -void SharedMemory::Close() { - shm_.Close(); - shm_ = SharedMemoryHandle(); - if (shm_.type_ == SharedMemoryHandle::POSIX) { - if (readonly_shm_.IsValid()) { - readonly_shm_.Close(); - readonly_shm_ = SharedMemoryHandle(); - } - } -} - -SharedMemoryHandle SharedMemory::GetReadOnlyHandle() const { - if (shm_.type_ == SharedMemoryHandle::POSIX) { - // We could imagine re-opening the file from /dev/fd, but that can't make it - // readonly on Mac: https://codereview.chromium.org/27265002/#msg10. - CHECK(readonly_shm_.IsValid()); - return readonly_shm_.Duplicate(); - } - - DCHECK(shm_.IsValid()); - SharedMemoryHandle new_handle; - bool success = MakeMachSharedMemoryHandleReadOnly(&new_handle, shm_, memory_); - if (success) - new_handle.SetOwnershipPassesToIPC(true); - return new_handle; -} - -} // namespace base
diff --git a/base/memory/shared_memory_mapping.cc b/base/memory/shared_memory_mapping.cc deleted file mode 100644 index 878a012..0000000 --- a/base/memory/shared_memory_mapping.cc +++ /dev/null
@@ -1,115 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/shared_memory_mapping.h" - -#include <utility> - -#include "base/logging.h" -#include "base/memory/shared_memory_tracker.h" -#include "base/unguessable_token.h" -#include "build_config.h" - -#if defined(OS_POSIX) -#include <sys/mman.h> -#endif - -#if defined(OS_WIN) -#include <aclapi.h> -#endif - -#if defined(OS_MACOSX) && !defined(OS_IOS) -#include <mach/mach_vm.h> -#include "base/mac/mach_logging.h" -#endif - -#if defined(OS_FUCHSIA) -#include <zircon/process.h> -#include <zircon/status.h> -#include <zircon/syscalls.h> -#endif - -namespace base { - -SharedMemoryMapping::SharedMemoryMapping() = default; - -SharedMemoryMapping::SharedMemoryMapping(SharedMemoryMapping&& mapping) - : memory_(mapping.memory_), - size_(mapping.size_), - mapped_size_(mapping.mapped_size_), - guid_(mapping.guid_) { - mapping.memory_ = nullptr; -} - -SharedMemoryMapping& SharedMemoryMapping::operator=( - SharedMemoryMapping&& mapping) { - Unmap(); - memory_ = mapping.memory_; - size_ = mapping.size_; - mapped_size_ = mapping.mapped_size_; - guid_ = mapping.guid_; - mapping.memory_ = nullptr; - return *this; -} - -SharedMemoryMapping::~SharedMemoryMapping() { - Unmap(); -} - -SharedMemoryMapping::SharedMemoryMapping(void* memory, - size_t size, - size_t mapped_size, - const UnguessableToken& guid) - : memory_(memory), size_(size), mapped_size_(mapped_size), guid_(guid) { - SharedMemoryTracker::GetInstance()->IncrementMemoryUsage(*this); -} - -void SharedMemoryMapping::Unmap() { - if (!IsValid()) - return; - - SharedMemoryTracker::GetInstance()->DecrementMemoryUsage(*this); -#if defined(OS_WIN) - if (!UnmapViewOfFile(memory_)) - DPLOG(ERROR) << "UnmapViewOfFile"; -#elif defined(OS_FUCHSIA) - uintptr_t addr = reinterpret_cast<uintptr_t>(memory_); - zx_status_t status = zx_vmar_unmap(zx_vmar_root_self(), addr, size_); - DLOG_IF(ERROR, status != ZX_OK) - << "zx_vmar_unmap failed: " << zx_status_get_string(status); -#elif defined(OS_MACOSX) && !defined(OS_IOS) - kern_return_t kr = mach_vm_deallocate( - mach_task_self(), reinterpret_cast<mach_vm_address_t>(memory_), size_); - MACH_DLOG_IF(ERROR, kr != KERN_SUCCESS, kr) << "mach_vm_deallocate"; -#else - if (munmap(memory_, size_) < 0) - DPLOG(ERROR) << "munmap"; -#endif -} - -ReadOnlySharedMemoryMapping::ReadOnlySharedMemoryMapping() = default; -ReadOnlySharedMemoryMapping::ReadOnlySharedMemoryMapping( - ReadOnlySharedMemoryMapping&&) = default; -ReadOnlySharedMemoryMapping& ReadOnlySharedMemoryMapping::operator=( - ReadOnlySharedMemoryMapping&&) = default; -ReadOnlySharedMemoryMapping::ReadOnlySharedMemoryMapping( - void* address, - size_t size, - size_t mapped_size, - const UnguessableToken& guid) - : SharedMemoryMapping(address, size, mapped_size, guid) {} - -WritableSharedMemoryMapping::WritableSharedMemoryMapping() = default; -WritableSharedMemoryMapping::WritableSharedMemoryMapping( - WritableSharedMemoryMapping&&) = default; -WritableSharedMemoryMapping& WritableSharedMemoryMapping::operator=( - WritableSharedMemoryMapping&&) = default; -WritableSharedMemoryMapping::WritableSharedMemoryMapping( - void* address, - size_t size, - size_t mapped_size, - const UnguessableToken& guid) - : SharedMemoryMapping(address, size, mapped_size, guid) {} - -} // namespace base
diff --git a/base/memory/shared_memory_mapping.h b/base/memory/shared_memory_mapping.h deleted file mode 100644 index ace4c15..0000000 --- a/base/memory/shared_memory_mapping.h +++ /dev/null
@@ -1,144 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_SHARED_MEMORY_MAPPING_H_ -#define BASE_MEMORY_SHARED_MEMORY_MAPPING_H_ - -#include <cstddef> - -#include "base/macros.h" -#include "base/unguessable_token.h" - -namespace base { - -namespace subtle { -class PlatformSharedMemoryRegion; -} // namespace subtle - -// Base class for scoped handles to a shared memory mapping created from a -// shared memory region. Created shared memory mappings remain valid even if the -// creator region is transferred or destroyed. -// -// Each mapping has an UnguessableToken that identifies the shared memory region -// it was created from. This is used for memory metrics, to avoid overcounting -// shared memory. -class BASE_EXPORT SharedMemoryMapping { - public: - // Default constructor initializes an invalid instance. - SharedMemoryMapping(); - - // Move operations are allowed. - SharedMemoryMapping(SharedMemoryMapping&& mapping); - SharedMemoryMapping& operator=(SharedMemoryMapping&& mapping); - - // Unmaps the region if the mapping is valid. - virtual ~SharedMemoryMapping(); - - // Returns true iff the mapping is valid. False means there is no - // corresponding area of memory. - bool IsValid() const { return memory_ != nullptr; } - - // Returns the logical size of the mapping in bytes. This is precisely the - // size requested by whoever created the mapping, and it is always less than - // or equal to |mapped_size()|. This is undefined for invalid instances. - size_t size() const { - DCHECK(IsValid()); - return size_; - } - - // Returns the actual size of the mapping in bytes. This is always at least - // as large as |size()| but may be larger due to platform mapping alignment - // constraints. This is undefined for invalid instances. - size_t mapped_size() const { - DCHECK(IsValid()); - return mapped_size_; - } - - // Returns 128-bit GUID of the region this mapping belongs to. - const UnguessableToken& guid() const { - DCHECK(IsValid()); - return guid_; - } - - protected: - SharedMemoryMapping(void* address, - size_t size, - size_t mapped_size, - const UnguessableToken& guid); - void* raw_memory_ptr() const { return memory_; } - - private: - friend class SharedMemoryTracker; - - void Unmap(); - - void* memory_ = nullptr; - size_t size_ = 0; - size_t mapped_size_ = 0; - UnguessableToken guid_; - - DISALLOW_COPY_AND_ASSIGN(SharedMemoryMapping); -}; - -// Class modeling a read-only mapping of a shared memory region into the -// current process' address space. This is created by ReadOnlySharedMemoryRegion -// instances. -class BASE_EXPORT ReadOnlySharedMemoryMapping : public SharedMemoryMapping { - public: - // Default constructor initializes an invalid instance. - ReadOnlySharedMemoryMapping(); - - // Move operations are allowed. - ReadOnlySharedMemoryMapping(ReadOnlySharedMemoryMapping&&); - ReadOnlySharedMemoryMapping& operator=(ReadOnlySharedMemoryMapping&&); - - // Returns the base address of the mapping. This is read-only memory. This is - // page-aligned. This is nullptr for invalid instances. - const void* memory() const { return raw_memory_ptr(); } - - private: - friend class ReadOnlySharedMemoryRegion; - ReadOnlySharedMemoryMapping(void* address, - size_t size, - size_t mapped_size, - const UnguessableToken& guid); - - DISALLOW_COPY_AND_ASSIGN(ReadOnlySharedMemoryMapping); -}; - -// Class modeling a writable mapping of a shared memory region into the -// current process' address space. This is created by *SharedMemoryRegion -// instances. -class BASE_EXPORT WritableSharedMemoryMapping : public SharedMemoryMapping { - public: - // Default constructor initializes an invalid instance. - WritableSharedMemoryMapping(); - - // Move operations are allowed. - WritableSharedMemoryMapping(WritableSharedMemoryMapping&&); - WritableSharedMemoryMapping& operator=(WritableSharedMemoryMapping&&); - - // Returns the base address of the mapping. This is writable memory. This is - // page-aligned. This is nullptr for invalid instances. - void* memory() const { return raw_memory_ptr(); } - - private: - friend WritableSharedMemoryMapping MapAtForTesting( - subtle::PlatformSharedMemoryRegion* region, - off_t offset, - size_t size); - friend class ReadOnlySharedMemoryRegion; - friend class WritableSharedMemoryRegion; - friend class UnsafeSharedMemoryRegion; - WritableSharedMemoryMapping(void* address, - size_t size, - size_t mapped_size, - const UnguessableToken& guid); - - DISALLOW_COPY_AND_ASSIGN(WritableSharedMemoryMapping); -}; - -} // namespace base - -#endif // BASE_MEMORY_SHARED_MEMORY_MAPPING_H_
diff --git a/base/memory/shared_memory_nacl.cc b/base/memory/shared_memory_nacl.cc deleted file mode 100644 index 4bcbb54..0000000 --- a/base/memory/shared_memory_nacl.cc +++ /dev/null
@@ -1,138 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/shared_memory.h" - -#include <errno.h> -#include <fcntl.h> -#include <stddef.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <unistd.h> - -#include <limits> - -#include "base/logging.h" -#include "base/memory/shared_memory_tracker.h" - -namespace base { - -SharedMemory::SharedMemory() - : mapped_size_(0), memory_(NULL), read_only_(false), requested_size_(0) {} - -SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) - : shm_(handle), - mapped_size_(0), - memory_(NULL), - read_only_(read_only), - requested_size_(0) {} - -SharedMemory::~SharedMemory() { - Unmap(); - Close(); -} - -// static -bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { - return handle.IsValid(); -} - -// static -void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { - DCHECK(handle.IsValid()); - handle.Close(); -} - -// static -SharedMemoryHandle SharedMemory::DuplicateHandle( - const SharedMemoryHandle& handle) { - return handle.Duplicate(); -} - -bool SharedMemory::CreateAndMapAnonymous(size_t size) { - // Untrusted code can't create descriptors or handles. - return false; -} - -bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { - // Untrusted code can't create descriptors or handles. - return false; -} - -bool SharedMemory::Delete(const std::string& name) { - return false; -} - -bool SharedMemory::Open(const std::string& name, bool read_only) { - return false; -} - -bool SharedMemory::MapAt(off_t offset, size_t bytes) { - if (!shm_.IsValid()) - return false; - - if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) - return false; - - if (memory_) - return false; - - memory_ = mmap(NULL, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE), - MAP_SHARED, shm_.GetHandle(), offset); - - bool mmap_succeeded = memory_ != MAP_FAILED && memory_ != NULL; - if (mmap_succeeded) { - mapped_size_ = bytes; - DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) & - (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); - mapped_id_ = shm_.GetGUID(); - SharedMemoryTracker::GetInstance()->IncrementMemoryUsage(*this); - } else { - memory_ = NULL; - } - - return mmap_succeeded; -} - -bool SharedMemory::Unmap() { - if (memory_ == NULL) - return false; - - SharedMemoryTracker::GetInstance()->DecrementMemoryUsage(*this); - if (munmap(memory_, mapped_size_) < 0) - DPLOG(ERROR) << "munmap"; - memory_ = NULL; - mapped_size_ = 0; - mapped_id_ = UnguessableToken(); - return true; -} - -SharedMemoryHandle SharedMemory::handle() const { - SharedMemoryHandle handle_copy = shm_; - handle_copy.SetOwnershipPassesToIPC(false); - return handle_copy; -} - -SharedMemoryHandle SharedMemory::TakeHandle() { - SharedMemoryHandle handle_copy = shm_; - handle_copy.SetOwnershipPassesToIPC(true); - Unmap(); - shm_ = SharedMemoryHandle(); - return handle_copy; -} - -void SharedMemory::Close() { - if (shm_.IsValid()) { - shm_.Close(); - shm_ = SharedMemoryHandle(); - } -} - -SharedMemoryHandle SharedMemory::GetReadOnlyHandle() const { - // Untrusted code can't create descriptors or handles, which is needed to - // drop permissions. - return SharedMemoryHandle(); -} - -} // namespace base
diff --git a/base/memory/shared_memory_posix.cc b/base/memory/shared_memory_posix.cc deleted file mode 100644 index f868eb2..0000000 --- a/base/memory/shared_memory_posix.cc +++ /dev/null
@@ -1,385 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/shared_memory.h" - -#include <errno.h> -#include <fcntl.h> -#include <stddef.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <unistd.h> - -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/shared_memory_helper.h" -#include "base/memory/shared_memory_tracker.h" -#include "base/posix/eintr_wrapper.h" -#include "base/posix/safe_strerror.h" -#include "base/process/process_metrics.h" -#include "base/scoped_generic.h" -#include "base/strings/utf_string_conversions.h" -#include "base/threading/thread_restrictions.h" -#include "base/unguessable_token.h" -#include "build_config.h" - -#if defined(OS_ANDROID) -#include "base/os_compat_android.h" -#include "third_party/ashmem/ashmem.h" -#endif - -#if defined(OS_MACOSX) && !defined(OS_IOS) -#error "MacOS uses shared_memory_mac.cc" -#endif - -namespace base { - -SharedMemory::SharedMemory() = default; - -SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) - : shm_(handle), read_only_(read_only) {} - -SharedMemory::~SharedMemory() { - Unmap(); - Close(); -} - -// static -bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { - return handle.IsValid(); -} - -// static -void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { - DCHECK(handle.IsValid()); - handle.Close(); -} - -// static -size_t SharedMemory::GetHandleLimit() { - return GetMaxFds(); -} - -// static -SharedMemoryHandle SharedMemory::DuplicateHandle( - const SharedMemoryHandle& handle) { - return handle.Duplicate(); -} - -// static -int SharedMemory::GetFdFromSharedMemoryHandle( - const SharedMemoryHandle& handle) { - return handle.GetHandle(); -} - -bool SharedMemory::CreateAndMapAnonymous(size_t size) { - return CreateAnonymous(size) && Map(size); -} - -#if !defined(OS_ANDROID) - -// Chromium mostly only uses the unique/private shmem as specified by -// "name == L"". The exception is in the StatsTable. -// TODO(jrg): there is no way to "clean up" all unused named shmem if -// we restart from a crash. (That isn't a new problem, but it is a problem.) -// In case we want to delete it later, it may be useful to save the value -// of mem_filename after FilePathForMemoryName(). -bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { - DCHECK(!shm_.IsValid()); - if (options.size == 0) return false; - - if (options.size > static_cast<size_t>(std::numeric_limits<int>::max())) - return false; - - // This function theoretically can block on the disk, but realistically - // the temporary files we create will just go into the buffer cache - // and be deleted before they ever make it out to disk. - ThreadRestrictions::ScopedAllowIO allow_io; - - bool fix_size = true; - ScopedFD fd; - ScopedFD readonly_fd; - FilePath path; - if (!options.name_deprecated || options.name_deprecated->empty()) { - bool result = - CreateAnonymousSharedMemory(options, &fd, &readonly_fd, &path); - if (!result) - return false; - } else { - if (!FilePathForMemoryName(*options.name_deprecated, &path)) - return false; - - // Make sure that the file is opened without any permission - // to other users on the system. - const mode_t kOwnerOnly = S_IRUSR | S_IWUSR; - - // First, try to create the file. - fd.reset(HANDLE_EINTR( - open(path.value().c_str(), O_RDWR | O_CREAT | O_EXCL, kOwnerOnly))); - if (!fd.is_valid() && options.open_existing_deprecated) { - // If this doesn't work, try and open an existing file in append mode. - // Opening an existing file in a world writable directory has two main - // security implications: - // - Attackers could plant a file under their control, so ownership of - // the file is checked below. - // - Attackers could plant a symbolic link so that an unexpected file - // is opened, so O_NOFOLLOW is passed to open(). -#if !defined(OS_AIX) - fd.reset(HANDLE_EINTR( - open(path.value().c_str(), O_RDWR | O_APPEND | O_NOFOLLOW))); -#else - // AIX has no 64-bit support for open flags such as - - // O_CLOEXEC, O_NOFOLLOW and O_TTY_INIT. - fd.reset(HANDLE_EINTR(open(path.value().c_str(), O_RDWR | O_APPEND))); -#endif - // Check that the current user owns the file. - // If uid != euid, then a more complex permission model is used and this - // API is not appropriate. - const uid_t real_uid = getuid(); - const uid_t effective_uid = geteuid(); - struct stat sb; - if (fd.is_valid() && - (fstat(fd.get(), &sb) != 0 || sb.st_uid != real_uid || - sb.st_uid != effective_uid)) { - LOG(ERROR) << - "Invalid owner when opening existing shared memory file."; - close(fd.get()); - return false; - } - - // An existing file was opened, so its size should not be fixed. - fix_size = false; - } - - if (options.share_read_only) { - // Also open as readonly so that we can GetReadOnlyHandle. - readonly_fd.reset(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY))); - if (!readonly_fd.is_valid()) { - DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed"; - close(fd.get()); - return false; - } - } - if (fd.is_valid()) { - // "a+" is always appropriate: if it's a new file, a+ is similar to w+. - if (!fdopen(fd.get(), "a+")) { - PLOG(ERROR) << "Creating file stream in " << path.value() << " failed"; - return false; - } - } - } - if (fd.is_valid() && fix_size) { - // Get current size. - struct stat stat; - if (fstat(fd.get(), &stat) != 0) - return false; - const size_t current_size = stat.st_size; - if (current_size != options.size) { - if (HANDLE_EINTR(ftruncate(fd.get(), options.size)) != 0) - return false; - } - requested_size_ = options.size; - } - if (!fd.is_valid()) { - PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed"; - FilePath dir = path.DirName(); - if (access(dir.value().c_str(), W_OK | X_OK) < 0) { - PLOG(ERROR) << "Unable to access(W_OK|X_OK) " << dir.value(); - if (dir.value() == "/dev/shm") { - LOG(FATAL) << "This is frequently caused by incorrect permissions on " - << "/dev/shm. Try 'sudo chmod 1777 /dev/shm' to fix."; - } - } - return false; - } - - int mapped_file = -1; - int readonly_mapped_file = -1; - - bool result = PrepareMapFile(std::move(fd), std::move(readonly_fd), - &mapped_file, &readonly_mapped_file); - shm_ = SharedMemoryHandle(FileDescriptor(mapped_file, false), options.size, - UnguessableToken::Create()); - readonly_shm_ = - SharedMemoryHandle(FileDescriptor(readonly_mapped_file, false), - options.size, shm_.GetGUID()); - return result; -} - -// Our current implementation of shmem is with mmap()ing of files. -// These files need to be deleted explicitly. -// In practice this call is only needed for unit tests. -bool SharedMemory::Delete(const std::string& name) { - FilePath path; - if (!FilePathForMemoryName(name, &path)) - return false; - - if (PathExists(path)) - return DeleteFile(path, false); - - // Doesn't exist, so success. - return true; -} - -bool SharedMemory::Open(const std::string& name, bool read_only) { - FilePath path; - if (!FilePathForMemoryName(name, &path)) - return false; - - read_only_ = read_only; - - int mode = read_only ? O_RDONLY : O_RDWR; - ScopedFD fd(HANDLE_EINTR(open(path.value().c_str(), mode))); - ScopedFD readonly_fd(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY))); - if (!readonly_fd.is_valid()) { - DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed"; - return false; - } - int mapped_file = -1; - int readonly_mapped_file = -1; - bool result = PrepareMapFile(std::move(fd), std::move(readonly_fd), - &mapped_file, &readonly_mapped_file); - // This form of sharing shared memory is deprecated. https://crbug.com/345734. - // However, we can't get rid of it without a significant refactor because its - // used to communicate between two versions of the same service process, very - // early in the life cycle. - // Technically, we should also pass the GUID from the original shared memory - // region. We don't do that - this means that we will overcount this memory, - // which thankfully isn't relevant since Chrome only communicates with a - // single version of the service process. - // We pass the size |0|, which is a dummy size and wrong, but otherwise - // harmless. - shm_ = SharedMemoryHandle(FileDescriptor(mapped_file, false), 0u, - UnguessableToken::Create()); - readonly_shm_ = SharedMemoryHandle( - FileDescriptor(readonly_mapped_file, false), 0, shm_.GetGUID()); - return result; -} -#endif // !defined(OS_ANDROID) - -bool SharedMemory::MapAt(off_t offset, size_t bytes) { - if (!shm_.IsValid()) - return false; - - if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) - return false; - - if (memory_) - return false; - -#if defined(OS_ANDROID) - // On Android, Map can be called with a size and offset of zero to use the - // ashmem-determined size. - if (bytes == 0) { - DCHECK_EQ(0, offset); - int ashmem_bytes = ashmem_get_size_region(shm_.GetHandle()); - if (ashmem_bytes < 0) - return false; - bytes = ashmem_bytes; - } - - // Sanity check. This shall catch invalid uses of the SharedMemory APIs - // but will not protect against direct mmap() attempts. - if (shm_.IsReadOnly()) { - // Use a DCHECK() to call writable mappings with read-only descriptors - // in debug builds immediately. Return an error for release builds - // or during unit-testing (assuming a ScopedLogAssertHandler was installed). - DCHECK(read_only_) - << "Trying to map a region writable with a read-only descriptor."; - if (!read_only_) { - return false; - } - if (!shm_.SetRegionReadOnly()) { // Ensure the region is read-only. - return false; - } - } -#endif - - memory_ = mmap(nullptr, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE), - MAP_SHARED, shm_.GetHandle(), offset); - - bool mmap_succeeded = memory_ && memory_ != reinterpret_cast<void*>(-1); - if (mmap_succeeded) { - mapped_size_ = bytes; - mapped_id_ = shm_.GetGUID(); - DCHECK_EQ(0U, - reinterpret_cast<uintptr_t>(memory_) & - (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); - SharedMemoryTracker::GetInstance()->IncrementMemoryUsage(*this); - } else { - memory_ = nullptr; - } - - return mmap_succeeded; -} - -bool SharedMemory::Unmap() { - if (!memory_) - return false; - - SharedMemoryTracker::GetInstance()->DecrementMemoryUsage(*this); - munmap(memory_, mapped_size_); - memory_ = nullptr; - mapped_size_ = 0; - mapped_id_ = UnguessableToken(); - return true; -} - -SharedMemoryHandle SharedMemory::handle() const { - return shm_; -} - -SharedMemoryHandle SharedMemory::TakeHandle() { - SharedMemoryHandle handle_copy = shm_; - handle_copy.SetOwnershipPassesToIPC(true); - Unmap(); - shm_ = SharedMemoryHandle(); - return handle_copy; -} - -#if !defined(OS_ANDROID) -void SharedMemory::Close() { - if (shm_.IsValid()) { - shm_.Close(); - shm_ = SharedMemoryHandle(); - } - if (readonly_shm_.IsValid()) { - readonly_shm_.Close(); - readonly_shm_ = SharedMemoryHandle(); - } -} - -// For the given shmem named |mem_name|, return a filename to mmap() -// (and possibly create). Modifies |filename|. Return false on -// error, or true of we are happy. -bool SharedMemory::FilePathForMemoryName(const std::string& mem_name, - FilePath* path) { - // mem_name will be used for a filename; make sure it doesn't - // contain anything which will confuse us. - DCHECK_EQ(std::string::npos, mem_name.find('/')); - DCHECK_EQ(std::string::npos, mem_name.find('\0')); - - FilePath temp_dir; - if (!GetShmemTempDir(false, &temp_dir)) - return false; - -#if defined(GOOGLE_CHROME_BUILD) - static const char kShmem[] = "com.google.Chrome.shmem."; -#else - static const char kShmem[] = "org.chromium.Chromium.shmem."; -#endif - CR_DEFINE_STATIC_LOCAL(const std::string, name_base, (kShmem)); - *path = temp_dir.AppendASCII(name_base + mem_name); - return true; -} - -SharedMemoryHandle SharedMemory::GetReadOnlyHandle() const { - CHECK(readonly_shm_.IsValid()); - return readonly_shm_.Duplicate(); -} -#endif // !defined(OS_ANDROID) - -} // namespace base
diff --git a/base/memory/shared_memory_tracker.cc b/base/memory/shared_memory_tracker.cc deleted file mode 100644 index ee2b490..0000000 --- a/base/memory/shared_memory_tracker.cc +++ /dev/null
@@ -1,62 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/shared_memory_tracker.h" - -#include "base/memory/shared_memory.h" -#include "base/strings/string_number_conversions.h" - -namespace base { - -const char SharedMemoryTracker::kDumpRootName[] = "shared_memory"; - -// static -SharedMemoryTracker* SharedMemoryTracker::GetInstance() { - static SharedMemoryTracker* instance = new SharedMemoryTracker; - return instance; -} - -// static -std::string SharedMemoryTracker::GetDumpNameForTracing( - const UnguessableToken& id) { - DCHECK(!id.is_empty()); - return std::string(kDumpRootName) + "/" + id.ToString(); -} - -void SharedMemoryTracker::IncrementMemoryUsage( - const SharedMemory& shared_memory) { - AutoLock hold(usages_lock_); - DCHECK(usages_.find(shared_memory.memory()) == usages_.end()); - usages_.emplace(shared_memory.memory(), UsageInfo(shared_memory.mapped_size(), - shared_memory.mapped_id())); -} - -void SharedMemoryTracker::IncrementMemoryUsage( - const SharedMemoryMapping& mapping) { - AutoLock hold(usages_lock_); - DCHECK(usages_.find(mapping.raw_memory_ptr()) == usages_.end()); - usages_.emplace(mapping.raw_memory_ptr(), - UsageInfo(mapping.mapped_size(), mapping.guid())); -} - -void SharedMemoryTracker::DecrementMemoryUsage( - const SharedMemory& shared_memory) { - AutoLock hold(usages_lock_); - DCHECK(usages_.find(shared_memory.memory()) != usages_.end()); - usages_.erase(shared_memory.memory()); -} - -void SharedMemoryTracker::DecrementMemoryUsage( - const SharedMemoryMapping& mapping) { - AutoLock hold(usages_lock_); - DCHECK(usages_.find(mapping.raw_memory_ptr()) != usages_.end()); - usages_.erase(mapping.raw_memory_ptr()); -} - -SharedMemoryTracker::SharedMemoryTracker() { -} - -SharedMemoryTracker::~SharedMemoryTracker() = default; - -} // namespace
diff --git a/base/memory/shared_memory_tracker.h b/base/memory/shared_memory_tracker.h deleted file mode 100644 index 72c7b7a..0000000 --- a/base/memory/shared_memory_tracker.h +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_SHARED_MEMORY_TRACKER_H_ -#define BASE_MEMORY_SHARED_MEMORY_TRACKER_H_ - -#include <map> -#include <string> - -#include "base/memory/shared_memory.h" -#include "base/memory/shared_memory_mapping.h" -#include "base/synchronization/lock.h" - -namespace base { - -// SharedMemoryTracker tracks shared memory usage. -class BASE_EXPORT SharedMemoryTracker { - public: - // Returns a singleton instance. - static SharedMemoryTracker* GetInstance(); - - static std::string GetDumpNameForTracing(const UnguessableToken& id); - - // Records shared memory usage on valid mapping. - void IncrementMemoryUsage(const SharedMemory& shared_memory); - void IncrementMemoryUsage(const SharedMemoryMapping& mapping); - - // Records shared memory usage on unmapping. - void DecrementMemoryUsage(const SharedMemory& shared_memory); - void DecrementMemoryUsage(const SharedMemoryMapping& mapping); - - // Root dump name for all shared memory dumps. - static const char kDumpRootName[]; - - private: - SharedMemoryTracker(); - ~SharedMemoryTracker(); - - // Information associated with each mapped address. - struct UsageInfo { - UsageInfo(size_t size, const UnguessableToken& id) - : mapped_size(size), mapped_id(id) {} - - size_t mapped_size; - UnguessableToken mapped_id; - }; - - // Used to lock when |usages_| is modified or read. - Lock usages_lock_; - std::map<void*, UsageInfo> usages_; - - DISALLOW_COPY_AND_ASSIGN(SharedMemoryTracker); -}; - -} // namespace base - -#endif // BASE_MEMORY_SHARED_MEMORY_TRACKER_H_
diff --git a/base/memory/shared_memory_win.cc b/base/memory/shared_memory_win.cc deleted file mode 100644 index cf06dd3..0000000 --- a/base/memory/shared_memory_win.cc +++ /dev/null
@@ -1,381 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/shared_memory.h" - -#include <aclapi.h> -#include <stddef.h> -#include <stdint.h> - -#include "base/allocator/partition_allocator/page_allocator.h" -#include "base/logging.h" -#include "base/memory/shared_memory_tracker.h" -#include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros.h" -#include "base/rand_util.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "base/unguessable_token.h" - -namespace base { -namespace { - -// Errors that can occur during Shared Memory construction. -// These match tools/metrics/histograms/histograms.xml. -// This enum is append-only. -enum CreateError { - SUCCESS = 0, - SIZE_ZERO = 1, - SIZE_TOO_LARGE = 2, - INITIALIZE_ACL_FAILURE = 3, - INITIALIZE_SECURITY_DESC_FAILURE = 4, - SET_SECURITY_DESC_FAILURE = 5, - CREATE_FILE_MAPPING_FAILURE = 6, - REDUCE_PERMISSIONS_FAILURE = 7, - ALREADY_EXISTS = 8, - CREATE_ERROR_LAST = ALREADY_EXISTS -}; - -// Emits UMA metrics about encountered errors. Pass zero (0) for |winerror| -// if there is no associated Windows error. -void LogError(CreateError error, DWORD winerror) { - UMA_HISTOGRAM_ENUMERATION("SharedMemory.CreateError", error, - CREATE_ERROR_LAST + 1); - static_assert(ERROR_SUCCESS == 0, "Windows error code changed!"); - if (winerror != ERROR_SUCCESS) - UmaHistogramSparse("SharedMemory.CreateWinError", winerror); -} - -typedef enum _SECTION_INFORMATION_CLASS { - SectionBasicInformation, -} SECTION_INFORMATION_CLASS; - -typedef struct _SECTION_BASIC_INFORMATION { - PVOID BaseAddress; - ULONG Attributes; - LARGE_INTEGER Size; -} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION; - -typedef ULONG(__stdcall* NtQuerySectionType)( - HANDLE SectionHandle, - SECTION_INFORMATION_CLASS SectionInformationClass, - PVOID SectionInformation, - ULONG SectionInformationLength, - PULONG ResultLength); - -// Returns the length of the memory section starting at the supplied address. -size_t GetMemorySectionSize(void* address) { - MEMORY_BASIC_INFORMATION memory_info; - if (!::VirtualQuery(address, &memory_info, sizeof(memory_info))) - return 0; - return memory_info.RegionSize - (static_cast<char*>(address) - - static_cast<char*>(memory_info.AllocationBase)); -} - -// Checks if the section object is safe to map. At the moment this just means -// it's not an image section. -bool IsSectionSafeToMap(HANDLE handle) { - static NtQuerySectionType nt_query_section_func; - if (!nt_query_section_func) { - nt_query_section_func = reinterpret_cast<NtQuerySectionType>( - ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), "NtQuerySection")); - DCHECK(nt_query_section_func); - } - - // The handle must have SECTION_QUERY access for this to succeed. - SECTION_BASIC_INFORMATION basic_information = {}; - ULONG status = - nt_query_section_func(handle, SectionBasicInformation, &basic_information, - sizeof(basic_information), nullptr); - if (status) - return false; - return (basic_information.Attributes & SEC_IMAGE) != SEC_IMAGE; -} - -// Returns a HANDLE on success and |nullptr| on failure. -// This function is similar to CreateFileMapping, but removes the permissions -// WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE. -// -// A newly created file mapping has two sets of permissions. It has access -// control permissions (WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE) and -// file permissions (FILE_MAP_READ, FILE_MAP_WRITE, etc.). ::DuplicateHandle() -// with the parameter DUPLICATE_SAME_ACCESS copies both sets of permissions. -// -// The Chrome sandbox prevents HANDLEs with the WRITE_DAC permission from being -// duplicated into unprivileged processes. But the only way to copy file -// permissions is with the parameter DUPLICATE_SAME_ACCESS. This means that -// there is no way for a privileged process to duplicate a file mapping into an -// unprivileged process while maintaining the previous file permissions. -// -// By removing all access control permissions of a file mapping immediately -// after creation, ::DuplicateHandle() effectively only copies the file -// permissions. -HANDLE CreateFileMappingWithReducedPermissions(SECURITY_ATTRIBUTES* sa, - size_t rounded_size, - LPCWSTR name) { - HANDLE h = CreateFileMapping(INVALID_HANDLE_VALUE, sa, PAGE_READWRITE, 0, - static_cast<DWORD>(rounded_size), name); - if (!h) { - LogError(CREATE_FILE_MAPPING_FAILURE, GetLastError()); - return nullptr; - } - - HANDLE h2; - BOOL success = ::DuplicateHandle( - GetCurrentProcess(), h, GetCurrentProcess(), &h2, - FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY, FALSE, 0); - BOOL rv = ::CloseHandle(h); - DCHECK(rv); - - if (!success) { - LogError(REDUCE_PERMISSIONS_FAILURE, GetLastError()); - return nullptr; - } - - return h2; -} - -} // namespace. - -SharedMemory::SharedMemory() {} - -SharedMemory::SharedMemory(const string16& name) : name_(name) {} - -SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) - : external_section_(true), shm_(handle), read_only_(read_only) {} - -SharedMemory::~SharedMemory() { - Unmap(); - Close(); -} - -// static -bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { - return handle.IsValid(); -} - -// static -void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { - handle.Close(); -} - -// static -size_t SharedMemory::GetHandleLimit() { - // Rounded down from value reported here: - // http://blogs.technet.com/b/markrussinovich/archive/2009/09/29/3283844.aspx - return static_cast<size_t>(1 << 23); -} - -// static -SharedMemoryHandle SharedMemory::DuplicateHandle( - const SharedMemoryHandle& handle) { - return handle.Duplicate(); -} - -bool SharedMemory::CreateAndMapAnonymous(size_t size) { - return CreateAnonymous(size) && Map(size); -} - -bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { - // TODO(crbug.com/210609): NaCl forces us to round up 64k here, wasting 32k - // per mapping on average. - static const size_t kSectionMask = 65536 - 1; - DCHECK(!options.executable); - DCHECK(!shm_.IsValid()); - if (options.size == 0) { - LogError(SIZE_ZERO, 0); - return false; - } - - // Check maximum accounting for overflow. - if (options.size > - static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask) { - LogError(SIZE_TOO_LARGE, 0); - return false; - } - - size_t rounded_size = (options.size + kSectionMask) & ~kSectionMask; - name_ = options.name_deprecated ? - ASCIIToUTF16(*options.name_deprecated) : L""; - SECURITY_ATTRIBUTES sa = {sizeof(sa), nullptr, FALSE}; - SECURITY_DESCRIPTOR sd; - ACL dacl; - - if (name_.empty()) { - // Add an empty DACL to enforce anonymous read-only sections. - sa.lpSecurityDescriptor = &sd; - if (!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION)) { - LogError(INITIALIZE_ACL_FAILURE, GetLastError()); - return false; - } - if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { - LogError(INITIALIZE_SECURITY_DESC_FAILURE, GetLastError()); - return false; - } - if (!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE)) { - LogError(SET_SECURITY_DESC_FAILURE, GetLastError()); - return false; - } - - // Windows ignores DACLs on certain unnamed objects (like shared sections). - // So, we generate a random name when we need to enforce read-only. - uint64_t rand_values[4]; - RandBytes(&rand_values, sizeof(rand_values)); - name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", - rand_values[0], rand_values[1], - rand_values[2], rand_values[3]); - } - DCHECK(!name_.empty()); - shm_ = SharedMemoryHandle( - CreateFileMappingWithReducedPermissions(&sa, rounded_size, name_.c_str()), - rounded_size, UnguessableToken::Create()); - if (!shm_.IsValid()) { - // The error is logged within CreateFileMappingWithReducedPermissions(). - return false; - } - - requested_size_ = options.size; - - // Check if the shared memory pre-exists. - if (GetLastError() == ERROR_ALREADY_EXISTS) { - // If the file already existed, set requested_size_ to 0 to show that - // we don't know the size. - requested_size_ = 0; - external_section_ = true; - if (!options.open_existing_deprecated) { - Close(); - // From "if" above: GetLastError() == ERROR_ALREADY_EXISTS. - LogError(ALREADY_EXISTS, ERROR_ALREADY_EXISTS); - return false; - } - } - - LogError(SUCCESS, ERROR_SUCCESS); - return true; -} - -bool SharedMemory::Delete(const std::string& name) { - // intentionally empty -- there is nothing for us to do on Windows. - return true; -} - -bool SharedMemory::Open(const std::string& name, bool read_only) { - DCHECK(!shm_.IsValid()); - DWORD access = FILE_MAP_READ | SECTION_QUERY; - if (!read_only) - access |= FILE_MAP_WRITE; - name_ = ASCIIToUTF16(name); - read_only_ = read_only; - - // This form of sharing shared memory is deprecated. https://crbug.com/345734. - // However, we can't get rid of it without a significant refactor because its - // used to communicate between two versions of the same service process, very - // early in the life cycle. - // Technically, we should also pass the GUID from the original shared memory - // region. We don't do that - this means that we will overcount this memory, - // which thankfully isn't relevant since Chrome only communicates with a - // single version of the service process. - // We pass the size |0|, which is a dummy size and wrong, but otherwise - // harmless. - shm_ = SharedMemoryHandle( - OpenFileMapping(access, false, name_.empty() ? nullptr : name_.c_str()), - 0u, UnguessableToken::Create()); - if (!shm_.IsValid()) - return false; - // If a name specified assume it's an external section. - if (!name_.empty()) - external_section_ = true; - // Note: size_ is not set in this case. - return true; -} - -bool SharedMemory::MapAt(off_t offset, size_t bytes) { - if (!shm_.IsValid()) { - DLOG(ERROR) << "Invalid SharedMemoryHandle."; - return false; - } - - if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) { - DLOG(ERROR) << "Bytes required exceeds the 2G limitation."; - return false; - } - - if (memory_) { - DLOG(ERROR) << "The SharedMemory has been mapped already."; - return false; - } - - if (external_section_ && !IsSectionSafeToMap(shm_.GetHandle())) { - DLOG(ERROR) << "SharedMemoryHandle is not safe to be mapped."; - return false; - } - - // Try to map the shared memory. On the first failure, release any reserved - // address space for a single retry. - for (int i = 0; i < 2; ++i) { - memory_ = MapViewOfFile( - shm_.GetHandle(), - read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, - static_cast<uint64_t>(offset) >> 32, static_cast<DWORD>(offset), bytes); - if (memory_) - break; - ReleaseReservation(); - } - if (!memory_) { - DPLOG(ERROR) << "Failed executing MapViewOfFile"; - return false; - } - - DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) & - (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); - mapped_size_ = GetMemorySectionSize(memory_); - mapped_id_ = shm_.GetGUID(); - SharedMemoryTracker::GetInstance()->IncrementMemoryUsage(*this); - return true; -} - -bool SharedMemory::Unmap() { - if (!memory_) - return false; - - SharedMemoryTracker::GetInstance()->DecrementMemoryUsage(*this); - UnmapViewOfFile(memory_); - memory_ = nullptr; - mapped_id_ = UnguessableToken(); - return true; -} - -SharedMemoryHandle SharedMemory::GetReadOnlyHandle() const { - HANDLE result; - ProcessHandle process = GetCurrentProcess(); - if (!::DuplicateHandle(process, shm_.GetHandle(), process, &result, - FILE_MAP_READ | SECTION_QUERY, FALSE, 0)) { - return SharedMemoryHandle(); - } - SharedMemoryHandle handle = - SharedMemoryHandle(result, shm_.GetSize(), shm_.GetGUID()); - handle.SetOwnershipPassesToIPC(true); - return handle; -} - -void SharedMemory::Close() { - if (shm_.IsValid()) { - shm_.Close(); - shm_ = SharedMemoryHandle(); - } -} - -SharedMemoryHandle SharedMemory::handle() const { - return shm_; -} - -SharedMemoryHandle SharedMemory::TakeHandle() { - SharedMemoryHandle handle(shm_); - handle.SetOwnershipPassesToIPC(true); - Unmap(); - shm_ = SharedMemoryHandle(); - return handle; -} - -} // namespace base
diff --git a/base/memory/unsafe_shared_memory_region.cc b/base/memory/unsafe_shared_memory_region.cc deleted file mode 100644 index 422b5a9..0000000 --- a/base/memory/unsafe_shared_memory_region.cc +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/unsafe_shared_memory_region.h" - -#include <utility> - -#include "base/memory/shared_memory.h" - -namespace base { - -// static -UnsafeSharedMemoryRegion UnsafeSharedMemoryRegion::Create(size_t size) { - subtle::PlatformSharedMemoryRegion handle = - subtle::PlatformSharedMemoryRegion::CreateUnsafe(size); - - return UnsafeSharedMemoryRegion(std::move(handle)); -} - -// static -UnsafeSharedMemoryRegion UnsafeSharedMemoryRegion::Deserialize( - subtle::PlatformSharedMemoryRegion handle) { - return UnsafeSharedMemoryRegion(std::move(handle)); -} - -// static -subtle::PlatformSharedMemoryRegion -UnsafeSharedMemoryRegion::TakeHandleForSerialization( - UnsafeSharedMemoryRegion region) { - return std::move(region.handle_); -} - -UnsafeSharedMemoryRegion::UnsafeSharedMemoryRegion() = default; -UnsafeSharedMemoryRegion::UnsafeSharedMemoryRegion( - UnsafeSharedMemoryRegion&& region) = default; -UnsafeSharedMemoryRegion& UnsafeSharedMemoryRegion::operator=( - UnsafeSharedMemoryRegion&& region) = default; -UnsafeSharedMemoryRegion::~UnsafeSharedMemoryRegion() = default; - -UnsafeSharedMemoryRegion UnsafeSharedMemoryRegion::Duplicate() const { - return UnsafeSharedMemoryRegion(handle_.Duplicate()); -} - -WritableSharedMemoryMapping UnsafeSharedMemoryRegion::Map() const { - return MapAt(0, handle_.GetSize()); -} - -WritableSharedMemoryMapping UnsafeSharedMemoryRegion::MapAt(off_t offset, - size_t size) const { - if (!IsValid()) - return {}; - - void* memory = nullptr; - size_t mapped_size = 0; - if (!handle_.MapAt(offset, size, &memory, &mapped_size)) - return {}; - - return WritableSharedMemoryMapping(memory, size, mapped_size, - handle_.GetGUID()); -} - -bool UnsafeSharedMemoryRegion::IsValid() const { - return handle_.IsValid(); -} - -UnsafeSharedMemoryRegion::UnsafeSharedMemoryRegion( - subtle::PlatformSharedMemoryRegion handle) - : handle_(std::move(handle)) { - if (handle_.IsValid()) { - CHECK_EQ(handle_.GetMode(), - subtle::PlatformSharedMemoryRegion::Mode::kUnsafe); - } -} - -} // namespace base
diff --git a/base/memory/unsafe_shared_memory_region.h b/base/memory/unsafe_shared_memory_region.h deleted file mode 100644 index d77eaaa..0000000 --- a/base/memory/unsafe_shared_memory_region.h +++ /dev/null
@@ -1,112 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef 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/memory/platform_shared_memory_region.h" -#include "base/memory/shared_memory_mapping.h" - -namespace base { - -// Scoped move-only handle to a region of platform shared memory. The instance -// owns the platform handle it wraps. Mappings created by this region are -// writable. These mappings remain valid even after the region handle is moved -// or destroyed. -// -// NOTE: UnsafeSharedMemoryRegion cannot be converted to a read-only region. Use -// with caution as the region will be writable to any process with a handle to -// the region. -// -// Use this if and only if the following is true: -// - You do not need to share the region as read-only, and, -// - You need to have several instances of the region simultaneously, possibly -// in different processes, that can produce writable mappings. - -class BASE_EXPORT UnsafeSharedMemoryRegion { - public: - using MappingType = WritableSharedMemoryMapping; - // Creates a new UnsafeSharedMemoryRegion instance of a given size that can be - // used for mapping writable shared memory into the virtual address space. - static UnsafeSharedMemoryRegion Create(size_t size); - - // Returns an UnsafeSharedMemoryRegion built from a platform-specific handle - // that was taken from another UnsafeSharedMemoryRegion instance. Returns an - // invalid region iff the |handle| is invalid. CHECK-fails if the |handle| - // isn't unsafe. - // This should be used only by the code passing a handle across - // process boundaries. - static UnsafeSharedMemoryRegion Deserialize( - subtle::PlatformSharedMemoryRegion handle); - - // Extracts a platform handle from the region. Ownership is transferred to the - // returned region object. - // This should be used only for sending the handle from the current - // process to another. - static subtle::PlatformSharedMemoryRegion TakeHandleForSerialization( - UnsafeSharedMemoryRegion region); - - // Default constructor initializes an invalid instance. - UnsafeSharedMemoryRegion(); - - // Move operations are allowed. - UnsafeSharedMemoryRegion(UnsafeSharedMemoryRegion&&); - UnsafeSharedMemoryRegion& operator=(UnsafeSharedMemoryRegion&&); - - // Destructor closes shared memory region if valid. - // All created mappings will remain valid. - ~UnsafeSharedMemoryRegion(); - - // Duplicates the underlying platform handle and creates a new - // UnsafeSharedMemoryRegion instance that owns the newly created handle. - // Returns a valid UnsafeSharedMemoryRegion on success, invalid otherwise. - // The current region instance remains valid in any case. - UnsafeSharedMemoryRegion Duplicate() const; - - // Maps the shared memory region into the caller's address space with write - // access. The mapped address is guaranteed to have an alignment of - // at least |subtle::PlatformSharedMemoryRegion::kMapMinimumAlignment|. - // Returns a valid WritableSharedMemoryMapping instance on success, invalid - // otherwise. - WritableSharedMemoryMapping Map() const; - - // Same as above, but maps only |size| bytes of the shared memory region - // starting with the given |offset|. |offset| must be aligned to value of - // |SysInfo::VMAllocationGranularity()|. Returns an invalid mapping if - // requested bytes are out of the region limits. - WritableSharedMemoryMapping MapAt(off_t offset, size_t size) const; - - // Whether the underlying platform handle is valid. - bool IsValid() const; - - // Returns the maximum mapping size that can be created from this region. - size_t GetSize() const { - DCHECK(IsValid()); - return handle_.GetSize(); - } - - private: - FRIEND_TEST_ALL_PREFIXES(DiscardableSharedMemoryTest, - LockShouldFailIfPlatformLockPagesFails); - friend class DiscardableSharedMemory; - - 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_; - - DISALLOW_COPY_AND_ASSIGN(UnsafeSharedMemoryRegion); -}; - -} // namespace base - -#endif // BASE_MEMORY_UNSAFE_SHARED_MEMORY_REGION_H_
diff --git a/base/memory/writable_shared_memory_region.cc b/base/memory/writable_shared_memory_region.cc deleted file mode 100644 index 7a29522..0000000 --- a/base/memory/writable_shared_memory_region.cc +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/writable_shared_memory_region.h" - -#include <utility> - -#include "base/memory/shared_memory.h" -#include "build_config.h" - -namespace base { - -// static -WritableSharedMemoryRegion WritableSharedMemoryRegion::Create(size_t size) { - subtle::PlatformSharedMemoryRegion handle = - subtle::PlatformSharedMemoryRegion::CreateWritable(size); - - return WritableSharedMemoryRegion(std::move(handle)); -} - -// static -WritableSharedMemoryRegion WritableSharedMemoryRegion::Deserialize( - subtle::PlatformSharedMemoryRegion handle) { - return WritableSharedMemoryRegion(std::move(handle)); -} - -// static -subtle::PlatformSharedMemoryRegion -WritableSharedMemoryRegion::TakeHandleForSerialization( - WritableSharedMemoryRegion region) { - return std::move(region.handle_); -} - -// static -ReadOnlySharedMemoryRegion WritableSharedMemoryRegion::ConvertToReadOnly( - WritableSharedMemoryRegion region) { - subtle::PlatformSharedMemoryRegion handle = std::move(region.handle_); - if (!handle.ConvertToReadOnly()) - return {}; - - return ReadOnlySharedMemoryRegion::Deserialize(std::move(handle)); -} - -WritableSharedMemoryRegion::WritableSharedMemoryRegion() = default; -WritableSharedMemoryRegion::WritableSharedMemoryRegion( - WritableSharedMemoryRegion&& region) = default; -WritableSharedMemoryRegion& WritableSharedMemoryRegion::operator=( - WritableSharedMemoryRegion&& region) = default; -WritableSharedMemoryRegion::~WritableSharedMemoryRegion() = default; - -WritableSharedMemoryMapping WritableSharedMemoryRegion::Map() const { - return MapAt(0, handle_.GetSize()); -} - -WritableSharedMemoryMapping WritableSharedMemoryRegion::MapAt( - off_t offset, - size_t size) const { - if (!IsValid()) - return {}; - - void* memory = nullptr; - size_t mapped_size = 0; - if (!handle_.MapAt(offset, size, &memory, &mapped_size)) - return {}; - - return WritableSharedMemoryMapping(memory, size, mapped_size, - handle_.GetGUID()); -} - -bool WritableSharedMemoryRegion::IsValid() const { - return handle_.IsValid(); -} - -WritableSharedMemoryRegion::WritableSharedMemoryRegion( - subtle::PlatformSharedMemoryRegion handle) - : handle_(std::move(handle)) { - if (handle_.IsValid()) { - CHECK_EQ(handle_.GetMode(), - subtle::PlatformSharedMemoryRegion::Mode::kWritable); - } -} - -} // namespace base
diff --git a/base/memory/writable_shared_memory_region.h b/base/memory/writable_shared_memory_region.h deleted file mode 100644 index b953a10..0000000 --- a/base/memory/writable_shared_memory_region.h +++ /dev/null
@@ -1,97 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_WRITABLE_SHARED_MEMORY_REGION_H_ -#define BASE_MEMORY_WRITABLE_SHARED_MEMORY_REGION_H_ - -#include "base/macros.h" -#include "base/memory/platform_shared_memory_region.h" -#include "base/memory/read_only_shared_memory_region.h" -#include "base/memory/shared_memory_mapping.h" - -namespace base { - -// Scoped move-only handle to a region of platform shared memory. The instance -// owns the platform handle it wraps. Mappings created by this region are -// writable. These mappings remain valid even after the region handle is moved -// or destroyed. -// -// This region can be locked to read-only access by converting it to a -// ReadOnlySharedMemoryRegion. However, unlike ReadOnlySharedMemoryRegion and -// UnsafeSharedMemoryRegion, ownership of this region (while writable) is unique -// and may only be transferred, not duplicated. -class BASE_EXPORT WritableSharedMemoryRegion { - public: - using MappingType = WritableSharedMemoryMapping; - // Creates a new WritableSharedMemoryRegion instance of a given - // size that can be used for mapping writable shared memory into the virtual - // address space. - static WritableSharedMemoryRegion Create(size_t size); - - // Returns a WritableSharedMemoryRegion built from a platform handle that was - // taken from another WritableSharedMemoryRegion instance. Returns an invalid - // region iff the |handle| is invalid. CHECK-fails if the |handle| isn't - // writable. - // This should be used only by the code passing handles across process - // boundaries. - static WritableSharedMemoryRegion Deserialize( - subtle::PlatformSharedMemoryRegion handle); - - // Extracts a platform handle from the region. Ownership is transferred to the - // returned region object. - // This should be used only for sending the handle from the current - // process to another. - static subtle::PlatformSharedMemoryRegion TakeHandleForSerialization( - WritableSharedMemoryRegion region); - - // Makes the region read-only. No new writable mappings of the region can be - // created after this call. Returns an invalid region on failure. - static ReadOnlySharedMemoryRegion ConvertToReadOnly( - WritableSharedMemoryRegion region); - - // Default constructor initializes an invalid instance. - WritableSharedMemoryRegion(); - - // Move operations are allowed. - WritableSharedMemoryRegion(WritableSharedMemoryRegion&&); - WritableSharedMemoryRegion& operator=(WritableSharedMemoryRegion&&); - - // Destructor closes shared memory region if valid. - // All created mappings will remain valid. - ~WritableSharedMemoryRegion(); - - // Maps the shared memory region into the caller's address space with write - // access. The mapped address is guaranteed to have an alignment of - // at least |subtle::PlatformSharedMemoryRegion::kMapMinimumAlignment|. - // Returns a valid WritableSharedMemoryMapping instance on success, invalid - // otherwise. - WritableSharedMemoryMapping Map() const; - - // Same as above, but maps only |size| bytes of the shared memory block - // starting with the given |offset|. |offset| must be aligned to value of - // |SysInfo::VMAllocationGranularity()|. Returns an invalid mapping if - // requested bytes are out of the region limits. - WritableSharedMemoryMapping MapAt(off_t offset, size_t size) const; - - // Whether underlying platform handles are valid. - bool IsValid() const; - - // Returns the maximum mapping size that can be created from this region. - size_t GetSize() const { - DCHECK(IsValid()); - return handle_.GetSize(); - } - - private: - explicit WritableSharedMemoryRegion( - subtle::PlatformSharedMemoryRegion handle); - - subtle::PlatformSharedMemoryRegion handle_; - - DISALLOW_COPY_AND_ASSIGN(WritableSharedMemoryRegion); -}; - -} // namespace base - -#endif // BASE_MEMORY_WRITABLE_SHARED_MEMORY_REGION_H_
diff --git a/build/gen.py b/build/gen.py index 5f73187..95f8fe1 100755 --- a/build/gen.py +++ b/build/gen.py
@@ -263,13 +263,7 @@ 'base/location.cc', 'base/logging.cc', 'base/md5.cc', - 'base/memory/platform_shared_memory_region.cc', - 'base/memory/read_only_shared_memory_region.cc', 'base/memory/ref_counted.cc', - 'base/memory/ref_counted_memory.cc', - 'base/memory/shared_memory_mapping.cc', - 'base/memory/shared_memory_handle.cc', - 'base/memory/shared_memory_tracker.cc', 'base/memory/weak_ptr.cc', 'base/message_loop/incoming_task_queue.cc', 'base/message_loop/message_loop.cc', @@ -554,19 +548,6 @@ ], 'tool': 'cxx', 'include_dirs': [], 'libs': []}, } - if is_win: - static_libraries['base']['sources'].extend([ - 'base/memory/platform_shared_memory_region_win.cc' - ]) - elif is_mac: - static_libraries['base']['sources'].extend([ - 'base/memory/platform_shared_memory_region_mac.cc' - ]) - elif is_linux: - static_libraries['base']['sources'].extend([ - 'base/memory/platform_shared_memory_region_posix.cc' - ]) - if is_posix: static_libraries['base']['sources'].extend([ 'base/base_paths_posix.cc', @@ -577,7 +558,6 @@ 'base/files/file_posix.cc', 'base/files/file_util_posix.cc', 'base/files/memory_mapped_file_posix.cc', - 'base/memory/shared_memory_helper.cc', 'base/message_loop/message_pump_libevent.cc', 'base/posix/file_descriptor_shuffle.cc', 'base/posix/global_descriptors.cc', @@ -626,8 +606,6 @@ 'tool': 'cxx', } static_libraries['base']['sources'].extend([ - 'base/memory/shared_memory_handle_posix.cc', - 'base/memory/shared_memory_posix.cc', 'base/nix/xdg_util.cc', 'base/process/internal_linux.cc', 'base/process/memory_linux.cc', @@ -675,8 +653,6 @@ 'base/mac/scoped_mach_port.cc', 'base/mac/scoped_mach_vm.cc', 'base/mac/scoped_nsautorelease_pool.mm', - 'base/memory/shared_memory_handle_mac.cc', - 'base/memory/shared_memory_mac.cc', 'base/message_loop/message_pump_mac.mm', 'base/process/process_handle_mac.cc', 'base/process/process_info_mac.cc', @@ -723,9 +699,6 @@ 'base/files/memory_mapped_file_win.cc', 'base/guid.cc', 'base/logging_win.cc', - 'base/memory/memory_pressure_monitor_win.cc', - 'base/memory/shared_memory_handle_win.cc', - 'base/memory/shared_memory_win.cc', 'base/message_loop/message_pump_win.cc', 'base/native_library_win.cc', 'base/power_monitor/power_monitor_device_source_win.cc',