Bug 1942129 pt4b - Remove use of RawShmem r=ipc-reviewers,nika,webgpu-reviewers,nical
Differential Revision: https://phabricator.services.mozilla.com/D236749
This commit is contained in:
@@ -42,11 +42,10 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Buffer)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
Buffer::Buffer(Device* const aParent, RawId aId, BufferAddress aSize,
|
||||
uint32_t aUsage, ipc::WritableSharedMemoryMapping&& aShmem)
|
||||
uint32_t aUsage, ipc::SharedMemoryMapping&& aShmem)
|
||||
: ChildOf(aParent), mId(aId), mSize(aSize), mUsage(aUsage) {
|
||||
mozilla::HoldJSObjects(this);
|
||||
mShmem =
|
||||
std::make_shared<ipc::WritableSharedMemoryMapping>(std::move(aShmem));
|
||||
mShmem = std::make_shared<ipc::SharedMemoryMapping>(std::move(aShmem));
|
||||
MOZ_ASSERT(mParent);
|
||||
}
|
||||
|
||||
@@ -63,14 +62,14 @@ already_AddRefed<Buffer> Buffer::Create(Device* aDevice, RawId aDeviceId,
|
||||
|
||||
if (!aDevice->IsBridgeAlive()) {
|
||||
// Create and return an invalid Buffer.
|
||||
RefPtr<Buffer> buffer = new Buffer(aDevice, bufferId, aDesc.mSize, 0,
|
||||
ipc::WritableSharedMemoryMapping());
|
||||
RefPtr<Buffer> buffer =
|
||||
new Buffer(aDevice, bufferId, aDesc.mSize, 0, nullptr);
|
||||
buffer->mValid = false;
|
||||
return buffer.forget();
|
||||
}
|
||||
|
||||
auto handle = ipc::UnsafeSharedMemoryHandle();
|
||||
auto mapping = ipc::WritableSharedMemoryMapping();
|
||||
ipc::MutableSharedMemoryHandle handle;
|
||||
ipc::SharedMemoryMapping mapping;
|
||||
|
||||
bool hasMapFlags = aDesc.mUsage & (dom::GPUBufferUsage_Binding::MAP_WRITE |
|
||||
dom::GPUBufferUsage_Binding::MAP_READ);
|
||||
@@ -85,17 +84,18 @@ already_AddRefed<Buffer> Buffer::Create(Device* aDevice, RawId aDeviceId,
|
||||
size_t size = checked.value();
|
||||
|
||||
if (size > 0 && size < maxSize) {
|
||||
auto maybeShmem = ipc::UnsafeSharedMemoryHandle::CreateAndMap(size);
|
||||
|
||||
if (maybeShmem.isSome()) {
|
||||
handle = ipc::shared_memory::Create(size);
|
||||
mapping = handle.Map();
|
||||
if (handle && mapping) {
|
||||
allocSucceeded = true;
|
||||
handle = std::move(maybeShmem.ref().first);
|
||||
mapping = std::move(maybeShmem.ref().second);
|
||||
|
||||
MOZ_RELEASE_ASSERT(mapping.Size() >= size);
|
||||
|
||||
// zero out memory
|
||||
memset(mapping.Bytes().data(), 0, size);
|
||||
memset(mapping.Address(), 0, size);
|
||||
} else {
|
||||
handle = nullptr;
|
||||
mapping = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,8 +259,7 @@ already_AddRefed<dom::Promise> Buffer::MapAsync(
|
||||
|
||||
static void ExternalBufferFreeCallback(void* aContents, void* aUserData) {
|
||||
Unused << aContents;
|
||||
auto shm = static_cast<std::shared_ptr<ipc::WritableSharedMemoryMapping>*>(
|
||||
aUserData);
|
||||
auto shm = static_cast<std::shared_ptr<ipc::SharedMemoryMapping>*>(aUserData);
|
||||
delete shm;
|
||||
}
|
||||
|
||||
@@ -353,8 +352,8 @@ void Buffer::GetMappedRange(JSContext* aCx, uint64_t aOffset,
|
||||
// unfortunately necessary: `JS::BufferContentsDeleter` requires that its
|
||||
// `userData` be a `void*`, and while `shared_ptr` can't be inter-converted
|
||||
// with `void*` (it's actually two pointers), `shared_ptr*` obviously can.
|
||||
std::shared_ptr<ipc::WritableSharedMemoryMapping>* data =
|
||||
new std::shared_ptr<ipc::WritableSharedMemoryMapping>(mShmem);
|
||||
std::shared_ptr<ipc::SharedMemoryMapping>* data =
|
||||
new std::shared_ptr<ipc::SharedMemoryMapping>(mShmem);
|
||||
|
||||
// 4. Let `view` be (potentially fallible operation follows) create an
|
||||
// `ArrayBuffer` of size `rangeSize`, but with its pointer mutably
|
||||
@@ -366,7 +365,8 @@ void Buffer::GetMappedRange(JSContext* aCx, uint64_t aOffset,
|
||||
// range for `size_t` before any conversion is performed.
|
||||
const auto checkedSize = CheckedInt<size_t>(rangeSize.value()).value();
|
||||
const auto checkedOffset = CheckedInt<size_t>(offset.value()).value();
|
||||
const auto span = (*data)->Bytes().Subspan(checkedOffset, checkedSize);
|
||||
const auto span =
|
||||
(*data)->DataAsSpan<uint8_t>().Subspan(checkedOffset, checkedSize);
|
||||
UniquePtr<void, JS::BufferContentsDeleter> contents{
|
||||
span.data(), {&ExternalBufferFreeCallback, data}};
|
||||
JS::Rooted<JSObject*> view(
|
||||
@@ -431,7 +431,7 @@ void Buffer::Unmap(JSContext* aCx, ErrorResult& aRv) {
|
||||
// We get here if the buffer was mapped at creation without map flags.
|
||||
// It won't be possible to map the buffer again so we can get rid of
|
||||
// our shmem on this side.
|
||||
mShmem = std::make_shared<ipc::WritableSharedMemoryMapping>();
|
||||
mShmem = std::make_shared<ipc::SharedMemoryMapping>();
|
||||
}
|
||||
|
||||
if (!GetDevice().IsLost()) {
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
#include "js/RootingAPI.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||
#include "mozilla/webgpu/WebGPUTypes.h"
|
||||
#include "nsTArray.h"
|
||||
#include "ObjectModel.h"
|
||||
#include "mozilla/ipc/RawShmem.h"
|
||||
#include <memory>
|
||||
|
||||
namespace mozilla {
|
||||
@@ -112,7 +112,7 @@ class Buffer final : public ObjectBase, public ChildOf<Device> {
|
||||
|
||||
private:
|
||||
Buffer(Device* const aParent, RawId aId, BufferAddress aSize, uint32_t aUsage,
|
||||
ipc::WritableSharedMemoryMapping&& aShmem);
|
||||
ipc::SharedMemoryMapping&& aShmem);
|
||||
virtual ~Buffer();
|
||||
Device& GetDevice() { return *mParent; }
|
||||
void Cleanup();
|
||||
@@ -143,10 +143,10 @@ class Buffer final : public ObjectBase, public ChildOf<Device> {
|
||||
// and destroyed when we first unmap the buffer, by clearing this
|
||||
// `shared_ptr`.
|
||||
//
|
||||
// Otherwise, this points to `WritableSharedMemoryMapping()` (the
|
||||
// default constructor), a zero-length mapping that doesn't point to
|
||||
// any shared memory.
|
||||
std::shared_ptr<ipc::WritableSharedMemoryMapping> mShmem;
|
||||
// Otherwise, this points to `SharedMemoryMapping()` (the default
|
||||
// constructor), a zero-length mapping that doesn't point to any shared
|
||||
// memory.
|
||||
std::shared_ptr<ipc::SharedMemoryMapping> mShmem;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/WebGLTexelConversions.h"
|
||||
#include "mozilla/dom/WebGLTypes.h"
|
||||
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "Utility.h"
|
||||
|
||||
@@ -118,16 +120,17 @@ void Queue::WriteBuffer(const Buffer& aBuffer, uint64_t aBufferOffset,
|
||||
return;
|
||||
}
|
||||
|
||||
auto alloc = mozilla::ipc::UnsafeSharedMemoryHandle::CreateAndMap(size);
|
||||
if (alloc.isNothing()) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
mozilla::ipc::MutableSharedMemoryHandle handle;
|
||||
if (size != 0) {
|
||||
handle = mozilla::ipc::shared_memory::Create(size);
|
||||
auto mapping = handle.Map();
|
||||
if (!handle || !mapping) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(mapping.DataAs<uint8_t>(), aData.Elements() + offset, size);
|
||||
}
|
||||
|
||||
auto handle = std::move(alloc.ref().first);
|
||||
auto mapping = std::move(alloc.ref().second);
|
||||
|
||||
memcpy(mapping.Bytes().data(), aData.Elements() + offset, size);
|
||||
ipc::ByteBuf bb;
|
||||
ffi::wgpu_queue_write_buffer(aBuffer.mId, aBufferOffset, ToFFI(&bb));
|
||||
mBridge->SendQueueWriteAction(mId, mParent->mId, std::move(bb),
|
||||
@@ -161,18 +164,19 @@ void Queue::WriteTexture(const dom::GPUTexelCopyTextureInfo& aDestination,
|
||||
}
|
||||
const auto size = checkedSize.value();
|
||||
|
||||
auto alloc = mozilla::ipc::UnsafeSharedMemoryHandle::CreateAndMap(size);
|
||||
if (alloc.isNothing()) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
mozilla::ipc::MutableSharedMemoryHandle handle;
|
||||
if (size != 0) {
|
||||
handle = mozilla::ipc::shared_memory::Create(size);
|
||||
auto mapping = handle.Map();
|
||||
if (!handle || !mapping) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(mapping.DataAs<uint8_t>(), aData.Elements() + aDataLayout.mOffset,
|
||||
size);
|
||||
}
|
||||
|
||||
auto handle = std::move(alloc.ref().first);
|
||||
auto mapping = std::move(alloc.ref().second);
|
||||
|
||||
memcpy(mapping.Bytes().data(), aData.Elements() + aDataLayout.mOffset,
|
||||
size);
|
||||
|
||||
ipc::ByteBuf bb;
|
||||
ffi::wgpu_queue_write_texture(copyView, dataLayout, extent, ToFFI(&bb));
|
||||
mBridge->SendQueueWriteAction(mId, mParent->mId, std::move(bb),
|
||||
@@ -395,18 +399,15 @@ void Queue::CopyExternalImageToTexture(
|
||||
return;
|
||||
}
|
||||
|
||||
auto alloc = mozilla::ipc::UnsafeSharedMemoryHandle::CreateAndMap(
|
||||
dstByteLength.value());
|
||||
if (alloc.isNothing()) {
|
||||
auto handle = mozilla::ipc::shared_memory::Create(dstByteLength.value());
|
||||
auto mapping = handle.Map();
|
||||
if (!handle || !mapping) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
auto handle = std::move(alloc.ref().first);
|
||||
auto mapping = std::move(alloc.ref().second);
|
||||
|
||||
const int32_t pixelSize = gfx::BytesPerPixel(surfaceFormat);
|
||||
auto* dstBegin = mapping.Bytes().data();
|
||||
auto* dstBegin = mapping.DataAs<uint8_t>();
|
||||
const auto* srcBegin =
|
||||
map.GetData() + srcOriginX * pixelSize + srcOriginY * map.GetStride();
|
||||
const auto srcOriginPos = gl::OriginPos::TopLeft;
|
||||
|
||||
@@ -17,7 +17,7 @@ using mozilla::dom::GPUCommandBufferDescriptor from "mozilla/dom/WebGPUBinding.h
|
||||
using mozilla::dom::GPUBufferDescriptor from "mozilla/dom/WebGPUBinding.h";
|
||||
using mozilla::webgpu::PopErrorScopeResult from "mozilla/webgpu/WebGPUTypes.h";
|
||||
using mozilla::webgpu::WebGPUCompilationMessage from "mozilla/webgpu/WebGPUTypes.h";
|
||||
[MoveOnly] using class mozilla::ipc::UnsafeSharedMemoryHandle from "mozilla/ipc/RawShmem.h";
|
||||
[MoveOnly] using mozilla::ipc::MutableSharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h";
|
||||
using struct mozilla::void_t from "mozilla/ipc/IPCCore.h";
|
||||
|
||||
include "mozilla/ipc/ByteBufUtils.h";
|
||||
@@ -48,7 +48,7 @@ parent:
|
||||
async ComputePass(RawId selfId, RawId aDeviceId, ByteBuf buf);
|
||||
async BumpImplicitBindGroupLayout(RawId pipelineId, bool isCompute, uint32_t index, RawId assignId);
|
||||
|
||||
async DeviceCreateBuffer(RawId deviceId, RawId bufferId, GPUBufferDescriptor desc, UnsafeSharedMemoryHandle shm);
|
||||
async DeviceCreateBuffer(RawId deviceId, RawId bufferId, GPUBufferDescriptor desc, MutableSharedMemoryHandle shm);
|
||||
|
||||
async InstanceRequestAdapter(GPURequestAdapterOptions options, RawId aAdapterId) returns (ByteBuf byteBuf);
|
||||
async AdapterRequestDevice(
|
||||
@@ -77,7 +77,8 @@ parent:
|
||||
async RenderBundleDrop(RawId selfId);
|
||||
async QueueSubmit(RawId selfId, RawId aDeviceId, RawId[] commandBuffers, RawId[] textureIds);
|
||||
async QueueOnSubmittedWorkDone(RawId selfId) returns (void_t ok);
|
||||
async QueueWriteAction(RawId selfId, RawId aDeviceId, ByteBuf buf, UnsafeSharedMemoryHandle shmem);
|
||||
// In the case of a zero-sized write action, `shmem` will be an invalid handle.
|
||||
async QueueWriteAction(RawId selfId, RawId aDeviceId, ByteBuf buf, MutableSharedMemoryHandle shmem);
|
||||
|
||||
async BindGroupLayoutDrop(RawId selfId);
|
||||
async PipelineLayoutDrop(RawId selfId);
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "PipelineLayout.h"
|
||||
#include "Sampler.h"
|
||||
#include "CompilationInfo.h"
|
||||
#include "mozilla/ipc/RawShmem.h"
|
||||
#include "Utility.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
#include "mozilla/webgpu/ffi/wgpu.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
class UnsafeSharedMemoryHandle;
|
||||
} // namespace ipc
|
||||
namespace dom {
|
||||
struct GPURequestAdapterOptions;
|
||||
} // namespace dom
|
||||
|
||||
@@ -549,11 +549,10 @@ WebGPUParent::BufferMapData* WebGPUParent::GetBufferMapData(RawId aBufferId) {
|
||||
|
||||
ipc::IPCResult WebGPUParent::RecvDeviceCreateBuffer(
|
||||
RawId aDeviceId, RawId aBufferId, dom::GPUBufferDescriptor&& aDesc,
|
||||
ipc::UnsafeSharedMemoryHandle&& aShmem) {
|
||||
ipc::MutableSharedMemoryHandle&& aShmem) {
|
||||
webgpu::StringHelper label(aDesc.mLabel);
|
||||
|
||||
auto shmem =
|
||||
ipc::WritableSharedMemoryMapping::Open(std::move(aShmem)).value();
|
||||
auto shmem = aShmem.Map();
|
||||
|
||||
bool hasMapFlags = aDesc.mUsage & (dom::GPUBufferUsage_Binding::MAP_WRITE |
|
||||
dom::GPUBufferUsage_Binding::MAP_READ);
|
||||
@@ -664,7 +663,7 @@ void WebGPUParent::MapCallback(uint8_t* aUserData,
|
||||
|
||||
MOZ_RELEASE_ASSERT(mapData->mShmem.Size() >= offset + size);
|
||||
if (src.ptr != nullptr && src.length >= size) {
|
||||
auto dst = mapData->mShmem.Bytes().Subspan(offset, size);
|
||||
auto dst = mapData->mShmem.DataAsSpan<uint8_t>().Subspan(offset, size);
|
||||
memcpy(dst.data(), src.ptr, size);
|
||||
}
|
||||
}
|
||||
@@ -747,7 +746,7 @@ ipc::IPCResult WebGPUParent::RecvBufferUnmap(RawId aDeviceId, RawId aBufferId,
|
||||
MOZ_RELEASE_ASSERT(offset <= shmSize);
|
||||
MOZ_RELEASE_ASSERT(size <= shmSize - offset);
|
||||
|
||||
auto src = mapData->mShmem.Bytes().Subspan(offset, size);
|
||||
auto src = mapData->mShmem.DataAsSpan<uint8_t>().Subspan(offset, size);
|
||||
memcpy(mapped.ptr, src.data(), size);
|
||||
}
|
||||
|
||||
@@ -912,14 +911,15 @@ ipc::IPCResult WebGPUParent::RecvQueueOnSubmittedWorkDone(
|
||||
|
||||
ipc::IPCResult WebGPUParent::RecvQueueWriteAction(
|
||||
RawId aQueueId, RawId aDeviceId, const ipc::ByteBuf& aByteBuf,
|
||||
ipc::UnsafeSharedMemoryHandle&& aShmem) {
|
||||
auto mapping =
|
||||
ipc::WritableSharedMemoryMapping::Open(std::move(aShmem)).value();
|
||||
ipc::MutableSharedMemoryHandle&& aShmem) {
|
||||
// `aShmem` may be an invalid handle, however this will simply result in an
|
||||
// invalid mapping with 0 size, which is used safely below.
|
||||
auto mapping = aShmem.Map();
|
||||
|
||||
ErrorBuffer error;
|
||||
ffi::wgpu_server_queue_write_action(mContext.get(), aQueueId,
|
||||
ToFFI(&aByteBuf), mapping.Bytes().data(),
|
||||
mapping.Size(), error.ToFFI());
|
||||
ffi::wgpu_server_queue_write_action(
|
||||
mContext.get(), aQueueId, ToFFI(&aByteBuf), mapping.DataAs<uint8_t>(),
|
||||
mapping.Size(), error.ToFFI());
|
||||
ForwardError(aDeviceId, error);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||
#include "mozilla/webgpu/ffi/wgpu.h"
|
||||
#include "mozilla/webgpu/PWebGPUParent.h"
|
||||
#include "mozilla/webrender/WebRenderAPI.h"
|
||||
#include "mozilla/ipc/RawShmem.h"
|
||||
#include "WebGPUTypes.h"
|
||||
#include "base/timer.h"
|
||||
|
||||
@@ -56,9 +56,9 @@ class WebGPUParent final : public PWebGPUParent, public SupportsWeakPtr {
|
||||
ipc::IPCResult RecvAdapterDrop(RawId aAdapterId);
|
||||
ipc::IPCResult RecvDeviceDestroy(RawId aDeviceId);
|
||||
ipc::IPCResult RecvDeviceDrop(RawId aDeviceId);
|
||||
ipc::IPCResult RecvDeviceCreateBuffer(RawId aDeviceId, RawId aBufferId,
|
||||
dom::GPUBufferDescriptor&& aDesc,
|
||||
ipc::UnsafeSharedMemoryHandle&& aShmem);
|
||||
ipc::IPCResult RecvDeviceCreateBuffer(
|
||||
RawId aDeviceId, RawId aBufferId, dom::GPUBufferDescriptor&& aDesc,
|
||||
ipc::MutableSharedMemoryHandle&& aShmem);
|
||||
ipc::IPCResult RecvBufferMap(RawId aDeviceId, RawId aBufferId, uint32_t aMode,
|
||||
uint64_t aOffset, uint64_t size,
|
||||
BufferMapResolver&& aResolver);
|
||||
@@ -83,7 +83,7 @@ class WebGPUParent final : public PWebGPUParent, public SupportsWeakPtr {
|
||||
RawId aQueueId, std::function<void(mozilla::void_t)>&& aResolver);
|
||||
ipc::IPCResult RecvQueueWriteAction(RawId aQueueId, RawId aDeviceId,
|
||||
const ipc::ByteBuf& aByteBuf,
|
||||
ipc::UnsafeSharedMemoryHandle&& aShmem);
|
||||
ipc::MutableSharedMemoryHandle&& aShmem);
|
||||
ipc::IPCResult RecvBindGroupLayoutDrop(RawId aBindGroupLayoutId);
|
||||
ipc::IPCResult RecvPipelineLayoutDrop(RawId aPipelineLayoutId);
|
||||
ipc::IPCResult RecvBindGroupDrop(RawId aBindGroupId);
|
||||
@@ -141,7 +141,7 @@ class WebGPUParent final : public PWebGPUParent, public SupportsWeakPtr {
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
struct BufferMapData {
|
||||
ipc::WritableSharedMemoryMapping mShmem;
|
||||
ipc::SharedMemoryMapping mShmem;
|
||||
// True if buffer's usage has MAP_READ or MAP_WRITE set.
|
||||
bool mHasMapFlags;
|
||||
uint64_t mMappedOffset;
|
||||
|
||||
@@ -2549,7 +2549,13 @@ pub unsafe extern "C" fn wgpu_server_queue_write_action(
|
||||
mut error_buf: ErrorBuffer,
|
||||
) {
|
||||
let action: QueueWriteAction = bincode::deserialize(byte_buf.as_slice()).unwrap();
|
||||
let data = slice::from_raw_parts(data, data_length);
|
||||
// It is undefined behavior to pass a null pointer to `slice::from_raw_parts`, so in the case
|
||||
// of a null pointer (which occurs if `data_length` is 0), we use a dangling pointer.
|
||||
let data = ptr::NonNull::new(data as *mut u8).unwrap_or_else(|| {
|
||||
assert!(data_length == 0);
|
||||
ptr::NonNull::dangling()
|
||||
});
|
||||
let data = slice::from_raw_parts(data.as_ptr(), data_length);
|
||||
let result = match action {
|
||||
QueueWriteAction::Buffer { dst, offset } => {
|
||||
global.queue_write_buffer(self_id, dst, offset, data)
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#include "RawShmem.h"
|
||||
#include "mozilla/ipc/ProtocolUtils.h"
|
||||
|
||||
namespace mozilla::ipc {
|
||||
|
||||
UnsafeSharedMemoryHandle::UnsafeSharedMemoryHandle()
|
||||
: mHandle(ipc::SharedMemory::NULLHandle()), mSize(0) {}
|
||||
|
||||
UnsafeSharedMemoryHandle::UnsafeSharedMemoryHandle(
|
||||
UnsafeSharedMemoryHandle&& aOther) noexcept
|
||||
: mHandle(std::move(aOther.mHandle)), mSize(aOther.mSize) {
|
||||
aOther.mHandle = ipc::SharedMemory::NULLHandle();
|
||||
aOther.mSize = 0;
|
||||
}
|
||||
|
||||
UnsafeSharedMemoryHandle& UnsafeSharedMemoryHandle::operator=(
|
||||
UnsafeSharedMemoryHandle&& aOther) noexcept {
|
||||
if (this == &aOther) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
mHandle = std::move(aOther.mHandle);
|
||||
mSize = aOther.mSize;
|
||||
aOther.mHandle = ipc::SharedMemory::NULLHandle();
|
||||
aOther.mSize = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Maybe<std::pair<UnsafeSharedMemoryHandle, WritableSharedMemoryMapping>>
|
||||
UnsafeSharedMemoryHandle::CreateAndMap(size_t aSize) {
|
||||
if (aSize == 0) {
|
||||
return Some(std::make_pair(UnsafeSharedMemoryHandle(),
|
||||
WritableSharedMemoryMapping()));
|
||||
}
|
||||
|
||||
RefPtr<ipc::SharedMemory> shm = MakeAndAddRef<ipc::SharedMemory>();
|
||||
if (NS_WARN_IF(!shm->Create(aSize)) || NS_WARN_IF(!shm->Map(aSize))) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
auto handle = shm->TakeHandle();
|
||||
|
||||
auto size = shm->Size();
|
||||
|
||||
return Some(std::make_pair(UnsafeSharedMemoryHandle(std::move(handle), size),
|
||||
WritableSharedMemoryMapping(std::move(shm))));
|
||||
}
|
||||
|
||||
WritableSharedMemoryMapping::WritableSharedMemoryMapping(
|
||||
RefPtr<ipc::SharedMemory>&& aRef)
|
||||
: mRef(aRef) {}
|
||||
|
||||
Maybe<WritableSharedMemoryMapping> WritableSharedMemoryMapping::Open(
|
||||
UnsafeSharedMemoryHandle aHandle) {
|
||||
if (aHandle.mSize == 0) {
|
||||
return Some(WritableSharedMemoryMapping(nullptr));
|
||||
}
|
||||
|
||||
RefPtr<ipc::SharedMemory> shm = MakeAndAddRef<ipc::SharedMemory>();
|
||||
if (NS_WARN_IF(!shm->SetHandle(std::move(aHandle.mHandle),
|
||||
ipc::SharedMemory::RightsReadWrite)) ||
|
||||
NS_WARN_IF(!shm->Map(aHandle.mSize))) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
shm->CloseHandle();
|
||||
|
||||
return Some(WritableSharedMemoryMapping(std::move(shm)));
|
||||
}
|
||||
|
||||
size_t WritableSharedMemoryMapping::Size() const {
|
||||
if (!mRef) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mRef->Size();
|
||||
}
|
||||
|
||||
Span<uint8_t> WritableSharedMemoryMapping::Bytes() {
|
||||
if (!mRef) {
|
||||
return Span<uint8_t>();
|
||||
}
|
||||
|
||||
uint8_t* mem = static_cast<uint8_t*>(mRef->Memory());
|
||||
return Span(mem, mRef->Size());
|
||||
}
|
||||
|
||||
} // namespace mozilla::ipc
|
||||
|
||||
namespace IPC {
|
||||
auto ParamTraits<mozilla::ipc::UnsafeSharedMemoryHandle>::Write(
|
||||
IPC::MessageWriter* aWriter, paramType&& aVar) -> void {
|
||||
IPC::WriteParam(aWriter, std::move(aVar.mHandle));
|
||||
IPC::WriteParam(aWriter, aVar.mSize);
|
||||
}
|
||||
|
||||
auto ParamTraits<mozilla::ipc::UnsafeSharedMemoryHandle>::Read(
|
||||
IPC::MessageReader* aReader, paramType* aVar) -> bool {
|
||||
return IPC::ReadParam(aReader, &aVar->mHandle) &&
|
||||
IPC::ReadParam(aReader, &aVar->mSize);
|
||||
}
|
||||
|
||||
} // namespace IPC
|
||||
@@ -1,114 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef MOZILLA_IPC_RAWSHMEM_H_
|
||||
#define MOZILLA_IPC_RAWSHMEM_H_
|
||||
|
||||
#include "chrome/common/ipc_message_utils.h"
|
||||
#include "mozilla/ipc/SharedMemory.h"
|
||||
#include "mozilla/Span.h"
|
||||
#include <utility>
|
||||
|
||||
namespace mozilla::ipc {
|
||||
|
||||
class WritableSharedMemoryMapping;
|
||||
|
||||
/// A handle to shared memory.
|
||||
///
|
||||
/// See the doc comment for `WritableSharedMemoryMapping` below.
|
||||
class UnsafeSharedMemoryHandle {
|
||||
friend class WritableSharedMemoryMapping;
|
||||
friend struct IPC::ParamTraits<UnsafeSharedMemoryHandle>;
|
||||
|
||||
public:
|
||||
UnsafeSharedMemoryHandle();
|
||||
UnsafeSharedMemoryHandle(UnsafeSharedMemoryHandle&& aOther) noexcept;
|
||||
UnsafeSharedMemoryHandle& operator=(
|
||||
UnsafeSharedMemoryHandle&& aOther) noexcept;
|
||||
|
||||
/// Attempts to allocate a shmem.
|
||||
///
|
||||
/// Returns `Nothing()` if allocation fails.
|
||||
/// If `aSize` is zero, a valid empty WritableSharedMemoryMapping is returned.
|
||||
static Maybe<std::pair<UnsafeSharedMemoryHandle, WritableSharedMemoryMapping>>
|
||||
CreateAndMap(size_t aSize);
|
||||
|
||||
private:
|
||||
UnsafeSharedMemoryHandle(SharedMemory::Handle&& aHandle, uint64_t aSize)
|
||||
: mHandle(std::move(aHandle)), mSize(aSize) {}
|
||||
|
||||
SharedMemory::Handle mHandle;
|
||||
uint64_t mSize;
|
||||
};
|
||||
|
||||
/// A Shared memory buffer mapping.
|
||||
///
|
||||
/// Unlike `ipc::Shmem`, the underlying shared memory buffer on each side of
|
||||
/// the process boundary is only deallocated with there respective
|
||||
/// `WritableSharedMemoryMapping`.
|
||||
///
|
||||
/// ## Usage
|
||||
///
|
||||
/// Typical usage goes as follows:
|
||||
/// - Allocate the memory using `UnsafeSharedMemoryHandle::Create`, returning a
|
||||
/// handle and a mapping.
|
||||
/// - Send the handle to the other process using an IPDL message.
|
||||
/// - On the other process, map the shared memory by creating
|
||||
/// WritableSharedMemoryMapping via `WritableSharedMemoryMapping::Open` and
|
||||
/// the received handle.
|
||||
///
|
||||
/// Do not send the shared memory handle again, it is only intended to establish
|
||||
/// the mapping on each side during initialization. The user of this class is
|
||||
/// responsible for managing the lifetime of the buffers on each side, as well
|
||||
/// as their identity, by for example storing them in hash map and referring to
|
||||
/// them via IDs in IPDL message if need be.
|
||||
///
|
||||
/// ## Empty shmems
|
||||
///
|
||||
/// An empty WritableSharedMemoryMapping is one that was created with size zero.
|
||||
/// It is analogous to a null RefPtr. It can be used like a non-empty shmem,
|
||||
/// including sending the handle and openning it on another process (resulting
|
||||
/// in an empty mapping on the other side).
|
||||
class WritableSharedMemoryMapping {
|
||||
friend class UnsafeSharedMemoryHandle;
|
||||
|
||||
public:
|
||||
WritableSharedMemoryMapping() = default;
|
||||
|
||||
WritableSharedMemoryMapping(WritableSharedMemoryMapping&& aMoved) = default;
|
||||
|
||||
WritableSharedMemoryMapping& operator=(WritableSharedMemoryMapping&& aMoved) =
|
||||
default;
|
||||
|
||||
/// Open the shmem and immediately close the handle.
|
||||
static Maybe<WritableSharedMemoryMapping> Open(
|
||||
UnsafeSharedMemoryHandle aHandle);
|
||||
|
||||
// Returns the size in bytes.
|
||||
size_t Size() const;
|
||||
|
||||
// Returns the shared memory as byte range.
|
||||
Span<uint8_t> Bytes();
|
||||
|
||||
private:
|
||||
explicit WritableSharedMemoryMapping(
|
||||
RefPtr<mozilla::ipc::SharedMemory>&& aRef);
|
||||
|
||||
RefPtr<mozilla::ipc::SharedMemory> mRef;
|
||||
};
|
||||
|
||||
} // namespace mozilla::ipc
|
||||
|
||||
namespace IPC {
|
||||
template <>
|
||||
struct ParamTraits<mozilla::ipc::UnsafeSharedMemoryHandle> {
|
||||
typedef mozilla::ipc::UnsafeSharedMemoryHandle paramType;
|
||||
static void Write(IPC::MessageWriter* aWriter, paramType&& aVar);
|
||||
static bool Read(IPC::MessageReader* aReader, paramType* aVar);
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif
|
||||
@@ -52,7 +52,6 @@ EXPORTS.mozilla.ipc += [
|
||||
"ProtocolMessageUtils.h",
|
||||
"ProtocolUtils.h",
|
||||
"RandomAccessStreamUtils.h",
|
||||
"RawShmem.h",
|
||||
"RustMessageUtils.h",
|
||||
"ScopedPort.h",
|
||||
"SerializedStructuredCloneBuffer.h",
|
||||
@@ -194,7 +193,6 @@ UNIFIED_SOURCES += [
|
||||
"ProcessUtils_common.cpp",
|
||||
"ProtocolUtils.cpp",
|
||||
"RandomAccessStreamUtils.cpp",
|
||||
"RawShmem.cpp",
|
||||
"ScopedPort.cpp",
|
||||
"SerializedStructuredCloneBuffer.cpp",
|
||||
"SharedMemory.cpp",
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#include "chrome/common/ipc_message.h"
|
||||
#include "chrome/common/ipc_message_utils.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "mozilla/RandomNum.h"
|
||||
#include "mozilla/ipc/RawShmem.h"
|
||||
|
||||
namespace mozilla::ipc {
|
||||
|
||||
static bool SerializeAndDeserialize(UnsafeSharedMemoryHandle&& aIn,
|
||||
UnsafeSharedMemoryHandle* aOut) {
|
||||
IPC::Message msg(MSG_ROUTING_NONE, 0);
|
||||
{
|
||||
IPC::MessageWriter writer(msg);
|
||||
IPC::WriteParam(&writer, std::move(aIn));
|
||||
}
|
||||
|
||||
IPC::MessageReader reader(msg);
|
||||
return IPC::ReadParam(&reader, aOut);
|
||||
}
|
||||
|
||||
void TestUnsafeSharedMemoryHandle(size_t aSize) {
|
||||
auto maybeHandle = UnsafeSharedMemoryHandle::CreateAndMap(aSize);
|
||||
ASSERT_TRUE(maybeHandle);
|
||||
auto [handle, mapping] = maybeHandle.extract();
|
||||
|
||||
EXPECT_EQ(mapping.Size(), aSize);
|
||||
|
||||
auto inBytes = mapping.Bytes();
|
||||
for (size_t i = 0; i < aSize; ++i) {
|
||||
inBytes[i] = static_cast<uint8_t>(i % 255);
|
||||
}
|
||||
|
||||
UnsafeSharedMemoryHandle out;
|
||||
ASSERT_TRUE(SerializeAndDeserialize(std::move(handle), &out));
|
||||
|
||||
auto mapping2 = WritableSharedMemoryMapping::Open(std::move(out)).value();
|
||||
|
||||
EXPECT_EQ(mapping2.Size(), aSize);
|
||||
auto outBytes = mapping2.Bytes();
|
||||
for (size_t i = 0; i < aSize; ++i) {
|
||||
EXPECT_EQ(outBytes[i], static_cast<uint8_t>(i % 255));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(UnsafeSharedMemoryHandle, Empty)
|
||||
{ TestUnsafeSharedMemoryHandle(0); }
|
||||
|
||||
TEST(UnsafeSharedMemoryHandle, SmallSize)
|
||||
{ TestUnsafeSharedMemoryHandle(2048); }
|
||||
|
||||
} // namespace mozilla::ipc
|
||||
@@ -12,7 +12,6 @@ SOURCES += [
|
||||
"TestLogging.cpp",
|
||||
"TestRandomAccessStreamUtils.cpp",
|
||||
"TestSharedMemory.cpp",
|
||||
"TestUnsafeSharedMemoryHandle.cpp",
|
||||
]
|
||||
|
||||
include("/ipc/chromium/chromium-config.mozbuild")
|
||||
|
||||
Reference in New Issue
Block a user