1
0
Fork 0
firefox/ipc/glue/SharedMemoryHandle.cpp
Daniel Baumann 5e9a113729
Adding upstream version 140.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-25 09:37:52 +02:00

231 lines
6.8 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* This source code was derived from Chromium code, and as such is also subject
* to the [Chromium license](ipc/chromium/src/LICENSE). */
#include "mozilla/ipc/SharedMemoryHandle.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "SharedMemoryPlatform.h"
#include "chrome/common/ipc_message_utils.h"
#include "mozilla/Atomics.h"
#include "nsDebug.h"
#include "nsIMemoryReporter.h"
namespace mozilla::ipc::shared_memory {
// Implementation of the shared memory logger in SharedMemoryPlatform.h.
LazyLogModule gSharedMemoryLog{"SharedMemory"};
class AllocationReporter final : public nsIMemoryReporter {
~AllocationReporter() = default;
public:
static Atomic<uint64_t> allocated;
NS_DECL_THREADSAFE_ISUPPORTS
NS_IMETHOD
CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
bool aAnonymize) override {
MOZ_COLLECT_REPORT(
"shmem-allocated", KIND_OTHER, UNITS_BYTES, allocated,
"Memory shared with other processes that is accessible (but not "
"necessarily mapped).");
return NS_OK;
}
};
Atomic<uint64_t> AllocationReporter::allocated;
NS_IMPL_ISUPPORTS(AllocationReporter, nsIMemoryReporter)
static void RegisterAllocationMemoryReporter() {
static Atomic<bool> registered;
if (registered.compareExchange(false, true)) {
RegisterStrongMemoryReporter(new AllocationReporter());
}
}
HandleBase::HandleBase() = default;
HandleBase::~HandleBase() {
if (mSize > 0) {
MOZ_ASSERT(AllocationReporter::allocated >= mSize,
"Can't destroy more than allocated");
SetSize(0);
}
mHandle = nullptr;
}
HandleBase& HandleBase::operator=(HandleBase&& aOther) {
mHandle = std::move(aOther.mHandle);
SetSize(std::exchange(aOther.mSize, 0));
return *this;
}
HandleBase HandleBase::Clone() const {
HandleBase hb;
hb.mHandle = Platform::CloneHandle(mHandle);
if (hb.mHandle) {
// TODO more intelligently handle clones to not count as additional
// allocations?
hb.SetSize(mSize);
}
return hb;
}
void HandleBase::ToMessageWriter(IPC::MessageWriter* aWriter) && {
WriteParam(aWriter, std::move(mHandle));
WriteParam(aWriter, mSize);
SetSize(0);
}
bool HandleBase::FromMessageReader(IPC::MessageReader* aReader) {
mozilla::ipc::shared_memory::PlatformHandle handle;
if (!ReadParam(aReader, &handle)) {
aReader->FatalError("Failed to read shared memory PlatformHandle");
return false;
}
if (handle && !Platform::IsSafeToMap(handle)) {
aReader->FatalError("Shared memory PlatformHandle is not safe to map");
return false;
}
uint64_t size = 0;
if (!ReadParam(aReader, &size)) {
aReader->FatalError("Failed to read shared memory handle size");
return false;
}
if (handle && !size) {
aReader->FatalError(
"Unexpected PlatformHandle for zero-sized shared memory handle");
return false;
}
mHandle = std::move(handle);
SetSize(size);
return true;
}
void HandleBase::SetSize(uint64_t aSize) {
RegisterAllocationMemoryReporter();
mozilla::ipc::shared_memory::AllocationReporter::allocated -= mSize;
mSize = aSize;
mozilla::ipc::shared_memory::AllocationReporter::allocated += mSize;
}
MutableMapping MutableHandle::Map(void* aFixedAddress) const {
return MutableMapping(*this, aFixedAddress);
}
MutableMapping MutableHandle::MapSubregion(uint64_t aOffset, size_t aSize,
void* aFixedAddress) const {
return MutableMapping(*this, aOffset, aSize, aFixedAddress);
}
MutableMappingWithHandle MutableHandle::MapWithHandle(void* aFixedAddress) && {
return MutableMappingWithHandle(std::move(*this), aFixedAddress);
}
ReadOnlyHandle MutableHandle::ToReadOnly() && {
return std::move(*this).ConvertTo<Type::ReadOnly>();
}
const ReadOnlyHandle& MutableHandle::AsReadOnly() const {
static_assert(sizeof(ReadOnlyHandle) == sizeof(MutableHandle));
return reinterpret_cast<const ReadOnlyHandle&>(*this);
}
ReadOnlyMapping ReadOnlyHandle::Map(void* aFixedAddress) const {
return ReadOnlyMapping(*this, aFixedAddress);
}
ReadOnlyMapping ReadOnlyHandle::MapSubregion(uint64_t aOffset, size_t aSize,
void* aFixedAddress) const {
return ReadOnlyMapping(*this, aOffset, aSize, aFixedAddress);
}
ReadOnlyMappingWithHandle ReadOnlyHandle::MapWithHandle(
void* aFixedAddress) && {
return ReadOnlyMappingWithHandle(std::move(*this), aFixedAddress);
}
FreezableHandle::~Handle() {
NS_WARNING_ASSERTION(!IsValid(), "freezable shared memory was never frozen");
}
MutableHandle FreezableHandle::WontFreeze() && {
return std::move(*this).ConvertTo<Type::Mutable>();
}
ReadOnlyHandle FreezableHandle::Freeze() && {
DebugOnly<const uint64_t> previous_size = Size();
if (Platform::Freeze(*this)) {
MOZ_ASSERT(Size() == previous_size);
return std::move(*this).ConvertTo<Type::ReadOnly>();
}
return nullptr;
}
FreezableMapping FreezableHandle::Map(void* aFixedAddress) && {
return FreezableMapping(std::move(*this), aFixedAddress);
}
FreezableMapping FreezableHandle::MapSubregion(uint64_t aOffset, size_t aSize,
void* aFixedAddress) && {
return FreezableMapping(std::move(*this), aOffset, aSize, aFixedAddress);
}
MutableHandle Create(uint64_t aSize) {
MutableHandle h;
const auto success = Platform::Create(h, aSize);
MOZ_ASSERT(success == h.IsValid());
if (success) {
MOZ_ASSERT(aSize == h.Size());
}
return h;
}
FreezableHandle CreateFreezable(uint64_t aSize) {
FreezableHandle h;
const auto success = Platform::CreateFreezable(h, aSize);
MOZ_ASSERT(success == h.IsValid());
if (success) {
MOZ_ASSERT(aSize == h.Size());
}
return h;
}
} // namespace mozilla::ipc::shared_memory
namespace IPC {
void ParamTraits<mozilla::ipc::shared_memory::MutableHandle>::Write(
MessageWriter* aWriter,
mozilla::ipc::shared_memory::MutableHandle&& aParam) {
std::move(aParam).ToMessageWriter(aWriter);
}
bool ParamTraits<mozilla::ipc::shared_memory::MutableHandle>::Read(
MessageReader* aReader,
mozilla::ipc::shared_memory::MutableHandle* aResult) {
return aResult->FromMessageReader(aReader);
}
void ParamTraits<mozilla::ipc::shared_memory::ReadOnlyHandle>::Write(
MessageWriter* aWriter,
mozilla::ipc::shared_memory::ReadOnlyHandle&& aParam) {
std::move(aParam).ToMessageWriter(aWriter);
}
bool ParamTraits<mozilla::ipc::shared_memory::ReadOnlyHandle>::Read(
MessageReader* aReader,
mozilla::ipc::shared_memory::ReadOnlyHandle* aResult) {
return aResult->FromMessageReader(aReader);
}
} // namespace IPC