Backed out 8 changesets (bug 1942129) for causing bustages at SharedMemoryMapping.h. CLOSED TREE

Backed out changeset 8d9053f1c203 (bug 1942129)
Backed out changeset 393e3c507c27 (bug 1942129)
Backed out changeset 8240d353d224 (bug 1942129)
Backed out changeset 8c4cd026b720 (bug 1942129)
Backed out changeset 742634b0d6e9 (bug 1942129)
Backed out changeset d16857f9812f (bug 1942129)
Backed out changeset 7ff7af041ee7 (bug 1942129)
Backed out changeset ef41d9e4c7de (bug 1942129)
This commit is contained in:
Butkovits Atila
2025-03-04 00:43:23 +02:00
parent 65e74408c3
commit 2406ce261c
132 changed files with 3543 additions and 2087 deletions

View File

@@ -220,6 +220,7 @@
#include "mozilla/gfx/Rect.h" #include "mozilla/gfx/Rect.h"
#include "mozilla/gfx/Types.h" #include "mozilla/gfx/Types.h"
#include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/ipc/SharedMemory.h"
#include "mozilla/net/UrlClassifierCommon.h" #include "mozilla/net/UrlClassifierCommon.h"
#include "mozilla/Tokenizer.h" #include "mozilla/Tokenizer.h"
#include "mozilla/widget/IMEData.h" #include "mozilla/widget/IMEData.h"

View File

@@ -443,28 +443,25 @@ bool DrawTargetWebgl::Init(const IntSize& size, const SurfaceFormat format,
return false; return false;
} }
size_t shmemSize = mozilla::ipc::shared_memory::PageAlignedSize(byteSize); size_t shmemSize = mozilla::ipc::SharedMemory::PageAlignedSize(byteSize);
if (NS_WARN_IF(shmemSize > UINT32_MAX)) { if (NS_WARN_IF(shmemSize > UINT32_MAX)) {
MOZ_ASSERT_UNREACHABLE("Buffer too big?"); MOZ_ASSERT_UNREACHABLE("Buffer too big?");
return false; return false;
} }
auto handle = mozilla::ipc::shared_memory::Create(shmemSize); auto shmem = MakeRefPtr<mozilla::ipc::SharedMemory>();
if (NS_WARN_IF(!handle)) { if (NS_WARN_IF(!shmem->Create(shmemSize)) ||
return false; NS_WARN_IF(!shmem->Map(shmemSize))) {
}
auto mapping = handle.Map();
if (NS_WARN_IF(!mapping)) {
return false; return false;
} }
mShmemHandle = std::move(handle).ToReadOnly(); mShmem = std::move(shmem);
mShmem = std::move(mapping); mShmemSize = shmemSize;
mSkia = new DrawTargetSkia; mSkia = new DrawTargetSkia;
auto stride = layers::ImageDataSerializer::ComputeRGBStride( auto stride = layers::ImageDataSerializer::ComputeRGBStride(
SurfaceFormat::B8G8R8A8, size.width); SurfaceFormat::B8G8R8A8, size.width);
if (!mSkia->Init(mShmem.DataAs<uint8_t>(), size, stride, if (!mSkia->Init(reinterpret_cast<uint8_t*>(mShmem->Memory()), size, stride,
SurfaceFormat::B8G8R8A8, true)) { SurfaceFormat::B8G8R8A8, true)) {
return false; return false;
} }

View File

@@ -14,8 +14,7 @@
#include "mozilla/LinkedList.h" #include "mozilla/LinkedList.h"
#include "mozilla/WeakPtr.h" #include "mozilla/WeakPtr.h"
#include "mozilla/ThreadLocal.h" #include "mozilla/ThreadLocal.h"
#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/ipc/SharedMemory.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "mozilla/layers/LayersTypes.h" #include "mozilla/layers/LayersTypes.h"
#include <vector> #include <vector>
@@ -382,13 +381,12 @@ class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr {
RefPtr<DrawTargetSkia> mSkia; RefPtr<DrawTargetSkia> mSkia;
// Skia DT pointing to the same pixel data, but without any applied clips. // Skia DT pointing to the same pixel data, but without any applied clips.
RefPtr<DrawTargetSkia> mSkiaNoClip; RefPtr<DrawTargetSkia> mSkiaNoClip;
// A Shmem read-only handle to the same memory as mShmem, to be consumed by
// TakeShmemHandle().
mozilla::ipc::ReadOnlySharedMemoryHandle mShmemHandle;
// The Shmem backing the Skia DT, if applicable. // The Shmem backing the Skia DT, if applicable.
mozilla::ipc::SharedMemoryMapping mShmem; RefPtr<mozilla::ipc::SharedMemory> mShmem;
// The currently cached snapshot of the WebGL context // The currently cached snapshot of the WebGL context
RefPtr<SourceSurfaceWebgl> mSnapshot; RefPtr<SourceSurfaceWebgl> mSnapshot;
// The mappable size of mShmem.
uint32_t mShmemSize = 0;
// Whether the framebuffer is still in the initially clear state. // Whether the framebuffer is still in the initially clear state.
bool mIsClear = true; bool mIsClear = true;
// Whether or not the Skia target has valid contents and is being drawn to // Whether or not the Skia target has valid contents and is being drawn to
@@ -607,10 +605,13 @@ class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr {
return stream.str(); return stream.str();
} }
mozilla::ipc::ReadOnlySharedMemoryHandle TakeShmemHandle() { mozilla::ipc::SharedMemory::Handle TakeShmemHandle() const {
return std::move(mShmemHandle); return mShmem ? mShmem->TakeHandle()
: mozilla::ipc::SharedMemory::NULLHandle();
} }
uint32_t GetShmemSize() const { return mShmemSize; }
private: private:
bool SupportsPattern(const Pattern& aPattern) { bool SupportsPattern(const Pattern& aPattern) {
return mSharedContext->SupportsPattern(aPattern); return mSharedContext->SupportsPattern(aPattern);

View File

@@ -13,6 +13,7 @@
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/IntegerRange.h" #include "mozilla/IntegerRange.h"
#include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/ipc/SharedMemory.h"
#include "mozilla/Logging.h" #include "mozilla/Logging.h"
#include "mozilla/TimeStamp.h" #include "mozilla/TimeStamp.h"
#include "nsExceptionHandler.h" #include "nsExceptionHandler.h"

View File

@@ -41,6 +41,7 @@
#include "nsTArray.h" #include "nsTArray.h"
#include "nsString.h" #include "nsString.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h" #include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "mozilla/ipc/SharedMemory.h"
// Manual reflection of WebIDL typedefs that are different from their // Manual reflection of WebIDL typedefs that are different from their
// OpenGL counterparts. // OpenGL counterparts.

View File

@@ -652,9 +652,9 @@ NS_INTERFACE_MAP_END
mozilla::ipc::IPCResult ContentChild::RecvSetXPCOMProcessAttributes( mozilla::ipc::IPCResult ContentChild::RecvSetXPCOMProcessAttributes(
XPCOMInitData&& aXPCOMInit, const StructuredCloneData& aInitialData, XPCOMInitData&& aXPCOMInit, const StructuredCloneData& aInitialData,
FullLookAndFeel&& aLookAndFeelData, dom::SystemFontList&& aFontList, FullLookAndFeel&& aLookAndFeelData, dom::SystemFontList&& aFontList,
Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aSharedUASheetHandle, Maybe<SharedMemoryHandle>&& aSharedUASheetHandle,
const uintptr_t& aSharedUASheetAddress, const uintptr_t& aSharedUASheetAddress,
nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aSharedFontListBlocks, nsTArray<SharedMemoryHandle>&& aSharedFontListBlocks,
const bool& aIsReadyForBackgroundProcessing) { const bool& aIsReadyForBackgroundProcessing) {
if (!sShutdownCanary) { if (!sShutdownCanary) {
return IPC_OK(); return IPC_OK();
@@ -1332,9 +1332,8 @@ void ContentChild::InitGraphicsDeviceData(const ContentDeviceData& aData) {
gfxPlatform::InitChild(aData); gfxPlatform::InitChild(aData);
} }
void ContentChild::InitSharedUASheets( void ContentChild::InitSharedUASheets(Maybe<SharedMemoryHandle>&& aHandle,
Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aHandle, uintptr_t aAddress) {
uintptr_t aAddress) {
MOZ_ASSERT_IF(!aHandle, !aAddress); MOZ_ASSERT_IF(!aHandle, !aAddress);
if (!aAddress) { if (!aAddress) {
@@ -2350,7 +2349,7 @@ mozilla::ipc::IPCResult ContentChild::RecvRegisterStringBundles(
for (auto& descriptor : aDescriptors) { for (auto& descriptor : aDescriptors) {
stringBundleService->RegisterContentBundle( stringBundleService->RegisterContentBundle(
descriptor.bundleURL(), std::move(descriptor.mapHandle())); descriptor.bundleURL(), descriptor.mapHandle(), descriptor.mapSize());
} }
return IPC_OK(); return IPC_OK();
@@ -2370,7 +2369,7 @@ mozilla::ipc::IPCResult ContentChild::RecvUpdateL10nFileSources(
} }
mozilla::ipc::IPCResult ContentChild::RecvUpdateSharedData( mozilla::ipc::IPCResult ContentChild::RecvUpdateSharedData(
mozilla::ipc::ReadOnlySharedMemoryHandle&& aMapHandle, SharedMemoryHandle&& aMapHandle, const uint32_t& aMapSize,
nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys) { nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys) {
nsTArray<RefPtr<BlobImpl>> blobImpls(aBlobs.Length()); nsTArray<RefPtr<BlobImpl>> blobImpls(aBlobs.Length());
for (auto& ipcBlob : aBlobs) { for (auto& ipcBlob : aBlobs) {
@@ -2378,12 +2377,12 @@ mozilla::ipc::IPCResult ContentChild::RecvUpdateSharedData(
} }
if (mSharedData) { if (mSharedData) {
mSharedData->Update(std::move(aMapHandle), std::move(blobImpls), mSharedData->Update(std::move(aMapHandle), aMapSize, std::move(blobImpls),
std::move(aChangedKeys)); std::move(aChangedKeys));
} else { } else {
mSharedData = mSharedData =
new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(), new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(),
std::move(aMapHandle), std::move(blobImpls)); std::move(aMapHandle), aMapSize, std::move(blobImpls));
} }
return IPC_OK(); return IPC_OK();
@@ -2444,7 +2443,7 @@ mozilla::ipc::IPCResult ContentChild::RecvRebuildFontList(
mozilla::ipc::IPCResult ContentChild::RecvFontListShmBlockAdded( mozilla::ipc::IPCResult ContentChild::RecvFontListShmBlockAdded(
const uint32_t& aGeneration, const uint32_t& aIndex, const uint32_t& aGeneration, const uint32_t& aIndex,
mozilla::ipc::ReadOnlySharedMemoryHandle&& aHandle) { SharedMemoryHandle&& aHandle) {
if (gfxPlatform::Initialized()) { if (gfxPlatform::Initialized()) {
gfxPlatformFontList::PlatformFontList()->ShmBlockAdded(aGeneration, aIndex, gfxPlatformFontList::PlatformFontList()->ShmBlockAdded(aGeneration, aIndex,
std::move(aHandle)); std::move(aHandle));

View File

@@ -17,7 +17,6 @@
#include "mozilla/Hal.h" #include "mozilla/Hal.h"
#include "mozilla/ipc/InputStreamUtils.h" #include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/ipc/SharedMemoryHandle.h"
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "nsClassHashtable.h" #include "nsClassHashtable.h"
@@ -120,9 +119,8 @@ class ContentChild final : public PContentChild,
const mozilla::dom::ipc::StructuredCloneData& aInitialData, const mozilla::dom::ipc::StructuredCloneData& aInitialData,
bool aIsReadyForBackgroundProcessing); bool aIsReadyForBackgroundProcessing);
void InitSharedUASheets( void InitSharedUASheets(Maybe<SharedMemoryHandle>&& aHandle,
Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aHandle, uintptr_t aAddress);
uintptr_t aAddress);
void InitGraphicsDeviceData(const ContentDeviceData& aData); void InitGraphicsDeviceData(const ContentDeviceData& aData);
@@ -311,7 +309,7 @@ class ContentChild final : public PContentChild,
nsTArray<L10nFileSourceDescriptor>&& aDescriptors); nsTArray<L10nFileSourceDescriptor>&& aDescriptors);
mozilla::ipc::IPCResult RecvUpdateSharedData( mozilla::ipc::IPCResult RecvUpdateSharedData(
mozilla::ipc::ReadOnlySharedMemoryHandle&& aMapHandle, SharedMemoryHandle&& aMapHandle, const uint32_t& aMapSize,
nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys); nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys);
mozilla::ipc::IPCResult RecvForceGlobalReflow( mozilla::ipc::IPCResult RecvForceGlobalReflow(
@@ -331,7 +329,7 @@ class ContentChild final : public PContentChild,
mozilla::ipc::IPCResult RecvRebuildFontList(const bool& aFullRebuild); mozilla::ipc::IPCResult RecvRebuildFontList(const bool& aFullRebuild);
mozilla::ipc::IPCResult RecvFontListShmBlockAdded( mozilla::ipc::IPCResult RecvFontListShmBlockAdded(
const uint32_t& aGeneration, const uint32_t& aIndex, const uint32_t& aGeneration, const uint32_t& aIndex,
mozilla::ipc::ReadOnlySharedMemoryHandle&& aHandle); SharedMemoryHandle&& aHandle);
mozilla::ipc::IPCResult RecvUpdateAppLocales( mozilla::ipc::IPCResult RecvUpdateAppLocales(
nsTArray<nsCString>&& aAppLocales); nsTArray<nsCString>&& aAppLocales);
@@ -505,10 +503,9 @@ class ContentChild final : public PContentChild,
mozilla::ipc::IPCResult RecvSetXPCOMProcessAttributes( mozilla::ipc::IPCResult RecvSetXPCOMProcessAttributes(
XPCOMInitData&& aXPCOMInit, const StructuredCloneData& aInitialData, XPCOMInitData&& aXPCOMInit, const StructuredCloneData& aInitialData,
FullLookAndFeel&& aLookAndFeelData, SystemFontList&& aFontList, FullLookAndFeel&& aLookAndFeelData, SystemFontList&& aFontList,
Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aSharedUASheetHandle, Maybe<SharedMemoryHandle>&& aSharedUASheetHandle,
const uintptr_t& aSharedUASheetAddress, const uintptr_t& aSharedUASheetAddress,
nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle>&& nsTArray<SharedMemoryHandle>&& aSharedFontListBlocks,
aSharedFontListBlocks,
const bool& aIsReadyForBackgroundProcessing); const bool& aIsReadyForBackgroundProcessing);
mozilla::ipc::IPCResult RecvProvideAnonymousTemporaryFile( mozilla::ipc::IPCResult RecvProvideAnonymousTemporaryFile(
@@ -538,7 +535,7 @@ class ContentChild final : public PContentChild,
// for use during gfx initialization. // for use during gfx initialization.
SystemFontList& SystemFontList() { return mFontList; } SystemFontList& SystemFontList() { return mFontList; }
nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle>& SharedFontListBlocks() { nsTArray<SharedMemoryHandle>& SharedFontListBlocks() {
return mSharedFontListBlocks; return mSharedFontListBlocks;
} }
@@ -837,7 +834,7 @@ class ContentChild final : public PContentChild,
// Temporary storage for look and feel data. // Temporary storage for look and feel data.
FullLookAndFeel mLookAndFeelData; FullLookAndFeel mLookAndFeelData;
// Temporary storage for list of shared-fontlist memory blocks. // Temporary storage for list of shared-fontlist memory blocks.
nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle> mSharedFontListBlocks; nsTArray<SharedMemoryHandle> mSharedFontListBlocks;
AppInfo mAppInfo; AppInfo mAppInfo;

View File

@@ -152,7 +152,7 @@
#include "mozilla/ipc/Endpoint.h" #include "mozilla/ipc/Endpoint.h"
#include "mozilla/ipc/FileDescriptorUtils.h" #include "mozilla/ipc/FileDescriptorUtils.h"
#include "mozilla/ipc/IPCStreamUtils.h" #include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/ipc/SharedMemory.h"
#include "mozilla/ipc/TestShellParent.h" #include "mozilla/ipc/TestShellParent.h"
#include "mozilla/layers/CompositorThread.h" #include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/ImageBridgeParent.h" #include "mozilla/layers/ImageBridgeParent.h"
@@ -1536,8 +1536,9 @@ void ContentParent::BroadcastStringBundle(
const StringBundleDescriptor& aBundle) { const StringBundleDescriptor& aBundle) {
for (auto* cp : AllProcesses(eLive)) { for (auto* cp : AllProcesses(eLive)) {
AutoTArray<StringBundleDescriptor, 1> array; AutoTArray<StringBundleDescriptor, 1> array;
array.AppendElement(StringBundleDescriptor(aBundle.bundleURL(), array.AppendElement(StringBundleDescriptor(
aBundle.mapHandle().Clone())); aBundle.bundleURL(), SharedMemory::CloneHandle(aBundle.mapHandle()),
aBundle.mapSize()));
Unused << cp->SendRegisterStringBundles(std::move(array)); Unused << cp->SendRegisterStringBundles(std::move(array));
} }
} }
@@ -1546,9 +1547,9 @@ void ContentParent::BroadcastShmBlockAdded(uint32_t aGeneration,
uint32_t aIndex) { uint32_t aIndex) {
auto* pfl = gfxPlatformFontList::PlatformFontList(); auto* pfl = gfxPlatformFontList::PlatformFontList();
for (auto* cp : AllProcesses(eLive)) { for (auto* cp : AllProcesses(eLive)) {
ReadOnlySharedMemoryHandle handle = SharedMemory::Handle handle =
pfl->ShareShmBlockToProcess(aIndex, cp->Pid()); pfl->ShareShmBlockToProcess(aIndex, cp->Pid());
if (!handle.IsValid()) { if (handle == SharedMemory::NULLHandle()) {
// If something went wrong here, we just skip it; the child will need to // If something went wrong here, we just skip it; the child will need to
// request the block as needed, at some performance cost. // request the block as needed, at some performance cost.
continue; continue;
@@ -2810,7 +2811,7 @@ bool ContentParent::InitInternal(ProcessPriority aInitialPriority) {
// If the shared fontlist is in use, collect its shmem block handles to pass // If the shared fontlist is in use, collect its shmem block handles to pass
// to the child. // to the child.
nsTArray<ReadOnlySharedMemoryHandle> sharedFontListBlocks; nsTArray<SharedMemoryHandle> sharedFontListBlocks;
gfxPlatformFontList::PlatformFontList()->ShareFontListToProcess( gfxPlatformFontList::PlatformFontList()->ShareFontListToProcess(
&sharedFontListBlocks, OtherPid()); &sharedFontListBlocks, OtherPid());
@@ -2849,10 +2850,10 @@ bool ContentParent::InitInternal(ProcessPriority aInitialPriority) {
screenManager.CopyScreensToRemote(this); screenManager.CopyScreensToRemote(this);
// Send the UA sheet shared memory buffer and the address it is mapped at. // Send the UA sheet shared memory buffer and the address it is mapped at.
Maybe<ReadOnlySharedMemoryHandle> sharedUASheetHandle; Maybe<SharedMemoryHandle> sharedUASheetHandle;
uintptr_t sharedUASheetAddress = sheetCache->GetSharedMemoryAddress(); uintptr_t sharedUASheetAddress = sheetCache->GetSharedMemoryAddress();
if (ReadOnlySharedMemoryHandle handle = sheetCache->CloneHandle()) { if (SharedMemoryHandle handle = sheetCache->CloneHandle()) {
sharedUASheetHandle.emplace(std::move(handle)); sharedUASheetHandle.emplace(std::move(handle));
} else { } else {
sharedUASheetAddress = 0; sharedUASheetAddress = 0;
@@ -5627,7 +5628,7 @@ mozilla::ipc::IPCResult ContentParent::RecvShutdownPerfStats(
mozilla::ipc::IPCResult ContentParent::RecvGetFontListShmBlock( mozilla::ipc::IPCResult ContentParent::RecvGetFontListShmBlock(
const uint32_t& aGeneration, const uint32_t& aIndex, const uint32_t& aGeneration, const uint32_t& aIndex,
ReadOnlySharedMemoryHandle* aOut) { SharedMemory::Handle* aOut) {
auto* fontList = gfxPlatformFontList::PlatformFontList(); auto* fontList = gfxPlatformFontList::PlatformFontList();
MOZ_RELEASE_ASSERT(fontList, "gfxPlatformFontList not initialized?"); MOZ_RELEASE_ASSERT(fontList, "gfxPlatformFontList not initialized?");
fontList->ShareFontListShmBlockToProcess(aGeneration, aIndex, Pid(), aOut); fontList->ShareFontListShmBlockToProcess(aGeneration, aIndex, Pid(), aOut);
@@ -5679,12 +5680,12 @@ mozilla::ipc::IPCResult ContentParent::RecvStartCmapLoading(
} }
mozilla::ipc::IPCResult ContentParent::RecvGetHyphDict( mozilla::ipc::IPCResult ContentParent::RecvGetHyphDict(
nsIURI* aURI, ReadOnlySharedMemoryHandle* aOutHandle) { nsIURI* aURI, SharedMemory::Handle* aOutHandle, uint32_t* aOutSize) {
if (!aURI) { if (!aURI) {
return IPC_FAIL(this, "aURI must not be null."); return IPC_FAIL(this, "aURI must not be null.");
} }
nsHyphenationManager::Instance()->ShareHyphDictToProcess(aURI, Pid(), nsHyphenationManager::Instance()->ShareHyphDictToProcess(
aOutHandle); aURI, Pid(), aOutHandle, aOutSize);
return IPC_OK(); return IPC_OK();
} }

View File

@@ -22,7 +22,7 @@
#include "mozilla/ipc/BackgroundUtils.h" #include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/GeckoChildProcessHost.h" #include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/ipc/InputStreamUtils.h" #include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/ipc/SharedMemory.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/DataMutex.h" #include "mozilla/DataMutex.h"
#include "mozilla/HalTypes.h" #include "mozilla/HalTypes.h"
@@ -1125,7 +1125,7 @@ class ContentParent final : public PContentParent,
mozilla::ipc::IPCResult RecvGetFontListShmBlock( mozilla::ipc::IPCResult RecvGetFontListShmBlock(
const uint32_t& aGeneration, const uint32_t& aIndex, const uint32_t& aGeneration, const uint32_t& aIndex,
mozilla::ipc::ReadOnlySharedMemoryHandle* aOut); mozilla::ipc::SharedMemory::Handle* aOut);
mozilla::ipc::IPCResult RecvInitializeFamily(const uint32_t& aGeneration, mozilla::ipc::IPCResult RecvInitializeFamily(const uint32_t& aGeneration,
const uint32_t& aFamilyIndex, const uint32_t& aFamilyIndex,
@@ -1149,7 +1149,8 @@ class ContentParent final : public PContentParent,
const uint32_t& aStartIndex); const uint32_t& aStartIndex);
mozilla::ipc::IPCResult RecvGetHyphDict( mozilla::ipc::IPCResult RecvGetHyphDict(
nsIURI* aURIParams, mozilla::ipc::ReadOnlySharedMemoryHandle* aOutHandle); nsIURI* aURIParams, mozilla::ipc::SharedMemory::Handle* aOutHandle,
uint32_t* aOutSize);
mozilla::ipc::IPCResult RecvNotifyBenchmarkResult(const nsAString& aCodecName, mozilla::ipc::IPCResult RecvNotifyBenchmarkResult(const nsAString& aCodecName,
const uint32_t& aDecodeFPS); const uint32_t& aDecodeFPS);

View File

@@ -72,9 +72,10 @@ void ContentProcess::InfallibleInit(int aArgc, char* aArgv[]) {
Maybe<const char*> parentBuildID = Maybe<const char*> parentBuildID =
geckoargs::sParentBuildID.Get(aArgc, aArgv); geckoargs::sParentBuildID.Get(aArgc, aArgv);
// command line: -jsInitHandle handle // command line: -jsInitHandle handle -jsInitLen length
Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle> jsInitHandle = Maybe<mozilla::ipc::SharedMemoryHandle> jsInitHandle =
geckoargs::sJsInitHandle.Get(aArgc, aArgv); geckoargs::sJsInitHandle.Get(aArgc, aArgv);
Maybe<uint64_t> jsInitLen = geckoargs::sJsInitLen.Get(aArgc, aArgv);
nsCOMPtr<nsIFile> appDirArg; nsCOMPtr<nsIFile> appDirArg;
Maybe<const char*> appDir = geckoargs::sAppDir.Get(aArgc, aArgv); Maybe<const char*> appDir = geckoargs::sAppDir.Get(aArgc, aArgv);
@@ -130,8 +131,8 @@ void ContentProcess::InfallibleInit(int aArgc, char* aArgv[]) {
MOZ_CRASH("InitPrefs failed"); MOZ_CRASH("InitPrefs failed");
} }
if (jsInitHandle && if (jsInitHandle && jsInitLen &&
!::mozilla::ipc::ImportSharedJSInit(jsInitHandle.extract())) { !::mozilla::ipc::ImportSharedJSInit(jsInitHandle.extract(), *jsInitLen)) {
MOZ_CRASH("ImportSharedJSInit failed"); MOZ_CRASH("ImportSharedJSInit failed");
} }

View File

@@ -7,36 +7,40 @@
#include "MemMapSnapshot.h" #include "MemMapSnapshot.h"
#include "mozilla/ResultExtensions.h" #include "mozilla/ResultExtensions.h"
#include "mozilla/ipc/SharedMemoryHandle.h"
namespace mozilla::ipc { namespace mozilla::ipc {
Result<Ok, nsresult> MemMapSnapshot::Init(size_t aSize) { Result<Ok, nsresult> MemMapSnapshot::Init(size_t aSize) {
MOZ_ASSERT(!mMem); MOZ_ASSERT(!mMem);
auto handle = shared_memory::CreateFreezable(aSize); auto aMem = MakeRefPtr<SharedMemory>();
if (NS_WARN_IF(!handle)) { if (NS_WARN_IF(!aMem->CreateFreezable(aSize))) {
return Err(NS_ERROR_FAILURE);
}
if (NS_WARN_IF(!aMem->Map(aSize))) {
return Err(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
auto mem = std::move(handle).Map(); mMem = std::move(aMem);
if (NS_WARN_IF(!mem)) {
return Err(NS_ERROR_FAILURE);
}
mMem = std::move(mem);
return Ok(); return Ok();
} }
Result<ReadOnlySharedMemoryHandle, nsresult> MemMapSnapshot::Finalize() { Result<Ok, nsresult> MemMapSnapshot::Finalize(RefPtr<SharedMemory>& aMem) {
MOZ_ASSERT(mMem); MOZ_ASSERT(mMem);
auto [_, readOnlyHandle] = std::move(mMem).Freeze(); auto size = mMem->Size();
if (NS_WARN_IF(!readOnlyHandle)) { if (NS_WARN_IF(!mMem->Freeze())) {
return Err(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
return std::move(readOnlyHandle); aMem = std::move(mMem);
// We need to re-map the memory as `Freeze()` unmaps it.
if (NS_WARN_IF(!aMem->Map(size))) {
return Err(NS_ERROR_FAILURE);
}
return Ok();
} }
} // namespace mozilla::ipc } // namespace mozilla::ipc

View File

@@ -12,7 +12,7 @@
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/RangedPtr.h" #include "mozilla/RangedPtr.h"
#include "mozilla/Result.h" #include "mozilla/Result.h"
#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/ipc/SharedMemory.h"
#include "ErrorList.h" #include "ErrorList.h"
namespace mozilla::ipc { namespace mozilla::ipc {
@@ -23,7 +23,7 @@ namespace mozilla::ipc {
* The Init() method initializes a read-write memory mapped region of the given * The Init() method initializes a read-write memory mapped region of the given
* size, which can be initialized with arbitrary data. The Finalize() method * size, which can be initialized with arbitrary data. The Finalize() method
* remaps that region as read-only (and backs it with a read-only file * remaps that region as read-only (and backs it with a read-only file
* descriptor), and returns a handle to it. * descriptor), and initializes an AutoMemMap with the new contents.
* *
* The file descriptor for the resulting AutoMemMap can be shared among * The file descriptor for the resulting AutoMemMap can be shared among
* processes, to safely access a shared, read-only copy of the data snapshot. * processes, to safely access a shared, read-only copy of the data snapshot.
@@ -31,17 +31,16 @@ namespace mozilla::ipc {
class MOZ_RAII MemMapSnapshot { class MOZ_RAII MemMapSnapshot {
public: public:
Result<Ok, nsresult> Init(size_t aSize); Result<Ok, nsresult> Init(size_t aSize);
Result<ReadOnlySharedMemoryHandle, nsresult> Finalize(); Result<Ok, nsresult> Finalize(RefPtr<SharedMemory>& aMem);
template <typename T> template <typename T>
RangedPtr<T> Get() { RangedPtr<T> Get() {
MOZ_ASSERT(mMem); MOZ_ASSERT(mMem);
auto span = mMem.DataAsSpan<T>(); return {static_cast<T*>(mMem->Memory()), mMem->MaxSize() / sizeof(T)};
return {span.data(), span.size()};
} }
private: private:
FreezableSharedMemoryMapping mMem; RefPtr<SharedMemory> mMem;
}; };
} // namespace mozilla::ipc } // namespace mozilla::ipc

View File

@@ -139,7 +139,7 @@ using mozilla::dom::BrowsingContextInitializer from "mozilla/dom/BrowsingContext
using mozilla::dom::PermitUnloadResult from "nsIDocumentViewer.h"; using mozilla::dom::PermitUnloadResult from "nsIDocumentViewer.h";
using mozilla::dom::MaybeDiscardedWindowContext from "mozilla/dom/WindowContext.h"; using mozilla::dom::MaybeDiscardedWindowContext from "mozilla/dom/WindowContext.h";
using mozilla::dom::WindowContextTransaction from "mozilla/dom/WindowContext.h"; using mozilla::dom::WindowContextTransaction from "mozilla/dom/WindowContext.h";
[MoveOnly] using mozilla::ipc::ReadOnlySharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h"; [MoveOnly] using mozilla::ipc::SharedMemoryHandle from "mozilla/ipc/SharedMemory.h";
using gfxSparseBitSet from "gfxFontUtils.h"; using gfxSparseBitSet from "gfxFontUtils.h";
using FontVisibility from "gfxFontEntry.h"; using FontVisibility from "gfxFontEntry.h";
using mozilla::dom::MediaControlAction from "mozilla/dom/MediaControlKeySource.h"; using mozilla::dom::MediaControlAction from "mozilla/dom/MediaControlKeySource.h";
@@ -400,7 +400,8 @@ struct VisitedQueryResult
struct StringBundleDescriptor struct StringBundleDescriptor
{ {
nsCString bundleURL; nsCString bundleURL;
ReadOnlySharedMemoryHandle mapHandle; SharedMemoryHandle mapHandle;
uint32_t mapSize;
}; };
struct IPCURLClassifierFeature struct IPCURLClassifierFeature
@@ -714,7 +715,7 @@ child:
* should map the new block and add to its index. * should map the new block and add to its index.
*/ */
async FontListShmBlockAdded(uint32_t aGeneration, uint32_t aIndex, async FontListShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
ReadOnlySharedMemoryHandle aHandle); SharedMemoryHandle aHandle);
async UpdateAppLocales(nsCString[] appLocales); async UpdateAppLocales(nsCString[] appLocales);
async UpdateRequestedLocales(nsCString[] requestedLocales); async UpdateRequestedLocales(nsCString[] requestedLocales);
@@ -731,7 +732,7 @@ child:
async SimpleURIUnknownRemoteSchemes(nsCString[] remoteSchemes); async SimpleURIUnknownRemoteSchemes(nsCString[] remoteSchemes);
async UpdateSharedData(ReadOnlySharedMemoryHandle aMapHandle, async UpdateSharedData(SharedMemoryHandle aMapHandle, uint32_t aSize,
IPCBlob[] blobs, IPCBlob[] blobs,
nsCString[] changedKeys); nsCString[] changedKeys);
@@ -802,9 +803,9 @@ child:
FullLookAndFeel lookAndFeeldata, FullLookAndFeel lookAndFeeldata,
/* used on MacOSX/Linux/Android only: */ /* used on MacOSX/Linux/Android only: */
SystemFontList systemFontList, SystemFontList systemFontList,
ReadOnlySharedMemoryHandle? sharedUASheetHandle, SharedMemoryHandle? sharedUASheetHandle,
uintptr_t sharedUASheetAddress, uintptr_t sharedUASheetAddress,
ReadOnlySharedMemoryHandle[] sharedFontListBlocks, SharedMemoryHandle[] sharedFontListBlocks,
bool aIsStartingUp); bool aIsStartingUp);
// Notify child that last-pb-context-exited notification was observed // Notify child that last-pb-context-exited notification was observed
@@ -1376,7 +1377,7 @@ parent:
* until it has mapped the font-list memory. * until it has mapped the font-list memory.
*/ */
sync GetFontListShmBlock(uint32_t aGeneration, uint32_t aIndex) sync GetFontListShmBlock(uint32_t aGeneration, uint32_t aIndex)
returns (ReadOnlySharedMemoryHandle aHandle); returns (SharedMemoryHandle aHandle);
/** /**
* Ask the parent to initialize a given font family, so that face metadata * Ask the parent to initialize a given font family, so that face metadata
@@ -1494,7 +1495,7 @@ parent:
* @param aLoaded * @param aLoaded
* Returns the size in bytes of the resource. * Returns the size in bytes of the resource.
*/ */
sync GetHyphDict(nullable nsIURI aURI) returns (ReadOnlySharedMemoryHandle aHandle); sync GetHyphDict(nullable nsIURI aURI) returns (SharedMemoryHandle aHandle, uint32_t aSize);
async CreateWindow(PBrowser aThisTab, async CreateWindow(PBrowser aThisTab,
MaybeDiscardedBrowsingContext aParent, MaybeDiscardedBrowsingContext aParent,

View File

@@ -43,10 +43,11 @@ static inline void AlignTo(size_t* aOffset, size_t aAlign) {
SharedMap::SharedMap() = default; SharedMap::SharedMap() = default;
SharedMap::SharedMap(nsIGlobalObject* aGlobal, SharedMemoryHandle&& aMapHandle, SharedMap::SharedMap(nsIGlobalObject* aGlobal, SharedMemoryHandle&& aMapHandle,
nsTArray<RefPtr<BlobImpl>>&& aBlobs) size_t aMapSize, nsTArray<RefPtr<BlobImpl>>&& aBlobs)
: DOMEventTargetHelper(aGlobal), : DOMEventTargetHelper(aGlobal),
mBlobImpls(std::move(aBlobs)), mBlobImpls(std::move(aBlobs)),
mHandle(std::move(aMapHandle)) {} mMapHandle(std::move(aMapHandle)),
mMapSize(aMapSize) {}
bool SharedMap::Has(const nsACString& aName) { bool SharedMap::Has(const nsACString& aName) {
Unused << MaybeRebuild(); Unused << MaybeRebuild();
@@ -96,13 +97,21 @@ void SharedMap::Entry::Read(JSContext* aCx,
holder.Read(aCx, aRetVal, aRv); holder.Read(aCx, aRetVal, aRv);
} }
void SharedMap::Update(SharedMemoryHandle&& aMapHandle, SharedMap::SharedMemoryHandle SharedMap::CloneHandle() const {
if (mMap->IsValid()) {
return mMap->CloneHandle();
}
return SharedMemory::CloneHandle(mMapHandle);
}
void SharedMap::Update(SharedMemoryHandle&& aMapHandle, size_t aMapSize,
nsTArray<RefPtr<BlobImpl>>&& aBlobs, nsTArray<RefPtr<BlobImpl>>&& aBlobs,
nsTArray<nsCString>&& aChangedKeys) { nsTArray<nsCString>&& aChangedKeys) {
MOZ_DIAGNOSTIC_ASSERT(!mWritable); MOZ_DIAGNOSTIC_ASSERT(!mWritable);
mMapping = nullptr; mMap->TakeHandleAndUnmap();
mHandle = std::move(aMapHandle); mMapHandle = std::move(aMapHandle);
mMapSize = aMapSize;
mEntries.Clear(); mEntries.Clear();
mEntryArray.reset(); mEntryArray.reset();
@@ -182,12 +191,10 @@ void SharedMap::Entry::ExtractData(char* aDestPtr, uint32_t aNewOffset,
} }
Result<Ok, nsresult> SharedMap::MaybeRebuild() { Result<Ok, nsresult> SharedMap::MaybeRebuild() {
if (mMapping || !mHandle) { if (!SharedMemory::IsHandleValid(mMapHandle)) {
return Ok(); return Ok();
} }
MOZ_DIAGNOSTIC_ASSERT(!mWritable);
// This function maps a shared memory region created by Serialize() and reads // This function maps a shared memory region created by Serialize() and reads
// its header block to build a new mEntries hashtable of its contents. // its header block to build a new mEntries hashtable of its contents.
// //
@@ -196,20 +203,24 @@ Result<Ok, nsresult> SharedMap::MaybeRebuild() {
// its shared memory region. When needed, that structured clone data is // its shared memory region. When needed, that structured clone data is
// retrieved directly as indexes into the SharedMap's shared memory region. // retrieved directly as indexes into the SharedMap's shared memory region.
mMapping = mHandle.Map(); if (!mMap->SetHandle(SharedMemory::CloneHandle(mMapHandle),
if (!mMapping) { SharedMemory::OpenRights::RightsReadOnly)) {
return Err(NS_ERROR_FAILURE);
}
mMapHandle = SharedMemory::NULLHandle();
if (!mMap->Map(mMapSize)) {
return Err(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
mHandle = nullptr;
Range<const uint8_t> inputRange(mMapping.DataAsSpan<uint8_t>()); // We should be able to pass this range as an initializer list or an immediate
InputBuffer buffer(inputRange); // param, but gcc currently chokes on that if optimization is enabled, and
// initializes everything to 0.
Range<uint8_t> range((uint8_t*)mMap->Memory(), mMap->Size());
InputBuffer buffer(range);
uint32_t count; uint32_t count;
buffer.codeUint32(count); buffer.codeUint32(count);
MOZ_ASSERT(mEntries.IsEmpty());
MOZ_ASSERT(mEntryArray.isNothing());
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
auto entry = MakeUnique<Entry>(*this); auto entry = MakeUnique<Entry>(*this);
entry->Code(buffer); entry->Code(buffer);
@@ -235,9 +246,9 @@ void SharedMap::MaybeRebuild() const {
WritableSharedMap::WritableSharedMap() { WritableSharedMap::WritableSharedMap() {
mWritable = true; mWritable = true;
// Serialize the initial empty contents of the map immediately so that we // Serialize the initial empty contents of the map immediately so that we
// always have a file descriptor to send. // always have a file descriptor to send to callers of CloneMapFile().
Unused << Serialize(); Unused << Serialize();
MOZ_RELEASE_ASSERT(mHandle.IsValid() && mMapping.IsValid()); MOZ_RELEASE_ASSERT(mMap->IsValid());
} }
SharedMap* WritableSharedMap::GetReadOnly() { SharedMap* WritableSharedMap::GetReadOnly() {
@@ -245,7 +256,7 @@ SharedMap* WritableSharedMap::GetReadOnly() {
nsTArray<RefPtr<BlobImpl>> blobs(mBlobImpls.Clone()); nsTArray<RefPtr<BlobImpl>> blobs(mBlobImpls.Clone());
mReadOnly = mReadOnly =
new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(), new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(),
mHandle.Clone(), std::move(blobs)); CloneHandle(), MapSize(), std::move(blobs));
} }
return mReadOnly; return mReadOnly;
} }
@@ -328,11 +339,8 @@ Result<Ok, nsresult> WritableSharedMap::Serialize() {
memcpy(ptr.get(), header.Get(), header.cursor()); memcpy(ptr.get(), header.Get(), header.cursor());
// We've already updated offsets at this point. We need this to succeed. // We've already updated offsets at this point. We need this to succeed.
auto result = mem.Finalize(); mMap->TakeHandleAndUnmap();
MOZ_RELEASE_ASSERT(result.isOk()); MOZ_RELEASE_ASSERT(mem.Finalize(mMap).isOk());
mHandle = result.unwrap();
mMapping = mHandle.Map();
MOZ_RELEASE_ASSERT(mMapping.IsValid());
return Ok(); return Ok();
} }
@@ -347,7 +355,8 @@ void WritableSharedMap::SendTo(ContentParent* aParent) const {
} }
} }
Unused << aParent->SendUpdateSharedData(mHandle.Clone(), blobs, mChangedKeys); Unused << aParent->SendUpdateSharedData(CloneHandle(), mMap->Size(), blobs,
mChangedKeys);
} }
void WritableSharedMap::BroadcastChanges() { void WritableSharedMap::BroadcastChanges() {
@@ -367,7 +376,7 @@ void WritableSharedMap::BroadcastChanges() {
if (mReadOnly) { if (mReadOnly) {
nsTArray<RefPtr<BlobImpl>> blobImpls(mBlobImpls.Clone()); nsTArray<RefPtr<BlobImpl>> blobImpls(mBlobImpls.Clone());
mReadOnly->Update(mHandle.Clone(), std::move(blobImpls), mReadOnly->Update(CloneHandle(), mMap->Size(), std::move(blobImpls),
std::move(mChangedKeys)); std::move(mChangedKeys));
} }

View File

@@ -10,8 +10,7 @@
#include "mozilla/dom/MozSharedMapBinding.h" #include "mozilla/dom/MozSharedMapBinding.h"
#include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/dom/ipc/StructuredCloneData.h"
#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/ipc/SharedMemory.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "mozilla/DOMEventTargetHelper.h" #include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
@@ -54,14 +53,13 @@ namespace ipc {
* WritableSharedMap instances. * WritableSharedMap instances.
*/ */
class SharedMap : public DOMEventTargetHelper { class SharedMap : public DOMEventTargetHelper {
protected: using SharedMemory = mozilla::ipc::SharedMemory;
using SharedMemoryMapping = mozilla::ipc::ReadOnlySharedMemoryMapping; using SharedMemoryHandle = mozilla::ipc::SharedMemoryHandle;
using SharedMemoryHandle = mozilla::ipc::ReadOnlySharedMemoryHandle;
public: public:
SharedMap(); SharedMap();
SharedMap(nsIGlobalObject* aGlobal, SharedMemoryHandle&&, SharedMap(nsIGlobalObject* aGlobal, SharedMemoryHandle&&, size_t,
nsTArray<RefPtr<BlobImpl>>&& aBlobs); nsTArray<RefPtr<BlobImpl>>&& aBlobs);
// Returns true if the map contains the given (UTF-8) key. // Returns true if the map contains the given (UTF-8) key.
@@ -95,16 +93,26 @@ class SharedMap : public DOMEventTargetHelper {
JS::MutableHandle<JS::Value> aResult) const; JS::MutableHandle<JS::Value> aResult) const;
/** /**
* Returns the size of the memory mapped region that backs this map. * Returns a copy of the read-only file descriptor which backs the shared
* memory region for this map. The file descriptor may be passed between
* processes, and used to update corresponding instances in child processes.
*/ */
size_t MapSize() const { return mMapping.Size(); } SharedMemoryHandle CloneHandle() const;
/**
* Returns the size of the memory mapped region that backs this map. Must be
* passed to the SharedMap() constructor or Update() method along with the
* descriptor returned by CloneMapFile() in order to initialize or update a
* child SharedMap.
*/
size_t MapSize() const { return mMap->Size(); }
/** /**
* Updates this instance to reflect the contents of the shared memory region * Updates this instance to reflect the contents of the shared memory region
* in the given map handle, and broadcasts a change event for the given set of * in the given map handle, and broadcasts a change event for the given set of
* changed (UTF-8-encoded) keys. * changed (UTF-8-encoded) keys.
*/ */
void Update(SharedMemoryHandle&& aMapHandle, void Update(SharedMemoryHandle&& aMapHandle, size_t aMapSize,
nsTArray<RefPtr<BlobImpl>>&& aBlobs, nsTArray<RefPtr<BlobImpl>>&& aBlobs,
nsTArray<nsCString>&& aChangedKeys); nsTArray<nsCString>&& aChangedKeys);
@@ -255,20 +263,24 @@ class SharedMap : public DOMEventTargetHelper {
Result<Ok, nsresult> MaybeRebuild(); Result<Ok, nsresult> MaybeRebuild();
void MaybeRebuild() const; void MaybeRebuild() const;
SharedMemoryHandle mMapHandle;
// The size of the memory-mapped region backed by mMap, in bytes.
size_t mMapSize = 0;
mutable nsClassHashtable<nsCStringHashKey, Entry> mEntries; mutable nsClassHashtable<nsCStringHashKey, Entry> mEntries;
mutable Maybe<nsTArray<Entry*>> mEntryArray; mutable Maybe<nsTArray<Entry*>> mEntryArray;
// Manages the memory mapping of the current snapshot. This is initialized // Manages the memory mapping of the current snapshot. This is initialized
// lazily after each SharedMap construction or update. // lazily after each SharedMap construction or updated, based on the values in
SharedMemoryHandle mHandle; // mMapFile and mMapSize.
SharedMemoryMapping mMapping; RefPtr<SharedMemory> mMap = MakeRefPtr<SharedMemory>();
bool mWritable = false; bool mWritable = false;
// Returns a pointer to the beginning of the memory mapped snapshot. Entry // Returns a pointer to the beginning of the memory mapped snapshot. Entry
// offsets are relative to this pointer, and Entry objects access their // offsets are relative to this pointer, and Entry objects access their
// structured clone data by indexing this pointer. // structured clone data by indexing this pointer.
const char* Data() { return mMapping.DataAs<char>(); } char* Data() { return static_cast<char*>(mMap->Memory()); }
}; };
class WritableSharedMap final : public SharedMap { class WritableSharedMap final : public SharedMap {

View File

@@ -27,36 +27,42 @@ static inline size_t GetAlignmentOffset(size_t aOffset, size_t aAlign) {
return mod ? aAlign - mod : 0; return mod ? aAlign - mod : 0;
} }
SharedStringMap::SharedStringMap(const ReadOnlySharedMemoryHandle& aMapHandle) { SharedStringMap::SharedStringMap(const SharedMemoryHandle& aMapHandle,
mHandle = aMapHandle.Clone(); size_t aMapSize) {
MOZ_RELEASE_ASSERT(mHandle.IsValid()); auto map = MakeRefPtr<SharedMemory>();
auto mapping = aMapHandle.Map(); {
MOZ_RELEASE_ASSERT(mapping.IsValid()); auto result = map->SetHandle(SharedMemory::CloneHandle(aMapHandle),
SharedMemory::OpenRights::RightsReadOnly);
MOZ_RELEASE_ASSERT(result);
}
{
auto result = map->Map(aMapSize);
MOZ_RELEASE_ASSERT(result);
}
// We return literal nsStrings and nsCStrings pointing to the mapped data, // We return literal nsStrings and nsCStrings pointing to the mapped data,
// which means that we may still have references to the mapped data even // which means that we may still have references to the mapped data even
// after this instance is destroyed. That means that we need to keep the // after this instance is destroyed. That means that we need to keep the
// mapping alive until process shutdown, in order to be safe. // mapping alive until process shutdown, in order to be safe.
mMappedMemory = std::move(mapping).Release(); mMappedMemory = map->TakeMapping();
mHandle = map->TakeHandle();
MOZ_RELEASE_ASSERT(GetHeader().mMagic == kSharedStringMapMagic); MOZ_RELEASE_ASSERT(GetHeader().mMagic == kSharedStringMapMagic);
} }
SharedStringMap::SharedStringMap(SharedStringMapBuilder&& aBuilder) { SharedStringMap::SharedStringMap(SharedStringMapBuilder&& aBuilder) {
ReadOnlySharedMemoryMappingWithHandle mappingWithHandle; RefPtr<SharedMemory> map;
auto result = aBuilder.Finalize(); auto result = aBuilder.Finalize(map);
MOZ_RELEASE_ASSERT(result.isOk()); MOZ_RELEASE_ASSERT(result.isOk() && map);
mHandle = result.unwrap();
auto mapping = mHandle.Map();
MOZ_RELEASE_ASSERT(mapping.IsValid());
mMappedMemory = std::move(mapping).Release(); mMappedMemory = map->TakeMapping();
mHandle = map->TakeHandle();
MOZ_RELEASE_ASSERT(GetHeader().mMagic == kSharedStringMapMagic); MOZ_RELEASE_ASSERT(GetHeader().mMagic == kSharedStringMapMagic);
} }
mozilla::ipc::ReadOnlySharedMemoryHandle SharedStringMap::CloneHandle() const { mozilla::ipc::SharedMemoryHandle SharedStringMap::CloneHandle() const {
return mHandle.Clone(); return SharedMemory::CloneHandle(mHandle);
} }
bool SharedStringMap::Has(const nsCString& aKey) { bool SharedStringMap::Has(const nsCString& aKey) {
@@ -91,8 +97,8 @@ void SharedStringMapBuilder::Add(const nsCString& aKey,
Entry{mKeyTable.Add(aKey), mValueTable.Add(aValue)}); Entry{mKeyTable.Add(aKey), mValueTable.Add(aValue)});
} }
Result<ReadOnlySharedMemoryHandle, nsresult> Result<Ok, nsresult> SharedStringMapBuilder::Finalize(
SharedStringMapBuilder::Finalize() { RefPtr<SharedMemory>& aMap) {
using Header = SharedStringMap::Header; using Header = SharedStringMap::Header;
MOZ_ASSERT(mEntries.Count() == mKeyTable.Count()); MOZ_ASSERT(mEntries.Count() == mKeyTable.Count());
@@ -141,7 +147,7 @@ SharedStringMapBuilder::Finalize() {
mValueTable.Clear(); mValueTable.Clear();
mEntries.Clear(); mEntries.Clear();
return mem.Finalize(); return mem.Finalize(aMap);
} }
} // namespace dom::ipc } // namespace dom::ipc

View File

@@ -9,8 +9,7 @@
#include "mozilla/Result.h" #include "mozilla/Result.h"
#include "mozilla/dom/ipc/StringTable.h" #include "mozilla/dom/ipc/StringTable.h"
#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/ipc/SharedMemory.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "nsTHashMap.h" #include "nsTHashMap.h"
namespace mozilla::dom::ipc { namespace mozilla::dom::ipc {
@@ -89,7 +88,7 @@ class SharedStringMap {
// Note: These constructors are infallible on the premise that this class // Note: These constructors are infallible on the premise that this class
// is used primarily in cases where it is critical to platform // is used primarily in cases where it is critical to platform
// functionality. // functionality.
explicit SharedStringMap(const mozilla::ipc::ReadOnlySharedMemoryHandle&); explicit SharedStringMap(const mozilla::ipc::SharedMemoryHandle&, size_t);
explicit SharedStringMap(SharedStringMapBuilder&&); explicit SharedStringMap(SharedStringMapBuilder&&);
/** /**
@@ -152,7 +151,7 @@ class SharedStringMap {
* used to construct new instances of SharedStringMap with the same data as * used to construct new instances of SharedStringMap with the same data as
* this instance. * this instance.
*/ */
mozilla::ipc::ReadOnlySharedMemoryHandle CloneHandle() const; mozilla::ipc::SharedMemoryHandle CloneHandle() const;
size_t MapSize() const { return mMappedMemory.size(); } size_t MapSize() const { return mMappedMemory.size(); }
@@ -173,23 +172,21 @@ class SharedStringMap {
StringTable<nsCString> KeyTable() const { StringTable<nsCString> KeyTable() const {
const auto& header = GetHeader(); const auto& header = GetHeader();
return { return {{&mMappedMemory.data()[header.mKeyStringsOffset],
{const_cast<uint8_t*>(&mMappedMemory.data()[header.mKeyStringsOffset]), header.mKeyStringsSize}};
header.mKeyStringsSize}};
} }
StringTable<nsString> ValueTable() const { StringTable<nsString> ValueTable() const {
const auto& header = GetHeader(); const auto& header = GetHeader();
return {{const_cast<uint8_t*>( return {{&mMappedMemory.data()[header.mValueStringsOffset],
&mMappedMemory.data()[header.mValueStringsOffset]),
header.mValueStringsSize}}; header.mValueStringsSize}};
} }
mozilla::ipc::ReadOnlySharedMemoryHandle mHandle; mozilla::ipc::SharedMemoryHandle mHandle;
// This is a leaked shared memory mapping (see the constructor definition for // This is a leaked shared memory mapping (see the constructor definition for
// an explanation). It replaces AutoMemMap::setPersistent behavior as part of // an explanation). It replaces AutoMemMap::setPersistent behavior as part of
// bug 1454816. // bug 1454816.
mozilla::ipc::shared_memory::LeakedReadOnlyMapping mMappedMemory; Span<uint8_t> mMappedMemory;
}; };
/** /**
@@ -208,9 +205,10 @@ class MOZ_RAII SharedStringMapBuilder {
/** /**
* Finalizes the binary representation of the map, writes it to a shared * Finalizes the binary representation of the map, writes it to a shared
* memory region, and then returns a read-only handle to it. * memory region, and then initializes the given SharedMemory with a reference
* to the read-only copy of it.
*/ */
Result<mozilla::ipc::ReadOnlySharedMemoryHandle, nsresult> Finalize(); Result<Ok, nsresult> Finalize(RefPtr<mozilla::ipc::SharedMemory>& aMap);
private: private:
using Entry = SharedStringMap::Entry; using Entry = SharedStringMap::Entry;

View File

@@ -22,7 +22,7 @@
#include "mozilla/ipc/GeckoChildProcessHost.h" #include "mozilla/ipc/GeckoChildProcessHost.h"
#if defined(XP_LINUX) && defined(MOZ_SANDBOX) #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
# include "mozilla/SandboxInfo.h" # include "mozilla/SandboxInfo.h"
# include "mozilla/ipc/SharedMemoryHandle.h" # include "mozilla/ipc/SharedMemory.h"
#endif #endif
#include "mozilla/Services.h" #include "mozilla/Services.h"
#include "mozilla/SSE.h" #include "mozilla/SSE.h"
@@ -303,7 +303,7 @@ class NotifyGMPProcessLoadedTask : public Runnable {
#if defined(XP_LINUX) && defined(MOZ_SANDBOX) #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
if (SandboxInfo::Get().Test(SandboxInfo::kEnabledForMedia) && if (SandboxInfo::Get().Test(SandboxInfo::kEnabledForMedia) &&
ipc::shared_memory::UsingPosixShm()) { ipc::SharedMemory::UsingPosixShm()) {
canProfile = false; canProfile = false;
} }
#endif #endif

View File

@@ -18,9 +18,11 @@ void GMPProcessChild::InitStatics(int aArgc, char* aArgv[]) {
Maybe<bool> nativeEvent = geckoargs::sPluginNativeEvent.Get(aArgc, aArgv); Maybe<bool> nativeEvent = geckoargs::sPluginNativeEvent.Get(aArgc, aArgv);
sUseNativeEventProcessing = nativeEvent.isSome() && *nativeEvent; sUseNativeEventProcessing = nativeEvent.isSome() && *nativeEvent;
auto prefsHandlePresent = geckoargs::sPrefsHandle.IsPresent(aArgc, aArgv); Maybe<uint64_t> prefsLen =
auto prefMapHandlePresent = geckoargs::sPrefMapHandle.IsPresent(aArgc, aArgv); geckoargs::sPrefsLen.Get(aArgc, aArgv, CheckArgFlag::None);
sUseXpcom = prefsHandlePresent && prefMapHandlePresent; Maybe<uint64_t> prefMapSize =
geckoargs::sPrefMapSize.Get(aArgc, aArgv, CheckArgFlag::None);
sUseXpcom = prefsLen.isSome() && prefMapSize.isSome();
} }
GMPProcessChild::~GMPProcessChild() = default; GMPProcessChild::~GMPProcessChild() = default;

View File

@@ -4,7 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GMPSharedMemManager.h" #include "GMPSharedMemManager.h"
#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/ipc/SharedMemory.h"
namespace mozilla::gmp { namespace mozilla::gmp {
@@ -49,7 +49,7 @@ bool GMPSharedMemManager::MgrTakeShmem(GMPSharedMemClass aClass, size_t aSize,
MOZ_ASSERT(MgrIsOnOwningThread()); MOZ_ASSERT(MgrIsOnOwningThread());
auto& pool = mPool[size_t(aClass)]; auto& pool = mPool[size_t(aClass)];
size_t alignedSize = ipc::shared_memory::PageAlignedSize(aSize); size_t alignedSize = ipc::SharedMemory::PageAlignedSize(aSize);
PurgeSmallerShmem(pool, alignedSize); PurgeSmallerShmem(pool, alignedSize);
if (pool.IsEmpty()) { if (pool.IsEmpty()) {
return MgrAllocShmem(alignedSize, aMem); return MgrAllocShmem(alignedSize, aMem);

View File

@@ -42,10 +42,11 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Buffer)
NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_TRACE_END
Buffer::Buffer(Device* const aParent, RawId aId, BufferAddress aSize, Buffer::Buffer(Device* const aParent, RawId aId, BufferAddress aSize,
uint32_t aUsage, ipc::SharedMemoryMapping&& aShmem) uint32_t aUsage, ipc::WritableSharedMemoryMapping&& aShmem)
: ChildOf(aParent), mId(aId), mSize(aSize), mUsage(aUsage) { : ChildOf(aParent), mId(aId), mSize(aSize), mUsage(aUsage) {
mozilla::HoldJSObjects(this); mozilla::HoldJSObjects(this);
mShmem = std::make_shared<ipc::SharedMemoryMapping>(std::move(aShmem)); mShmem =
std::make_shared<ipc::WritableSharedMemoryMapping>(std::move(aShmem));
MOZ_ASSERT(mParent); MOZ_ASSERT(mParent);
} }
@@ -62,14 +63,14 @@ already_AddRefed<Buffer> Buffer::Create(Device* aDevice, RawId aDeviceId,
if (!aDevice->IsBridgeAlive()) { if (!aDevice->IsBridgeAlive()) {
// Create and return an invalid Buffer. // Create and return an invalid Buffer.
RefPtr<Buffer> buffer = RefPtr<Buffer> buffer = new Buffer(aDevice, bufferId, aDesc.mSize, 0,
new Buffer(aDevice, bufferId, aDesc.mSize, 0, nullptr); ipc::WritableSharedMemoryMapping());
buffer->mValid = false; buffer->mValid = false;
return buffer.forget(); return buffer.forget();
} }
ipc::MutableSharedMemoryHandle handle; auto handle = ipc::UnsafeSharedMemoryHandle();
ipc::SharedMemoryMapping mapping; auto mapping = ipc::WritableSharedMemoryMapping();
bool hasMapFlags = aDesc.mUsage & (dom::GPUBufferUsage_Binding::MAP_WRITE | bool hasMapFlags = aDesc.mUsage & (dom::GPUBufferUsage_Binding::MAP_WRITE |
dom::GPUBufferUsage_Binding::MAP_READ); dom::GPUBufferUsage_Binding::MAP_READ);
@@ -84,18 +85,17 @@ already_AddRefed<Buffer> Buffer::Create(Device* aDevice, RawId aDeviceId,
size_t size = checked.value(); size_t size = checked.value();
if (size > 0 && size < maxSize) { if (size > 0 && size < maxSize) {
handle = ipc::shared_memory::Create(size); auto maybeShmem = ipc::UnsafeSharedMemoryHandle::CreateAndMap(size);
mapping = handle.Map();
if (handle && mapping) { if (maybeShmem.isSome()) {
allocSucceeded = true; allocSucceeded = true;
handle = std::move(maybeShmem.ref().first);
mapping = std::move(maybeShmem.ref().second);
MOZ_RELEASE_ASSERT(mapping.Size() >= size); MOZ_RELEASE_ASSERT(mapping.Size() >= size);
// zero out memory // zero out memory
memset(mapping.Address(), 0, size); memset(mapping.Bytes().data(), 0, size);
} else {
handle = nullptr;
mapping = nullptr;
} }
} }
@@ -259,7 +259,8 @@ already_AddRefed<dom::Promise> Buffer::MapAsync(
static void ExternalBufferFreeCallback(void* aContents, void* aUserData) { static void ExternalBufferFreeCallback(void* aContents, void* aUserData) {
Unused << aContents; Unused << aContents;
auto shm = static_cast<std::shared_ptr<ipc::SharedMemoryMapping>*>(aUserData); auto shm = static_cast<std::shared_ptr<ipc::WritableSharedMemoryMapping>*>(
aUserData);
delete shm; delete shm;
} }
@@ -352,8 +353,8 @@ void Buffer::GetMappedRange(JSContext* aCx, uint64_t aOffset,
// unfortunately necessary: `JS::BufferContentsDeleter` requires that its // unfortunately necessary: `JS::BufferContentsDeleter` requires that its
// `userData` be a `void*`, and while `shared_ptr` can't be inter-converted // `userData` be a `void*`, and while `shared_ptr` can't be inter-converted
// with `void*` (it's actually two pointers), `shared_ptr*` obviously can. // with `void*` (it's actually two pointers), `shared_ptr*` obviously can.
std::shared_ptr<ipc::SharedMemoryMapping>* data = std::shared_ptr<ipc::WritableSharedMemoryMapping>* data =
new std::shared_ptr<ipc::SharedMemoryMapping>(mShmem); new std::shared_ptr<ipc::WritableSharedMemoryMapping>(mShmem);
// 4. Let `view` be (potentially fallible operation follows) create an // 4. Let `view` be (potentially fallible operation follows) create an
// `ArrayBuffer` of size `rangeSize`, but with its pointer mutably // `ArrayBuffer` of size `rangeSize`, but with its pointer mutably
@@ -365,8 +366,7 @@ void Buffer::GetMappedRange(JSContext* aCx, uint64_t aOffset,
// range for `size_t` before any conversion is performed. // range for `size_t` before any conversion is performed.
const auto checkedSize = CheckedInt<size_t>(rangeSize.value()).value(); const auto checkedSize = CheckedInt<size_t>(rangeSize.value()).value();
const auto checkedOffset = CheckedInt<size_t>(offset.value()).value(); const auto checkedOffset = CheckedInt<size_t>(offset.value()).value();
const auto span = const auto span = (*data)->Bytes().Subspan(checkedOffset, checkedSize);
(*data)->DataAsSpan<uint8_t>().Subspan(checkedOffset, checkedSize);
UniquePtr<void, JS::BufferContentsDeleter> contents{ UniquePtr<void, JS::BufferContentsDeleter> contents{
span.data(), {&ExternalBufferFreeCallback, data}}; span.data(), {&ExternalBufferFreeCallback, data}};
JS::Rooted<JSObject*> view( 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. // 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 // It won't be possible to map the buffer again so we can get rid of
// our shmem on this side. // our shmem on this side.
mShmem = std::make_shared<ipc::SharedMemoryMapping>(); mShmem = std::make_shared<ipc::WritableSharedMemoryMapping>();
} }
if (!GetDevice().IsLost()) { if (!GetDevice().IsLost()) {

View File

@@ -8,10 +8,10 @@
#include "js/RootingAPI.h" #include "js/RootingAPI.h"
#include "mozilla/dom/Nullable.h" #include "mozilla/dom/Nullable.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "mozilla/webgpu/WebGPUTypes.h" #include "mozilla/webgpu/WebGPUTypes.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "ObjectModel.h" #include "ObjectModel.h"
#include "mozilla/ipc/RawShmem.h"
#include <memory> #include <memory>
namespace mozilla { namespace mozilla {
@@ -112,7 +112,7 @@ class Buffer final : public ObjectBase, public ChildOf<Device> {
private: private:
Buffer(Device* const aParent, RawId aId, BufferAddress aSize, uint32_t aUsage, Buffer(Device* const aParent, RawId aId, BufferAddress aSize, uint32_t aUsage,
ipc::SharedMemoryMapping&& aShmem); ipc::WritableSharedMemoryMapping&& aShmem);
virtual ~Buffer(); virtual ~Buffer();
Device& GetDevice() { return *mParent; } Device& GetDevice() { return *mParent; }
void Cleanup(); 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 // and destroyed when we first unmap the buffer, by clearing this
// `shared_ptr`. // `shared_ptr`.
// //
// Otherwise, this points to `SharedMemoryMapping()` (the default // Otherwise, this points to `WritableSharedMemoryMapping()` (the
// constructor), a zero-length mapping that doesn't point to any shared // default constructor), a zero-length mapping that doesn't point to
// memory. // any shared memory.
std::shared_ptr<ipc::SharedMemoryMapping> mShmem; std::shared_ptr<ipc::WritableSharedMemoryMapping> mShmem;
}; };
} // namespace webgpu } // namespace webgpu

View File

@@ -20,8 +20,6 @@
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"
#include "mozilla/dom/WebGLTexelConversions.h" #include "mozilla/dom/WebGLTexelConversions.h"
#include "mozilla/dom/WebGLTypes.h" #include "mozilla/dom/WebGLTypes.h"
#include "mozilla/ipc/SharedMemoryHandle.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "nsLayoutUtils.h" #include "nsLayoutUtils.h"
#include "Utility.h" #include "Utility.h"
@@ -120,17 +118,16 @@ void Queue::WriteBuffer(const Buffer& aBuffer, uint64_t aBufferOffset,
return; return;
} }
mozilla::ipc::MutableSharedMemoryHandle handle; auto alloc = mozilla::ipc::UnsafeSharedMemoryHandle::CreateAndMap(size);
if (size != 0) { if (alloc.isNothing()) {
handle = mozilla::ipc::shared_memory::Create(size); aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
auto mapping = handle.Map(); return;
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; ipc::ByteBuf bb;
ffi::wgpu_queue_write_buffer(aBuffer.mId, aBufferOffset, ToFFI(&bb)); ffi::wgpu_queue_write_buffer(aBuffer.mId, aBufferOffset, ToFFI(&bb));
mBridge->SendQueueWriteAction(mId, mParent->mId, std::move(bb), mBridge->SendQueueWriteAction(mId, mParent->mId, std::move(bb),
@@ -164,19 +161,18 @@ void Queue::WriteTexture(const dom::GPUTexelCopyTextureInfo& aDestination,
} }
const auto size = checkedSize.value(); const auto size = checkedSize.value();
mozilla::ipc::MutableSharedMemoryHandle handle; auto alloc = mozilla::ipc::UnsafeSharedMemoryHandle::CreateAndMap(size);
if (size != 0) { if (alloc.isNothing()) {
handle = mozilla::ipc::shared_memory::Create(size); aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
auto mapping = handle.Map(); return;
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; ipc::ByteBuf bb;
ffi::wgpu_queue_write_texture(copyView, dataLayout, extent, ToFFI(&bb)); ffi::wgpu_queue_write_texture(copyView, dataLayout, extent, ToFFI(&bb));
mBridge->SendQueueWriteAction(mId, mParent->mId, std::move(bb), mBridge->SendQueueWriteAction(mId, mParent->mId, std::move(bb),
@@ -399,15 +395,18 @@ void Queue::CopyExternalImageToTexture(
return; return;
} }
auto handle = mozilla::ipc::shared_memory::Create(dstByteLength.value()); auto alloc = mozilla::ipc::UnsafeSharedMemoryHandle::CreateAndMap(
auto mapping = handle.Map(); dstByteLength.value());
if (!handle || !mapping) { if (alloc.isNothing()) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY); aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return; return;
} }
auto handle = std::move(alloc.ref().first);
auto mapping = std::move(alloc.ref().second);
const int32_t pixelSize = gfx::BytesPerPixel(surfaceFormat); const int32_t pixelSize = gfx::BytesPerPixel(surfaceFormat);
auto* dstBegin = mapping.DataAs<uint8_t>(); auto* dstBegin = mapping.Bytes().data();
const auto* srcBegin = const auto* srcBegin =
map.GetData() + srcOriginX * pixelSize + srcOriginY * map.GetStride(); map.GetData() + srcOriginX * pixelSize + srcOriginY * map.GetStride();
const auto srcOriginPos = gl::OriginPos::TopLeft; const auto srcOriginPos = gl::OriginPos::TopLeft;

View File

@@ -17,7 +17,7 @@ using mozilla::dom::GPUCommandBufferDescriptor from "mozilla/dom/WebGPUBinding.h
using mozilla::dom::GPUBufferDescriptor 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::PopErrorScopeResult from "mozilla/webgpu/WebGPUTypes.h";
using mozilla::webgpu::WebGPUCompilationMessage from "mozilla/webgpu/WebGPUTypes.h"; using mozilla::webgpu::WebGPUCompilationMessage from "mozilla/webgpu/WebGPUTypes.h";
[MoveOnly] using mozilla::ipc::MutableSharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h"; [MoveOnly] using class mozilla::ipc::UnsafeSharedMemoryHandle from "mozilla/ipc/RawShmem.h";
using struct mozilla::void_t from "mozilla/ipc/IPCCore.h"; using struct mozilla::void_t from "mozilla/ipc/IPCCore.h";
include "mozilla/ipc/ByteBufUtils.h"; include "mozilla/ipc/ByteBufUtils.h";
@@ -48,7 +48,7 @@ parent:
async ComputePass(RawId selfId, RawId aDeviceId, ByteBuf buf); async ComputePass(RawId selfId, RawId aDeviceId, ByteBuf buf);
async BumpImplicitBindGroupLayout(RawId pipelineId, bool isCompute, uint32_t index, RawId assignId); async BumpImplicitBindGroupLayout(RawId pipelineId, bool isCompute, uint32_t index, RawId assignId);
async DeviceCreateBuffer(RawId deviceId, RawId bufferId, GPUBufferDescriptor desc, MutableSharedMemoryHandle shm); async DeviceCreateBuffer(RawId deviceId, RawId bufferId, GPUBufferDescriptor desc, UnsafeSharedMemoryHandle shm);
async InstanceRequestAdapter(GPURequestAdapterOptions options, RawId aAdapterId) returns (ByteBuf byteBuf); async InstanceRequestAdapter(GPURequestAdapterOptions options, RawId aAdapterId) returns (ByteBuf byteBuf);
async AdapterRequestDevice( async AdapterRequestDevice(
@@ -77,8 +77,7 @@ parent:
async RenderBundleDrop(RawId selfId); async RenderBundleDrop(RawId selfId);
async QueueSubmit(RawId selfId, RawId aDeviceId, RawId[] commandBuffers, RawId[] textureIds); async QueueSubmit(RawId selfId, RawId aDeviceId, RawId[] commandBuffers, RawId[] textureIds);
async QueueOnSubmittedWorkDone(RawId selfId) returns (void_t ok); async QueueOnSubmittedWorkDone(RawId selfId) returns (void_t ok);
// In the case of a zero-sized write action, `shmem` will be an invalid handle. async QueueWriteAction(RawId selfId, RawId aDeviceId, ByteBuf buf, UnsafeSharedMemoryHandle shmem);
async QueueWriteAction(RawId selfId, RawId aDeviceId, ByteBuf buf, MutableSharedMemoryHandle shmem);
async BindGroupLayoutDrop(RawId selfId); async BindGroupLayoutDrop(RawId selfId);
async PipelineLayoutDrop(RawId selfId); async PipelineLayoutDrop(RawId selfId);

View File

@@ -25,6 +25,7 @@
#include "PipelineLayout.h" #include "PipelineLayout.h"
#include "Sampler.h" #include "Sampler.h"
#include "CompilationInfo.h" #include "CompilationInfo.h"
#include "mozilla/ipc/RawShmem.h"
#include "Utility.h" #include "Utility.h"
#include <utility> #include <utility>

View File

@@ -12,6 +12,9 @@
#include "mozilla/webgpu/ffi/wgpu.h" #include "mozilla/webgpu/ffi/wgpu.h"
namespace mozilla { namespace mozilla {
namespace ipc {
class UnsafeSharedMemoryHandle;
} // namespace ipc
namespace dom { namespace dom {
struct GPURequestAdapterOptions; struct GPURequestAdapterOptions;
} // namespace dom } // namespace dom

View File

@@ -549,10 +549,11 @@ WebGPUParent::BufferMapData* WebGPUParent::GetBufferMapData(RawId aBufferId) {
ipc::IPCResult WebGPUParent::RecvDeviceCreateBuffer( ipc::IPCResult WebGPUParent::RecvDeviceCreateBuffer(
RawId aDeviceId, RawId aBufferId, dom::GPUBufferDescriptor&& aDesc, RawId aDeviceId, RawId aBufferId, dom::GPUBufferDescriptor&& aDesc,
ipc::MutableSharedMemoryHandle&& aShmem) { ipc::UnsafeSharedMemoryHandle&& aShmem) {
webgpu::StringHelper label(aDesc.mLabel); webgpu::StringHelper label(aDesc.mLabel);
auto shmem = aShmem.Map(); auto shmem =
ipc::WritableSharedMemoryMapping::Open(std::move(aShmem)).value();
bool hasMapFlags = aDesc.mUsage & (dom::GPUBufferUsage_Binding::MAP_WRITE | bool hasMapFlags = aDesc.mUsage & (dom::GPUBufferUsage_Binding::MAP_WRITE |
dom::GPUBufferUsage_Binding::MAP_READ); dom::GPUBufferUsage_Binding::MAP_READ);
@@ -663,7 +664,7 @@ void WebGPUParent::MapCallback(uint8_t* aUserData,
MOZ_RELEASE_ASSERT(mapData->mShmem.Size() >= offset + size); MOZ_RELEASE_ASSERT(mapData->mShmem.Size() >= offset + size);
if (src.ptr != nullptr && src.length >= size) { if (src.ptr != nullptr && src.length >= size) {
auto dst = mapData->mShmem.DataAsSpan<uint8_t>().Subspan(offset, size); auto dst = mapData->mShmem.Bytes().Subspan(offset, size);
memcpy(dst.data(), src.ptr, size); memcpy(dst.data(), src.ptr, size);
} }
} }
@@ -746,7 +747,7 @@ ipc::IPCResult WebGPUParent::RecvBufferUnmap(RawId aDeviceId, RawId aBufferId,
MOZ_RELEASE_ASSERT(offset <= shmSize); MOZ_RELEASE_ASSERT(offset <= shmSize);
MOZ_RELEASE_ASSERT(size <= shmSize - offset); MOZ_RELEASE_ASSERT(size <= shmSize - offset);
auto src = mapData->mShmem.DataAsSpan<uint8_t>().Subspan(offset, size); auto src = mapData->mShmem.Bytes().Subspan(offset, size);
memcpy(mapped.ptr, src.data(), size); memcpy(mapped.ptr, src.data(), size);
} }
@@ -911,15 +912,14 @@ ipc::IPCResult WebGPUParent::RecvQueueOnSubmittedWorkDone(
ipc::IPCResult WebGPUParent::RecvQueueWriteAction( ipc::IPCResult WebGPUParent::RecvQueueWriteAction(
RawId aQueueId, RawId aDeviceId, const ipc::ByteBuf& aByteBuf, RawId aQueueId, RawId aDeviceId, const ipc::ByteBuf& aByteBuf,
ipc::MutableSharedMemoryHandle&& aShmem) { ipc::UnsafeSharedMemoryHandle&& aShmem) {
// `aShmem` may be an invalid handle, however this will simply result in an auto mapping =
// invalid mapping with 0 size, which is used safely below. ipc::WritableSharedMemoryMapping::Open(std::move(aShmem)).value();
auto mapping = aShmem.Map();
ErrorBuffer error; ErrorBuffer error;
ffi::wgpu_server_queue_write_action( ffi::wgpu_server_queue_write_action(mContext.get(), aQueueId,
mContext.get(), aQueueId, ToFFI(&aByteBuf), mapping.DataAs<uint8_t>(), ToFFI(&aByteBuf), mapping.Bytes().data(),
mapping.Size(), error.ToFFI()); mapping.Size(), error.ToFFI());
ForwardError(aDeviceId, error); ForwardError(aDeviceId, error);
return IPC_OK(); return IPC_OK();
} }

View File

@@ -9,10 +9,10 @@
#include <unordered_map> #include <unordered_map>
#include "mozilla/WeakPtr.h" #include "mozilla/WeakPtr.h"
#include "mozilla/ipc/SharedMemoryHandle.h"
#include "mozilla/webgpu/ffi/wgpu.h" #include "mozilla/webgpu/ffi/wgpu.h"
#include "mozilla/webgpu/PWebGPUParent.h" #include "mozilla/webgpu/PWebGPUParent.h"
#include "mozilla/webrender/WebRenderAPI.h" #include "mozilla/webrender/WebRenderAPI.h"
#include "mozilla/ipc/RawShmem.h"
#include "WebGPUTypes.h" #include "WebGPUTypes.h"
#include "base/timer.h" #include "base/timer.h"
@@ -56,9 +56,9 @@ class WebGPUParent final : public PWebGPUParent, public SupportsWeakPtr {
ipc::IPCResult RecvAdapterDrop(RawId aAdapterId); ipc::IPCResult RecvAdapterDrop(RawId aAdapterId);
ipc::IPCResult RecvDeviceDestroy(RawId aDeviceId); ipc::IPCResult RecvDeviceDestroy(RawId aDeviceId);
ipc::IPCResult RecvDeviceDrop(RawId aDeviceId); ipc::IPCResult RecvDeviceDrop(RawId aDeviceId);
ipc::IPCResult RecvDeviceCreateBuffer( ipc::IPCResult RecvDeviceCreateBuffer(RawId aDeviceId, RawId aBufferId,
RawId aDeviceId, RawId aBufferId, dom::GPUBufferDescriptor&& aDesc, dom::GPUBufferDescriptor&& aDesc,
ipc::MutableSharedMemoryHandle&& aShmem); ipc::UnsafeSharedMemoryHandle&& aShmem);
ipc::IPCResult RecvBufferMap(RawId aDeviceId, RawId aBufferId, uint32_t aMode, ipc::IPCResult RecvBufferMap(RawId aDeviceId, RawId aBufferId, uint32_t aMode,
uint64_t aOffset, uint64_t size, uint64_t aOffset, uint64_t size,
BufferMapResolver&& aResolver); BufferMapResolver&& aResolver);
@@ -83,7 +83,7 @@ class WebGPUParent final : public PWebGPUParent, public SupportsWeakPtr {
RawId aQueueId, std::function<void(mozilla::void_t)>&& aResolver); RawId aQueueId, std::function<void(mozilla::void_t)>&& aResolver);
ipc::IPCResult RecvQueueWriteAction(RawId aQueueId, RawId aDeviceId, ipc::IPCResult RecvQueueWriteAction(RawId aQueueId, RawId aDeviceId,
const ipc::ByteBuf& aByteBuf, const ipc::ByteBuf& aByteBuf,
ipc::MutableSharedMemoryHandle&& aShmem); ipc::UnsafeSharedMemoryHandle&& aShmem);
ipc::IPCResult RecvBindGroupLayoutDrop(RawId aBindGroupLayoutId); ipc::IPCResult RecvBindGroupLayoutDrop(RawId aBindGroupLayoutId);
ipc::IPCResult RecvPipelineLayoutDrop(RawId aPipelineLayoutId); ipc::IPCResult RecvPipelineLayoutDrop(RawId aPipelineLayoutId);
ipc::IPCResult RecvBindGroupDrop(RawId aBindGroupId); ipc::IPCResult RecvBindGroupDrop(RawId aBindGroupId);
@@ -141,7 +141,7 @@ class WebGPUParent final : public PWebGPUParent, public SupportsWeakPtr {
void ActorDestroy(ActorDestroyReason aWhy) override; void ActorDestroy(ActorDestroyReason aWhy) override;
struct BufferMapData { struct BufferMapData {
ipc::SharedMemoryMapping mShmem; ipc::WritableSharedMemoryMapping mShmem;
// True if buffer's usage has MAP_READ or MAP_WRITE set. // True if buffer's usage has MAP_READ or MAP_WRITE set.
bool mHasMapFlags; bool mHasMapFlags;
uint64_t mMappedOffset; uint64_t mMappedOffset;

View File

@@ -239,7 +239,7 @@ struct MemWriter {
// An istream like class for reading from memory // An istream like class for reading from memory
struct MemReader { struct MemReader {
constexpr MemReader(const char* aData, size_t aLen) constexpr MemReader(char* aData, size_t aLen)
: mData(aData), mEnd(aData + aLen) {} : mData(aData), mEnd(aData + aLen) {}
void read(char* s, std::streamsize n) { void read(char* s, std::streamsize n) {
if (n <= (mEnd - mData)) { if (n <= (mEnd - mData)) {
@@ -255,8 +255,8 @@ struct MemReader {
bool good() { return !eof(); } bool good() { return !eof(); }
void SetIsBad() { mData = mEnd + 1; } void SetIsBad() { mData = mEnd + 1; }
const char* mData; char* mData;
const char* mEnd; char* mEnd;
}; };
class ContiguousBuffer { class ContiguousBuffer {

View File

@@ -10,6 +10,7 @@
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Types.h" #include "mozilla/gfx/Types.h"
#include "mozilla/ipc/SharedMemory.h"
#include "mozilla/layers/TextureClient.h" #include "mozilla/layers/TextureClient.h"
namespace mozilla { namespace mozilla {

View File

@@ -21,27 +21,28 @@ namespace mozilla {
namespace layers { namespace layers {
struct ShmemAndHandle { struct ShmemAndHandle {
ipc::SharedMemoryMapping shmem; RefPtr<ipc::SharedMemory> shmem;
ipc::MutableSharedMemoryHandle handle; Handle handle;
}; };
static Maybe<ShmemAndHandle> CreateAndMapShmem(size_t aSize) { static Maybe<ShmemAndHandle> CreateAndMapShmem(size_t aSize) {
auto handle = ipc::shared_memory::Create(aSize); auto shmem = MakeRefPtr<ipc::SharedMemory>();
if (!handle) { if (!shmem->Create(aSize) || !shmem->Map(aSize)) {
return Nothing();
}
auto mapping = handle.Map();
if (!mapping) {
return Nothing(); return Nothing();
} }
return Some(ShmemAndHandle{std::move(mapping), std::move(handle)}); auto shmemHandle = shmem->TakeHandle();
if (!shmemHandle) {
return Nothing();
}
return Some(ShmemAndHandle{shmem.forget(), std::move(shmemHandle)});
} }
CanvasDrawEventRecorder::CanvasDrawEventRecorder( CanvasDrawEventRecorder::CanvasDrawEventRecorder(
dom::ThreadSafeWorkerRef* aWorkerRef) dom::ThreadSafeWorkerRef* aWorkerRef)
: mWorkerRef(aWorkerRef), mIsOnWorker(!!aWorkerRef) { : mWorkerRef(aWorkerRef), mIsOnWorker(!!aWorkerRef) {
mDefaultBufferSize = ipc::shared_memory::PageAlignedSize( mDefaultBufferSize = ipc::SharedMemory::PageAlignedSize(
StaticPrefs::gfx_canvas_remote_default_buffer_size()); StaticPrefs::gfx_canvas_remote_default_buffer_size());
mMaxDefaultBuffers = StaticPrefs::gfx_canvas_remote_max_default_buffers(); mMaxDefaultBuffers = StaticPrefs::gfx_canvas_remote_max_default_buffers();
mMaxSpinCount = StaticPrefs::gfx_canvas_remote_max_spin_count(); mMaxSpinCount = StaticPrefs::gfx_canvas_remote_max_spin_count();
@@ -65,7 +66,7 @@ bool CanvasDrawEventRecorder::Init(TextureType aTextureType,
return false; return false;
} }
mHeader = header->shmem.DataAs<Header>(); mHeader = static_cast<Header*>(header->shmem->Memory());
mHeader->eventCount = 0; mHeader->eventCount = 0;
mHeader->writerWaitCount = 0; mHeader->writerWaitCount = 0;
mHeader->writerState = State::Processing; mHeader->writerState = State::Processing;
@@ -75,20 +76,20 @@ bool CanvasDrawEventRecorder::Init(TextureType aTextureType,
// We always keep at least two buffers. This means that when we // We always keep at least two buffers. This means that when we
// have to add a new buffer, there is at least a full buffer that requires // have to add a new buffer, there is at least a full buffer that requires
// translating while the handle is sent over. // translating while the handle is sent over.
AutoTArray<ipc::ReadOnlySharedMemoryHandle, 2> bufferHandles; AutoTArray<Handle, 2> bufferHandles;
auto buffer = CreateAndMapShmem(mDefaultBufferSize); auto buffer = CreateAndMapShmem(mDefaultBufferSize);
if (NS_WARN_IF(buffer.isNothing())) { if (NS_WARN_IF(buffer.isNothing())) {
return false; return false;
} }
mCurrentBuffer = CanvasBuffer(std::move(buffer->shmem)); mCurrentBuffer = CanvasBuffer(std::move(buffer->shmem));
bufferHandles.AppendElement(std::move(buffer->handle).ToReadOnly()); bufferHandles.AppendElement(std::move(buffer->handle));
buffer = CreateAndMapShmem(mDefaultBufferSize); buffer = CreateAndMapShmem(mDefaultBufferSize);
if (NS_WARN_IF(buffer.isNothing())) { if (NS_WARN_IF(buffer.isNothing())) {
return false; return false;
} }
mRecycledBuffers.emplace(std::move(buffer->shmem), 0); mRecycledBuffers.emplace(buffer->shmem.forget(), 0);
bufferHandles.AppendElement(std::move(buffer->handle).ToReadOnly()); bufferHandles.AppendElement(std::move(buffer->handle));
mWriterSemaphore.reset(CrossProcessSemaphore::Create("CanvasRecorder", 0)); mWriterSemaphore.reset(CrossProcessSemaphore::Create("CanvasRecorder", 0));
auto writerSem = mWriterSemaphore->CloneHandle(); auto writerSem = mWriterSemaphore->CloneHandle();
@@ -106,13 +107,13 @@ bool CanvasDrawEventRecorder::Init(TextureType aTextureType,
if (!mHelpers->InitTranslator(aTextureType, aWebglTextureType, aBackendType, if (!mHelpers->InitTranslator(aTextureType, aWebglTextureType, aBackendType,
std::move(header->handle), std::move(header->handle),
std::move(bufferHandles), std::move(readerSem), std::move(bufferHandles), mDefaultBufferSize,
std::move(writerSem))) { std::move(readerSem), std::move(writerSem))) {
return false; return false;
} }
mTextureType = aTextureType; mTextureType = aTextureType;
mHeaderShmem = std::move(header->shmem); mHeaderShmem = header->shmem;
return true; return true;
} }
@@ -245,7 +246,7 @@ gfx::ContiguousBuffer& CanvasDrawEventRecorder::GetContiguousBuffer(
} }
size_t bufferSize = std::max(mDefaultBufferSize, size_t bufferSize = std::max(mDefaultBufferSize,
ipc::shared_memory::PageAlignedSize(aSize + 1)); ipc::SharedMemory::PageAlignedSize(aSize + 1));
auto newBuffer = CreateAndMapShmem(bufferSize); auto newBuffer = CreateAndMapShmem(bufferSize);
if (NS_WARN_IF(newBuffer.isNothing())) { if (NS_WARN_IF(newBuffer.isNothing())) {
mHeader->writerState = State::Failed; mHeader->writerState = State::Failed;
@@ -253,7 +254,7 @@ gfx::ContiguousBuffer& CanvasDrawEventRecorder::GetContiguousBuffer(
return mCurrentBuffer; return mCurrentBuffer;
} }
if (!mHelpers->AddBuffer(std::move(newBuffer->handle).ToReadOnly())) { if (!mHelpers->AddBuffer(std::move(newBuffer->handle), bufferSize)) {
mHeader->writerState = State::Failed; mHeader->writerState = State::Failed;
mCurrentBuffer = CanvasBuffer(); mCurrentBuffer = CanvasBuffer();
return mCurrentBuffer; return mCurrentBuffer;

View File

@@ -12,7 +12,7 @@
#include "mozilla/Atomics.h" #include "mozilla/Atomics.h"
#include "mozilla/gfx/DrawEventRecorder.h" #include "mozilla/gfx/DrawEventRecorder.h"
#include "mozilla/ipc/CrossProcessSemaphore.h" #include "mozilla/ipc/CrossProcessSemaphore.h"
#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/ipc/SharedMemory.h"
#include "mozilla/layers/LayersTypes.h" #include "mozilla/layers/LayersTypes.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
@@ -27,6 +27,7 @@ class ThreadSafeWorkerRef;
namespace layers { namespace layers {
typedef mozilla::ipc::SharedMemory::Handle Handle;
typedef mozilla::CrossProcessSemaphoreHandle CrossProcessSemaphoreHandle; typedef mozilla::CrossProcessSemaphoreHandle CrossProcessSemaphoreHandle;
class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate, class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
@@ -71,15 +72,16 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
public: public:
virtual ~Helpers() = default; virtual ~Helpers() = default;
virtual bool InitTranslator( virtual bool InitTranslator(TextureType aTextureType,
TextureType aTextureType, TextureType aWebglTextureType, TextureType aWebglTextureType,
gfx::BackendType aBackendType, gfx::BackendType aBackendType,
ipc::MutableSharedMemoryHandle&& aReadHandle, Handle&& aReadHandle,
nsTArray<ipc::ReadOnlySharedMemoryHandle>&& aBufferHandles, nsTArray<Handle>&& aBufferHandles,
CrossProcessSemaphoreHandle&& aReaderSem, uint64_t aBufferSize,
CrossProcessSemaphoreHandle&& aWriterSem) = 0; CrossProcessSemaphoreHandle&& aReaderSem,
CrossProcessSemaphoreHandle&& aWriterSem) = 0;
virtual bool AddBuffer(ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) = 0; virtual bool AddBuffer(Handle&& aBufferHandle, uint64_t aBufferSize) = 0;
/** /**
* @returns true if the reader of the CanvasEventRingBuffer has permanently * @returns true if the reader of the CanvasEventRingBuffer has permanently
@@ -161,28 +163,29 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
UniquePtr<Helpers> mHelpers; UniquePtr<Helpers> mHelpers;
TextureType mTextureType = TextureType::Unknown; TextureType mTextureType = TextureType::Unknown;
ipc::SharedMemoryMapping mHeaderShmem; RefPtr<ipc::SharedMemory> mHeaderShmem;
Header* mHeader = nullptr; Header* mHeader = nullptr;
struct CanvasBuffer : public gfx::ContiguousBuffer { struct CanvasBuffer : public gfx::ContiguousBuffer {
ipc::SharedMemoryMapping shmem; RefPtr<ipc::SharedMemory> shmem;
CanvasBuffer() : ContiguousBuffer(nullptr) {} CanvasBuffer() : ContiguousBuffer(nullptr) {}
explicit CanvasBuffer(ipc::SharedMemoryMapping&& aShmem) explicit CanvasBuffer(RefPtr<ipc::SharedMemory>&& aShmem)
: ContiguousBuffer(aShmem.DataAs<char>(), aShmem.Size()), : ContiguousBuffer(static_cast<char*>(aShmem->Memory()),
aShmem->Size()),
shmem(std::move(aShmem)) {} shmem(std::move(aShmem)) {}
size_t Capacity() { return shmem ? shmem.Size() : 0; } size_t Capacity() { return shmem ? shmem->Size() : 0; }
}; };
struct RecycledBuffer { struct RecycledBuffer {
ipc::SharedMemoryMapping shmem; RefPtr<ipc::SharedMemory> shmem;
int64_t eventCount = 0; int64_t eventCount = 0;
explicit RecycledBuffer(ipc::SharedMemoryMapping&& aShmem, explicit RecycledBuffer(RefPtr<ipc::SharedMemory>&& aShmem,
int64_t aEventCount) int64_t aEventCount)
: shmem(std::move(aShmem)), eventCount(aEventCount) {} : shmem(std::move(aShmem)), eventCount(aEventCount) {}
size_t Capacity() { return shmem.Size(); } size_t Capacity() { return shmem->Size(); }
}; };
CanvasBuffer mCurrentBuffer; CanvasBuffer mCurrentBuffer;

View File

@@ -26,6 +26,7 @@ using gfx::ReadElement;
using gfx::ReferencePtr; using gfx::ReferencePtr;
using gfx::SurfaceFormat; using gfx::SurfaceFormat;
using gfx::WriteElement; using gfx::WriteElement;
using ipc::SharedMemory;
const EventType CANVAS_BEGIN_TRANSACTION = EventType::LAST; const EventType CANVAS_BEGIN_TRANSACTION = EventType::LAST;
const EventType CANVAS_END_TRANSACTION = EventType(EventType::LAST + 1); const EventType CANVAS_END_TRANSACTION = EventType(EventType::LAST + 1);

View File

@@ -9,7 +9,6 @@
#include "mozilla/Likely.h" #include "mozilla/Likely.h"
#include "mozilla/StaticPrefs_image.h" #include "mozilla/StaticPrefs_image.h"
#include "mozilla/Types.h" // for decltype #include "mozilla/Types.h" // for decltype
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "mozilla/layers/SharedSurfacesChild.h" #include "mozilla/layers/SharedSurfacesChild.h"
#include "mozilla/layers/SharedSurfacesParent.h" #include "mozilla/layers/SharedSurfacesParent.h"
#include "nsDebug.h" // for NS_ABORT_OOM #include "nsDebug.h" // for NS_ABORT_OOM
@@ -31,9 +30,10 @@ using namespace mozilla::layers;
namespace mozilla { namespace mozilla {
namespace gfx { namespace gfx {
void SourceSurfaceSharedDataWrapper::Init( void SourceSurfaceSharedDataWrapper::Init(const IntSize& aSize, int32_t aStride,
const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat, SurfaceFormat aFormat,
ipc::ReadOnlySharedMemoryHandle aHandle, base::ProcessId aCreatorPid) { SharedMemory::Handle aHandle,
base::ProcessId aCreatorPid) {
MOZ_ASSERT(!mBuf); MOZ_ASSERT(!mBuf);
mSize = aSize; mSize = aSize;
mStride = aStride; mStride = aStride;
@@ -41,8 +41,8 @@ void SourceSurfaceSharedDataWrapper::Init(
mCreatorPid = aCreatorPid; mCreatorPid = aCreatorPid;
size_t len = GetAlignedDataLength(); size_t len = GetAlignedDataLength();
mBufHandle = std::move(aHandle); mBuf = MakeAndAddRef<SharedMemory>();
if (!mBufHandle) { if (!mBuf->SetHandle(std::move(aHandle), ipc::SharedMemory::RightsReadOnly)) {
MOZ_CRASH("Invalid shared memory handle!"); MOZ_CRASH("Invalid shared memory handle!");
} }
@@ -63,7 +63,7 @@ void SourceSurfaceSharedDataWrapper::Init(
// We don't support unmapping for this surface, and we failed to map it. // We don't support unmapping for this surface, and we failed to map it.
NS_ABORT_OOM(len); NS_ABORT_OOM(len);
} else { } else {
mBufHandle = nullptr; mBuf->CloseHandle();
} }
} }
@@ -80,20 +80,15 @@ void SourceSurfaceSharedDataWrapper::Init(SourceSurfaceSharedData* aSurface) {
bool SourceSurfaceSharedDataWrapper::EnsureMapped(size_t aLength) { bool SourceSurfaceSharedDataWrapper::EnsureMapped(size_t aLength) {
MOZ_ASSERT(!GetData()); MOZ_ASSERT(!GetData());
auto mapping = mBufHandle.Map(); while (!mBuf->Map(aLength)) {
while (!mapping) {
nsTArray<RefPtr<SourceSurfaceSharedDataWrapper>> expired; nsTArray<RefPtr<SourceSurfaceSharedDataWrapper>> expired;
if (!SharedSurfacesParent::AgeOneGeneration(expired)) { if (!SharedSurfacesParent::AgeOneGeneration(expired)) {
return false; return false;
} }
MOZ_ASSERT(!expired.Contains(this)); MOZ_ASSERT(!expired.Contains(this));
SharedSurfacesParent::ExpireMap(expired); SharedSurfacesParent::ExpireMap(expired);
mapping = mBufHandle.Map();
} }
mBuf = std::make_shared<ipc::MutableOrReadOnlySharedMemoryMapping>(
std::move(mapping));
return true; return true;
} }
@@ -148,8 +143,7 @@ void SourceSurfaceSharedDataWrapper::Unmap() {
void SourceSurfaceSharedDataWrapper::ExpireMap() { void SourceSurfaceSharedDataWrapper::ExpireMap() {
MutexAutoLock lock(*mHandleLock); MutexAutoLock lock(*mHandleLock);
if (mMapCount == 0) { if (mMapCount == 0) {
// This unmaps the stored memory mapping. mBuf->Unmap();
*mBuf = nullptr;
} }
} }
@@ -161,10 +155,9 @@ bool SourceSurfaceSharedData::Init(const IntSize& aSize, int32_t aStride,
mFormat = aFormat; mFormat = aFormat;
size_t len = GetAlignedDataLength(); size_t len = GetAlignedDataLength();
mBufHandle = ipc::shared_memory::Create(len); mBuf = new SharedMemory();
mBuf = std::make_shared<ipc::MutableOrReadOnlySharedMemoryMapping>( if (NS_WARN_IF(!mBuf->Create(len)) || NS_WARN_IF(!mBuf->Map(len))) {
mBufHandle.Map()); mBuf = nullptr;
if (NS_WARN_IF(!mBufHandle) || NS_WARN_IF(!mBuf || !*mBuf)) {
return false; return false;
} }
@@ -194,23 +187,17 @@ void SourceSurfaceSharedData::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
uint8_t* SourceSurfaceSharedData::GetDataInternal() const { uint8_t* SourceSurfaceSharedData::GetDataInternal() const {
mMutex.AssertCurrentThreadOwns(); mMutex.AssertCurrentThreadOwns();
// This class's mappings are always mutable, so we can safely cast away the
// const in the values returned here (see the comment above the `mBuf`
// declaration).
// If we have an old buffer lingering, it is because we get reallocated to // If we have an old buffer lingering, it is because we get reallocated to
// get a new handle to share, but there were still active mappings. // get a new handle to share, but there were still active mappings.
if (MOZ_UNLIKELY(mOldBuf)) { if (MOZ_UNLIKELY(mOldBuf)) {
MOZ_ASSERT(mMapCount > 0); MOZ_ASSERT(mMapCount > 0);
MOZ_ASSERT(mFinalized); MOZ_ASSERT(mFinalized);
return const_cast<uint8_t*>(mOldBuf->DataAs<uint8_t>()); return static_cast<uint8_t*>(mOldBuf->Memory());
} }
// Const cast to match `GetData()`. return static_cast<uint8_t*>(mBuf->Memory());
return const_cast<uint8_t*>(mBuf->DataAs<uint8_t>());
} }
nsresult SourceSurfaceSharedData::CloneHandle( nsresult SourceSurfaceSharedData::CloneHandle(SharedMemory::Handle& aHandle) {
ipc::ReadOnlySharedMemoryHandle& aHandle) {
MutexAutoLock lock(mMutex); MutexAutoLock lock(mMutex);
MOZ_ASSERT(mHandleCount > 0); MOZ_ASSERT(mHandleCount > 0);
@@ -218,7 +205,7 @@ nsresult SourceSurfaceSharedData::CloneHandle(
return NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
} }
aHandle = mBufHandle.Clone().ToReadOnly(); aHandle = mBuf->CloneHandle();
if (MOZ_UNLIKELY(!aHandle)) { if (MOZ_UNLIKELY(!aHandle)) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@@ -236,7 +223,7 @@ void SourceSurfaceSharedData::CloseHandleInternal() {
} }
if (mShared) { if (mShared) {
mBufHandle = nullptr; mBuf->CloseHandle();
mClosed = true; mClosed = true;
} }
} }
@@ -255,25 +242,21 @@ bool SourceSurfaceSharedData::ReallocHandle() {
} }
size_t len = GetAlignedDataLength(); size_t len = GetAlignedDataLength();
auto handle = ipc::shared_memory::Create(len); RefPtr<SharedMemory> buf = new SharedMemory();
auto mapping = handle.Map(); if (NS_WARN_IF(!buf->Create(len)) || NS_WARN_IF(!buf->Map(len))) {
if (NS_WARN_IF(!handle) || NS_WARN_IF(!mapping)) {
return false; return false;
} }
size_t copyLen = GetDataLength(); size_t copyLen = GetDataLength();
memcpy(mapping.Address(), mBuf->Address(), copyLen); memcpy(buf->Memory(), mBuf->Memory(), copyLen);
#ifdef SHARED_SURFACE_PROTECT_FINALIZED #ifdef SHARED_SURFACE_PROTECT_FINALIZED
ipc::shared_memory::LocalProtect(mapping.DataAs<char>(), len, buf->Protect(static_cast<char*>(buf->Memory()), len, RightsRead);
ipc::shared_memory::AccessRead);
#endif #endif
if (mMapCount > 0 && !mOldBuf) { if (mMapCount > 0 && !mOldBuf) {
mOldBuf = std::move(mBuf); mOldBuf = std::move(mBuf);
} }
mBufHandle = std::move(handle); mBuf = std::move(buf);
mBuf = std::make_shared<ipc::MutableOrReadOnlySharedMemoryMapping>(
std::move(mapping));
mClosed = false; mClosed = false;
mShared = false; mShared = false;
return true; return true;
@@ -285,10 +268,7 @@ void SourceSurfaceSharedData::Finalize() {
#ifdef SHARED_SURFACE_PROTECT_FINALIZED #ifdef SHARED_SURFACE_PROTECT_FINALIZED
size_t len = GetAlignedDataLength(); size_t len = GetAlignedDataLength();
// This class's mappings are always mutable, so we can safely cast away the mBuf->Protect(static_cast<char*>(mBuf->Memory()), len, RightsRead);
// const (see the comment above the `mBuf` declaration).
ipc::shared_memory::LocalProtect(const_cast<char*>(mBuf->DataAs<char>()), len,
ipc::shared_memory::AccessRead);
#endif #endif
mFinalized = true; mFinalized = true;

View File

@@ -10,8 +10,7 @@
#include "base/process.h" #include "base/process.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "mozilla/Mutex.h" #include "mozilla/Mutex.h"
#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/ipc/SharedMemory.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "nsExpirationTracker.h" #include "nsExpirationTracker.h"
namespace mozilla { namespace mozilla {
@@ -35,6 +34,8 @@ class SourceSurfaceSharedData;
* mapped in the given shared memory handle as read only memory. * mapped in the given shared memory handle as read only memory.
*/ */
class SourceSurfaceSharedDataWrapper final : public DataSourceSurface { class SourceSurfaceSharedDataWrapper final : public DataSourceSurface {
typedef mozilla::ipc::SharedMemory SharedMemory;
public: public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceSharedDataWrapper, MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceSharedDataWrapper,
override) override)
@@ -42,8 +43,7 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface {
SourceSurfaceSharedDataWrapper() = default; SourceSurfaceSharedDataWrapper() = default;
void Init(const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat, void Init(const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat,
mozilla::ipc::ReadOnlySharedMemoryHandle aHandle, SharedMemory::Handle aHandle, base::ProcessId aCreatorPid);
base::ProcessId aCreatorPid);
void Init(SourceSurfaceSharedData* aSurface); void Init(SourceSurfaceSharedData* aSurface);
@@ -57,11 +57,7 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface {
IntSize GetSize() const override { return mSize; } IntSize GetSize() const override { return mSize; }
SurfaceFormat GetFormat() const override { return mFormat; } SurfaceFormat GetFormat() const override { return mFormat; }
uint8_t* GetData() override { uint8_t* GetData() override { return static_cast<uint8_t*>(mBuf->Memory()); }
// Cast away const-ness of shared memory to match the
// `DataSourceSurface::GetData` interface. The data will not be written to.
return mBuf ? const_cast<uint8_t*>(mBuf->DataAs<uint8_t>()) : nullptr;
}
bool OnHeap() const override { return false; } bool OnHeap() const override { return false; }
@@ -101,7 +97,7 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface {
} }
size_t GetAlignedDataLength() const { size_t GetAlignedDataLength() const {
return mozilla::ipc::shared_memory::PageAlignedSize(GetDataLength()); return mozilla::ipc::SharedMemory::PageAlignedSize(GetDataLength());
} }
bool EnsureMapped(size_t aLength); bool EnsureMapped(size_t aLength);
@@ -112,9 +108,7 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface {
int32_t mStride = 0; int32_t mStride = 0;
uint32_t mConsumers = 1; uint32_t mConsumers = 1;
IntSize mSize; IntSize mSize;
// This is only used to support EnsureMapped if we fail initially. RefPtr<SharedMemory> mBuf;
mozilla::ipc::ReadOnlySharedMemoryHandle mBufHandle;
std::shared_ptr<mozilla::ipc::MutableOrReadOnlySharedMemoryMapping> mBuf;
SurfaceFormat mFormat = SurfaceFormat::UNKNOWN; SurfaceFormat mFormat = SurfaceFormat::UNKNOWN;
base::ProcessId mCreatorPid = 0; base::ProcessId mCreatorPid = 0;
bool mCreatorRef = true; bool mCreatorRef = true;
@@ -125,6 +119,8 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface {
* source surface. * source surface.
*/ */
class SourceSurfaceSharedData : public DataSourceSurface { class SourceSurfaceSharedData : public DataSourceSurface {
typedef mozilla::ipc::SharedMemory SharedMemory;
public: public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceSharedData, override) MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceSharedData, override)
@@ -201,7 +197,7 @@ class SourceSurfaceSharedData : public DataSourceSurface {
* NS_ERROR_NOT_AVAILABLE -- handle was closed, need to reallocate. * NS_ERROR_NOT_AVAILABLE -- handle was closed, need to reallocate.
* NS_ERROR_FAILURE -- failed to create a handle to share. * NS_ERROR_FAILURE -- failed to create a handle to share.
*/ */
nsresult CloneHandle(mozilla::ipc::ReadOnlySharedMemoryHandle& aHandle); nsresult CloneHandle(SharedMemory::Handle& aHandle);
/** /**
* Indicates the buffer is not expected to be shared with any more processes. * Indicates the buffer is not expected to be shared with any more processes.
@@ -318,7 +314,7 @@ class SourceSurfaceSharedData : public DataSourceSurface {
} }
size_t GetAlignedDataLength() const { size_t GetAlignedDataLength() const {
return mozilla::ipc::shared_memory::PageAlignedSize(GetDataLength()); return mozilla::ipc::SharedMemory::PageAlignedSize(GetDataLength());
} }
/** /**
@@ -332,11 +328,8 @@ class SourceSurfaceSharedData : public DataSourceSurface {
int32_t mHandleCount; int32_t mHandleCount;
Maybe<IntRect> mDirtyRect; Maybe<IntRect> mDirtyRect;
IntSize mSize; IntSize mSize;
mozilla::ipc::MutableSharedMemoryHandle mBufHandle; RefPtr<SharedMemory> mBuf;
// This class always has mutable mappings, however we need to share them with RefPtr<SharedMemory> mOldBuf;
// the wrapper which may be read-only, so we use MutableOrReadOnly.
std::shared_ptr<mozilla::ipc::MutableOrReadOnlySharedMemoryMapping> mBuf;
std::shared_ptr<mozilla::ipc::MutableOrReadOnlySharedMemoryMapping> mOldBuf;
SurfaceFormat mFormat; SurfaceFormat mFormat;
bool mClosed : 1; bool mClosed : 1;
bool mFinalized : 1; bool mFinalized : 1;

View File

@@ -86,8 +86,9 @@
#include "nsThreadUtils.h" // for NS_IsMainThread #include "nsThreadUtils.h" // for NS_IsMainThread
#include "nsViewportInfo.h" // for ViewportMinScale(), ViewportMaxScale() #include "nsViewportInfo.h" // for ViewportMinScale(), ViewportMaxScale()
#include "prsystem.h" // for PR_GetPhysicalMemorySize #include "prsystem.h" // for PR_GetPhysicalMemorySize
#include "ScrollSnap.h" // for ScrollSnapUtils #include "mozilla/ipc/SharedMemory.h" // for SharedMemory
#include "ScrollAnimationPhysics.h" // for ComputeAcceleratedWheelDelta #include "ScrollSnap.h" // for ScrollSnapUtils
#include "ScrollAnimationPhysics.h" // for ComputeAcceleratedWheelDelta
#include "SmoothMsdScrollAnimation.h" #include "SmoothMsdScrollAnimation.h"
#include "SmoothScrollAnimation.h" #include "SmoothScrollAnimation.h"
#include "WheelScrollAnimation.h" #include "WheelScrollAnimation.h"

View File

@@ -26,6 +26,7 @@
#include "mozilla/gfx/Logging.h" // for gfxDebug #include "mozilla/gfx/Logging.h" // for gfxDebug
#include "mozilla/gfx/gfxVars.h" #include "mozilla/gfx/gfxVars.h"
#include "mozilla/ipc/CrossProcessSemaphore.h" #include "mozilla/ipc/CrossProcessSemaphore.h"
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
#include "mozilla/layers/CanvasRenderer.h" #include "mozilla/layers/CanvasRenderer.h"
#include "mozilla/layers/CompositableForwarder.h" #include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/ISurfaceAllocator.h" #include "mozilla/layers/ISurfaceAllocator.h"

View File

@@ -18,7 +18,6 @@
#include "mozilla/gfx/Point.h" #include "mozilla/gfx/Point.h"
#include "mozilla/ipc/Endpoint.h" #include "mozilla/ipc/Endpoint.h"
#include "mozilla/ipc/ProcessChild.h" #include "mozilla/ipc/ProcessChild.h"
#include "mozilla/ipc/SharedMemoryHandle.h"
#include "mozilla/layers/CanvasDrawEventRecorder.h" #include "mozilla/layers/CanvasDrawEventRecorder.h"
#include "mozilla/layers/ImageDataSerializer.h" #include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/SourceSurfaceSharedData.h" #include "mozilla/layers/SourceSurfaceSharedData.h"
@@ -40,29 +39,27 @@ class RecorderHelpers final : public CanvasDrawEventRecorder::Helpers {
~RecorderHelpers() override = default; ~RecorderHelpers() override = default;
bool InitTranslator( bool InitTranslator(TextureType aTextureType, TextureType aWebglTextureType,
TextureType aTextureType, TextureType aWebglTextureType, gfx::BackendType aBackendType, Handle&& aReadHandle,
gfx::BackendType aBackendType, nsTArray<Handle>&& aBufferHandles, uint64_t aBufferSize,
ipc::MutableSharedMemoryHandle&& aReadHandle, CrossProcessSemaphoreHandle&& aReaderSem,
nsTArray<ipc::ReadOnlySharedMemoryHandle>&& aBufferHandles, CrossProcessSemaphoreHandle&& aWriterSem) override {
CrossProcessSemaphoreHandle&& aReaderSem,
CrossProcessSemaphoreHandle&& aWriterSem) override {
NS_ASSERT_OWNINGTHREAD(RecorderHelpers); NS_ASSERT_OWNINGTHREAD(RecorderHelpers);
if (NS_WARN_IF(!mCanvasChild)) { if (NS_WARN_IF(!mCanvasChild)) {
return false; return false;
} }
return mCanvasChild->SendInitTranslator( return mCanvasChild->SendInitTranslator(
aTextureType, aWebglTextureType, aBackendType, std::move(aReadHandle), aTextureType, aWebglTextureType, aBackendType, std::move(aReadHandle),
std::move(aBufferHandles), std::move(aReaderSem), std::move(aBufferHandles), aBufferSize, std::move(aReaderSem),
std::move(aWriterSem)); std::move(aWriterSem));
} }
bool AddBuffer(ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) override { bool AddBuffer(Handle&& aBufferHandle, uint64_t aBufferSize) override {
NS_ASSERT_OWNINGTHREAD(RecorderHelpers); NS_ASSERT_OWNINGTHREAD(RecorderHelpers);
if (!mCanvasChild) { if (!mCanvasChild) {
return false; return false;
} }
return mCanvasChild->SendAddBuffer(std::move(aBufferHandle)); return mCanvasChild->SendAddBuffer(std::move(aBufferHandle), aBufferSize);
} }
bool ReaderClosed() override { bool ReaderClosed() override {
@@ -195,9 +192,7 @@ class SourceSurfaceCanvasRecording final : public gfx::SourceSurface {
class CanvasDataShmemHolder { class CanvasDataShmemHolder {
public: public:
CanvasDataShmemHolder( CanvasDataShmemHolder(ipc::SharedMemory* aShmem, CanvasChild* aCanvasChild)
const std::shared_ptr<ipc::ReadOnlySharedMemoryMapping>& aShmem,
CanvasChild* aCanvasChild)
: mMutex("CanvasChild::DataShmemHolder::mMutex"), : mMutex("CanvasChild::DataShmemHolder::mMutex"),
mShmem(aShmem), mShmem(aShmem),
mCanvasChild(aCanvasChild) {} mCanvasChild(aCanvasChild) {}
@@ -264,7 +259,7 @@ class CanvasDataShmemHolder {
return; return;
} }
mCanvasChild->ReturnDataSurfaceShmem(std::move(mShmem)); mCanvasChild->ReturnDataSurfaceShmem(mShmem.forget());
mCanvasChild = nullptr; mCanvasChild = nullptr;
mWorkerRef = nullptr; mWorkerRef = nullptr;
} }
@@ -281,7 +276,7 @@ class CanvasDataShmemHolder {
private: private:
Mutex mMutex; Mutex mMutex;
std::shared_ptr<ipc::ReadOnlySharedMemoryMapping> mShmem; RefPtr<ipc::SharedMemory> mShmem;
RefPtr<CanvasChild> mCanvasChild MOZ_GUARDED_BY(mMutex); RefPtr<CanvasChild> mCanvasChild MOZ_GUARDED_BY(mMutex);
RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef MOZ_GUARDED_BY(mMutex); RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef MOZ_GUARDED_BY(mMutex);
}; };
@@ -494,26 +489,26 @@ bool CanvasChild::EnsureDataSurfaceShmem(gfx::IntSize aSize,
if (!sizeRequired) { if (!sizeRequired) {
return false; return false;
} }
sizeRequired = ipc::shared_memory::PageAlignedSize(sizeRequired); sizeRequired = ipc::SharedMemory::PageAlignedSize(sizeRequired);
if (!mDataSurfaceShmemAvailable || mDataSurfaceShmem->Size() < sizeRequired) { if (!mDataSurfaceShmemAvailable || mDataSurfaceShmem->Size() < sizeRequired) {
RecordEvent(RecordedPauseTranslation()); RecordEvent(RecordedPauseTranslation());
auto shmemHandle = ipc::shared_memory::Create(sizeRequired); auto dataSurfaceShmem = MakeRefPtr<ipc::SharedMemory>();
if (!dataSurfaceShmem->Create(sizeRequired) ||
!dataSurfaceShmem->Map(sizeRequired)) {
return false;
}
auto shmemHandle = dataSurfaceShmem->TakeHandle();
if (!shmemHandle) { if (!shmemHandle) {
return false; return false;
} }
auto roMapping = shmemHandle.AsReadOnly().Map(); if (!SendSetDataSurfaceBuffer(std::move(shmemHandle), sizeRequired)) {
if (!roMapping) {
return false; return false;
} }
if (!SendSetDataSurfaceBuffer(std::move(shmemHandle))) { mDataSurfaceShmem = dataSurfaceShmem.forget();
return false;
}
mDataSurfaceShmem = std::make_shared<ipc::ReadOnlySharedMemoryMapping>(
std::move(roMapping));
mDataSurfaceShmemAvailable = true; mDataSurfaceShmemAvailable = true;
} }
@@ -565,7 +560,8 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
// use that directly without having to allocate a new shmem for retrieval. // use that directly without having to allocate a new shmem for retrieval.
auto it = mTextureInfo.find(aTextureOwnerId); auto it = mTextureInfo.find(aTextureOwnerId);
if (it != mTextureInfo.end() && it->second.mSnapshotShmem) { if (it != mTextureInfo.end() && it->second.mSnapshotShmem) {
const auto* shmemPtr = it->second.mSnapshotShmem->DataAs<uint8_t>(); const auto shmemPtr =
reinterpret_cast<uint8_t*>(it->second.mSnapshotShmem->Memory());
MOZ_ASSERT(shmemPtr); MOZ_ASSERT(shmemPtr);
mRecorder->RecordEvent(RecordedPrepareShmem(aTextureOwnerId)); mRecorder->RecordEvent(RecordedPrepareShmem(aTextureOwnerId));
auto checkpoint = CreateCheckpoint(); auto checkpoint = CreateCheckpoint();
@@ -578,12 +574,10 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
delete closure; delete closure;
return nullptr; return nullptr;
} }
// We can cast away the const of `shmemPtr` to match the call because the
// DataSourceSurface will not be written to.
RefPtr<gfx::DataSourceSurface> dataSurface = RefPtr<gfx::DataSourceSurface> dataSurface =
gfx::Factory::CreateWrappingDataSourceSurface( gfx::Factory::CreateWrappingDataSourceSurface(
const_cast<uint8_t*>(shmemPtr), stride, ssSize, ssFormat, shmemPtr, stride, ssSize, ssFormat, ReleaseDataShmemHolder,
ReleaseDataShmemHolder, closure); closure);
aMayInvalidate = true; aMayInvalidate = true;
return dataSurface.forget(); return dataSurface.forget();
} }
@@ -609,14 +603,11 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
mDataSurfaceShmemAvailable = false; mDataSurfaceShmemAvailable = false;
const auto* data = mDataSurfaceShmem->DataAs<uint8_t>(); auto* data = static_cast<uint8_t*>(mDataSurfaceShmem->Memory());
// We can cast away the const of `data` to match the call because the
// DataSourceSurface will not be written to.
RefPtr<gfx::DataSourceSurface> dataSurface = RefPtr<gfx::DataSourceSurface> dataSurface =
gfx::Factory::CreateWrappingDataSourceSurface( gfx::Factory::CreateWrappingDataSourceSurface(
const_cast<uint8_t*>(data), stride, ssSize, ssFormat, data, stride, ssSize, ssFormat, ReleaseDataShmemHolder, closure);
ReleaseDataShmemHolder, closure);
aMayInvalidate = false; aMayInvalidate = false;
return dataSurface.forget(); return dataSurface.forget();
} }
@@ -640,9 +631,10 @@ already_AddRefed<gfx::SourceSurface> CanvasChild::WrapSurface(
} }
void CanvasChild::ReturnDataSurfaceShmem( void CanvasChild::ReturnDataSurfaceShmem(
std::shared_ptr<ipc::ReadOnlySharedMemoryMapping>&& aDataSurfaceShmem) { already_AddRefed<ipc::SharedMemory> aDataSurfaceShmem) {
RefPtr<ipc::SharedMemory> data = aDataSurfaceShmem;
// We can only reuse the latest data surface shmem. // We can only reuse the latest data surface shmem.
if (aDataSurfaceShmem == mDataSurfaceShmem) { if (data == mDataSurfaceShmem) {
MOZ_ASSERT(!mDataSurfaceShmemAvailable); MOZ_ASSERT(!mDataSurfaceShmemAvailable);
mDataSurfaceShmemAvailable = true; mDataSurfaceShmemAvailable = true;
} }
@@ -688,17 +680,17 @@ bool CanvasChild::RequiresRefresh(
} }
ipc::IPCResult CanvasChild::RecvSnapshotShmem( ipc::IPCResult CanvasChild::RecvSnapshotShmem(
const RemoteTextureOwnerId aTextureOwnerId, const RemoteTextureOwnerId aTextureOwnerId, Handle&& aShmemHandle,
ipc::ReadOnlySharedMemoryHandle&& aShmemHandle, uint32_t aShmemSize, SnapshotShmemResolver&& aResolve) {
SnapshotShmemResolver&& aResolve) {
auto it = mTextureInfo.find(aTextureOwnerId); auto it = mTextureInfo.find(aTextureOwnerId);
if (it != mTextureInfo.end()) { if (it != mTextureInfo.end()) {
auto shmem = aShmemHandle.Map(); auto shmem = MakeRefPtr<ipc::SharedMemory>();
if (NS_WARN_IF(!shmem)) { if (NS_WARN_IF(!shmem->SetHandle(std::move(aShmemHandle),
ipc::SharedMemory::RightsReadOnly)) ||
NS_WARN_IF(!shmem->Map(aShmemSize))) {
shmem = nullptr; shmem = nullptr;
} else { } else {
it->second.mSnapshotShmem = it->second.mSnapshotShmem = std::move(shmem);
std::make_shared<ipc::ReadOnlySharedMemoryMapping>(std::move(shmem));
} }
aResolve(true); aResolve(true);
} else { } else {

View File

@@ -9,7 +9,6 @@
#include "mozilla/gfx/RecordedEvent.h" #include "mozilla/gfx/RecordedEvent.h"
#include "mozilla/ipc/CrossProcessSemaphore.h" #include "mozilla/ipc/CrossProcessSemaphore.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "mozilla/layers/PCanvasChild.h" #include "mozilla/layers/PCanvasChild.h"
#include "mozilla/layers/SourceSurfaceSharedData.h" #include "mozilla/layers/SourceSurfaceSharedData.h"
#include "mozilla/WeakPtr.h" #include "mozilla/WeakPtr.h"
@@ -57,10 +56,9 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
ipc::IPCResult RecvNotifyRequiresRefresh( ipc::IPCResult RecvNotifyRequiresRefresh(
const RemoteTextureOwnerId aTextureOwnerId); const RemoteTextureOwnerId aTextureOwnerId);
ipc::IPCResult RecvSnapshotShmem( ipc::IPCResult RecvSnapshotShmem(const RemoteTextureOwnerId aTextureOwnerId,
const RemoteTextureOwnerId aTextureOwnerId, Handle&& aShmemHandle, uint32_t aShmemSize,
ipc::ReadOnlySharedMemoryHandle&& aShmemHandle, SnapshotShmemResolver&& aResolve);
SnapshotShmemResolver&& aResolve);
ipc::IPCResult RecvNotifyTextureDestruction( ipc::IPCResult RecvNotifyTextureDestruction(
const RemoteTextureOwnerId aTextureOwnerId); const RemoteTextureOwnerId aTextureOwnerId);
@@ -164,7 +162,7 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
bool RequiresRefresh(const RemoteTextureOwnerId aTextureOwnerId) const; bool RequiresRefresh(const RemoteTextureOwnerId aTextureOwnerId) const;
void ReturnDataSurfaceShmem( void ReturnDataSurfaceShmem(
std::shared_ptr<ipc::ReadOnlySharedMemoryMapping>&& aDataSurfaceShmem); already_AddRefed<ipc::SharedMemory> aDataSurfaceShmem);
protected: protected:
void ActorDestroy(ActorDestroyReason aWhy) final; void ActorDestroy(ActorDestroyReason aWhy) final;
@@ -187,12 +185,12 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef; RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef;
RefPtr<CanvasDrawEventRecorder> mRecorder; RefPtr<CanvasDrawEventRecorder> mRecorder;
std::shared_ptr<ipc::ReadOnlySharedMemoryMapping> mDataSurfaceShmem; RefPtr<ipc::SharedMemory> mDataSurfaceShmem;
bool mDataSurfaceShmemAvailable = false; bool mDataSurfaceShmemAvailable = false;
int64_t mLastWriteLockCheckpoint = 0; int64_t mLastWriteLockCheckpoint = 0;
uint32_t mTransactionsSinceGetDataSurface = kCacheDataSurfaceThreshold; uint32_t mTransactionsSinceGetDataSurface = kCacheDataSurfaceThreshold;
struct TextureInfo { struct TextureInfo {
std::shared_ptr<mozilla::ipc::ReadOnlySharedMemoryMapping> mSnapshotShmem; RefPtr<mozilla::ipc::SharedMemory> mSnapshotShmem;
bool mRequiresRefresh = false; bool mRequiresRefresh = false;
}; };
std::unordered_map<RemoteTextureOwnerId, TextureInfo, std::unordered_map<RemoteTextureOwnerId, TextureInfo,

View File

@@ -18,7 +18,6 @@
#include "mozilla/gfx/GPUProcessManager.h" #include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/gfx/Logging.h" #include "mozilla/gfx/Logging.h"
#include "mozilla/ipc/Endpoint.h" #include "mozilla/ipc/Endpoint.h"
#include "mozilla/ipc/SharedMemoryHandle.h"
#include "mozilla/layers/BufferTexture.h" #include "mozilla/layers/BufferTexture.h"
#include "mozilla/layers/CanvasTranslator.h" #include "mozilla/layers/CanvasTranslator.h"
#include "mozilla/layers/ImageDataSerializer.h" #include "mozilla/layers/ImageDataSerializer.h"
@@ -103,6 +102,21 @@ bool CanvasTranslator::IsInTaskQueue() const {
return gfx::CanvasRenderThread::IsInCanvasRenderThread(); return gfx::CanvasRenderThread::IsInCanvasRenderThread();
} }
static bool CreateAndMapShmem(RefPtr<ipc::SharedMemory>& aShmem,
Handle&& aHandle,
ipc::SharedMemory::OpenRights aOpenRights,
size_t aSize) {
auto shmem = MakeRefPtr<ipc::SharedMemory>();
if (!shmem->SetHandle(std::move(aHandle), aOpenRights) ||
!shmem->Map(aSize)) {
return false;
}
shmem->CloseHandle();
aShmem = shmem.forget();
return true;
}
StaticRefPtr<gfx::SharedContextWebgl> CanvasTranslator::sSharedContext; StaticRefPtr<gfx::SharedContextWebgl> CanvasTranslator::sSharedContext;
bool CanvasTranslator::EnsureSharedContextWebgl() { bool CanvasTranslator::EnsureSharedContextWebgl() {
@@ -140,8 +154,8 @@ void CanvasTranslator::Shutdown() {
mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator( mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
TextureType aTextureType, TextureType aWebglTextureType, TextureType aTextureType, TextureType aWebglTextureType,
gfx::BackendType aBackendType, ipc::MutableSharedMemoryHandle&& aReadHandle, gfx::BackendType aBackendType, Handle&& aReadHandle,
nsTArray<ipc::ReadOnlySharedMemoryHandle>&& aBufferHandles, nsTArray<Handle>&& aBufferHandles, uint64_t aBufferSize,
CrossProcessSemaphoreHandle&& aReaderSem, CrossProcessSemaphoreHandle&& aReaderSem,
CrossProcessSemaphoreHandle&& aWriterSem) { CrossProcessSemaphoreHandle&& aWriterSem) {
if (mHeaderShmem) { if (mHeaderShmem) {
@@ -153,13 +167,14 @@ mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
mBackendType = aBackendType; mBackendType = aBackendType;
mOtherPid = OtherPid(); mOtherPid = OtherPid();
mHeaderShmem = aReadHandle.Map(); mHeaderShmem = MakeAndAddRef<ipc::SharedMemory>();
if (!mHeaderShmem) { if (!CreateAndMapShmem(mHeaderShmem, std::move(aReadHandle),
ipc::SharedMemory::RightsReadWrite, sizeof(Header))) {
Deactivate(); Deactivate();
return IPC_FAIL(this, "Failed to map canvas header shared memory."); return IPC_FAIL(this, "Failed to map canvas header shared memory.");
} }
mHeader = mHeaderShmem.DataAs<Header>(); mHeader = static_cast<Header*>(mHeaderShmem->Memory());
mWriterSemaphore.reset(CrossProcessSemaphore::Create(std::move(aWriterSem))); mWriterSemaphore.reset(CrossProcessSemaphore::Create(std::move(aWriterSem)));
mWriterSemaphore->CloseHandle(); mWriterSemaphore->CloseHandle();
@@ -178,10 +193,10 @@ mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
} }
// Use the first buffer as our current buffer. // Use the first buffer as our current buffer.
mDefaultBufferSize = aBufferHandles[0].Size(); mDefaultBufferSize = aBufferSize;
auto handleIter = aBufferHandles.begin(); auto handleIter = aBufferHandles.begin();
mCurrentShmem.shmem = std::move(*handleIter).Map(); if (!CreateAndMapShmem(mCurrentShmem.shmem, std::move(*handleIter),
if (!mCurrentShmem.shmem) { ipc::SharedMemory::RightsReadOnly, aBufferSize)) {
Deactivate(); Deactivate();
return IPC_FAIL(this, "Failed to map canvas buffer shared memory."); return IPC_FAIL(this, "Failed to map canvas buffer shared memory.");
} }
@@ -190,8 +205,8 @@ mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
// Add all other buffers to our recycled CanvasShmems. // Add all other buffers to our recycled CanvasShmems.
for (handleIter++; handleIter < aBufferHandles.end(); handleIter++) { for (handleIter++; handleIter < aBufferHandles.end(); handleIter++) {
CanvasShmem newShmem; CanvasShmem newShmem;
newShmem.shmem = std::move(*handleIter).Map(); if (!CreateAndMapShmem(newShmem.shmem, std::move(*handleIter),
if (!newShmem.shmem) { ipc::SharedMemory::RightsReadOnly, aBufferSize)) {
Deactivate(); Deactivate();
return IPC_FAIL(this, "Failed to map canvas buffer shared memory."); return IPC_FAIL(this, "Failed to map canvas buffer shared memory.");
} }
@@ -232,7 +247,7 @@ ipc::IPCResult CanvasTranslator::RecvRestartTranslation() {
} }
ipc::IPCResult CanvasTranslator::RecvAddBuffer( ipc::IPCResult CanvasTranslator::RecvAddBuffer(
ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) { ipc::SharedMemory::Handle&& aBufferHandle, uint64_t aBufferSize) {
if (mDeactivated) { if (mDeactivated) {
// The other side might have sent a resume message before we deactivated. // The other side might have sent a resume message before we deactivated.
return IPC_OK(); return IPC_OK();
@@ -240,20 +255,20 @@ ipc::IPCResult CanvasTranslator::RecvAddBuffer(
if (UsePendingCanvasTranslatorEvents()) { if (UsePendingCanvasTranslatorEvents()) {
MutexAutoLock lock(mCanvasTranslatorEventsLock); MutexAutoLock lock(mCanvasTranslatorEventsLock);
mPendingCanvasTranslatorEvents.push_back( mPendingCanvasTranslatorEvents.push_back(CanvasTranslatorEvent::AddBuffer(
CanvasTranslatorEvent::AddBuffer(std::move(aBufferHandle))); std::move(aBufferHandle), aBufferSize));
PostCanvasTranslatorEvents(lock); PostCanvasTranslatorEvents(lock);
} else { } else {
DispatchToTaskQueue(NewRunnableMethod<ipc::ReadOnlySharedMemoryHandle&&>( DispatchToTaskQueue(NewRunnableMethod<ipc::SharedMemory::Handle&&, size_t>(
"CanvasTranslator::AddBuffer", this, &CanvasTranslator::AddBuffer, "CanvasTranslator::AddBuffer", this, &CanvasTranslator::AddBuffer,
std::move(aBufferHandle))); std::move(aBufferHandle), aBufferSize));
} }
return IPC_OK(); return IPC_OK();
} }
bool CanvasTranslator::AddBuffer( bool CanvasTranslator::AddBuffer(ipc::SharedMemory::Handle&& aBufferHandle,
ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) { size_t aBufferSize) {
MOZ_ASSERT(IsInTaskQueue()); MOZ_ASSERT(IsInTaskQueue());
if (mHeader->readerState == State::Failed) { if (mHeader->readerState == State::Failed) {
// We failed before we got to the pause event. // We failed before we got to the pause event.
@@ -282,8 +297,8 @@ bool CanvasTranslator::AddBuffer(
} }
CanvasShmem newShmem; CanvasShmem newShmem;
newShmem.shmem = aBufferHandle.Map(); if (!CreateAndMapShmem(newShmem.shmem, std::move(aBufferHandle),
if (!newShmem.shmem) { ipc::SharedMemory::RightsReadOnly, aBufferSize)) {
return false; return false;
} }
@@ -294,7 +309,7 @@ bool CanvasTranslator::AddBuffer(
} }
ipc::IPCResult CanvasTranslator::RecvSetDataSurfaceBuffer( ipc::IPCResult CanvasTranslator::RecvSetDataSurfaceBuffer(
ipc::MutableSharedMemoryHandle&& aBufferHandle) { ipc::SharedMemory::Handle&& aBufferHandle, uint64_t aBufferSize) {
if (mDeactivated) { if (mDeactivated) {
// The other side might have sent a resume message before we deactivated. // The other side might have sent a resume message before we deactivated.
return IPC_OK(); return IPC_OK();
@@ -303,19 +318,21 @@ ipc::IPCResult CanvasTranslator::RecvSetDataSurfaceBuffer(
if (UsePendingCanvasTranslatorEvents()) { if (UsePendingCanvasTranslatorEvents()) {
MutexAutoLock lock(mCanvasTranslatorEventsLock); MutexAutoLock lock(mCanvasTranslatorEventsLock);
mPendingCanvasTranslatorEvents.push_back( mPendingCanvasTranslatorEvents.push_back(
CanvasTranslatorEvent::SetDataSurfaceBuffer(std::move(aBufferHandle))); CanvasTranslatorEvent::SetDataSurfaceBuffer(std::move(aBufferHandle),
aBufferSize));
PostCanvasTranslatorEvents(lock); PostCanvasTranslatorEvents(lock);
} else { } else {
DispatchToTaskQueue(NewRunnableMethod<ipc::MutableSharedMemoryHandle&&>( DispatchToTaskQueue(NewRunnableMethod<ipc::SharedMemory::Handle&&, size_t>(
"CanvasTranslator::SetDataSurfaceBuffer", this, "CanvasTranslator::SetDataSurfaceBuffer", this,
&CanvasTranslator::SetDataSurfaceBuffer, std::move(aBufferHandle))); &CanvasTranslator::SetDataSurfaceBuffer, std::move(aBufferHandle),
aBufferSize));
} }
return IPC_OK(); return IPC_OK();
} }
bool CanvasTranslator::SetDataSurfaceBuffer( bool CanvasTranslator::SetDataSurfaceBuffer(
ipc::MutableSharedMemoryHandle&& aBufferHandle) { ipc::SharedMemory::Handle&& aBufferHandle, size_t aBufferSize) {
MOZ_ASSERT(IsInTaskQueue()); MOZ_ASSERT(IsInTaskQueue());
if (mHeader->readerState == State::Failed) { if (mHeader->readerState == State::Failed) {
// We failed before we got to the pause event. // We failed before we got to the pause event.
@@ -332,8 +349,8 @@ bool CanvasTranslator::SetDataSurfaceBuffer(
return false; return false;
} }
mDataSurfaceShmem = aBufferHandle.Map(); if (!CreateAndMapShmem(mDataSurfaceShmem, std::move(aBufferHandle),
if (!mDataSurfaceShmem) { ipc::SharedMemory::RightsReadWrite, aBufferSize)) {
return false; return false;
} }
@@ -368,11 +385,11 @@ void CanvasTranslator::GetDataSurface(uint64_t aSurfaceRef) {
ImageDataSerializer::ComputeRGBStride(format, dstSize.width); ImageDataSerializer::ComputeRGBStride(format, dstSize.width);
auto requiredSize = auto requiredSize =
ImageDataSerializer::ComputeRGBBufferSize(dstSize, format); ImageDataSerializer::ComputeRGBBufferSize(dstSize, format);
if (requiredSize <= 0 || size_t(requiredSize) > mDataSurfaceShmem.Size()) { if (requiredSize <= 0 || size_t(requiredSize) > mDataSurfaceShmem->Size()) {
return; return;
} }
uint8_t* dst = mDataSurfaceShmem.DataAs<uint8_t>(); uint8_t* dst = static_cast<uint8_t*>(mDataSurfaceShmem->Memory());
const uint8_t* src = map->GetData(); const uint8_t* src = map->GetData();
const uint8_t* endSrc = src + (srcSize.height * srcStride); const uint8_t* endSrc = src + (srcSize.height * srcStride);
while (src < endSrc) { while (src < endSrc) {
@@ -778,11 +795,12 @@ void CanvasTranslator::HandleCanvasTranslatorEvents() {
dispatchTranslate = TranslateRecording(); dispatchTranslate = TranslateRecording();
break; break;
case CanvasTranslatorEvent::Tag::AddBuffer: case CanvasTranslatorEvent::Tag::AddBuffer:
dispatchTranslate = AddBuffer(event->TakeBufferHandle()); dispatchTranslate =
AddBuffer(event->TakeBufferHandle(), event->BufferSize());
break; break;
case CanvasTranslatorEvent::Tag::SetDataSurfaceBuffer: case CanvasTranslatorEvent::Tag::SetDataSurfaceBuffer:
dispatchTranslate = dispatchTranslate = SetDataSurfaceBuffer(event->TakeBufferHandle(),
SetDataSurfaceBuffer(event->TakeDataSurfaceBufferHandle()); event->BufferSize());
break; break;
case CanvasTranslatorEvent::Tag::ClearCachedResources: case CanvasTranslatorEvent::Tag::ClearCachedResources:
ClearCachedResources(); ClearCachedResources();
@@ -1053,7 +1071,8 @@ void CanvasTranslator::CacheSnapshotShmem(
nsCOMPtr<nsIThread> thread = nsCOMPtr<nsIThread> thread =
gfx::CanvasRenderThread::GetCanvasRenderThread(); gfx::CanvasRenderThread::GetCanvasRenderThread();
RefPtr<CanvasTranslator> translator = this; RefPtr<CanvasTranslator> translator = this;
SendSnapshotShmem(aTextureOwnerId, std::move(shmemHandle)) SendSnapshotShmem(aTextureOwnerId, std::move(shmemHandle),
webgl->GetShmemSize())
->Then( ->Then(
thread, __func__, thread, __func__,
[=](bool) { translator->RemoveTexture(aTextureOwnerId); }, [=](bool) { translator->RemoveTexture(aTextureOwnerId); },

View File

@@ -15,16 +15,13 @@
#include "mozilla/gfx/InlineTranslator.h" #include "mozilla/gfx/InlineTranslator.h"
#include "mozilla/gfx/RecordedEvent.h" #include "mozilla/gfx/RecordedEvent.h"
#include "CanvasChild.h" #include "CanvasChild.h"
#include "mozilla/ipc/SharedMemoryHandle.h"
#include "mozilla/layers/CanvasDrawEventRecorder.h" #include "mozilla/layers/CanvasDrawEventRecorder.h"
#include "mozilla/layers/LayersSurfaces.h" #include "mozilla/layers/LayersSurfaces.h"
#include "mozilla/layers/PCanvasParent.h" #include "mozilla/layers/PCanvasParent.h"
#include "mozilla/layers/RemoteTextureMap.h" #include "mozilla/layers/RemoteTextureMap.h"
#include "mozilla/ipc/CrossProcessSemaphore.h" #include "mozilla/ipc/CrossProcessSemaphore.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "mozilla/Monitor.h" #include "mozilla/Monitor.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "mozilla/Variant.h"
namespace mozilla { namespace mozilla {
@@ -84,13 +81,14 @@ class CanvasTranslator final : public gfx::InlineTranslator,
* @param aReaderSem reading blocked semaphore for the CanvasEventRingBuffer * @param aReaderSem reading blocked semaphore for the CanvasEventRingBuffer
* @param aWriterSem writing blocked semaphore for the CanvasEventRingBuffer * @param aWriterSem writing blocked semaphore for the CanvasEventRingBuffer
*/ */
ipc::IPCResult RecvInitTranslator( ipc::IPCResult RecvInitTranslator(TextureType aTextureType,
TextureType aTextureType, TextureType aWebglTextureType, TextureType aWebglTextureType,
gfx::BackendType aBackendType, gfx::BackendType aBackendType,
ipc::MutableSharedMemoryHandle&& aReadHandle, Handle&& aReadHandle,
nsTArray<ipc::ReadOnlySharedMemoryHandle>&& aBufferHandles, nsTArray<Handle>&& aBufferHandles,
CrossProcessSemaphoreHandle&& aReaderSem, uint64_t aBufferSize,
CrossProcessSemaphoreHandle&& aWriterSem); CrossProcessSemaphoreHandle&& aReaderSem,
CrossProcessSemaphoreHandle&& aWriterSem);
/** /**
* Restart the translation from a Stopped state. * Restart the translation from a Stopped state.
@@ -101,13 +99,13 @@ class CanvasTranslator final : public gfx::InlineTranslator,
* Adds a new buffer to be translated. The current buffer will be recycled if * Adds a new buffer to be translated. The current buffer will be recycled if
* it is of the default size. The translation will then be restarted. * it is of the default size. The translation will then be restarted.
*/ */
ipc::IPCResult RecvAddBuffer(ipc::ReadOnlySharedMemoryHandle&& aBufferHandle); ipc::IPCResult RecvAddBuffer(Handle&& aBufferHandle, uint64_t aBufferSize);
/** /**
* Sets the shared memory to be used for readback. * Sets the shared memory to be used for readback.
*/ */
ipc::IPCResult RecvSetDataSurfaceBuffer( ipc::IPCResult RecvSetDataSurfaceBuffer(Handle&& aBufferHandle,
ipc::MutableSharedMemoryHandle&& aBufferHandle); uint64_t aBufferSize);
ipc::IPCResult RecvClearCachedResources(); ipc::IPCResult RecvClearCachedResources();
@@ -318,25 +316,23 @@ class CanvasTranslator final : public gfx::InlineTranslator,
const Tag mTag; const Tag mTag;
private: private:
Variant<ipc::ReadOnlySharedMemoryHandle, ipc::MutableSharedMemoryHandle> ipc::SharedMemory::Handle mBufferHandle;
mBufferHandle; const size_t mBufferSize;
public: public:
explicit CanvasTranslatorEvent(const Tag aTag) explicit CanvasTranslatorEvent(const Tag aTag)
: mTag(aTag), mBufferHandle(ipc::ReadOnlySharedMemoryHandle()) { : mTag(aTag), mBufferSize(0) {
MOZ_ASSERT(mTag == Tag::TranslateRecording || MOZ_ASSERT(mTag == Tag::TranslateRecording ||
mTag == Tag::ClearCachedResources || mTag == Tag::ClearCachedResources ||
mTag == Tag::DropFreeBuffersWhenDormant); mTag == Tag::DropFreeBuffersWhenDormant);
} }
CanvasTranslatorEvent(const Tag aTag, CanvasTranslatorEvent(const Tag aTag,
ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) ipc::SharedMemory::Handle&& aBufferHandle,
: mTag(aTag), mBufferHandle(std::move(aBufferHandle)) { size_t aBufferSize)
MOZ_ASSERT(mTag == Tag::AddBuffer); : mTag(aTag),
} mBufferHandle(std::move(aBufferHandle)),
CanvasTranslatorEvent(const Tag aTag, mBufferSize(aBufferSize) {
ipc::MutableSharedMemoryHandle&& aBufferHandle) MOZ_ASSERT(mTag == Tag::AddBuffer || mTag == Tag::SetDataSurfaceBuffer);
: mTag(aTag), mBufferHandle(std::move(aBufferHandle)) {
MOZ_ASSERT(mTag == Tag::SetDataSurfaceBuffer);
} }
static UniquePtr<CanvasTranslatorEvent> TranslateRecording() { static UniquePtr<CanvasTranslatorEvent> TranslateRecording() {
@@ -344,15 +340,15 @@ class CanvasTranslator final : public gfx::InlineTranslator,
} }
static UniquePtr<CanvasTranslatorEvent> AddBuffer( static UniquePtr<CanvasTranslatorEvent> AddBuffer(
ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) { ipc::SharedMemory::Handle&& aBufferHandle, size_t aBufferSize) {
return MakeUnique<CanvasTranslatorEvent>(Tag::AddBuffer, return MakeUnique<CanvasTranslatorEvent>(
std::move(aBufferHandle)); Tag::AddBuffer, std::move(aBufferHandle), aBufferSize);
} }
static UniquePtr<CanvasTranslatorEvent> SetDataSurfaceBuffer( static UniquePtr<CanvasTranslatorEvent> SetDataSurfaceBuffer(
ipc::MutableSharedMemoryHandle&& aBufferHandle) { ipc::SharedMemory::Handle&& aBufferHandle, size_t aBufferSize) {
return MakeUnique<CanvasTranslatorEvent>(Tag::SetDataSurfaceBuffer, return MakeUnique<CanvasTranslatorEvent>(
std::move(aBufferHandle)); Tag::SetDataSurfaceBuffer, std::move(aBufferHandle), aBufferSize);
} }
static UniquePtr<CanvasTranslatorEvent> ClearCachedResources() { static UniquePtr<CanvasTranslatorEvent> ClearCachedResources() {
@@ -363,20 +359,20 @@ class CanvasTranslator final : public gfx::InlineTranslator,
return MakeUnique<CanvasTranslatorEvent>(Tag::DropFreeBuffersWhenDormant); return MakeUnique<CanvasTranslatorEvent>(Tag::DropFreeBuffersWhenDormant);
} }
ipc::ReadOnlySharedMemoryHandle TakeBufferHandle() { ipc::SharedMemory::Handle TakeBufferHandle() {
if (mTag == Tag::AddBuffer) { if (mTag == Tag::AddBuffer || mTag == Tag::SetDataSurfaceBuffer) {
return std::move(mBufferHandle).as<ipc::ReadOnlySharedMemoryHandle>(); return std::move(mBufferHandle);
} }
MOZ_ASSERT_UNREACHABLE("unexpected to be called"); MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return nullptr; return mozilla::ipc::SharedMemory::NULLHandle();
} }
ipc::MutableSharedMemoryHandle TakeDataSurfaceBufferHandle() { size_t BufferSize() {
if (mTag == Tag::SetDataSurfaceBuffer) { if (mTag == Tag::AddBuffer || mTag == Tag::SetDataSurfaceBuffer) {
return std::move(mBufferHandle).as<ipc::MutableSharedMemoryHandle>(); return mBufferSize;
} }
MOZ_ASSERT_UNREACHABLE("unexpected to be called"); MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return nullptr; return 0;
} }
}; };
@@ -384,13 +380,13 @@ class CanvasTranslator final : public gfx::InlineTranslator,
* @returns true if next HandleCanvasTranslatorEvents() needs to call * @returns true if next HandleCanvasTranslatorEvents() needs to call
* TranslateRecording(). * TranslateRecording().
*/ */
bool AddBuffer(ipc::ReadOnlySharedMemoryHandle&& aBufferHandle); bool AddBuffer(Handle&& aBufferHandle, size_t aBufferSize);
/* /*
* @returns true if next HandleCanvasTranslatorEvents() needs to call * @returns true if next HandleCanvasTranslatorEvents() needs to call
* TranslateRecording(). * TranslateRecording().
*/ */
bool SetDataSurfaceBuffer(ipc::MutableSharedMemoryHandle&& aBufferHandle); bool SetDataSurfaceBuffer(Handle&& aBufferHandle, size_t aBufferSize);
bool ReadNextEvent(EventType& aEventType); bool ReadNextEvent(EventType& aEventType);
@@ -474,7 +470,7 @@ class CanvasTranslator final : public gfx::InlineTranslator,
using State = CanvasDrawEventRecorder::State; using State = CanvasDrawEventRecorder::State;
using Header = CanvasDrawEventRecorder::Header; using Header = CanvasDrawEventRecorder::Header;
ipc::SharedMemoryMapping mHeaderShmem; RefPtr<ipc::SharedMemory> mHeaderShmem;
Header* mHeader = nullptr; Header* mHeader = nullptr;
// Limit event processing to stop at the designated checkpoint, rather than // Limit event processing to stop at the designated checkpoint, rather than
// proceed beyond it. This also forces processing to continue, even when it // proceed beyond it. This also forces processing to continue, even when it
@@ -483,20 +479,20 @@ class CanvasTranslator final : public gfx::InlineTranslator,
int64_t mFlushCheckpoint = 0; int64_t mFlushCheckpoint = 0;
struct CanvasShmem { struct CanvasShmem {
ipc::ReadOnlySharedMemoryMapping shmem; RefPtr<ipc::SharedMemory> shmem;
bool IsValid() const { return shmem.IsValid(); } bool IsValid() const { return !!shmem; }
auto Size() { return shmem ? shmem.Size() : 0; } auto Size() { return shmem ? shmem->Size() : 0; }
gfx::MemReader CreateMemReader() { gfx::MemReader CreateMemReader() {
if (!shmem) { if (!shmem) {
return {nullptr, 0}; return {nullptr, 0};
} }
return {shmem.DataAs<char>(), Size()}; return {static_cast<char*>(shmem->Memory()), Size()};
} }
}; };
std::queue<CanvasShmem> mCanvasShmems; std::queue<CanvasShmem> mCanvasShmems;
CanvasShmem mCurrentShmem; CanvasShmem mCurrentShmem;
gfx::MemReader mCurrentMemReader{0, 0}; gfx::MemReader mCurrentMemReader{0, 0};
ipc::SharedMemoryMapping mDataSurfaceShmem; RefPtr<ipc::SharedMemory> mDataSurfaceShmem;
UniquePtr<CrossProcessSemaphore> mWriterSemaphore; UniquePtr<CrossProcessSemaphore> mWriterSemaphore;
UniquePtr<CrossProcessSemaphore> mReaderSemaphore; UniquePtr<CrossProcessSemaphore> mReaderSemaphore;
TextureType mTextureType = TextureType::Unknown; TextureType mTextureType = TextureType::Unknown;

View File

@@ -17,6 +17,7 @@
#include "mozilla/TimeStamp.h" // for TimeStamp #include "mozilla/TimeStamp.h" // for TimeStamp
#include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/ipc/SharedMemory.h"
#include "mozilla/layers/CompositorController.h" #include "mozilla/layers/CompositorController.h"
#include "mozilla/layers/CompositorVsyncSchedulerOwner.h" #include "mozilla/layers/CompositorVsyncSchedulerOwner.h"
#include "mozilla/layers/FocusTarget.h" #include "mozilla/layers/FocusTarget.h"

View File

@@ -11,7 +11,8 @@
#include <stdint.h> // for uint32_t #include <stdint.h> // for uint32_t
#include "gfxTypes.h" #include "gfxTypes.h"
#include "mozilla/dom/ipc/IdType.h" #include "mozilla/dom/ipc/IdType.h"
#include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "nsIMemoryReporter.h" // for nsIMemoryReporter #include "nsIMemoryReporter.h" // for nsIMemoryReporter
#include "mozilla/Atomics.h" // for Atomic #include "mozilla/Atomics.h" // for Atomic

View File

@@ -13,7 +13,8 @@
#include "mozilla/Attributes.h" // for override #include "mozilla/Attributes.h" // for override
#include "mozilla/Atomics.h" #include "mozilla/Atomics.h"
#include "mozilla/RefPtr.h" // for already_AddRefed #include "mozilla/RefPtr.h" // for already_AddRefed
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
#include "mozilla/layers/CompositableForwarder.h" #include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/PImageBridgeChild.h" #include "mozilla/layers/PImageBridgeChild.h"

View File

@@ -14,6 +14,7 @@
#include "mozilla/Attributes.h" // for override #include "mozilla/Attributes.h" // for override
#include "mozilla/dom/ipc/IdType.h" #include "mozilla/dom/ipc/IdType.h"
#include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
#include "mozilla/layers/CompositorThread.h" #include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/PImageBridgeParent.h" #include "mozilla/layers/PImageBridgeParent.h"
#include "nsISupportsImpl.h" #include "nsISupportsImpl.h"

View File

@@ -24,6 +24,7 @@ using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
using mozilla::gfx::Matrix4x4 from "mozilla/gfx/Matrix.h"; using mozilla::gfx::Matrix4x4 from "mozilla/gfx/Matrix.h";
using mozilla::gfx::FenceInfo from "mozilla/gfx/FileHandleWrapper.h"; using mozilla::gfx::FenceInfo from "mozilla/gfx/FileHandleWrapper.h";
[RefCounted] using mozilla::gfx::FileHandleWrapper from "mozilla/gfx/FileHandleWrapper.h"; [RefCounted] using mozilla::gfx::FileHandleWrapper from "mozilla/gfx/FileHandleWrapper.h";
[MoveOnly] using mozilla::ipc::SharedMemory::Handle from "mozilla/ipc/SharedMemory.h";
using gfxImageFormat from "gfxTypes.h"; using gfxImageFormat from "gfxTypes.h";
using mozilla::layers::MaybeVideoBridgeSource from "mozilla/layers/VideoBridgeUtils.h"; using mozilla::layers::MaybeVideoBridgeSource from "mozilla/layers/VideoBridgeUtils.h";
using mozilla::layers::RemoteTextureId from "mozilla/layers/LayersTypes.h"; using mozilla::layers::RemoteTextureId from "mozilla/layers/LayersTypes.h";
@@ -34,7 +35,6 @@ using mozilla::layers::GpuProcessQueryId from "mozilla/layers/LayersTypes.h";
using mozilla::wr::ExternalImageSource from "mozilla/webrender/WebRenderTypes.h"; using mozilla::wr::ExternalImageSource from "mozilla/webrender/WebRenderTypes.h";
using mozilla::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h"; using mozilla::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h";
using mozilla::layers::SurfaceDescriptorRemoteDecoderId from "mozilla/layers/LayersTypes.h"; using mozilla::layers::SurfaceDescriptorRemoteDecoderId from "mozilla/layers/LayersTypes.h";
[MoveOnly] using mozilla::ipc::ReadOnlySharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h";
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
@@ -186,12 +186,12 @@ namespace layers {
MemoryOrShmem data; MemoryOrShmem data;
}; };
struct SurfaceDescriptorShared [Comparable] struct SurfaceDescriptorShared
{ {
IntSize size; IntSize size;
int32_t stride; int32_t stride;
SurfaceFormat format; SurfaceFormat format;
ReadOnlySharedMemoryHandle handle; Handle handle;
}; };
[Comparable] struct SurfaceDescriptorExternalImage [Comparable] struct SurfaceDescriptorExternalImage

View File

@@ -11,9 +11,8 @@ include "mozilla/layers/CanvasTranslator.h";
[MoveOnly] using mozilla::CrossProcessSemaphoreHandle from "mozilla/ipc/CrossProcessSemaphore.h"; [MoveOnly] using mozilla::CrossProcessSemaphoreHandle from "mozilla/ipc/CrossProcessSemaphore.h";
using mozilla::layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h"; using mozilla::layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h";
using mozilla::layers::TextureType from "mozilla/layers/LayersTypes.h"; using mozilla::layers::TextureType from "mozilla/layers/LayersTypes.h";
[MoveOnly] using mozilla::ipc::SharedMemory::Handle from "mozilla/ipc/SharedMemory.h";
using mozilla::gfx::BackendType from "mozilla/gfx/Types.h"; using mozilla::gfx::BackendType from "mozilla/gfx/Types.h";
[MoveOnly] using mozilla::ipc::ReadOnlySharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h";
[MoveOnly] using mozilla::ipc::MutableSharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h";
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
@@ -35,8 +34,8 @@ parent:
* are handles for the semaphores to handle waiting on either side. * are handles for the semaphores to handle waiting on either side.
*/ */
async InitTranslator(TextureType aTextureType, TextureType aWebglTextureType, async InitTranslator(TextureType aTextureType, TextureType aWebglTextureType,
BackendType aBackendType, MutableSharedMemoryHandle aHeaderHandle, BackendType aBackendType, Handle aHeaderHandle,
ReadOnlySharedMemoryHandle[] aBufferHandles, Handle[] aBufferHandles, uint64_t aBufferSize,
CrossProcessSemaphoreHandle aReaderSem, CrossProcessSemaphoreHandle aReaderSem,
CrossProcessSemaphoreHandle aWriterSem); CrossProcessSemaphoreHandle aWriterSem);
@@ -49,12 +48,12 @@ parent:
* Adds a new buffer to be translated. The current buffer will be recycled if * Adds a new buffer to be translated. The current buffer will be recycled if
* it is of the default size. The translation will then be restarted. * it is of the default size. The translation will then be restarted.
*/ */
async AddBuffer(ReadOnlySharedMemoryHandle aBufferHandle); async AddBuffer(Handle aBufferHandle, uint64_t aBufferSize);
/** /**
* Sets the shared memory to be used for readback. * Sets the shared memory to be used for readback.
*/ */
async SetDataSurfaceBuffer(MutableSharedMemoryHandle aBufferHandle); async SetDataSurfaceBuffer(Handle aBufferHandle, uint64_t aBufferSize);
/** /**
* Notify CanvasTranslator it is about to be minimized. * Notify CanvasTranslator it is about to be minimized.
@@ -98,7 +97,7 @@ child:
/** /**
* Cache the shmem of the framebuffer for snapshotting. * Cache the shmem of the framebuffer for snapshotting.
*/ */
async SnapshotShmem(RemoteTextureOwnerId aTextureOwnerId, ReadOnlySharedMemoryHandle aShmemHandle) returns (bool aSuccess); async SnapshotShmem(RemoteTextureOwnerId aTextureOwnerId, Handle aShmemHandle, uint32_t aShmemSize) returns (bool aSuccess);
async NotifyTextureDestruction(RemoteTextureOwnerId aTextureOwnerId); async NotifyTextureDestruction(RemoteTextureOwnerId aTextureOwnerId);
}; };

View File

@@ -14,6 +14,7 @@ include "mozilla/layers/WebRenderMessageUtils.h";
using mozilla::TimeDuration from "mozilla/TimeStamp.h"; using mozilla::TimeDuration from "mozilla/TimeStamp.h";
using mozilla::CSSToLayoutDeviceScale from "Units.h"; using mozilla::CSSToLayoutDeviceScale from "Units.h";
using mozilla::gfx::IntSize from "mozilla/gfx/2D.h"; using mozilla::gfx::IntSize from "mozilla/gfx/2D.h";
[MoveOnly] using mozilla::ipc::SharedMemory::Handle from "mozilla/ipc/SharedMemory.h";
using mozilla::layers::CompositorOptions from "mozilla/layers/LayersMessageUtils.h"; using mozilla::layers::CompositorOptions from "mozilla/layers/LayersMessageUtils.h";
using mozilla::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h"; using mozilla::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h";
using mozilla::wr::MemoryReport from "mozilla/webrender/WebRenderTypes.h"; using mozilla::wr::MemoryReport from "mozilla/webrender/WebRenderTypes.h";

View File

@@ -5,12 +5,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SharedPlanarYCbCrImage.h" #include "SharedPlanarYCbCrImage.h"
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
#include <stdio.h> // for printf #include <stdio.h> // for printf
#include "gfx2DGlue.h" // for Moz2D transition helpers #include "gfx2DGlue.h" // for Moz2D transition helpers
#include "ISurfaceAllocator.h" // for ISurfaceAllocator, etc #include "ISurfaceAllocator.h" // for ISurfaceAllocator, etc
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/gfx/Types.h" // for SurfaceFormat::SurfaceFormat::YUV #include "mozilla/gfx/Types.h" // for SurfaceFormat::SurfaceFormat::YUV
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
#include "mozilla/layers/ImageClient.h" // for ImageClient #include "mozilla/layers/ImageClient.h" // for ImageClient
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
#include "mozilla/layers/TextureClient.h" #include "mozilla/layers/TextureClient.h"

View File

@@ -220,7 +220,7 @@ nsresult SharedSurfacesChild::ShareInternal(SourceSurfaceSharedData* aSurface,
// Attempt to share a handle with the GPU process. The handle may or may not // Attempt to share a handle with the GPU process. The handle may or may not
// be available -- it will only be available if it is either not yet finalized // be available -- it will only be available if it is either not yet finalized
// and/or if it has been finalized but never used for drawing in process. // and/or if it has been finalized but never used for drawing in process.
ipc::ReadOnlySharedMemoryHandle handle; ipc::SharedMemory::Handle handle = ipc::SharedMemory::NULLHandle();
nsresult rv = aSurface->CloneHandle(handle); nsresult rv = aSurface->CloneHandle(handle);
if (rv == NS_ERROR_NOT_AVAILABLE) { if (rv == NS_ERROR_NOT_AVAILABLE) {
// It is at least as expensive to copy the image to the GPU process if we // It is at least as expensive to copy the image to the GPU process if we

View File

@@ -12,6 +12,7 @@
#include "mozilla/StaticMutex.h" // for StaticMutex #include "mozilla/StaticMutex.h" // for StaticMutex
#include "mozilla/StaticPtr.h" // for StaticAutoPtr #include "mozilla/StaticPtr.h" // for StaticAutoPtr
#include "mozilla/RefPtr.h" // for already_AddRefed #include "mozilla/RefPtr.h" // for already_AddRefed
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
#include "mozilla/gfx/2D.h" // for SurfaceFormat #include "mozilla/gfx/2D.h" // for SurfaceFormat
#include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptorShared #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptorShared

View File

@@ -8,6 +8,7 @@
#include <string.h> #include <string.h>
#include <algorithm> #include <algorithm>
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/ipc/SharedMemory.h"
#include "mozilla/layers/PTextureChild.h" #include "mozilla/layers/PTextureChild.h"
#include "mozilla/layers/WebRenderBridgeChild.h" #include "mozilla/layers/WebRenderBridgeChild.h"

View File

@@ -14,13 +14,15 @@
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/ipc/SharedMemory.h"
// This is split out from SharedFontList.h because that header is included // This is split out from SharedFontList.h because that header is included
// quite widely (via gfxPlatformFontList.h, gfxTextRun.h, etc). This header, // quite widely (via gfxPlatformFontList.h, gfxTextRun.h, etc), and other code
// which defines the actual shared-memory FontList class, is included only by // such as the generated DOM bindings code gets upset at (indirect) inclusion
// the .cpp files that implement or directly interface with the font list, to // of <windows.h> via SharedMemory.h. So this header, which defines the actual
// avoid polluting other headers. // shared-memory FontList class, is included only by the .cpp files that
// implement or directly interface with the font list, to avoid polluting other
// headers.
namespace mozilla { namespace mozilla {
namespace fontlist { namespace fontlist {
@@ -241,14 +243,14 @@ class FontList {
* list has changed/grown since the child was first initialized). * list has changed/grown since the child was first initialized).
*/ */
void ShareShmBlockToProcess(uint32_t aIndex, base::ProcessId aPid, void ShareShmBlockToProcess(uint32_t aIndex, base::ProcessId aPid,
ipc::ReadOnlySharedMemoryHandle* aOut) { ipc::SharedMemory::Handle* aOut) {
MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length()); MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length());
if (aIndex >= mReadOnlyShmems.Length()) { if (aIndex >= mReadOnlyShmems.Length()) {
// Block index out of range // Block index out of range
*aOut = nullptr; *aOut = ipc::SharedMemory::NULLHandle();
return; return;
} }
*aOut = mReadOnlyShmems[aIndex].Clone(); *aOut = mReadOnlyShmems[aIndex]->CloneHandle();
if (!*aOut) { if (!*aOut) {
MOZ_CRASH("failed to share block"); MOZ_CRASH("failed to share block");
} }
@@ -259,14 +261,14 @@ class FontList {
* shared to the given process. This is used at child process startup * shared to the given process. This is used at child process startup
* to pass the complete list at once. * to pass the complete list at once.
*/ */
void ShareBlocksToProcess(nsTArray<ipc::ReadOnlySharedMemoryHandle>* aBlocks, void ShareBlocksToProcess(nsTArray<ipc::SharedMemory::Handle>* aBlocks,
base::ProcessId aPid); base::ProcessId aPid);
ipc::ReadOnlySharedMemoryHandle ShareBlockToProcess(uint32_t aIndex, ipc::SharedMemory::Handle ShareBlockToProcess(uint32_t aIndex,
base::ProcessId aPid); base::ProcessId aPid);
void ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex, void ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
ipc::ReadOnlySharedMemoryHandle aHandle); ipc::SharedMemory::Handle aHandle);
/** /**
* Support for memory reporter. * Support for memory reporter.
*/ */
@@ -296,22 +298,13 @@ class FontList {
private: private:
struct ShmBlock { struct ShmBlock {
// Takes ownership of aShmem. In a child process, aShmem will be mapped as // Takes ownership of aShmem. Note that in a child process, aShmem will be
// read-only. // mapped as read-only.
explicit ShmBlock(ipc::ReadOnlySharedMemoryMapping&& aShmem) explicit ShmBlock(RefPtr<ipc::SharedMemory>&& aShmem)
: mShmem(std::move(aShmem)) { : mShmem(std::move(aShmem)) {}
MOZ_ASSERT(!XRE_IsParentProcess());
}
explicit ShmBlock(ipc::SharedMemoryMapping&& aShmem)
: mShmem(std::move(aShmem)) {
MOZ_ASSERT(XRE_IsParentProcess());
}
// Get pointer to the mapped memory. // Get pointer to the mapped memory.
void* Memory() const { return mShmem.Address(); } void* Memory() const { return mShmem->Memory(); }
void Clear() { mShmem = nullptr; }
// Only the parent process does allocation, so only it will update this // Only the parent process does allocation, so only it will update this
// field. Content processes read the value when checking Pointer validity. // field. Content processes read the value when checking Pointer validity.
@@ -333,8 +326,7 @@ class FontList {
return static_cast<BlockHeader*>(Memory())->mBlockSize; return static_cast<BlockHeader*>(Memory())->mBlockSize;
} }
private: RefPtr<ipc::SharedMemory> mShmem;
ipc::MutableOrReadOnlySharedMemoryMapping mShmem;
}; };
Header& GetHeader() const; Header& GetHeader() const;
@@ -377,10 +369,10 @@ class FontList {
nsTArray<mozilla::UniquePtr<ShmBlock>> mBlocks; nsTArray<mozilla::UniquePtr<ShmBlock>> mBlocks;
/** /**
* Auxiliary array, used only in the parent process; holds read-only handles * Auxiliary array, used only in the parent process; holds read-only copies
* for the shmem blocks; these are what will be shared to child processes. * of the shmem blocks; these are what will be shared to child processes.
*/ */
nsTArray<ipc::ReadOnlySharedMemoryHandle> mReadOnlyShmems; nsTArray<RefPtr<ipc::SharedMemory>> mReadOnlyShmems;
#ifdef XP_WIN #ifdef XP_WIN
// Bool array to track whether we have read face names from the name table. // Bool array to track whether we have read face names from the name table.

View File

@@ -6,6 +6,7 @@
#include "gfxPlatformFontList.h" #include "gfxPlatformFontList.h"
#include "gfxFontUtils.h" #include "gfxFontUtils.h"
#include "gfxFont.h" #include "gfxFont.h"
#include "mozilla/ipc/SharedMemory.h"
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
#include "prerror.h" #include "prerror.h"
#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentChild.h"
@@ -740,21 +741,25 @@ FontList::FontList(uint32_t aGeneration) {
// SetXPCOMProcessAttributes. // SetXPCOMProcessAttributes.
auto& blocks = dom::ContentChild::GetSingleton()->SharedFontListBlocks(); auto& blocks = dom::ContentChild::GetSingleton()->SharedFontListBlocks();
for (auto& handle : blocks) { for (auto& handle : blocks) {
if (!handle) { auto newShm = MakeRefPtr<ipc::SharedMemory>();
if (!newShm->IsHandleValid(handle)) {
// Bail out and let UpdateShmBlocks try to do its thing below. // Bail out and let UpdateShmBlocks try to do its thing below.
break; break;
} }
if (handle.Size() < SHM_BLOCK_SIZE) { if (!newShm->SetHandle(std::move(handle),
ipc::SharedMemory::OpenRights::RightsReadOnly)) {
MOZ_CRASH("failed to set shm handle");
}
if (!newShm->Map(SHM_BLOCK_SIZE) || !newShm->Memory()) {
MOZ_CRASH("failed to map shared memory"); MOZ_CRASH("failed to map shared memory");
} }
auto newShm = handle.Map(); uint32_t size = static_cast<BlockHeader*>(newShm->Memory())->mBlockSize;
if (!newShm || !newShm.Address()) {
MOZ_CRASH("failed to map shared memory");
}
uint32_t size = newShm.DataAs<BlockHeader>()->mBlockSize;
MOZ_ASSERT(size >= SHM_BLOCK_SIZE); MOZ_ASSERT(size >= SHM_BLOCK_SIZE);
if (newShm.Size() < size) { if (size != SHM_BLOCK_SIZE) {
MOZ_CRASH("failed to map shared memory"); newShm->Unmap();
if (!newShm->Map(size) || !newShm->Memory()) {
MOZ_CRASH("failed to map shared memory");
}
} }
mBlocks.AppendElement(new ShmBlock(std::move(newShm))); mBlocks.AppendElement(new ShmBlock(std::move(newShm)));
} }
@@ -799,17 +804,17 @@ FontList::Header& FontList::GetHeader() const MOZ_NO_THREAD_SAFETY_ANALYSIS {
bool FontList::AppendShmBlock(uint32_t aSizeNeeded) { bool FontList::AppendShmBlock(uint32_t aSizeNeeded) {
MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(XRE_IsParentProcess());
uint32_t size = std::max(aSizeNeeded, SHM_BLOCK_SIZE); uint32_t size = std::max(aSizeNeeded, SHM_BLOCK_SIZE);
auto handle = ipc::shared_memory::CreateFreezable(size); auto newShm = MakeRefPtr<ipc::SharedMemory>();
if (!handle) { if (!newShm->CreateFreezable(size)) {
MOZ_CRASH("failed to create shared memory"); MOZ_CRASH("failed to create shared memory");
return false; return false;
} }
auto [newShm, readOnly] = std::move(handle).Map().Freeze(); if (!newShm->Map(size) || !newShm->Memory()) {
if (!newShm || !newShm.Address()) {
MOZ_CRASH("failed to map shared memory"); MOZ_CRASH("failed to map shared memory");
return false; return false;
} }
if (!readOnly) { auto readOnly = MakeRefPtr<ipc::SharedMemory>();
if (!newShm->ReadOnlyCopy(readOnly.get())) {
MOZ_CRASH("failed to create read-only copy"); MOZ_CRASH("failed to create read-only copy");
return false; return false;
} }
@@ -843,13 +848,19 @@ bool FontList::AppendShmBlock(uint32_t aSizeNeeded) {
} }
void FontList::ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex, void FontList::ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
ipc::ReadOnlySharedMemoryHandle aHandle) { ipc::SharedMemory::Handle aHandle) {
MOZ_ASSERT(!XRE_IsParentProcess()); MOZ_ASSERT(!XRE_IsParentProcess());
MOZ_ASSERT(mBlocks.Length() > 0); MOZ_ASSERT(mBlocks.Length() > 0);
if (!aHandle) { auto newShm = MakeRefPtr<ipc::SharedMemory>();
if (!newShm->IsHandleValid(aHandle)) {
return; return;
} }
if (!newShm->SetHandle(std::move(aHandle),
ipc::SharedMemory::RightsReadOnly)) {
MOZ_CRASH("failed to set shm handle");
}
if (aIndex != mBlocks.Length()) { if (aIndex != mBlocks.Length()) {
return; return;
} }
@@ -857,15 +868,17 @@ void FontList::ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
return; return;
} }
auto newShm = aHandle.Map(); if (!newShm->Map(SHM_BLOCK_SIZE) || !newShm->Memory()) {
if (!newShm || !newShm.Address() || newShm.Size() < SHM_BLOCK_SIZE) {
MOZ_CRASH("failed to map shared memory"); MOZ_CRASH("failed to map shared memory");
} }
uint32_t size = newShm.DataAs<BlockHeader>()->mBlockSize; uint32_t size = static_cast<BlockHeader*>(newShm->Memory())->mBlockSize;
MOZ_ASSERT(size >= SHM_BLOCK_SIZE); MOZ_ASSERT(size >= SHM_BLOCK_SIZE);
if (newShm.Size() < size) { if (size != SHM_BLOCK_SIZE) {
MOZ_CRASH("failed to map shared memory"); newShm->Unmap();
if (!newShm->Map(size) || !newShm->Memory()) {
MOZ_CRASH("failed to map shared memory");
}
} }
mBlocks.AppendElement(new ShmBlock(std::move(newShm))); mBlocks.AppendElement(new ShmBlock(std::move(newShm)));
@@ -873,7 +886,7 @@ void FontList::ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
void FontList::DetachShmBlocks() { void FontList::DetachShmBlocks() {
for (auto& i : mBlocks) { for (auto& i : mBlocks) {
i->Clear(); i->mShmem = nullptr;
} }
mBlocks.Clear(); mBlocks.Clear();
mReadOnlyShmems.Clear(); mReadOnlyShmems.Clear();
@@ -884,22 +897,29 @@ FontList::ShmBlock* FontList::GetBlockFromParent(uint32_t aIndex) {
// If we have no existing blocks, we don't want a generation check yet; // If we have no existing blocks, we don't want a generation check yet;
// the header in the first block will define the generation of this list // the header in the first block will define the generation of this list
uint32_t generation = aIndex == 0 ? 0 : GetGeneration(); uint32_t generation = aIndex == 0 ? 0 : GetGeneration();
ipc::ReadOnlySharedMemoryHandle handle; ipc::SharedMemory::Handle handle = ipc::SharedMemory::NULLHandle();
if (!dom::ContentChild::GetSingleton()->SendGetFontListShmBlock( if (!dom::ContentChild::GetSingleton()->SendGetFontListShmBlock(
generation, aIndex, &handle)) { generation, aIndex, &handle)) {
return nullptr; return nullptr;
} }
if (!handle) { auto newShm = MakeRefPtr<ipc::SharedMemory>();
if (!newShm->IsHandleValid(handle)) {
return nullptr; return nullptr;
} }
auto newShm = handle.Map(); if (!newShm->SetHandle(std::move(handle),
if (!newShm || !newShm.Address() || newShm.Size() < SHM_BLOCK_SIZE) { ipc::SharedMemory::RightsReadOnly)) {
MOZ_CRASH("failed to set shm handle");
}
if (!newShm->Map(SHM_BLOCK_SIZE) || !newShm->Memory()) {
MOZ_CRASH("failed to map shared memory"); MOZ_CRASH("failed to map shared memory");
} }
uint32_t size = newShm.DataAs<BlockHeader>()->mBlockSize; uint32_t size = static_cast<BlockHeader*>(newShm->Memory())->mBlockSize;
MOZ_ASSERT(size >= SHM_BLOCK_SIZE); MOZ_ASSERT(size >= SHM_BLOCK_SIZE);
if (newShm.Size() < size) { if (size != SHM_BLOCK_SIZE) {
MOZ_CRASH("failed to map shared memory"); newShm->Unmap();
if (!newShm->Map(size) || !newShm->Memory()) {
MOZ_CRASH("failed to map shared memory");
}
} }
return new ShmBlock(std::move(newShm)); return new ShmBlock(std::move(newShm));
} }
@@ -927,10 +947,10 @@ bool FontList::UpdateShmBlocks(bool aMustLock) MOZ_NO_THREAD_SAFETY_ANALYSIS {
} }
void FontList::ShareBlocksToProcess( void FontList::ShareBlocksToProcess(
nsTArray<ipc::ReadOnlySharedMemoryHandle>* aBlocks, base::ProcessId aPid) { nsTArray<ipc::SharedMemory::Handle>* aBlocks, base::ProcessId aPid) {
MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length()); MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length());
for (auto& shmem : mReadOnlyShmems) { for (auto& shmem : mReadOnlyShmems) {
auto handle = shmem.Clone(); auto handle = shmem->CloneHandle();
if (!handle) { if (!handle) {
// If something went wrong here, we just bail out; the child will need to // If something went wrong here, we just bail out; the child will need to
// request the blocks as needed, at some performance cost. (Although in // request the blocks as needed, at some performance cost. (Although in
@@ -943,13 +963,13 @@ void FontList::ShareBlocksToProcess(
} }
} }
ipc::ReadOnlySharedMemoryHandle FontList::ShareBlockToProcess( ipc::SharedMemory::Handle FontList::ShareBlockToProcess(uint32_t aIndex,
uint32_t aIndex, base::ProcessId aPid) { base::ProcessId aPid) {
MOZ_RELEASE_ASSERT(XRE_IsParentProcess()); MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length()); MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length());
MOZ_RELEASE_ASSERT(aIndex < mReadOnlyShmems.Length()); MOZ_RELEASE_ASSERT(aIndex < mReadOnlyShmems.Length());
return mReadOnlyShmems[aIndex].Clone(); return mReadOnlyShmems[aIndex]->CloneHandle();
} }
Pointer FontList::Alloc(uint32_t aSize) { Pointer FontList::Alloc(uint32_t aSize) {
@@ -1390,7 +1410,7 @@ size_t FontList::SizeOfExcludingThis(
mozilla::MallocSizeOf aMallocSizeOf) const { mozilla::MallocSizeOf aMallocSizeOf) const {
size_t result = mBlocks.ShallowSizeOfExcludingThis(aMallocSizeOf); size_t result = mBlocks.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (const auto& b : mBlocks) { for (const auto& b : mBlocks) {
result += aMallocSizeOf(b.get()); result += aMallocSizeOf(b.get()) + aMallocSizeOf(b->mShmem.get());
} }
return result; return result;
} }

View File

@@ -9,6 +9,7 @@
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "mozilla/ipc/Shmem.h" #include "mozilla/ipc/Shmem.h"
#include "mozilla/ipc/SharedMemory.h"
#include "gfxASurface.h" #include "gfxASurface.h"
#include "gfxImageSurface.h" #include "gfxImageSurface.h"
@@ -32,6 +33,7 @@ extern const cairo_user_data_key_t SHM_KEY;
template <typename Base, typename Sub> template <typename Base, typename Sub>
class gfxBaseSharedMemorySurface : public Base { class gfxBaseSharedMemorySurface : public Base {
typedef mozilla::ipc::SharedMemory SharedMemory;
typedef mozilla::ipc::Shmem Shmem; typedef mozilla::ipc::Shmem Shmem;
protected: protected:

View File

@@ -3111,7 +3111,7 @@ void gfxPlatformFontList::CancelInitOtherFamilyNamesTask() {
void gfxPlatformFontList::ShareFontListShmBlockToProcess( void gfxPlatformFontList::ShareFontListShmBlockToProcess(
uint32_t aGeneration, uint32_t aIndex, base::ProcessId aPid, uint32_t aGeneration, uint32_t aIndex, base::ProcessId aPid,
mozilla::ipc::ReadOnlySharedMemoryHandle* aOut) { mozilla::ipc::SharedMemory::Handle* aOut) {
auto list = SharedFontList(); auto list = SharedFontList();
if (!list) { if (!list) {
return; return;
@@ -3119,12 +3119,12 @@ void gfxPlatformFontList::ShareFontListShmBlockToProcess(
if (!aGeneration || list->GetGeneration() == aGeneration) { if (!aGeneration || list->GetGeneration() == aGeneration) {
list->ShareShmBlockToProcess(aIndex, aPid, aOut); list->ShareShmBlockToProcess(aIndex, aPid, aOut);
} else { } else {
*aOut = nullptr; *aOut = mozilla::ipc::SharedMemory::NULLHandle();
} }
} }
void gfxPlatformFontList::ShareFontListToProcess( void gfxPlatformFontList::ShareFontListToProcess(
nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle>* aBlocks, nsTArray<mozilla::ipc::SharedMemory::Handle>* aBlocks,
base::ProcessId aPid) { base::ProcessId aPid) {
auto list = SharedFontList(); auto list = SharedFontList();
if (list) { if (list) {
@@ -3132,16 +3132,15 @@ void gfxPlatformFontList::ShareFontListToProcess(
} }
} }
mozilla::ipc::ReadOnlySharedMemoryHandle mozilla::ipc::SharedMemory::Handle gfxPlatformFontList::ShareShmBlockToProcess(
gfxPlatformFontList::ShareShmBlockToProcess(uint32_t aIndex, uint32_t aIndex, base::ProcessId aPid) {
base::ProcessId aPid) {
MOZ_RELEASE_ASSERT(SharedFontList()); MOZ_RELEASE_ASSERT(SharedFontList());
return SharedFontList()->ShareBlockToProcess(aIndex, aPid); return SharedFontList()->ShareBlockToProcess(aIndex, aPid);
} }
void gfxPlatformFontList::ShmBlockAdded( void gfxPlatformFontList::ShmBlockAdded(
uint32_t aGeneration, uint32_t aIndex, uint32_t aGeneration, uint32_t aIndex,
mozilla::ipc::ReadOnlySharedMemoryHandle aHandle) { mozilla::ipc::SharedMemory::Handle aHandle) {
if (SharedFontList()) { if (SharedFontList()) {
AutoLock lock(mLock); AutoLock lock(mLock);
SharedFontList()->ShmBlockAdded(aGeneration, aIndex, std::move(aHandle)); SharedFontList()->ShmBlockAdded(aGeneration, aIndex, std::move(aHandle));

View File

@@ -27,7 +27,7 @@
#include "mozilla/MemoryReporting.h" #include "mozilla/MemoryReporting.h"
#include "mozilla/RangedArray.h" #include "mozilla/RangedArray.h"
#include "mozilla/RecursiveMutex.h" #include "mozilla/RecursiveMutex.h"
#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/ipc/SharedMemory.h"
#include "nsLanguageAtomService.h" #include "nsLanguageAtomService.h"
namespace mozilla { namespace mozilla {
@@ -353,20 +353,20 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
// Create a handle for a single shmem block (identified by index) ready to // Create a handle for a single shmem block (identified by index) ready to
// be shared to the given processId. // be shared to the given processId.
void ShareFontListShmBlockToProcess( void ShareFontListShmBlockToProcess(uint32_t aGeneration, uint32_t aIndex,
uint32_t aGeneration, uint32_t aIndex, base::ProcessId aPid, base::ProcessId aPid,
mozilla::ipc::ReadOnlySharedMemoryHandle* aOut); mozilla::ipc::SharedMemory::Handle* aOut);
// Populate the array aBlocks with the complete list of shmem handles ready // Populate the array aBlocks with the complete list of shmem handles ready
// to be shared to the given processId. // to be shared to the given processId.
void ShareFontListToProcess( void ShareFontListToProcess(
nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle>* aBlocks, nsTArray<mozilla::ipc::SharedMemory::Handle>* aBlocks,
base::ProcessId aPid); base::ProcessId aPid);
void ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex, void ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
mozilla::ipc::ReadOnlySharedMemoryHandle aHandle); mozilla::ipc::SharedMemory::Handle aHandle);
mozilla::ipc::ReadOnlySharedMemoryHandle ShareShmBlockToProcess( mozilla::ipc::SharedMemory::Handle ShareShmBlockToProcess(
uint32_t aIndex, base::ProcessId aPid); uint32_t aIndex, base::ProcessId aPid);
void SetCharacterMap(uint32_t aGeneration, uint32_t aFamilyIndex, bool aAlias, void SetCharacterMap(uint32_t aGeneration, uint32_t aFamilyIndex, bool aAlias,

View File

@@ -13,6 +13,7 @@
#include "mozilla/dom/WebXRBinding.h" #include "mozilla/dom/WebXRBinding.h"
#include "mozilla/dom/XRFrame.h" #include "mozilla/dom/XRFrame.h"
#include "mozilla/gfx/PVRManagerChild.h" #include "mozilla/gfx/PVRManagerChild.h"
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
#include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator #include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator
#include "mozilla/layers/LayersTypes.h" // for LayersBackend #include "mozilla/layers/LayersTypes.h" // for LayersBackend

View File

@@ -2549,13 +2549,7 @@ pub unsafe extern "C" fn wgpu_server_queue_write_action(
mut error_buf: ErrorBuffer, mut error_buf: ErrorBuffer,
) { ) {
let action: QueueWriteAction = bincode::deserialize(byte_buf.as_slice()).unwrap(); let action: QueueWriteAction = bincode::deserialize(byte_buf.as_slice()).unwrap();
// It is undefined behavior to pass a null pointer to `slice::from_raw_parts`, so in the case let data = slice::from_raw_parts(data, data_length);
// 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 { let result = match action {
QueueWriteAction::Buffer { dst, offset } => { QueueWriteAction::Buffer { dst, offset } => {
global.queue_write_buffer(self_id, dst, offset, data) global.queue_write_buffer(self_id, dst, offset, data)

View File

@@ -7,7 +7,6 @@
#include "ImageMemoryReporter.h" #include "ImageMemoryReporter.h"
#include "Image.h" #include "Image.h"
#include "base/process_util.h" #include "base/process_util.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "mozilla/layers/SharedSurfacesParent.h" #include "mozilla/layers/SharedSurfacesParent.h"
#include "mozilla/StaticPrefs_image.h" #include "mozilla/StaticPrefs_image.h"
#include "nsIMemoryReporter.h" #include "nsIMemoryReporter.h"
@@ -114,7 +113,7 @@ void ImageMemoryReporter::ReportSharedSurface(
path.AppendInt(aEntry.mCreatorRef); path.AppendInt(aEntry.mCreatorRef);
path.AppendLiteral(")/decoded-"); path.AppendLiteral(")/decoded-");
size_t surfaceSize = mozilla::ipc::shared_memory::PageAlignedSize( size_t surfaceSize = mozilla::ipc::SharedMemory::PageAlignedSize(
aEntry.mSize.height * aEntry.mStride); aEntry.mSize.height * aEntry.mStride);
// If this memory has already been reported elsewhere (e.g. as part of our // If this memory has already been reported elsewhere (e.g. as part of our

View File

@@ -331,10 +331,11 @@ void nsHyphenationManager::LoadAliases() {
void nsHyphenationManager::ShareHyphDictToProcess( void nsHyphenationManager::ShareHyphDictToProcess(
nsIURI* aURI, base::ProcessId aPid, nsIURI* aURI, base::ProcessId aPid,
mozilla::ipc::ReadOnlySharedMemoryHandle* aOutHandle) { mozilla::ipc::SharedMemory::Handle* aOutHandle, uint32_t* aOutSize) {
MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(XRE_IsParentProcess());
// aURI will be referring to an omnijar resource (otherwise just bail). // aURI will be referring to an omnijar resource (otherwise just bail).
*aOutHandle = nullptr; *aOutHandle = mozilla::ipc::SharedMemory::NULLHandle();
*aOutSize = 0;
// Extract the locale code from the URI, and get the corresponding // Extract the locale code from the URI, and get the corresponding
// hyphenator (loading it into shared memory if necessary). // hyphenator (loading it into shared memory if necessary).
@@ -357,7 +358,7 @@ void nsHyphenationManager::ShareHyphDictToProcess(
return; return;
} }
*aOutHandle = hyph->CloneHandle(); hyph->CloneHandle(aOutHandle, aOutSize);
} }
size_t nsHyphenationManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) { size_t nsHyphenationManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) {

View File

@@ -8,7 +8,7 @@
#include "base/process.h" #include "base/process.h"
#include "mozilla/Omnijar.h" #include "mozilla/Omnijar.h"
#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/ipc/SharedMemory.h"
#include "nsHashKeys.h" #include "nsHashKeys.h"
#include "nsAtomHashKeys.h" #include "nsAtomHashKeys.h"
#include "nsInterfaceHashtable.h" #include "nsInterfaceHashtable.h"
@@ -27,9 +27,9 @@ class nsHyphenationManager : public nsIObserver {
already_AddRefed<nsHyphenator> GetHyphenator(nsAtom* aLocale); already_AddRefed<nsHyphenator> GetHyphenator(nsAtom* aLocale);
void ShareHyphDictToProcess( void ShareHyphDictToProcess(nsIURI* aURI, base::ProcessId aPid,
nsIURI* aURI, base::ProcessId aPid, mozilla::ipc::SharedMemory::Handle* aOutHandle,
mozilla::ipc::ReadOnlySharedMemoryHandle* aOutHandle); uint32_t* aOutSize);
static nsHyphenationManager* Instance(); static nsHyphenationManager* Instance();

View File

@@ -7,8 +7,6 @@
#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentChild.h"
#include "mozilla/Omnijar.h" #include "mozilla/Omnijar.h"
#include "mozilla/ipc/SharedMemoryHandle.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsIChannel.h" #include "nsIChannel.h"
#include "nsIFile.h" #include "nsIFile.h"
@@ -34,7 +32,7 @@ void DefaultDelete<const CompiledData>::operator()(
mapped_hyph_free_compiled_data(const_cast<CompiledData*>(aData)); mapped_hyph_free_compiled_data(const_cast<CompiledData*>(aData));
} }
static const uint8_t* GetItemPtrFromJarURI(nsIJARURI* aJAR, uint32_t* aLength) { static const void* GetItemPtrFromJarURI(nsIJARURI* aJAR, uint32_t* aLength) {
// Try to get the jarfile's nsZipArchive, find the relevant item, and return // Try to get the jarfile's nsZipArchive, find the relevant item, and return
// a pointer to its data provided it is stored uncompressed. // a pointer to its data provided it is stored uncompressed.
nsCOMPtr<nsIURI> jarFile; nsCOMPtr<nsIURI> jarFile;
@@ -68,53 +66,63 @@ static const uint8_t* GetItemPtrFromJarURI(nsIJARURI* aJAR, uint32_t* aLength) {
return nullptr; return nullptr;
} }
static ipc::ReadOnlySharedMemoryMapping GetHyphDictFromParent(nsIURI* aURI) { static RefPtr<ipc::SharedMemory> GetHyphDictFromParent(nsIURI* aURI,
uint32_t* aLength) {
MOZ_ASSERT(!XRE_IsParentProcess()); MOZ_ASSERT(!XRE_IsParentProcess());
ipc::ReadOnlySharedMemoryHandle handle; ipc::SharedMemory::Handle handle = ipc::SharedMemory::NULLHandle();
uint32_t size;
MOZ_ASSERT(aURI); MOZ_ASSERT(aURI);
if (!dom::ContentChild::GetSingleton()->SendGetHyphDict(aURI, &handle)) { if (!dom::ContentChild::GetSingleton()->SendGetHyphDict(aURI, &handle,
&size)) {
return nullptr; return nullptr;
} }
if (!handle.IsValid()) { RefPtr<ipc::SharedMemory> shm = MakeRefPtr<ipc::SharedMemory>();
if (!shm->IsHandleValid(handle)) {
return nullptr; return nullptr;
} }
auto map = handle.Map(); if (!shm->SetHandle(std::move(handle), ipc::SharedMemory::RightsReadOnly)) {
if (!map) {
return nullptr; return nullptr;
} }
if (!map.Address()) { if (!shm->Map(size)) {
return nullptr; return nullptr;
} }
return map; char* addr = static_cast<char*>(shm->Memory());
if (!addr) {
return nullptr;
}
*aLength = size;
return shm;
} }
static ipc::ReadOnlySharedMemoryHandle CopyToShmem(const CompiledData* aData) { static RefPtr<ipc::SharedMemory> CopyToShmem(const CompiledData* aData) {
MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(XRE_IsParentProcess());
// The shm-related calls here are not expected to fail, but if they do, // The shm-related calls here are not expected to fail, but if they do,
// we'll just return null (as if the resource was unavailable) and proceed // we'll just return null (as if the resource was unavailable) and proceed
// without hyphenation. // without hyphenation.
uint32_t size = mapped_hyph_compiled_data_size(aData); uint32_t size = mapped_hyph_compiled_data_size(aData);
auto handle = ipc::shared_memory::CreateFreezable(size); RefPtr<ipc::SharedMemory> shm = MakeRefPtr<ipc::SharedMemory>();
if (!handle) { if (!shm->CreateFreezable(size)) {
return nullptr; return nullptr;
} }
auto map = std::move(handle).Map(); if (!shm->Map(size)) {
if (!map) {
return nullptr; return nullptr;
} }
char* buffer = map.DataAs<char>(); char* buffer = static_cast<char*>(shm->Memory());
if (!buffer) { if (!buffer) {
return nullptr; return nullptr;
} }
memcpy(buffer, mapped_hyph_compiled_data_ptr(aData), size); memcpy(buffer, mapped_hyph_compiled_data_ptr(aData), size);
auto [_, readOnlyHandle] = std::move(map).Freeze(); if (!shm->Freeze()) {
return std::move(readOnlyHandle); return nullptr;
}
return shm;
} }
static ipc::ReadOnlySharedMemoryHandle LoadFromURI(nsIURI* aURI, static RefPtr<ipc::SharedMemory> LoadFromURI(nsIURI* aURI, uint32_t* aLength,
bool aPrecompiled) { bool aPrecompiled) {
MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(XRE_IsParentProcess());
nsCOMPtr<nsIChannel> channel; nsCOMPtr<nsIChannel> channel;
if (NS_FAILED(NS_NewChannel( if (NS_FAILED(NS_NewChannel(
@@ -137,15 +145,14 @@ static ipc::ReadOnlySharedMemoryHandle LoadFromURI(nsIURI* aURI,
} }
if (aPrecompiled) { if (aPrecompiled) {
auto handle = ipc::shared_memory::CreateFreezable(available); RefPtr<ipc::SharedMemory> shm = MakeRefPtr<ipc::SharedMemory>();
if (!handle) { if (!shm->CreateFreezable(available)) {
return nullptr; return nullptr;
} }
auto map = std::move(handle).Map(); if (!shm->Map(available)) {
if (!map) {
return nullptr; return nullptr;
} }
char* buffer = map.DataAs<char>(); char* buffer = static_cast<char*>(shm->Memory());
if (!buffer) { if (!buffer) {
return nullptr; return nullptr;
} }
@@ -161,13 +168,12 @@ static ipc::ReadOnlySharedMemoryHandle LoadFromURI(nsIURI* aURI,
return nullptr; return nullptr;
} }
auto [_, readOnlyHandle] = std::move(map).Freeze(); if (!shm->Freeze()) {
if (!readOnlyHandle) {
return nullptr; return nullptr;
} }
return std::move(readOnlyHandle); *aLength = bytesRead;
return shm;
} }
// Read from the URI into a temporary buffer, compile it, then copy the // Read from the URI into a temporary buffer, compile it, then copy the
@@ -182,6 +188,7 @@ static ipc::ReadOnlySharedMemoryHandle LoadFromURI(nsIURI* aURI,
UniquePtr<const CompiledData> data(mapped_hyph_compile_buffer( UniquePtr<const CompiledData> data(mapped_hyph_compile_buffer(
reinterpret_cast<const uint8_t*>(buffer.get()), bytesRead, false)); reinterpret_cast<const uint8_t*>(buffer.get()), bytesRead, false));
if (data) { if (data) {
*aLength = mapped_hyph_compiled_data_size(data.get());
return CopyToShmem(data.get()); return CopyToShmem(data.get());
} }
@@ -189,7 +196,8 @@ static ipc::ReadOnlySharedMemoryHandle LoadFromURI(nsIURI* aURI,
} }
nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized) nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized)
: mDict(Span<const uint8_t>()), : mDict(static_cast<const void*>(nullptr)),
mDictSize(0),
mHyphenateCapitalized(aHyphenateCapitalized) { mHyphenateCapitalized(aHyphenateCapitalized) {
// Files with extension ".hyf" are expected to be precompiled mapped_hyph // Files with extension ".hyf" are expected to be precompiled mapped_hyph
// tables; we also support uncompiled ".dic" files, but they are more // tables; we also support uncompiled ".dic" files, but they are more
@@ -202,11 +210,13 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized)
// them a compiled version of the resource, so that we only pay the cost of // them a compiled version of the resource, so that we only pay the cost of
// compilation once per language per session. // compilation once per language per session.
if (!precompiled && !XRE_IsParentProcess()) { if (!precompiled && !XRE_IsParentProcess()) {
auto shm = GetHyphDictFromParent(aURI); uint32_t length;
RefPtr<ipc::SharedMemory> shm = GetHyphDictFromParent(aURI, &length);
if (shm) { if (shm) {
// We don't need to validate mDict because the parent process // We don't need to validate mDict because the parent process
// will have done so. // will have done so.
mDict.emplace<ipc::ReadOnlySharedMemoryMapping>(std::move(shm)); mDictSize = length;
mDict = AsVariant(std::move(shm));
} }
return; return;
} }
@@ -216,13 +226,15 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized)
// This gives us a raw pointer into the omnijar's data (if uncompressed); // This gives us a raw pointer into the omnijar's data (if uncompressed);
// we do not own it and must not attempt to free it! // we do not own it and must not attempt to free it!
uint32_t length; uint32_t length;
const uint8_t* ptr = GetItemPtrFromJarURI(jar, &length); const void* ptr = GetItemPtrFromJarURI(jar, &length);
if (ptr) { if (ptr) {
if (precompiled) { if (precompiled) {
// The data should be directly usable by mapped_hyph; validate that it // The data should be directly usable by mapped_hyph; validate that it
// looks correct, and save the pointer. // looks correct, and save the pointer.
if (mapped_hyph_is_valid_hyphenator(ptr, length)) { if (mapped_hyph_is_valid_hyphenator(static_cast<const uint8_t*>(ptr),
mDict.emplace<Span<const uint8_t>>(ptr, length); length)) {
mDictSize = length;
mDict = AsVariant(ptr);
return; return;
} }
} else { } else {
@@ -230,12 +242,13 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized)
// We then move it to shared memory so we can expose it to content // We then move it to shared memory so we can expose it to content
// processes. // processes.
MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(XRE_IsParentProcess());
UniquePtr<const CompiledData> data( UniquePtr<const CompiledData> data(mapped_hyph_compile_buffer(
mapped_hyph_compile_buffer(ptr, length, false)); static_cast<const uint8_t*>(ptr), length, false));
if (data) { if (data) {
auto shm = CopyToShmem(data.get()); RefPtr<ipc::SharedMemory> shm = CopyToShmem(data.get());
if (shm) { if (shm) {
mDict.emplace<ipc::ReadOnlySharedMemoryHandle>(std::move(shm)); mDictSize = mapped_hyph_compiled_data_size(data.get());
mDict = AsVariant(std::move(shm));
return; return;
} }
} }
@@ -246,17 +259,19 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized)
// buffer; if we're a child, send a request to the parent for the // buffer; if we're a child, send a request to the parent for the
// shared-memory copy (which it will load if not already available). // shared-memory copy (which it will load if not already available).
if (XRE_IsParentProcess()) { if (XRE_IsParentProcess()) {
auto shm = LoadFromURI(aURI, precompiled); RefPtr<ipc::SharedMemory> shm = LoadFromURI(aURI, &length, precompiled);
if (shm) { if (shm) {
mDict.emplace<ipc::ReadOnlySharedMemoryHandle>(std::move(shm)); mDictSize = length;
mDict = AsVariant(std::move(shm));
return; return;
} }
} else { } else {
auto shm = GetHyphDictFromParent(aURI); RefPtr<ipc::SharedMemory> shm = GetHyphDictFromParent(aURI, &length);
if (shm) { if (shm) {
// We don't need to validate mDict because the parent process // We don't need to validate mDict because the parent process
// will have done so. // will have done so.
mDict.emplace<ipc::ReadOnlySharedMemoryMapping>(std::move(shm)); mDictSize = length;
mDict = AsVariant(std::move(shm));
return; return;
} }
} }
@@ -297,9 +312,10 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized)
UniquePtr<const CompiledData> data( UniquePtr<const CompiledData> data(
mapped_hyph_compile_file(path.get(), false)); mapped_hyph_compile_file(path.get(), false));
if (data) { if (data) {
auto shm = CopyToShmem(data.get()); RefPtr<ipc::SharedMemory> shm = CopyToShmem(data.get());
if (shm) { if (shm) {
mDict.emplace<ipc::ReadOnlySharedMemoryHandle>(std::move(shm)); mDictSize = mapped_hyph_compiled_data_size(data.get());
mDict = AsVariant(std::move(shm));
return; return;
} }
} }
@@ -317,9 +333,8 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized)
bool nsHyphenator::IsValid() { bool nsHyphenator::IsValid() {
return mDict.match( return mDict.match(
[](Span<const uint8_t>& span) { return span.data() != nullptr; }, [](const void*& ptr) { return ptr != nullptr; },
[](ipc::ReadOnlySharedMemoryHandle& shm) { return shm.IsValid(); }, [](RefPtr<ipc::SharedMemory>& shm) { return shm != nullptr; },
[](ipc::ReadOnlySharedMemoryMapping& shm) { return shm.IsValid(); },
[](UniquePtr<const HyphDic>& hyph) { return hyph != nullptr; }); [](UniquePtr<const HyphDic>& hyph) { return hyph != nullptr; });
} }
@@ -426,22 +441,17 @@ void nsHyphenator::HyphenateWord(const nsAString& aString, uint32_t aStart,
AutoTArray<uint8_t, 200> hyphenValues; AutoTArray<uint8_t, 200> hyphenValues;
hyphenValues.SetLength(utf8.Length()); hyphenValues.SetLength(utf8.Length());
int32_t result = mDict.match( int32_t result = mDict.match(
[&](Span<const uint8_t>& span) { [&](const void*& ptr) {
return mapped_hyph_find_hyphen_values_raw( return mapped_hyph_find_hyphen_values_raw(
span.data(), span.size(), utf8.BeginReading(), utf8.Length(), static_cast<const uint8_t*>(ptr), mDictSize, utf8.BeginReading(),
hyphenValues.Elements(), hyphenValues.Length());
},
[&](ipc::ReadOnlySharedMemoryHandle& shm) {
// Only the parent process can have a handle stored. We should never
// get to this point with just a handle.
MOZ_ASSERT_UNREACHABLE("Unexpected HyphenateWord with only a handle");
return 0;
},
[&](ipc::ReadOnlySharedMemoryMapping& shm) {
return mapped_hyph_find_hyphen_values_raw(
shm.DataAs<uint8_t>(), shm.Size(), utf8.BeginReading(),
utf8.Length(), hyphenValues.Elements(), hyphenValues.Length()); utf8.Length(), hyphenValues.Elements(), hyphenValues.Length());
}, },
[&](RefPtr<ipc::SharedMemory>& shm) {
return mapped_hyph_find_hyphen_values_raw(
static_cast<const uint8_t*>(shm->Memory()), mDictSize,
utf8.BeginReading(), utf8.Length(), hyphenValues.Elements(),
hyphenValues.Length());
},
[&](UniquePtr<const HyphDic>& hyph) { [&](UniquePtr<const HyphDic>& hyph) {
return mapped_hyph_find_hyphen_values_dic( return mapped_hyph_find_hyphen_values_dic(
hyph.get(), utf8.BeginReading(), utf8.Length(), hyph.get(), utf8.BeginReading(), utf8.Length(),
@@ -476,11 +486,14 @@ void nsHyphenator::HyphenateWord(const nsAString& aString, uint32_t aStart,
} }
} }
ipc::ReadOnlySharedMemoryHandle nsHyphenator::CloneHandle() { void nsHyphenator::CloneHandle(ipc::SharedMemory::Handle* aOutHandle,
MOZ_ASSERT(XRE_IsParentProcess()); uint32_t* aOutSize) {
// If the resource is invalid, or if we fail to share it to the child
if (mDict.is<ipc::ReadOnlySharedMemoryHandle>()) { // process, we'll just bail out and continue without hyphenation; no need
return mDict.as<ipc::ReadOnlySharedMemoryHandle>().Clone(); // for this to be a fatal error.
if (!mDict.is<RefPtr<ipc::SharedMemory>>()) {
return;
} }
return nullptr; *aOutHandle = mDict.as<RefPtr<ipc::SharedMemory>>()->CloneHandle();
*aOutSize = mDictSize;
} }

View File

@@ -6,10 +6,8 @@
#ifndef nsHyphenator_h__ #ifndef nsHyphenator_h__
#define nsHyphenator_h__ #define nsHyphenator_h__
#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/ipc/SharedMemory.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/Span.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "mozilla/Variant.h" #include "mozilla/Variant.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
@@ -44,7 +42,8 @@ class nsHyphenator {
nsresult Hyphenate(const nsAString& aText, nsTArray<bool>& aHyphens); nsresult Hyphenate(const nsAString& aText, nsTArray<bool>& aHyphens);
mozilla::ipc::ReadOnlySharedMemoryHandle CloneHandle(); void CloneHandle(mozilla::ipc::SharedMemory::Handle* aOutHandle,
uint32_t* aOutSize);
private: private:
~nsHyphenator() = default; ~nsHyphenator() = default;
@@ -52,13 +51,12 @@ class nsHyphenator {
void HyphenateWord(const nsAString& aString, uint32_t aStart, uint32_t aLimit, void HyphenateWord(const nsAString& aString, uint32_t aStart, uint32_t aLimit,
nsTArray<bool>& aHyphens); nsTArray<bool>& aHyphens);
mozilla::Variant< mozilla::Variant<const void*, // raw pointer to uncompressed omnijar data
mozilla::Span<const uint8_t>, // raw pointer to uncompressed omnijar data RefPtr<mozilla::ipc::SharedMemory>, // shmem block
mozilla::ipc::ReadOnlySharedMemoryHandle, // shmem handle, in the parent mozilla::UniquePtr<const HyphDic> // loaded by mapped_hyph
mozilla::ipc::ReadOnlySharedMemoryMapping, // mapped shmem, in the child >
mozilla::UniquePtr<const HyphDic> // loaded by mapped_hyph
>
mDict; mDict;
uint32_t mDictSize; // size of mDict data (not used if type is HyphDic)
bool mHyphenateCapitalized; bool mHyphenateCapitalized;
}; };

View File

@@ -8,7 +8,7 @@
%{C++ %{C++
#include "mozilla/MemoryReporting.h" #include "mozilla/MemoryReporting.h"
#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/ipc/SharedMemory.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
@@ -27,7 +27,7 @@ class ContentParent;
%} %}
[ptr] native ContentParent(mozilla::dom::ContentParent); [ptr] native ContentParent(mozilla::dom::ContentParent);
native ReadOnlySharedMemoryHandle(mozilla::ipc::ReadOnlySharedMemoryHandle&&); [ref] native SharedMemoryHandle(mozilla::ipc::SharedMemoryHandle);
native MallocSizeOf(mozilla::MallocSizeOf); native MallocSizeOf(mozilla::MallocSizeOf);
[scriptable, builtinclass, uuid(D85A17C2-AA7C-11d2-9B8C-00805F8A16D9)] [scriptable, builtinclass, uuid(D85A17C2-AA7C-11d2-9B8C-00805F8A16D9)]
@@ -104,5 +104,6 @@ interface nsIStringBundleService : nsISupports
[notxpcom, nostdcall] void sendContentBundles(in ContentParent aContentParent); [notxpcom, nostdcall] void sendContentBundles(in ContentParent aContentParent);
[notxpcom, nostdcall] void registerContentBundle(in ACString aBundleURL, [notxpcom, nostdcall] void registerContentBundle(in ACString aBundleURL,
in ReadOnlySharedMemoryHandle aMapHandle); [const] in SharedMemoryHandle aMapHandle,
in size_t aMapSize);
}; };

View File

@@ -27,7 +27,6 @@
#include "nsSimpleEnumerator.h" #include "nsSimpleEnumerator.h"
#include "nsStringStream.h" #include "nsStringStream.h"
#include "mozilla/dom/txXSLTMsgsURL.h" #include "mozilla/dom/txXSLTMsgsURL.h"
#include "mozilla/ipc/SharedMemoryHandle.h"
#include "mozilla/BinarySearch.h" #include "mozilla/BinarySearch.h"
#include "mozilla/ClearOnShutdown.h" #include "mozilla/ClearOnShutdown.h"
#include "mozilla/ResultExtensions.h" #include "mozilla/ResultExtensions.h"
@@ -202,7 +201,8 @@ class SharedStringBundle final : public nsStringBundleBase {
* called in child processes, for bundles initially created in the parent * called in child processes, for bundles initially created in the parent
* process. * process.
*/ */
void SetMapFile(mozilla::ipc::ReadOnlySharedMemoryHandle&& aHandle); void SetMapFile(const mozilla::ipc::SharedMemoryHandle& aHandle,
size_t aSize);
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
NS_DECLARE_STATIC_IID_ACCESSOR(SHAREDSTRINGBUNDLE_IID) NS_DECLARE_STATIC_IID_ACCESSOR(SHAREDSTRINGBUNDLE_IID)
@@ -211,21 +211,21 @@ class SharedStringBundle final : public nsStringBundleBase {
/** /**
* Returns a copy of the file descriptor pointing to the shared memory * Returns a copy of the file descriptor pointing to the shared memory
* key-value store for this string bundle. This should only be called in the * key-values tore for this string bundle. This should only be called in the
* parent process, and may be used to send shared string bundles to child * parent process, and may be used to send shared string bundles to child
* processes. * processes.
*/ */
mozilla::ipc::ReadOnlySharedMemoryHandle CloneHandle() const { mozilla::ipc::SharedMemoryHandle CloneHandle() const {
MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(XRE_IsParentProcess());
if (mMapHandle.isSome()) { if (mMapHandle.isSome()) {
return mMapHandle.ref().Clone(); return mozilla::ipc::SharedMemory::CloneHandle(mMapHandle.ref());
} }
return mStringMap->CloneHandle(); return mStringMap->CloneHandle();
} }
size_t MapSize() const { size_t MapSize() const {
if (mMapHandle.isSome()) { if (mMapHandle.isSome()) {
return mMapHandle->Size(); return mMapSize;
} }
if (mStringMap) { if (mStringMap) {
return mStringMap->MapSize(); return mStringMap->MapSize();
@@ -241,6 +241,7 @@ class SharedStringBundle final : public nsStringBundleBase {
StringBundleDescriptor descriptor; StringBundleDescriptor descriptor;
descriptor.bundleURL() = BundleURL(); descriptor.bundleURL() = BundleURL();
descriptor.mapHandle() = CloneHandle(); descriptor.mapHandle() = CloneHandle();
descriptor.mapSize() = MapSize();
return descriptor; return descriptor;
} }
@@ -265,7 +266,8 @@ class SharedStringBundle final : public nsStringBundleBase {
private: private:
RefPtr<SharedStringMap> mStringMap; RefPtr<SharedStringMap> mStringMap;
Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle> mMapHandle; Maybe<mozilla::ipc::SharedMemoryHandle> mMapHandle;
size_t mMapSize;
}; };
NS_DEFINE_STATIC_IID_ACCESSOR(SharedStringBundle, SHAREDSTRINGBUNDLE_IID) NS_DEFINE_STATIC_IID_ACCESSOR(SharedStringBundle, SHAREDSTRINGBUNDLE_IID)
@@ -513,7 +515,8 @@ nsresult SharedStringBundle::LoadProperties() {
if (mStringMap) return NS_OK; if (mStringMap) return NS_OK;
if (mMapHandle.isSome()) { if (mMapHandle.isSome()) {
mStringMap = new SharedStringMap(mMapHandle.extract()); mStringMap = new SharedStringMap(mMapHandle.ref(), mMapSize);
mMapHandle.reset();
return NS_OK; return NS_OK;
} }
@@ -567,10 +570,11 @@ nsresult SharedStringBundle::LoadProperties() {
} }
void SharedStringBundle::SetMapFile( void SharedStringBundle::SetMapFile(
mozilla::ipc::ReadOnlySharedMemoryHandle&& aHandle) { const mozilla::ipc::SharedMemoryHandle& aHandle, size_t aSize) {
MOZ_ASSERT(XRE_IsContentProcess()); MOZ_ASSERT(XRE_IsContentProcess());
mStringMap = nullptr; mStringMap = nullptr;
mMapHandle.emplace(std::move(aHandle)); mMapHandle.emplace(mozilla::ipc::SharedMemory::CloneHandle(aHandle));
mMapSize = aSize;
} }
NS_IMETHODIMP NS_IMETHODIMP
@@ -818,7 +822,7 @@ void nsStringBundleService::SendContentBundles(ContentParent* aContentParent) {
void nsStringBundleService::RegisterContentBundle( void nsStringBundleService::RegisterContentBundle(
const nsACString& aBundleURL, const nsACString& aBundleURL,
mozilla::ipc::ReadOnlySharedMemoryHandle&& aMapHandle) { const mozilla::ipc::SharedMemoryHandle& aMapHandle, size_t aMapSize) {
RefPtr<StringBundleProxy> proxy; RefPtr<StringBundleProxy> proxy;
bundleCacheEntry_t* cacheEntry = mBundleMap.Get(aBundleURL); bundleCacheEntry_t* cacheEntry = mBundleMap.Get(aBundleURL);
@@ -836,7 +840,7 @@ void nsStringBundleService::RegisterContentBundle(
auto bundle = MakeBundleRefPtr<SharedStringBundle>( auto bundle = MakeBundleRefPtr<SharedStringBundle>(
PromiseFlatCString(aBundleURL).get()); PromiseFlatCString(aBundleURL).get());
bundle->SetMapFile(std::move(aMapHandle)); bundle->SetMapFile(aMapHandle, aMapSize);
if (proxy) { if (proxy) {
proxy->Retarget(bundle); proxy->Retarget(bundle);

View File

@@ -73,7 +73,7 @@ MessageBufferReader::MessageBufferReader(MessageReader* reader,
return; return;
} }
if (shmem_ok) { if (shmem_ok) {
mozilla::ipc::shared_memory::MutableHandle handle; mozilla::ipc::shared_memory::Handle handle;
if (!IPC::ReadParam(reader, &handle)) { if (!IPC::ReadParam(reader, &handle)) {
reader->FatalError("failed to read shared memory handle"); reader->FatalError("failed to read shared memory handle");
return; return;

View File

@@ -18,7 +18,6 @@
#include "base/pickle.h" #include "base/pickle.h"
#include "chrome/common/ipc_message.h" #include "chrome/common/ipc_message.h"
#include "mozilla/CheckedInt.h" #include "mozilla/CheckedInt.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#if defined(XP_WIN) #if defined(XP_WIN)
# include <windows.h> # include <windows.h>
@@ -33,6 +32,7 @@ namespace mozilla::ipc {
class IProtocol; class IProtocol;
template <typename P> template <typename P>
struct IPDLParamTraits; struct IPDLParamTraits;
class SharedMemory;
namespace shared_memory { namespace shared_memory {
class Cursor; class Cursor;
} }

View File

@@ -7,15 +7,16 @@
#include "mozilla/ipc/BigBuffer.h" #include "mozilla/ipc/BigBuffer.h"
#include "chrome/common/ipc_message_utils.h" #include "chrome/common/ipc_message_utils.h"
#include "mozilla/ipc/SharedMemory.h"
#include "nsDebug.h" #include "nsDebug.h"
namespace mozilla::ipc { namespace mozilla::ipc {
BigBuffer::BigBuffer(Adopt, SharedMemoryMappingWithHandle&& aSharedMemory, BigBuffer::BigBuffer(Adopt, SharedMemory* aSharedMemory, size_t aSize)
size_t aSize) : mSize(aSize), mData(AsVariant(RefPtr{aSharedMemory})) {
: mSize(aSize), mData(AsVariant(std::move(aSharedMemory))) { MOZ_RELEASE_ASSERT(aSharedMemory && aSharedMemory->Memory(),
MOZ_RELEASE_ASSERT(mData.as<1>(), "shared memory must be valid"); "shared memory must be non-null and mapped");
MOZ_RELEASE_ASSERT(mSize <= mData.as<1>().Size(), MOZ_RELEASE_ASSERT(mSize <= aSharedMemory->Size(),
"shared memory region isn't large enough"); "shared memory region isn't large enough");
} }
@@ -23,11 +24,13 @@ BigBuffer::BigBuffer(Adopt, uint8_t* aData, size_t aSize)
: mSize(aSize), mData(AsVariant(UniqueFreePtr<uint8_t[]>{aData})) {} : mSize(aSize), mData(AsVariant(UniqueFreePtr<uint8_t[]>{aData})) {}
uint8_t* BigBuffer::Data() { uint8_t* BigBuffer::Data() {
return mData.is<0>() ? mData.as<0>().get() : mData.as<1>().DataAs<uint8_t>(); return mData.is<0>() ? mData.as<0>().get()
: reinterpret_cast<uint8_t*>(mData.as<1>()->Memory());
} }
const uint8_t* BigBuffer::Data() const { const uint8_t* BigBuffer::Data() const {
return mData.is<0>() ? mData.as<0>().get() return mData.is<0>()
: mData.as<1>().DataAs<const uint8_t>(); ? mData.as<0>().get()
: reinterpret_cast<const uint8_t*>(mData.as<1>()->Memory());
} }
auto BigBuffer::TryAllocBuffer(size_t aSize) -> Maybe<Storage> { auto BigBuffer::TryAllocBuffer(size_t aSize) -> Maybe<Storage> {
@@ -38,12 +41,12 @@ auto BigBuffer::TryAllocBuffer(size_t aSize) -> Maybe<Storage> {
return Some(AsVariant(std::move(mem))); return Some(AsVariant(std::move(mem)));
} }
size_t capacity = shared_memory::PageAlignedSize(aSize); RefPtr<SharedMemory> shmem = new SharedMemory();
auto mapping = shared_memory::Create(capacity).MapWithHandle(); size_t capacity = SharedMemory::PageAlignedSize(aSize);
if (!mapping) { if (!shmem->Create(capacity) || !shmem->Map(capacity)) {
return {}; return {};
} }
return Some(AsVariant(std::move(mapping))); return Some(AsVariant(shmem));
} }
} // namespace mozilla::ipc } // namespace mozilla::ipc
@@ -59,11 +62,8 @@ void IPC::ParamTraits<mozilla::ipc::BigBuffer>::Write(MessageWriter* aWriter,
WriteParam(aWriter, isShmem); WriteParam(aWriter, isShmem);
if (isShmem) { if (isShmem) {
auto handle = data.as<1>().Handle().Clone(); if (!data.as<1>()->WriteHandle(aWriter)) {
if (!handle) {
aWriter->FatalError("Failed to write data shmem"); aWriter->FatalError("Failed to write data shmem");
} else {
WriteParam(aWriter, std::move(handle));
} }
} else { } else {
aWriter->WriteBytes(data.as<0>().get(), size); aWriter->WriteBytes(data.as<0>().get(), size);
@@ -81,18 +81,13 @@ bool IPC::ParamTraits<mozilla::ipc::BigBuffer>::Read(MessageReader* aReader,
} }
if (isShmem) { if (isShmem) {
MutableSharedMemoryHandle handle; RefPtr<SharedMemory> shmem = new SharedMemory();
size_t expected_size = shared_memory::PageAlignedSize(size); size_t capacity = SharedMemory::PageAlignedSize(size);
if (!ReadParam(aReader, &handle) || !handle) { if (!shmem->ReadHandle(aReader) || !shmem->Map(capacity)) {
aReader->FatalError("Failed to read data shmem"); aReader->FatalError("Failed to read data shmem");
return false; return false;
} }
auto mapping = std::move(handle).MapWithHandle(); *aResult = BigBuffer(BigBuffer::Adopt{}, shmem, size);
if (!mapping || mapping.Size() != expected_size) {
aReader->FatalError("Failed to map data shmem");
return false;
}
*aResult = BigBuffer(BigBuffer::Adopt{}, std::move(mapping), size);
return true; return true;
} }

View File

@@ -9,10 +9,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <inttypes.h> #include <inttypes.h>
#include "mozilla/Maybe.h"
#include "mozilla/Span.h" #include "mozilla/Span.h"
#include "mozilla/Variant.h" #include "mozilla/Variant.h"
#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/ipc/SharedMemory.h"
namespace mozilla::ipc { namespace mozilla::ipc {
@@ -63,8 +62,8 @@ class BigBuffer {
// Create a new BigBuffer from an existing shared memory region, taking // Create a new BigBuffer from an existing shared memory region, taking
// ownership of that shared memory region. The shared memory region must be // ownership of that shared memory region. The shared memory region must be
// valid and large enough to fit aSize bytes. // non-null, mapped, and large enough to fit aSize bytes.
BigBuffer(Adopt, SharedMemoryMappingWithHandle&& aSharedMemory, size_t aSize); BigBuffer(Adopt, SharedMemory* aSharedMemory, size_t aSize);
// Create a new BigBuffer from an existing memory buffer, taking ownership of // Create a new BigBuffer from an existing memory buffer, taking ownership of
// that memory region. The region will be freed using `free()` when it is no // that memory region. The region will be freed using `free()` when it is no
@@ -88,16 +87,14 @@ class BigBuffer {
// If the BigBuffer is backed by shared memory, returns a pointer to the // If the BigBuffer is backed by shared memory, returns a pointer to the
// backing SharedMemory region. // backing SharedMemory region.
// This is only meant to be used in tests. SharedMemory* GetSharedMemory() const {
const SharedMemoryMappingWithHandle* GetSharedMemory() const { return mData.is<1>() ? mData.as<1>().get() : nullptr;
return mData.is<1>() ? &mData.as<1>() : nullptr;
} }
private: private:
friend struct IPC::ParamTraits<mozilla::ipc::BigBuffer>; friend struct IPC::ParamTraits<mozilla::ipc::BigBuffer>;
using Storage = using Storage = Variant<UniqueFreePtr<uint8_t[]>, RefPtr<SharedMemory>>;
Variant<UniqueFreePtr<uint8_t[]>, SharedMemoryMappingWithHandle>;
// Empty storage which holds no data. // Empty storage which holds no data.
static Storage NoData() { return AsVariant(UniqueFreePtr<uint8_t[]>{}); } static Storage NoData() { return AsVariant(UniqueFreePtr<uint8_t[]>{}); }

View File

@@ -15,7 +15,7 @@
#endif #endif
#if !defined(XP_WIN) && !defined(XP_NETBSD) && !defined(XP_OPENBSD) #if !defined(XP_WIN) && !defined(XP_NETBSD) && !defined(XP_OPENBSD)
# include <pthread.h> # include <pthread.h>
# include "mozilla/ipc/SharedMemoryMapping.h" # include "mozilla/ipc/SharedMemory.h"
# include "mozilla/Atomics.h" # include "mozilla/Atomics.h"
#endif #endif
@@ -39,7 +39,7 @@ namespace mozilla {
#if defined(XP_WIN) #if defined(XP_WIN)
typedef mozilla::UniqueFileHandle CrossProcessMutexHandle; typedef mozilla::UniqueFileHandle CrossProcessMutexHandle;
#elif !defined(XP_NETBSD) && !defined(XP_OPENBSD) #elif !defined(XP_NETBSD) && !defined(XP_OPENBSD)
typedef mozilla::ipc::MutableSharedMemoryHandle CrossProcessMutexHandle; typedef mozilla::ipc::SharedMemory::Handle CrossProcessMutexHandle;
#else #else
// Stub for other platforms. We can't use uintptr_t here since different // Stub for other platforms. We can't use uintptr_t here since different
// processes could disagree on its size. // processes could disagree on its size.
@@ -104,7 +104,7 @@ class CrossProcessMutex {
#if defined(XP_WIN) #if defined(XP_WIN)
HANDLE mMutex; HANDLE mMutex;
#elif !defined(XP_NETBSD) && !defined(XP_OPENBSD) #elif !defined(XP_NETBSD) && !defined(XP_OPENBSD)
mozilla::ipc::SharedMemoryMappingWithHandle mSharedBuffer; RefPtr<mozilla::ipc::SharedMemory> mSharedBuffer;
pthread_mutex_t* mMutex; pthread_mutex_t* mMutex;
mozilla::Atomic<int32_t>* mCount; mozilla::Atomic<int32_t>* mCount;
#endif #endif

View File

@@ -6,7 +6,6 @@
#include "CrossProcessMutex.h" #include "CrossProcessMutex.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
#include "mozilla/ipc/SharedMemoryHandle.h"
#include "nsDebug.h" #include "nsDebug.h"
#include "nsISupportsImpl.h" #include "nsISupportsImpl.h"
@@ -44,12 +43,16 @@ CrossProcessMutex::CrossProcessMutex(const char*)
// they specifically are not on Linux. // they specifically are not on Linux.
MOZ_RELEASE_ASSERT(false); MOZ_RELEASE_ASSERT(false);
#endif #endif
mSharedBuffer = ipc::shared_memory::Create(sizeof(MutexData)).MapWithHandle(); mSharedBuffer = new ipc::SharedMemory;
if (!mSharedBuffer) { if (!mSharedBuffer->Create(sizeof(MutexData))) {
MOZ_CRASH(); MOZ_CRASH();
} }
MutexData* data = mSharedBuffer.DataAs<MutexData>(); if (!mSharedBuffer->Map(sizeof(MutexData))) {
MOZ_CRASH();
}
MutexData* data = static_cast<MutexData*>(mSharedBuffer->Memory());
if (!data) { if (!data) {
MOZ_CRASH(); MOZ_CRASH();
@@ -66,12 +69,22 @@ CrossProcessMutex::CrossProcessMutex(const char*)
CrossProcessMutex::CrossProcessMutex(CrossProcessMutexHandle aHandle) CrossProcessMutex::CrossProcessMutex(CrossProcessMutexHandle aHandle)
: mMutex(nullptr), mCount(nullptr) { : mMutex(nullptr), mCount(nullptr) {
mSharedBuffer = std::move(aHandle).MapWithHandle(); mSharedBuffer = new ipc::SharedMemory;
if (!mSharedBuffer) {
if (!mSharedBuffer->IsHandleValid(aHandle)) {
MOZ_CRASH(); MOZ_CRASH();
} }
MutexData* data = mSharedBuffer.DataAs<MutexData>(); if (!mSharedBuffer->SetHandle(std::move(aHandle),
ipc::SharedMemory::RightsReadWrite)) {
MOZ_CRASH();
}
if (!mSharedBuffer->Map(sizeof(MutexData))) {
MOZ_CRASH();
}
MutexData* data = static_cast<MutexData*>(mSharedBuffer->Memory());
if (!data) { if (!data) {
MOZ_CRASH(); MOZ_CRASH();
@@ -112,14 +125,16 @@ void CrossProcessMutex::Unlock() {
} }
CrossProcessMutexHandle CrossProcessMutex::CloneHandle() { CrossProcessMutexHandle CrossProcessMutex::CloneHandle() {
CrossProcessMutexHandle result = ipc::SharedMemory::NULLHandle();
if (mSharedBuffer) { if (mSharedBuffer) {
auto handle = mSharedBuffer.Handle().Clone(); result = mSharedBuffer->CloneHandle();
if (!handle) { if (!result) {
MOZ_CRASH(); MOZ_CRASH();
} }
return handle;
} }
return nullptr;
return result;
} }
} // namespace mozilla } // namespace mozilla

View File

@@ -16,7 +16,7 @@
#else #else
# include <pthread.h> # include <pthread.h>
# include <semaphore.h> # include <semaphore.h>
# include "mozilla/ipc/SharedMemoryMapping.h" # include "mozilla/ipc/SharedMemory.h"
# include "mozilla/Atomics.h" # include "mozilla/Atomics.h"
#endif #endif
@@ -41,7 +41,13 @@ typedef mozilla::UniqueFileHandle CrossProcessSemaphoreHandle;
#elif defined(XP_DARWIN) #elif defined(XP_DARWIN)
typedef mozilla::UniqueMachSendRight CrossProcessSemaphoreHandle; typedef mozilla::UniqueMachSendRight CrossProcessSemaphoreHandle;
#else #else
typedef mozilla::ipc::MutableSharedMemoryHandle CrossProcessSemaphoreHandle; typedef mozilla::ipc::SharedMemory::Handle CrossProcessSemaphoreHandle;
template <>
inline bool IsHandleValid<CrossProcessSemaphoreHandle>(
const CrossProcessSemaphoreHandle& handle) {
return !(handle == mozilla::ipc::SharedMemory::NULLHandle());
}
#endif #endif
class CrossProcessSemaphore { class CrossProcessSemaphore {
@@ -102,8 +108,7 @@ class CrossProcessSemaphore {
CrossProcessSemaphoreHandle mSemaphore; CrossProcessSemaphoreHandle mSemaphore;
#else #else
mozilla::ipc::MutableSharedMemoryHandle mHandle; RefPtr<mozilla::ipc::SharedMemory> mSharedBuffer;
mozilla::ipc::SharedMemoryMapping mSharedBuffer;
sem_t* mSemaphore; sem_t* mSemaphore;
mozilla::Atomic<int32_t>* mRefCount; mozilla::Atomic<int32_t>* mRefCount;
#endif #endif

View File

@@ -28,17 +28,16 @@ namespace mozilla {
/* static */ /* static */
CrossProcessSemaphore* CrossProcessSemaphore::Create(const char*, CrossProcessSemaphore* CrossProcessSemaphore::Create(const char*,
uint32_t aInitialValue) { uint32_t aInitialValue) {
auto handle = ipc::shared_memory::Create(sizeof(SemaphoreData)); RefPtr<ipc::SharedMemory> sharedBuffer = new ipc::SharedMemory;
if (!handle) { if (!sharedBuffer->Create(sizeof(SemaphoreData))) {
return nullptr; return nullptr;
} }
auto mapping = handle.Map(); if (!sharedBuffer->Map(sizeof(SemaphoreData))) {
if (!mapping) {
return nullptr; return nullptr;
} }
SemaphoreData* data = mapping.DataAs<SemaphoreData>(); SemaphoreData* data = static_cast<SemaphoreData*>(sharedBuffer->Memory());
if (!data) { if (!data) {
return nullptr; return nullptr;
@@ -49,8 +48,7 @@ CrossProcessSemaphore* CrossProcessSemaphore::Create(const char*,
} }
CrossProcessSemaphore* sem = new CrossProcessSemaphore; CrossProcessSemaphore* sem = new CrossProcessSemaphore;
sem->mHandle = std::move(handle); sem->mSharedBuffer = sharedBuffer;
sem->mSharedBuffer = std::move(mapping);
sem->mSemaphore = &data->mSemaphore; sem->mSemaphore = &data->mSemaphore;
sem->mRefCount = &data->mRefCount; sem->mRefCount = &data->mRefCount;
*sem->mRefCount = 1; *sem->mRefCount = 1;
@@ -63,14 +61,24 @@ CrossProcessSemaphore* CrossProcessSemaphore::Create(const char*,
/* static */ /* static */
CrossProcessSemaphore* CrossProcessSemaphore::Create( CrossProcessSemaphore* CrossProcessSemaphore::Create(
CrossProcessSemaphoreHandle aHandle) { CrossProcessSemaphoreHandle aHandle) {
auto mapping = aHandle.Map(); RefPtr<ipc::SharedMemory> sharedBuffer = new ipc::SharedMemory;
if (!mapping) {
if (!sharedBuffer->IsHandleValid(aHandle)) {
return nullptr; return nullptr;
} }
aHandle = nullptr; if (!sharedBuffer->SetHandle(std::move(aHandle),
ipc::SharedMemory::RightsReadWrite)) {
return nullptr;
}
SemaphoreData* data = mapping.DataAs<SemaphoreData>(); if (!sharedBuffer->Map(sizeof(SemaphoreData))) {
return nullptr;
}
sharedBuffer->CloseHandle();
SemaphoreData* data = static_cast<SemaphoreData*>(sharedBuffer->Memory());
if (!data) { if (!data) {
return nullptr; return nullptr;
@@ -87,7 +95,7 @@ CrossProcessSemaphore* CrossProcessSemaphore::Create(
} }
CrossProcessSemaphore* sem = new CrossProcessSemaphore; CrossProcessSemaphore* sem = new CrossProcessSemaphore;
sem->mSharedBuffer = std::move(mapping); sem->mSharedBuffer = sharedBuffer;
sem->mSemaphore = &data->mSemaphore; sem->mSemaphore = &data->mSemaphore;
sem->mRefCount = &data->mRefCount; sem->mRefCount = &data->mRefCount;
return sem; return sem;
@@ -139,16 +147,18 @@ void CrossProcessSemaphore::Signal() {
} }
CrossProcessSemaphoreHandle CrossProcessSemaphore::CloneHandle() { CrossProcessSemaphoreHandle CrossProcessSemaphore::CloneHandle() {
CrossProcessSemaphoreHandle result = ipc::SharedMemory::NULLHandle();
if (mSharedBuffer) { if (mSharedBuffer) {
auto handle = mHandle.Clone(); result = mSharedBuffer->CloneHandle();
if (!handle) { if (!result) {
MOZ_CRASH(); MOZ_CRASH();
} }
return handle;
} }
return nullptr;
return result;
} }
void CrossProcessSemaphore::CloseHandle() { mHandle = nullptr; } void CrossProcessSemaphore::CloseHandle() { mSharedBuffer->CloseHandle(); }
} // namespace mozilla } // namespace mozilla

View File

@@ -71,10 +71,9 @@ static void DoNotifyOnUnlock(DataPipeAutoLock& aLock,
class DataPipeLink : public NodeController::PortObserver { class DataPipeLink : public NodeController::PortObserver {
public: public:
DataPipeLink(bool aReceiverSide, std::shared_ptr<Mutex> aMutex, DataPipeLink(bool aReceiverSide, std::shared_ptr<Mutex> aMutex,
ScopedPort aPort, MutableSharedMemoryHandle&& aShmemHandle, ScopedPort aPort, SharedMemory::Handle aShmemHandle,
const std::shared_ptr<SharedMemoryMapping> aShmem, SharedMemory* aShmem, uint32_t aCapacity, nsresult aPeerStatus,
uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset, uint32_t aOffset, uint32_t aAvailable)
uint32_t aAvailable)
: mMutex(std::move(aMutex)), : mMutex(std::move(aMutex)),
mPort(std::move(aPort)), mPort(std::move(aPort)),
mShmemHandle(std::move(aShmemHandle)), mShmemHandle(std::move(aShmemHandle)),
@@ -166,8 +165,8 @@ class DataPipeLink : public NodeController::PortObserver {
std::shared_ptr<Mutex> mMutex; std::shared_ptr<Mutex> mMutex;
ScopedPort mPort MOZ_GUARDED_BY(*mMutex); ScopedPort mPort MOZ_GUARDED_BY(*mMutex);
MutableSharedMemoryHandle mShmemHandle MOZ_GUARDED_BY(*mMutex); SharedMemory::Handle mShmemHandle MOZ_GUARDED_BY(*mMutex);
const std::shared_ptr<SharedMemoryMapping> mShmem; const RefPtr<SharedMemory> mShmem;
const uint32_t mCapacity; const uint32_t mCapacity;
const bool mReceiverSide; const bool mReceiverSide;
@@ -246,10 +245,10 @@ DataPipeBase::DataPipeBase(bool aReceiverSide, nsresult aError)
mStatus(NS_SUCCEEDED(aError) ? NS_BASE_STREAM_CLOSED : aError) {} mStatus(NS_SUCCEEDED(aError) ? NS_BASE_STREAM_CLOSED : aError) {}
DataPipeBase::DataPipeBase(bool aReceiverSide, ScopedPort aPort, DataPipeBase::DataPipeBase(bool aReceiverSide, ScopedPort aPort,
MutableSharedMemoryHandle&& aShmemHandle, SharedMemory::Handle aShmemHandle,
const std::shared_ptr<SharedMemoryMapping>& aShmem, SharedMemory* aShmem, uint32_t aCapacity,
uint32_t aCapacity, nsresult aPeerStatus, nsresult aPeerStatus, uint32_t aOffset,
uint32_t aOffset, uint32_t aAvailable) uint32_t aAvailable)
: mMutex(std::make_shared<Mutex>(aReceiverSide ? "DataPipeReceiver" : mMutex(std::make_shared<Mutex>(aReceiverSide ? "DataPipeReceiver"
: "DataPipeSender")), : "DataPipeSender")),
mStatus(NS_OK), mStatus(NS_OK),
@@ -319,7 +318,7 @@ nsresult DataPipeBase::ProcessSegmentsInternal(
// Extract an iterator over the next contiguous region of the shared memory // Extract an iterator over the next contiguous region of the shared memory
// buffer which will be used . // buffer which will be used .
char* start = link->mShmem->DataAs<char>() + link->mOffset; char* start = static_cast<char*>(link->mShmem->Memory()) + link->mOffset;
char* iter = start; char* iter = start;
char* end = start + std::min({aCount - *aProcessedCount, link->mAvailable, char* end = start + std::min({aCount - *aProcessedCount, link->mAvailable,
link->mCapacity - link->mOffset}); link->mCapacity - link->mOffset});
@@ -481,17 +480,21 @@ bool DataPipeRead(IPC::MessageReader* aReader, RefPtr<T>* aResult) {
aReader->FatalError("failed to read DataPipe port"); aReader->FatalError("failed to read DataPipe port");
return false; return false;
} }
MutableSharedMemoryHandle shmemHandle; SharedMemory::Handle shmemHandle;
if (!ReadParam(aReader, &shmemHandle)) { if (!ReadParam(aReader, &shmemHandle)) {
aReader->FatalError("failed to read DataPipe shmem"); aReader->FatalError("failed to read DataPipe shmem");
return false; return false;
} }
// Due to the awkward shared memory API provided by SharedMemory, we need to
if (!shmemHandle) { // transfer ownership into the `shmem` here, then steal it back later in the
aReader->FatalError("failed to create DataPipe shmem handle"); // function. Bug 1797039 tracks potential changes to the RawShmem API which
// could improve this situation.
RefPtr shmem = new SharedMemory();
if (!shmem->SetHandle(std::move(shmemHandle),
SharedMemory::RightsReadWrite)) {
aReader->FatalError("failed to create DataPipe shmem from handle");
return false; return false;
} }
uint32_t capacity = 0; uint32_t capacity = 0;
nsresult peerStatus = NS_OK; nsresult peerStatus = NS_OK;
uint32_t offset = 0; uint32_t offset = 0;
@@ -505,14 +508,12 @@ bool DataPipeRead(IPC::MessageReader* aReader, RefPtr<T>* aResult) {
aReader->FatalError("received DataPipe state values are inconsistent"); aReader->FatalError("received DataPipe state values are inconsistent");
return false; return false;
} }
auto mapping = std::make_shared<SharedMemoryMapping>(shmemHandle.Map()); if (!shmem->Map(SharedMemory::PageAlignedSize(capacity))) {
if (!*mapping ||
mapping->Size() != shared_memory::PageAlignedSize(capacity)) {
aReader->FatalError("failed to map DataPipe shared memory region"); aReader->FatalError("failed to map DataPipe shared memory region");
return false; return false;
} }
*aResult = new T(std::move(port), std::move(shmemHandle), mapping, capacity, *aResult = new T(std::move(port), shmem->TakeHandle(), shmem, capacity,
peerStatus, offset, available); peerStatus, offset, available);
if (MOZ_LOG_TEST(gDataPipeLog, LogLevel::Debug)) { if (MOZ_LOG_TEST(gDataPipeLog, LogLevel::Debug)) {
DataPipeAutoLock lock(*(*aResult)->mMutex); DataPipeAutoLock lock(*(*aResult)->mMutex);
@@ -587,7 +588,7 @@ NS_IMETHODIMP DataPipeSender::AsyncWait(nsIOutputStreamCallback* aCallback,
nsIEventTarget* aTarget) { nsIEventTarget* aTarget) {
AsyncWaitInternal( AsyncWaitInternal(
aCallback ? NS_NewCancelableRunnableFunction( aCallback ? NS_NewCancelableRunnableFunction(
"DataPipeSender::AsyncWait", "DataPipeReceiver::AsyncWait",
[self = RefPtr{this}, callback = RefPtr{aCallback}] { [self = RefPtr{this}, callback = RefPtr{aCallback}] {
MOZ_LOG(gDataPipeLog, LogLevel::Debug, MOZ_LOG(gDataPipeLog, LogLevel::Debug,
("Calling OnOutputStreamReady(%p, %p)", ("Calling OnOutputStreamReady(%p, %p)",
@@ -716,31 +717,27 @@ nsresult NewDataPipe(uint32_t aCapacity, DataPipeSender** aSender,
auto [senderPort, receiverPort] = controller->CreatePortPair(); auto [senderPort, receiverPort] = controller->CreatePortPair();
// Create and allocate the shared memory region. // Create and allocate the shared memory region.
size_t alignedCapacity = shared_memory::PageAlignedSize(aCapacity); auto shmem = MakeRefPtr<SharedMemory>();
auto handle = shared_memory::Create(alignedCapacity); size_t alignedCapacity = SharedMemory::PageAlignedSize(aCapacity);
if (!handle) { if (!shmem->Create(alignedCapacity) || !shmem->Map(alignedCapacity)) {
return NS_ERROR_OUT_OF_MEMORY;
}
auto mapping = std::make_shared<SharedMemoryMapping>(handle.Map());
if (!*mapping) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
// We'll first clone then take the handle from the region so that the sender & // We'll first clone then take the handle from the region so that the sender &
// receiver each have a handle. This avoids the need to duplicate the handle // receiver each have a handle. This avoids the need to duplicate the handle
// when serializing, when errors are non-recoverable. // when serializing, when errors are non-recoverable.
auto senderShmemHandle = handle.Clone(); SharedMemory::Handle senderShmemHandle = shmem->CloneHandle();
auto receiverShmemHandle = std::move(handle); SharedMemory::Handle receiverShmemHandle = shmem->TakeHandle();
if (!senderShmemHandle || !receiverShmemHandle) { if (!senderShmemHandle || !receiverShmemHandle) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
RefPtr sender = RefPtr sender =
new DataPipeSender(std::move(senderPort), std::move(senderShmemHandle), new DataPipeSender(std::move(senderPort), std::move(senderShmemHandle),
mapping, aCapacity, NS_OK, 0, aCapacity); shmem, aCapacity, NS_OK, 0, aCapacity);
RefPtr receiver = new DataPipeReceiver(std::move(receiverPort), RefPtr receiver = new DataPipeReceiver(std::move(receiverPort),
std::move(receiverShmemHandle), std::move(receiverShmemHandle), shmem,
mapping, aCapacity, NS_OK, 0, 0); aCapacity, NS_OK, 0, 0);
sender.forget(aSender); sender.forget(aSender);
receiver.forget(aReceiver); receiver.forget(aReceiver);
return NS_OK; return NS_OK;

View File

@@ -7,14 +7,12 @@
#ifndef mozilla_ipc_DataPipe_h #ifndef mozilla_ipc_DataPipe_h
#define mozilla_ipc_DataPipe_h #define mozilla_ipc_DataPipe_h
#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/ipc/SharedMemory.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "mozilla/ipc/NodeController.h" #include "mozilla/ipc/NodeController.h"
#include "nsIAsyncInputStream.h" #include "nsIAsyncInputStream.h"
#include "nsIAsyncOutputStream.h" #include "nsIAsyncOutputStream.h"
#include "nsIIPCSerializableInputStream.h" #include "nsIIPCSerializableInputStream.h"
#include "nsISupports.h" #include "nsISupports.h"
#include <memory>
namespace mozilla { namespace mozilla {
namespace ipc { namespace ipc {
@@ -32,8 +30,7 @@ class DataPipeBase {
protected: protected:
explicit DataPipeBase(bool aReceiverSide, nsresult aError); explicit DataPipeBase(bool aReceiverSide, nsresult aError);
DataPipeBase(bool aReceiverSide, ScopedPort aPort, DataPipeBase(bool aReceiverSide, ScopedPort aPort,
MutableSharedMemoryHandle&& aShmemHandle, SharedMemory::Handle aShmemHandle, SharedMemory* aShmem,
const std::shared_ptr<SharedMemoryMapping>& aShmem,
uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset, uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset,
uint32_t aAvailable); uint32_t aAvailable);
@@ -102,10 +99,9 @@ class DataPipeSender final : public nsIAsyncOutputStream,
explicit DataPipeSender(nsresult aError) explicit DataPipeSender(nsresult aError)
: data_pipe_detail::DataPipeBase(/* aReceiverSide */ false, aError) {} : data_pipe_detail::DataPipeBase(/* aReceiverSide */ false, aError) {}
DataPipeSender(ScopedPort aPort, MutableSharedMemoryHandle&& aShmemHandle, DataPipeSender(ScopedPort aPort, SharedMemory::Handle aShmemHandle,
const std::shared_ptr<SharedMemoryMapping>& aShmem, SharedMemory* aShmem, uint32_t aCapacity, nsresult aPeerStatus,
uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset, uint32_t aOffset, uint32_t aAvailable)
uint32_t aAvailable)
: data_pipe_detail::DataPipeBase( : data_pipe_detail::DataPipeBase(
/* aReceiverSide */ false, std::move(aPort), /* aReceiverSide */ false, std::move(aPort),
std::move(aShmemHandle), aShmem, aCapacity, aPeerStatus, aOffset, std::move(aShmemHandle), aShmem, aCapacity, aPeerStatus, aOffset,
@@ -139,10 +135,9 @@ class DataPipeReceiver final : public nsIAsyncInputStream,
explicit DataPipeReceiver(nsresult aError) explicit DataPipeReceiver(nsresult aError)
: data_pipe_detail::DataPipeBase(/* aReceiverSide */ true, aError) {} : data_pipe_detail::DataPipeBase(/* aReceiverSide */ true, aError) {}
DataPipeReceiver(ScopedPort aPort, MutableSharedMemoryHandle&& aShmemHandle, DataPipeReceiver(ScopedPort aPort, SharedMemory::Handle aShmemHandle,
const std::shared_ptr<SharedMemoryMapping>& aShmem, SharedMemory* aShmem, uint32_t aCapacity,
uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset, nsresult aPeerStatus, uint32_t aOffset, uint32_t aAvailable)
uint32_t aAvailable)
: data_pipe_detail::DataPipeBase( : data_pipe_detail::DataPipeBase(
/* aReceiverSide */ true, std::move(aPort), std::move(aShmemHandle), /* aReceiverSide */ true, std::move(aPort), std::move(aShmemHandle),
aShmem, aCapacity, aPeerStatus, aOffset, aAvailable) {} aShmem, aCapacity, aPeerStatus, aOffset, aAvailable) {}

View File

@@ -15,6 +15,7 @@
#include "chrome/common/process_watcher.h" #include "chrome/common/process_watcher.h"
#ifdef XP_DARWIN #ifdef XP_DARWIN
# include <mach/mach_traps.h> # include <mach/mach_traps.h>
# include "SharedMemory.h"
# include "base/rand_util.h" # include "base/rand_util.h"
# include "chrome/common/mach_ipc_mac.h" # include "chrome/common/mach_ipc_mac.h"
# include "mozilla/StaticPrefs_media.h" # include "mozilla/StaticPrefs_media.h"

View File

@@ -29,16 +29,18 @@ void IdleSchedulerChild::Init(IdlePeriodState* aIdlePeriodState) {
mIdlePeriodState = aIdlePeriodState; mIdlePeriodState = aIdlePeriodState;
RefPtr<IdleSchedulerChild> scheduler = this; RefPtr<IdleSchedulerChild> scheduler = this;
auto resolve = [&](std::tuple<mozilla::Maybe<MutableSharedMemoryHandle>, auto resolve =
uint32_t>&& aResult) { [&](std::tuple<mozilla::Maybe<SharedMemoryHandle>, uint32_t>&& aResult) {
if (auto& handle = std::get<0>(aResult)) { if (std::get<0>(aResult)) {
mActiveCounter = handle->Map(); mActiveCounter->SetHandle(std::move(*std::get<0>(aResult)),
mChildId = std::get<1>(aResult); SharedMemory::RightsReadWrite);
if (mChildId && mIdlePeriodState && mIdlePeriodState->IsActive()) { mActiveCounter->Map(sizeof(int32_t));
SetActive(); mChildId = std::get<1>(aResult);
} if (mChildId && mIdlePeriodState && mIdlePeriodState->IsActive()) {
} SetActive();
}; }
}
};
auto reject = [&](ResponseRejectReason) {}; auto reject = [&](ResponseRejectReason) {};
SendInitForIdleUse(std::move(resolve), std::move(reject)); SendInitForIdleUse(std::move(resolve), std::move(reject));
@@ -52,21 +54,23 @@ IPCResult IdleSchedulerChild::RecvIdleTime(uint64_t aId, TimeDuration aBudget) {
} }
void IdleSchedulerChild::SetActive() { void IdleSchedulerChild::SetActive() {
if (mChildId && CanSend() && mActiveCounter) { if (mChildId && CanSend() && mActiveCounter->Memory()) {
auto counters = mActiveCounter.DataAsSpan<Atomic<int32_t>>(); ++(static_cast<Atomic<int32_t>*>(
++counters[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]; mActiveCounter->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]);
++counters[mChildId]; ++(static_cast<Atomic<int32_t>*>(mActiveCounter->Memory())[mChildId]);
} }
} }
bool IdleSchedulerChild::SetPaused() { bool IdleSchedulerChild::SetPaused() {
if (mChildId && CanSend() && mActiveCounter) { if (mChildId && CanSend() && mActiveCounter->Memory()) {
auto counters = mActiveCounter.DataAsSpan<Atomic<int32_t>>(); --(static_cast<Atomic<int32_t>*>(mActiveCounter->Memory())[mChildId]);
--counters[mChildId];
// The following expression reduces the global activity count and checks if // The following expression reduces the global activity count and checks if
// it drops below the cpu counter limit. // it drops below the cpu counter limit.
return counters[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]-- == return (static_cast<Atomic<int32_t>*>(mActiveCounter->Memory())
counters[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER]; [NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER])-- ==
static_cast<Atomic<int32_t>*>(
mActiveCounter
->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER];
} }
return false; return false;

View File

@@ -11,7 +11,7 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/ipc/PIdleSchedulerChild.h" #include "mozilla/ipc/PIdleSchedulerChild.h"
#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/ipc/SharedMemory.h"
class nsIIdlePeriod; class nsIIdlePeriod;
@@ -58,7 +58,7 @@ class IdleSchedulerChild final : public PIdleSchedulerChild {
friend class BackgroundChildImpl; friend class BackgroundChildImpl;
// See IdleScheduleParent::sActiveChildCounter // See IdleScheduleParent::sActiveChildCounter
SharedMemoryMapping mActiveCounter; RefPtr<SharedMemory> mActiveCounter = MakeRefPtr<SharedMemory>();
IdlePeriodState* mIdlePeriodState = nullptr; IdlePeriodState* mIdlePeriodState = nullptr;

View File

@@ -9,10 +9,7 @@
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
#include "mozilla/ipc/IdleSchedulerParent.h" #include "mozilla/ipc/IdleSchedulerParent.h"
#include "mozilla/AppShutdown.h" #include "mozilla/AppShutdown.h"
#include "mozilla/NeverDestroyed.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
#include "mozilla/ipc/SharedMemoryHandle.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "nsSystemInfo.h" #include "nsSystemInfo.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsITimer.h" #include "nsITimer.h"
@@ -20,18 +17,8 @@
namespace mozilla::ipc { namespace mozilla::ipc {
// Shared memory for counting how many child processes are running MOZ_RUNINIT RefPtr<SharedMemory> IdleSchedulerParent::sActiveChildCounter =
// tasks. This memory is shared across all the child processes. nullptr;
// The [0] is used for counting all the processes and
// [childId] is for counting per process activity.
// This way the global activity can be checked in a fast way by just looking
// at [0] value.
// [1] is used for cpu count for child processes.
static SharedMemoryMappingWithHandle& sActiveChildCounter() {
static NeverDestroyed<SharedMemoryMappingWithHandle> mapping;
return *mapping;
}
std::bitset<NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT> std::bitset<NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT>
IdleSchedulerParent::sInUseChildCounters; IdleSchedulerParent::sInUseChildCounters;
MOZ_RUNINIT LinkedList<IdleSchedulerParent> MOZ_RUNINIT LinkedList<IdleSchedulerParent>
@@ -121,9 +108,9 @@ void IdleSchedulerParent::CalculateNumIdleTasks() {
sMaxConcurrentGCs = std::clamp(sNumCPUs / sPrefConcurrentGCsCPUDivisor, 1u, sMaxConcurrentGCs = std::clamp(sNumCPUs / sPrefConcurrentGCsCPUDivisor, 1u,
sPrefConcurrentGCsMax); sPrefConcurrentGCsMax);
if (sActiveChildCounter()) { if (sActiveChildCounter && sActiveChildCounter->Memory()) {
sActiveChildCounter() static_cast<Atomic<int32_t>*>(
.DataAsSpan<Atomic<int32_t>>()[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] = sActiveChildCounter->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] =
static_cast<int32_t>(sMaxConcurrentIdleTasksInChildProcesses); static_cast<int32_t>(sMaxConcurrentIdleTasksInChildProcesses);
} }
IdleSchedulerParent::Schedule(nullptr); IdleSchedulerParent::Schedule(nullptr);
@@ -134,12 +121,14 @@ IdleSchedulerParent::~IdleSchedulerParent() {
// that is the case. // that is the case.
if (mChildId) { if (mChildId) {
sInUseChildCounters[mChildId] = false; sInUseChildCounters[mChildId] = false;
if (sActiveChildCounter()) { if (sActiveChildCounter && sActiveChildCounter->Memory() &&
auto counters = sActiveChildCounter().DataAsSpan<Atomic<int32_t>>(); static_cast<Atomic<int32_t>*>(
if (counters[mChildId]) { sActiveChildCounter->Memory())[mChildId]) {
--counters[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]; --static_cast<Atomic<int32_t>*>(
counters[mChildId] = 0; sActiveChildCounter
} ->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER];
static_cast<Atomic<int32_t>*>(sActiveChildCounter->Memory())[mChildId] =
0;
} }
} }
@@ -166,7 +155,7 @@ IdleSchedulerParent::~IdleSchedulerParent() {
sChildProcessesAlive--; sChildProcessesAlive--;
if (sChildProcessesAlive == 0) { if (sChildProcessesAlive == 0) {
MOZ_ASSERT(sIdleAndGCRequests.isEmpty()); MOZ_ASSERT(sIdleAndGCRequests.isEmpty());
sActiveChildCounter() = nullptr; sActiveChildCounter = nullptr;
if (sStarvationPreventer) { if (sStarvationPreventer) {
sStarvationPreventer->Cancel(); sStarvationPreventer->Cancel();
@@ -188,22 +177,27 @@ IPCResult IdleSchedulerParent::RecvInitForIdleUse(
// Create a shared memory object which is shared across all the relevant // Create a shared memory object which is shared across all the relevant
// processes. // processes.
if (!sActiveChildCounter()) { if (!sActiveChildCounter) {
sActiveChildCounter = MakeRefPtr<SharedMemory>();
size_t shmemSize = NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT * sizeof(int32_t); size_t shmemSize = NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT * sizeof(int32_t);
sActiveChildCounter() = shared_memory::Create(shmemSize).MapWithHandle(); if (sActiveChildCounter->Create(shmemSize) &&
if (sActiveChildCounter()) { sActiveChildCounter->Map(shmemSize)) {
memset(sActiveChildCounter().Address(), 0, shmemSize); memset(sActiveChildCounter->Memory(), 0, shmemSize);
sInUseChildCounters[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER] = true; sInUseChildCounters[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER] = true;
sInUseChildCounters[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] = true; sInUseChildCounters[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] = true;
sActiveChildCounter().DataAsSpan<Atomic<int32_t>>() static_cast<Atomic<int32_t>*>(
[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] = sActiveChildCounter
->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] =
static_cast<int32_t>(sMaxConcurrentIdleTasksInChildProcesses); static_cast<int32_t>(sMaxConcurrentIdleTasksInChildProcesses);
} else { } else {
sActiveChildCounter() = nullptr; sActiveChildCounter = nullptr;
} }
} }
MutableSharedMemoryHandle activeCounter = Maybe<SharedMemory::Handle> activeCounter;
sActiveChildCounter() ? sActiveChildCounter().Handle().Clone() : nullptr; if (SharedMemory::Handle handle =
sActiveChildCounter ? sActiveChildCounter->CloneHandle() : nullptr) {
activeCounter.emplace(std::move(handle));
}
uint32_t unusedId = 0; uint32_t unusedId = 0;
for (uint32_t i = 0; i < NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT; ++i) { for (uint32_t i = 0; i < NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT; ++i) {
@@ -217,9 +211,8 @@ IPCResult IdleSchedulerParent::RecvInitForIdleUse(
// If there wasn't an empty item, we'll fallback to 0. // If there wasn't an empty item, we'll fallback to 0.
mChildId = unusedId; mChildId = unusedId;
aResolve( aResolve(std::tuple<mozilla::Maybe<SharedMemory::Handle>&&, const uint32_t&>(
std::tuple<mozilla::Maybe<MutableSharedMemoryHandle>&&, const uint32_t&>( std::move(activeCounter), mChildId));
Some(std::move(activeCounter)), mChildId));
return IPC_OK(); return IPC_OK();
} }
@@ -325,9 +318,10 @@ IPCResult IdleSchedulerParent::RecvDoneGC() {
} }
int32_t IdleSchedulerParent::ActiveCount() { int32_t IdleSchedulerParent::ActiveCount() {
if (sActiveChildCounter()) { if (sActiveChildCounter) {
return sActiveChildCounter().DataAsSpan<Atomic<int32_t>>() return (static_cast<Atomic<int32_t>*>(
[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]; sActiveChildCounter
->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]);
} }
return 0; return 0;
} }

View File

@@ -13,7 +13,7 @@
#include "mozilla/LinkedList.h" #include "mozilla/LinkedList.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/ipc/PIdleSchedulerParent.h" #include "mozilla/ipc/PIdleSchedulerParent.h"
#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/ipc/SharedMemory.h"
#include <bitset> #include <bitset>
#define NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT 1024 #define NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT 1024
@@ -82,6 +82,14 @@ class IdleSchedulerParent final
bool IsDoingIdleTask() const { return !isInList() && mRequestedIdleBudget; } bool IsDoingIdleTask() const { return !isInList() && mRequestedIdleBudget; }
bool IsNotDoingIdleTask() const { return !mRequestedIdleBudget; } bool IsNotDoingIdleTask() const { return !mRequestedIdleBudget; }
// Shared memory for counting how many child processes are running
// tasks. This memory is shared across all the child processes.
// The [0] is used for counting all the processes and
// [childId] is for counting per process activity.
// This way the global activity can be checked in a fast way by just looking
// at [0] value.
// [1] is used for cpu count for child processes.
static RefPtr<SharedMemory> sActiveChildCounter;
// A bit is set if there is a child with child Id as the offset. // A bit is set if there is a child with child Id as the offset.
// The bit is used to check per child specific activity counters in // The bit is used to check per child specific activity counters in
// sActiveChildCounter. // sActiveChildCounter.

View File

@@ -5,7 +5,7 @@
include protocol PBackground; include protocol PBackground;
using mozilla::TimeDuration from "mozilla/TimeStamp.h"; using mozilla::TimeDuration from "mozilla/TimeStamp.h";
[MoveOnly] using mozilla::ipc::MutableSharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h"; [MoveOnly] using mozilla::ipc::SharedMemoryHandle from "mozilla/ipc/SharedMemory.h";
namespace mozilla { namespace mozilla {
namespace ipc { namespace ipc {
@@ -39,7 +39,7 @@ child:
async IdleTime(uint64_t id, TimeDuration budget); async IdleTime(uint64_t id, TimeDuration budget);
parent: parent:
async InitForIdleUse() returns (MutableSharedMemoryHandle? state, uint32_t childId); async InitForIdleUse() returns (SharedMemoryHandle? state, uint32_t childId);
async RequestIdleTime(uint64_t id, TimeDuration budget); async RequestIdleTime(uint64_t id, TimeDuration budget);
async IdleTimeUsed(uint64_t id); async IdleTimeUsed(uint64_t id);

View File

@@ -55,18 +55,22 @@ void ProcessChild::AddPlatformBuildID(geckoargs::ChildProcessArgs& aExtraArgs) {
/* static */ /* static */
bool ProcessChild::InitPrefs(int aArgc, char* aArgv[]) { bool ProcessChild::InitPrefs(int aArgc, char* aArgv[]) {
Maybe<ReadOnlySharedMemoryHandle> prefsHandle = Maybe<SharedMemoryHandle> prefsHandle =
geckoargs::sPrefsHandle.Get(aArgc, aArgv); geckoargs::sPrefsHandle.Get(aArgc, aArgv);
Maybe<ReadOnlySharedMemoryHandle> prefMapHandle = Maybe<SharedMemoryHandle> prefMapHandle =
geckoargs::sPrefMapHandle.Get(aArgc, aArgv); geckoargs::sPrefMapHandle.Get(aArgc, aArgv);
Maybe<uint64_t> prefsLen = geckoargs::sPrefsLen.Get(aArgc, aArgv);
Maybe<uint64_t> prefMapSize = geckoargs::sPrefMapSize.Get(aArgc, aArgv);
if (prefsHandle.isNothing() || prefMapHandle.isNothing()) { if (prefsLen.isNothing() || prefMapSize.isNothing() ||
prefsHandle.isNothing() || prefMapHandle.isNothing()) {
return false; return false;
} }
SharedPreferenceDeserializer deserializer; SharedPreferenceDeserializer deserializer;
return deserializer.DeserializeFromSharedMemory(std::move(*prefsHandle), return deserializer.DeserializeFromSharedMemory(std::move(*prefsHandle),
std::move(*prefMapHandle)); std::move(*prefMapHandle),
*prefsLen, *prefMapSize);
} }
#ifdef ENABLE_TESTS #ifdef ENABLE_TESTS

View File

@@ -12,8 +12,7 @@
#include "mozilla/GeckoArgs.h" #include "mozilla/GeckoArgs.h"
#include "mozilla/ipc/FileDescriptor.h" #include "mozilla/ipc/FileDescriptor.h"
#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/ipc/SharedMemory.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
@@ -37,21 +36,22 @@ class SharedPreferenceSerializer final {
bool SerializeToSharedMemory(const GeckoProcessType aDestinationProcessType, bool SerializeToSharedMemory(const GeckoProcessType aDestinationProcessType,
const nsACString& aDestinationRemoteType); const nsACString& aDestinationRemoteType);
const ReadOnlySharedMemoryHandle& GetPrefsHandle() const { size_t GetPrefMapSize() const { return mPrefMapSize; }
return mPrefsHandle; size_t GetPrefsLength() const { return mPrefsLength; }
}
const ReadOnlySharedMemoryHandle& GetPrefMapHandle() const { const SharedMemoryHandle& GetPrefsHandle() const { return mPrefsHandle; }
return mPrefMapHandle;
} const SharedMemoryHandle& GetPrefMapHandle() const { return mPrefMapHandle; }
void AddSharedPrefCmdLineArgs(GeckoChildProcessHost& procHost, void AddSharedPrefCmdLineArgs(GeckoChildProcessHost& procHost,
geckoargs::ChildProcessArgs& aExtraOpts) const; geckoargs::ChildProcessArgs& aExtraOpts) const;
private: private:
DISALLOW_COPY_AND_ASSIGN(SharedPreferenceSerializer); DISALLOW_COPY_AND_ASSIGN(SharedPreferenceSerializer);
ReadOnlySharedMemoryHandle mPrefMapHandle; size_t mPrefMapSize;
ReadOnlySharedMemoryHandle mPrefsHandle; size_t mPrefsLength;
SharedMemoryHandle mPrefMapHandle;
SharedMemoryHandle mPrefsHandle;
}; };
class SharedPreferenceDeserializer final { class SharedPreferenceDeserializer final {
@@ -59,13 +59,18 @@ class SharedPreferenceDeserializer final {
SharedPreferenceDeserializer(); SharedPreferenceDeserializer();
~SharedPreferenceDeserializer(); ~SharedPreferenceDeserializer();
bool DeserializeFromSharedMemory(ReadOnlySharedMemoryHandle&& aPrefsHandle, bool DeserializeFromSharedMemory(SharedMemoryHandle aPrefsHandle,
ReadOnlySharedMemoryHandle&& aPrefMapHandle); SharedMemoryHandle aPrefMapHandle,
uint64_t aPrefsLen, uint64_t aPrefMapSize);
const SharedMemoryHandle& GetPrefMapHandle() const;
private: private:
DISALLOW_COPY_AND_ASSIGN(SharedPreferenceDeserializer); DISALLOW_COPY_AND_ASSIGN(SharedPreferenceDeserializer);
ReadOnlySharedMemoryHandle mPrefMapHandle; Maybe<SharedMemoryHandle> mPrefMapHandle;
ReadOnlySharedMemoryMapping mShmem; Maybe<size_t> mPrefsLen;
Maybe<size_t> mPrefMapSize;
RefPtr<SharedMemory> mShmem = MakeRefPtr<SharedMemory>();
}; };
// Generate command line argument to spawn a child process. If the shared memory // Generate command line argument to spawn a child process. If the shared memory
@@ -75,7 +80,7 @@ void ExportSharedJSInit(GeckoChildProcessHost& procHost,
// Initialize the content used by the JS engine during the initialization of a // Initialize the content used by the JS engine during the initialization of a
// JS::Runtime. // JS::Runtime.
bool ImportSharedJSInit(ReadOnlySharedMemoryHandle&& aJsInitHandle); bool ImportSharedJSInit(SharedMemoryHandle aJsInitHandle, uint64_t aJsInitLen);
} // namespace ipc } // namespace ipc
} // namespace mozilla } // namespace mozilla

View File

@@ -19,7 +19,8 @@
namespace mozilla { namespace mozilla {
namespace ipc { namespace ipc {
SharedPreferenceSerializer::SharedPreferenceSerializer() { SharedPreferenceSerializer::SharedPreferenceSerializer()
: mPrefMapSize(0), mPrefsLength(0) {
MOZ_COUNT_CTOR(SharedPreferenceSerializer); MOZ_COUNT_CTOR(SharedPreferenceSerializer);
} }
@@ -29,7 +30,9 @@ SharedPreferenceSerializer::~SharedPreferenceSerializer() {
SharedPreferenceSerializer::SharedPreferenceSerializer( SharedPreferenceSerializer::SharedPreferenceSerializer(
SharedPreferenceSerializer&& aOther) SharedPreferenceSerializer&& aOther)
: mPrefMapHandle(std::move(aOther.mPrefMapHandle)), : mPrefMapSize(aOther.mPrefMapSize),
mPrefsLength(aOther.mPrefsLength),
mPrefMapHandle(std::move(aOther.mPrefMapHandle)),
mPrefsHandle(std::move(aOther.mPrefsHandle)) { mPrefsHandle(std::move(aOther.mPrefsHandle)) {
MOZ_COUNT_CTOR(SharedPreferenceSerializer); MOZ_COUNT_CTOR(SharedPreferenceSerializer);
} }
@@ -37,7 +40,7 @@ SharedPreferenceSerializer::SharedPreferenceSerializer(
bool SharedPreferenceSerializer::SerializeToSharedMemory( bool SharedPreferenceSerializer::SerializeToSharedMemory(
const GeckoProcessType aDestinationProcessType, const GeckoProcessType aDestinationProcessType,
const nsACString& aDestinationRemoteType) { const nsACString& aDestinationRemoteType) {
mPrefMapHandle = Preferences::EnsureSnapshot(); mPrefMapHandle = Preferences::EnsureSnapshot(&mPrefMapSize);
bool destIsWebContent = bool destIsWebContent =
aDestinationProcessType == GeckoProcessType_Content && aDestinationProcessType == GeckoProcessType_Content &&
@@ -47,38 +50,40 @@ bool SharedPreferenceSerializer::SerializeToSharedMemory(
// Serialize the early prefs. // Serialize the early prefs.
nsAutoCStringN<1024> prefs; nsAutoCStringN<1024> prefs;
Preferences::SerializePreferences(prefs, destIsWebContent); Preferences::SerializePreferences(prefs, destIsWebContent);
auto prefsLength = prefs.Length(); mPrefsLength = prefs.Length();
RefPtr<SharedMemory> shm = MakeRefPtr<SharedMemory>();
// Set up the shared memory. // Set up the shared memory.
auto handle = shared_memory::Create(prefsLength); if (!shm->Create(prefs.Length())) {
if (!handle) {
NS_ERROR("failed to create shared memory in the parent"); NS_ERROR("failed to create shared memory in the parent");
return false; return false;
} }
auto mapping = handle.Map(); if (!shm->Map(prefs.Length())) {
if (!mapping) {
NS_ERROR("failed to map shared memory in the parent"); NS_ERROR("failed to map shared memory in the parent");
return false; return false;
} }
// Copy the serialized prefs into the shared memory. // Copy the serialized prefs into the shared memory.
memcpy(mapping.DataAs<char>(), prefs.get(), prefsLength); memcpy(static_cast<char*>(shm->Memory()), prefs.get(), mPrefsLength);
mPrefsHandle = std::move(handle).ToReadOnly(); mPrefsHandle = shm->TakeHandleAndUnmap();
return true; return true;
} }
void SharedPreferenceSerializer::AddSharedPrefCmdLineArgs( void SharedPreferenceSerializer::AddSharedPrefCmdLineArgs(
mozilla::ipc::GeckoChildProcessHost& procHost, mozilla::ipc::GeckoChildProcessHost& procHost,
geckoargs::ChildProcessArgs& aExtraOpts) const { geckoargs::ChildProcessArgs& aExtraOpts) const {
auto prefsHandle = GetPrefsHandle().Clone(); SharedMemoryHandle prefsHandle = SharedMemory::CloneHandle(GetPrefsHandle());
MOZ_RELEASE_ASSERT(prefsHandle, "failed to clone prefs handle"); MOZ_RELEASE_ASSERT(prefsHandle, "failed to duplicate prefs handle");
auto prefMapHandle = GetPrefMapHandle().Clone(); SharedMemoryHandle prefMapHandle =
MOZ_RELEASE_ASSERT(prefMapHandle, "failed to clone pref map handle"); SharedMemory::CloneHandle(GetPrefMapHandle());
MOZ_RELEASE_ASSERT(prefMapHandle, "failed to duplicate pref map handle");
// Pass the handles via command line flags. // Pass the handles and lengths via command line flags.
geckoargs::sPrefsHandle.Put(std::move(prefsHandle), aExtraOpts); geckoargs::sPrefsHandle.Put(std::move(prefsHandle), aExtraOpts);
geckoargs::sPrefsLen.Put((uintptr_t)(GetPrefsLength()), aExtraOpts);
geckoargs::sPrefMapHandle.Put(std::move(prefMapHandle), aExtraOpts); geckoargs::sPrefMapHandle.Put(std::move(prefMapHandle), aExtraOpts);
geckoargs::sPrefMapSize.Put((uintptr_t)(GetPrefMapSize()), aExtraOpts);
} }
SharedPreferenceDeserializer::SharedPreferenceDeserializer() { SharedPreferenceDeserializer::SharedPreferenceDeserializer() {
@@ -90,56 +95,79 @@ SharedPreferenceDeserializer::~SharedPreferenceDeserializer() {
} }
bool SharedPreferenceDeserializer::DeserializeFromSharedMemory( bool SharedPreferenceDeserializer::DeserializeFromSharedMemory(
ReadOnlySharedMemoryHandle&& aPrefsHandle, SharedMemoryHandle aPrefsHandle, SharedMemoryHandle aPrefMapHandle,
ReadOnlySharedMemoryHandle&& aPrefMapHandle) { uint64_t aPrefsLen, uint64_t aPrefMapSize) {
if (!aPrefsHandle || !aPrefMapHandle) { if (!aPrefsHandle || !aPrefMapHandle || !aPrefsLen || !aPrefMapSize) {
return false; return false;
} }
mPrefMapHandle = std::move(aPrefMapHandle); mPrefMapHandle.emplace(std::move(aPrefMapHandle));
mPrefsLen = Some((uintptr_t)(aPrefsLen));
mPrefMapSize = Some((uintptr_t)(aPrefMapSize));
// Init the shared-memory base preference mapping first, so that only changed // Init the shared-memory base preference mapping first, so that only changed
// preferences wind up in heap memory. // preferences wind up in heap memory.
Preferences::InitSnapshot(mPrefMapHandle); Preferences::InitSnapshot(mPrefMapHandle.ref(), *mPrefMapSize);
// Set up early prefs from the shared memory. // Set up early prefs from the shared memory.
mShmem = aPrefsHandle.Map(); if (!mShmem->SetHandle(std::move(aPrefsHandle),
if (!mShmem) { SharedMemory::RightsReadOnly)) {
NS_ERROR("failed to open shared memory in the child");
return false;
}
if (!mShmem->Map(*mPrefsLen)) {
NS_ERROR("failed to map shared memory in the child"); NS_ERROR("failed to map shared memory in the child");
return false; return false;
} }
Preferences::DeserializePreferences(mShmem.DataAs<char>(), mShmem.Size()); Preferences::DeserializePreferences(static_cast<char*>(mShmem->Memory()),
*mPrefsLen);
return true; return true;
} }
const SharedMemoryHandle& SharedPreferenceDeserializer::GetPrefMapHandle()
const {
MOZ_ASSERT(mPrefMapHandle.isSome());
return mPrefMapHandle.ref();
}
void ExportSharedJSInit(mozilla::ipc::GeckoChildProcessHost& procHost, void ExportSharedJSInit(mozilla::ipc::GeckoChildProcessHost& procHost,
geckoargs::ChildProcessArgs& aExtraOpts) { geckoargs::ChildProcessArgs& aExtraOpts) {
auto& shmem = xpc::SelfHostedShmem::GetSingleton(); auto& shmem = xpc::SelfHostedShmem::GetSingleton();
auto handle = shmem.Handle().Clone(); SharedMemoryHandle handle = SharedMemory::CloneHandle(shmem.Handle());
size_t len = shmem.Content().Length();
// If the file is not found or the content is empty, then we would start the // If the file is not found or the content is empty, then we would start the
// content process without this optimization. // content process without this optimization.
if (!handle) { if (!SharedMemory::IsHandleValid(handle) || !len) {
NS_ERROR("Can't use SelfHosted shared memory handle."); NS_ERROR("Can't use SelfHosted shared memory handle.");
return; return;
} }
// command line: -jsInitHandle handle // command line: -jsInitHandle handle -jsInitLen length
geckoargs::sJsInitHandle.Put(std::move(handle), aExtraOpts); geckoargs::sJsInitHandle.Put(std::move(handle), aExtraOpts);
geckoargs::sJsInitLen.Put((uintptr_t)(len), aExtraOpts);
} }
bool ImportSharedJSInit(ReadOnlySharedMemoryHandle&& aJsInitHandle) { bool ImportSharedJSInit(SharedMemoryHandle aJsInitHandle, uint64_t aJsInitLen) {
// This is an optimization, and as such we can safely recover if the command // This is an optimization, and as such we can safely recover if the command
// line argument are not provided. // line argument are not provided.
if (!aJsInitHandle) { if (!aJsInitLen || !aJsInitHandle) {
return true; return true;
} }
size_t len = (uintptr_t)(aJsInitLen);
if (!len) {
return false;
}
// Initialize the shared memory with the file handle and size of the content // Initialize the shared memory with the file handle and size of the content
// of the self-hosted Xdr. // of the self-hosted Xdr.
auto& shmem = xpc::SelfHostedShmem::GetSingleton(); auto& shmem = xpc::SelfHostedShmem::GetSingleton();
if (!shmem.InitFromChild(std::move(aJsInitHandle))) { if (!shmem.InitFromChild(std::move(aJsInitHandle), len)) {
NS_ERROR("failed to open shared memory in the child"); NS_ERROR("failed to open shared memory in the child");
return false; return false;
} }

View File

@@ -339,13 +339,14 @@ IProtocol::~IProtocol() {
// almost directly do. // almost directly do.
IProtocol* IProtocol::Lookup(int32_t aId) { return mToplevel->Lookup(aId); } IProtocol* IProtocol::Lookup(int32_t aId) { return mToplevel->Lookup(aId); }
Shmem IProtocol::CreateSharedMemory(size_t aSize, bool aUnsafe) { Shmem::SharedMemory* IProtocol::CreateSharedMemory(size_t aSize, bool aUnsafe,
return mToplevel->CreateSharedMemory(aSize, aUnsafe); int32_t* aId) {
return mToplevel->CreateSharedMemory(aSize, aUnsafe, aId);
} }
Shmem::Segment* IProtocol::LookupSharedMemory(int32_t aId) { Shmem::SharedMemory* IProtocol::LookupSharedMemory(int32_t aId) {
return mToplevel->LookupSharedMemory(aId); return mToplevel->LookupSharedMemory(aId);
} }
bool IProtocol::IsTrackingSharedMemory(const Shmem::Segment* aSegment) { bool IProtocol::IsTrackingSharedMemory(Shmem::SharedMemory* aSegment) {
return mToplevel->IsTrackingSharedMemory(aSegment); return mToplevel->IsTrackingSharedMemory(aSegment);
} }
bool IProtocol::DestroySharedMemory(Shmem& aShmem) { bool IProtocol::DestroySharedMemory(Shmem& aShmem) {
@@ -419,8 +420,14 @@ bool IProtocol::AllocShmem(size_t aSize, Shmem* aOutMem) {
return false; return false;
} }
*aOutMem = CreateSharedMemory(aSize, false); Shmem::id_t id;
return aOutMem->IsReadable(); Shmem::SharedMemory* rawmem(CreateSharedMemory(aSize, false, &id));
if (!rawmem) {
return false;
}
*aOutMem = Shmem(rawmem, id, aSize, false);
return true;
} }
bool IProtocol::AllocUnsafeShmem(size_t aSize, Shmem* aOutMem) { bool IProtocol::AllocUnsafeShmem(size_t aSize, Shmem* aOutMem) {
@@ -430,8 +437,14 @@ bool IProtocol::AllocUnsafeShmem(size_t aSize, Shmem* aOutMem) {
return false; return false;
} }
*aOutMem = CreateSharedMemory(aSize, true); Shmem::id_t id;
return aOutMem->IsReadable(); Shmem::SharedMemory* rawmem(CreateSharedMemory(aSize, true, &id));
if (!rawmem) {
return false;
}
*aOutMem = Shmem(rawmem, id, aSize, true);
return true;
} }
bool IProtocol::DeallocShmem(Shmem& aMem) { bool IProtocol::DeallocShmem(Shmem& aMem) {
@@ -746,30 +759,35 @@ IProtocol* IToplevelProtocol::Lookup(int32_t aId) {
return nullptr; return nullptr;
} }
Shmem IToplevelProtocol::CreateSharedMemory(size_t aSize, bool aUnsafe) { Shmem::SharedMemory* IToplevelProtocol::CreateSharedMemory(size_t aSize,
auto shmemBuilder = Shmem::Builder(aSize); bool aUnsafe,
if (!shmemBuilder) { Shmem::id_t* aId) {
return {}; RefPtr<Shmem::SharedMemory> segment(Shmem::Alloc(aSize));
if (!segment) {
return nullptr;
} }
auto [createdMessage, shmem] = int32_t id = NextId();
shmemBuilder.Build(NextId(), aUnsafe, MSG_ROUTING_CONTROL); Shmem shmem(segment.get(), id, aSize, aUnsafe);
if (!createdMessage) {
return {};
}
Unused << GetIPCChannel()->Send(std::move(createdMessage));
MOZ_ASSERT(!mShmemMap.Contains(shmem.Id()), UniquePtr<Message> descriptor = shmem.MkCreatedMessage(MSG_ROUTING_CONTROL);
"Don't insert with an existing ID"); if (!descriptor) {
mShmemMap.InsertOrUpdate(shmem.Id(), shmem.GetSegment()); return nullptr;
return shmem; }
Unused << GetIPCChannel()->Send(std::move(descriptor));
*aId = shmem.Id();
Shmem::SharedMemory* rawSegment = segment.get();
MOZ_ASSERT(!mShmemMap.Contains(*aId), "Don't insert with an existing ID");
mShmemMap.InsertOrUpdate(*aId, std::move(segment));
return rawSegment;
} }
Shmem::Segment* IToplevelProtocol::LookupSharedMemory(Shmem::id_t aId) { Shmem::SharedMemory* IToplevelProtocol::LookupSharedMemory(Shmem::id_t aId) {
auto entry = mShmemMap.Lookup(aId); auto entry = mShmemMap.Lookup(aId);
return entry ? entry.Data().get() : nullptr; return entry ? entry.Data().get() : nullptr;
} }
bool IToplevelProtocol::IsTrackingSharedMemory(const Shmem::Segment* segment) { bool IToplevelProtocol::IsTrackingSharedMemory(Shmem::SharedMemory* segment) {
for (const auto& shmem : mShmemMap.Values()) { for (const auto& shmem : mShmemMap.Values()) {
if (segment == shmem) { if (segment == shmem) {
return true; return true;
@@ -780,7 +798,8 @@ bool IToplevelProtocol::IsTrackingSharedMemory(const Shmem::Segment* segment) {
bool IToplevelProtocol::DestroySharedMemory(Shmem& shmem) { bool IToplevelProtocol::DestroySharedMemory(Shmem& shmem) {
Shmem::id_t aId = shmem.Id(); Shmem::id_t aId = shmem.Id();
if (!LookupSharedMemory(aId)) { Shmem::SharedMemory* segment = LookupSharedMemory(aId);
if (!segment) {
return false; return false;
} }
@@ -802,12 +821,12 @@ void IToplevelProtocol::DeallocShmems() { mShmemMap.Clear(); }
bool IToplevelProtocol::ShmemCreated(const Message& aMsg) { bool IToplevelProtocol::ShmemCreated(const Message& aMsg) {
Shmem::id_t id; Shmem::id_t id;
RefPtr<Shmem::Segment> segment(Shmem::OpenExisting(aMsg, &id, true)); RefPtr<Shmem::SharedMemory> rawmem(Shmem::OpenExisting(aMsg, &id, true));
if (!segment) { if (!rawmem) {
return false; return false;
} }
MOZ_ASSERT(!mShmemMap.Contains(id), "Don't insert with an existing ID"); MOZ_ASSERT(!mShmemMap.Contains(id), "Don't insert with an existing ID");
mShmemMap.InsertOrUpdate(id, std::move(segment)); mShmemMap.InsertOrUpdate(id, std::move(rawmem));
return true; return true;
} }

View File

@@ -26,6 +26,7 @@
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "mozilla/ipc/MessageChannel.h" #include "mozilla/ipc/MessageChannel.h"
#include "mozilla/ipc/MessageLink.h" #include "mozilla/ipc/MessageLink.h"
#include "mozilla/ipc/SharedMemory.h"
#include "mozilla/ipc/Shmem.h" #include "mozilla/ipc/Shmem.h"
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "nsTHashMap.h" #include "nsTHashMap.h"
@@ -196,9 +197,10 @@ class IProtocol : public HasResultCodes {
// Lookup() is forwarded directly to the toplevel protocol. // Lookup() is forwarded directly to the toplevel protocol.
IProtocol* Lookup(int32_t aId); IProtocol* Lookup(int32_t aId);
Shmem CreateSharedMemory(size_t aSize, bool aUnsafe); Shmem::SharedMemory* CreateSharedMemory(size_t aSize, bool aUnsafe,
Shmem::Segment* LookupSharedMemory(int32_t aId); int32_t* aId);
bool IsTrackingSharedMemory(const Shmem::Segment* aSegment); Shmem::SharedMemory* LookupSharedMemory(int32_t aId);
bool IsTrackingSharedMemory(Shmem::SharedMemory* aSegment);
bool DestroySharedMemory(Shmem& aShmem); bool DestroySharedMemory(Shmem& aShmem);
MessageChannel* GetIPCChannel(); MessageChannel* GetIPCChannel();
@@ -446,9 +448,10 @@ class IToplevelProtocol : public IRefCountedProtocol {
// Shadows the method on IProtocol, which will forward to the top. // Shadows the method on IProtocol, which will forward to the top.
IProtocol* Lookup(int32_t aId); IProtocol* Lookup(int32_t aId);
Shmem CreateSharedMemory(size_t aSize, bool aUnsafe); Shmem::SharedMemory* CreateSharedMemory(size_t aSize, bool aUnsafe,
Shmem::Segment* LookupSharedMemory(int32_t aId); int32_t* aId);
bool IsTrackingSharedMemory(const Shmem::Segment* aSegment); Shmem::SharedMemory* LookupSharedMemory(int32_t aId);
bool IsTrackingSharedMemory(Shmem::SharedMemory* aSegment);
bool DestroySharedMemory(Shmem& aShmem); bool DestroySharedMemory(Shmem& aShmem);
MessageChannel* GetIPCChannel() { return &mChannel; } MessageChannel* GetIPCChannel() { return &mChannel; }
@@ -558,7 +561,7 @@ class IToplevelProtocol : public IRefCountedProtocol {
// Used to be on mState // Used to be on mState
int32_t mLastLocalId; int32_t mLastLocalId;
IDMap<RefPtr<ActorLifecycleProxy>> mActorMap; IDMap<RefPtr<ActorLifecycleProxy>> mActorMap;
IDMap<RefPtr<Shmem::Segment>> mShmemMap; IDMap<RefPtr<Shmem::SharedMemory>> mShmemMap;
MessageChannel mChannel; MessageChannel mChannel;
}; };

108
ipc/glue/RawShmem.cpp Normal file
View File

@@ -0,0 +1,108 @@
/* -*- 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

114
ipc/glue/RawShmem.h Normal file
View File

@@ -0,0 +1,114 @@
/* -*- 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

211
ipc/glue/SharedMemory.cpp Normal file
View File

@@ -0,0 +1,211 @@
/* -*- 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/SharedMemory.h"
#include <utility>
#include "chrome/common/ipc_message_utils.h"
#include "mozilla/Atomics.h"
#include "nsIMemoryReporter.h"
#ifdef FUZZING
# include "mozilla/ipc/SharedMemoryFuzzer.h"
#endif
namespace mozilla::ipc {
static Atomic<size_t> gShmemAllocated;
static Atomic<size_t> gShmemMapped;
class ShmemReporter final : public nsIMemoryReporter {
~ShmemReporter() = default;
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_IMETHOD
CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
bool aAnonymize) override {
MOZ_COLLECT_REPORT(
"shmem-allocated", KIND_OTHER, UNITS_BYTES, gShmemAllocated,
"Memory shared with other processes that is accessible (but not "
"necessarily mapped).");
MOZ_COLLECT_REPORT(
"shmem-mapped", KIND_OTHER, UNITS_BYTES, gShmemMapped,
"Memory shared with other processes that is mapped into the address "
"space.");
return NS_OK;
}
};
NS_IMPL_ISUPPORTS(ShmemReporter, nsIMemoryReporter)
SharedMemory::SharedMemory() : mAllocSize(0), mMappedSize(0) {
static Atomic<bool> registered;
if (registered.compareExchange(false, true)) {
RegisterStrongMemoryReporter(new ShmemReporter());
}
}
SharedMemory::~SharedMemory() {
Unmap();
CloseHandle();
ResetImpl();
MOZ_ASSERT(gShmemAllocated >= mAllocSize,
"Can't destroy more than allocated");
gShmemAllocated -= mAllocSize;
mAllocSize = 0;
}
bool SharedMemory::Create(size_t aNBytes, bool freezable) {
MOZ_ASSERT(!IsValid(), "already initialized");
bool ok = CreateImpl(aNBytes, freezable);
if (ok) {
mAllocSize = aNBytes;
mFreezable = freezable;
mReadOnly = false;
mExternalHandle = false;
gShmemAllocated += mAllocSize;
}
return ok;
}
bool SharedMemory::Map(size_t aNBytes, void* fixedAddress) {
if (!mHandle) {
return false;
}
MOZ_ASSERT(!mMemory, "can't map memory when a mapping already exists");
auto address = MapImpl(aNBytes, fixedAddress);
if (address) {
mMappedSize = aNBytes;
mMemory = UniqueMapping(*address, MappingDeleter(mMappedSize));
gShmemMapped += mMappedSize;
return true;
}
return false;
}
void SharedMemory::Unmap() {
if (!mMemory) {
return;
}
MOZ_ASSERT(gShmemMapped >= mMappedSize, "Can't unmap more than mapped");
mMemory = nullptr;
gShmemMapped -= std::exchange(mMappedSize, 0);
}
void* SharedMemory::Memory() const {
#ifdef FUZZING
return SharedMemoryFuzzer::MutateSharedMemory(mMemory.get(), mAllocSize);
#else
return mMemory.get();
#endif
}
Span<uint8_t> SharedMemory::TakeMapping() {
// NOTE: this doesn't reduce gShmemMapped since it _is_ still mapped memory
// (and will be until the process terminates).
return {static_cast<uint8_t*>(mMemory.release()),
std::exchange(mMappedSize, 0)};
}
SharedMemory::Handle SharedMemory::TakeHandle() {
gShmemAllocated -= mAllocSize;
mAllocSize = 0;
return std::move(mHandle);
}
bool SharedMemory::SetHandle(Handle aHandle, OpenRights aRights) {
MOZ_ASSERT(!IsValid(),
"SetHandle cannot be called when a valid handle is already held");
ResetImpl();
mHandle = std::move(aHandle);
mAllocSize = 0;
mMappedSize = 0;
mFreezable = false;
mReadOnly = aRights == OpenRights::RightsReadOnly;
mExternalHandle = true;
return true;
}
bool SharedMemory::ReadOnlyCopy(SharedMemory* ro_out) {
MOZ_ASSERT(mHandle);
MOZ_ASSERT(!mReadOnly);
MOZ_ASSERT(mFreezable);
if (ro_out == this) {
MOZ_ASSERT(
!mMemory,
"Memory cannot be mapped when creating a read-only copy of this.");
}
auto handle = ReadOnlyCopyImpl();
auto allocSize = mAllocSize;
TakeHandle();
if (!handle) {
return false;
}
mFreezable = false;
// Reset ro_out (unmapping, etc).
ro_out->~SharedMemory();
ro_out->mHandle = std::move(*handle);
ro_out->mAllocSize = allocSize;
gShmemAllocated += ro_out->mAllocSize;
ro_out->mReadOnly = true;
ro_out->mFreezable = false;
ro_out->mExternalHandle = mExternalHandle;
return true;
}
bool SharedMemory::WriteHandle(IPC::MessageWriter* aWriter) {
Handle handle = CloneHandle(mHandle);
if (!handle) {
return false;
}
IPC::WriteParam(aWriter, std::move(handle));
return true;
}
bool SharedMemory::ReadHandle(IPC::MessageReader* aReader) {
Handle handle;
return IPC::ReadParam(aReader, &handle) && IsHandleValid(handle) &&
SetHandle(std::move(handle), RightsReadWrite);
}
void SharedMemory::Protect(char* aAddr, size_t aSize, int aRights) {
// Don't allow altering of rights on freezable shared memory handles.
MOZ_ASSERT(!mFreezable);
char* memStart = reinterpret_cast<char*>(Memory());
if (!memStart) MOZ_CRASH("SharedMemory region points at NULL!");
char* memEnd = memStart + Size();
char* protStart = aAddr;
if (!protStart) MOZ_CRASH("trying to Protect() a NULL region!");
char* protEnd = protStart + aSize;
if (!(memStart <= protStart && protEnd <= memEnd)) {
MOZ_CRASH("attempt to Protect() a region outside this SharedMemory");
}
// checks alignment etc.
SystemProtect(aAddr, aSize, aRights);
}
size_t SharedMemory::PageAlignedSize(size_t aSize) {
size_t pageSize = SystemPageSize();
size_t nPagesNeeded = size_t(ceil(double(aSize) / double(pageSize)));
return pageSize * nPagesNeeded;
}
} // namespace mozilla::ipc

190
ipc/glue/SharedMemory.h Normal file
View File

@@ -0,0 +1,190 @@
/* -*- 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). */
#ifndef mozilla_ipc_SharedMemory_h
#define mozilla_ipc_SharedMemory_h
#include <cstddef>
#include "mozilla/Maybe.h"
#include "mozilla/UniquePtrExtensions.h"
#include "nsISupportsImpl.h" // NS_INLINE_DECL_REFCOUNTING
#if !(defined(XP_DARWIN) || defined(XP_WIN))
# include <string>
#endif
namespace IPC {
class MessageWriter;
class MessageReader;
} // namespace IPC
namespace {
enum Rights { RightsNone = 0, RightsRead = 1 << 0, RightsWrite = 1 << 1 };
} // namespace
namespace mozilla::ipc {
// Rust Bindgen code doesn't actually use these types, but `UniqueFileHandle`
// and `UniqueMachSendRight` aren't defined and some headers need to type check,
// so we define a dummy type.
#if defined(RUST_BINDGEN)
using SharedMemoryHandle = void*;
#elif defined(XP_DARWIN)
using SharedMemoryHandle = mozilla::UniqueMachSendRight;
#else
using SharedMemoryHandle = mozilla::UniqueFileHandle;
#endif
class SharedMemory {
~SharedMemory();
/// # Provided methods
public:
using Handle = SharedMemoryHandle;
enum OpenRights {
RightsReadOnly = RightsRead,
RightsReadWrite = RightsRead | RightsWrite,
};
SharedMemory();
// bug 1168843, compositor thread may create shared memory instances that are
// destroyed by main thread on shutdown, so this must use thread-safe RC to
// avoid hitting assertion
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedMemory)
size_t Size() const { return mMappedSize; }
size_t MaxSize() const { return mAllocSize; }
bool Create(size_t nBytes, bool freezable = false);
bool Map(size_t nBytes, void* fixedAddress = nullptr);
void Unmap();
void* Memory() const;
/// Take the mapping memory.
///
/// This prevents unmapping the memory.
Span<uint8_t> TakeMapping();
Handle TakeHandleAndUnmap() {
auto handle = TakeHandle();
Unmap();
return handle;
}
Handle TakeHandle();
Handle CloneHandle() {
mFreezable = false;
return SharedMemory::CloneHandle(mHandle);
}
void CloseHandle() { TakeHandle(); }
bool SetHandle(Handle aHandle, OpenRights aRights);
bool IsValid() const { return IsHandleValid(mHandle); }
static bool IsHandleValid(const Handle& aHandle) {
// `operator!=` had ambiguous overload resolution with the windows Handle
// (mozilla::UniqueFileHandle), so invert `operator==` instead.
return !(aHandle == NULLHandle());
}
static Handle NULLHandle() { return nullptr; }
bool CreateFreezable(size_t nBytes) { return Create(nBytes, true); }
[[nodiscard]] bool Freeze() {
Unmap();
return ReadOnlyCopy(this);
}
bool WriteHandle(IPC::MessageWriter* aWriter);
bool ReadHandle(IPC::MessageReader* aReader);
void Protect(char* aAddr, size_t aSize, int aRights);
static size_t PageAlignedSize(size_t aSize);
/// Public methods which should be defined as part of each implementation.
public:
[[nodiscard]] bool ReadOnlyCopy(SharedMemory* ro_out);
static void SystemProtect(char* aAddr, size_t aSize, int aRights);
[[nodiscard]] static bool SystemProtectFallible(char* aAddr, size_t aSize,
int aRights);
static Handle CloneHandle(const Handle& aHandle);
static size_t SystemPageSize();
static void* FindFreeAddressSpace(size_t size);
/// Private methods which should be defined as part of each implementation.
private:
bool CreateImpl(size_t size, bool freezable);
Maybe<void*> MapImpl(size_t nBytes, void* fixedAddress);
static void UnmapImpl(size_t nBytes, void* address);
Maybe<Handle> ReadOnlyCopyImpl();
void ResetImpl();
/// Common members
private:
struct MappingDeleter {
size_t mMappedSize = 0;
explicit MappingDeleter(size_t size) : mMappedSize(size) {}
MappingDeleter() = default;
void operator()(void* ptr) {
MOZ_ASSERT(mMappedSize != 0);
UnmapImpl(mMappedSize, ptr);
// Guard against multiple calls of the same deleter, which shouldn't
// happen (but could, if `UniquePtr::reset` were used). Calling
// `munmap` with an incorrect non-zero length would be bad.
mMappedSize = 0;
}
};
#ifndef RUST_BINDGEN
using UniqueMapping = mozilla::UniquePtr<void, MappingDeleter>;
#else
using UniqueMapping = void*;
#endif
// The held handle, if any.
Handle mHandle = NULLHandle();
// The size of the shmem region requested in Create(), if
// successful. SharedMemory instances that are opened from a
// foreign handle have an alloc size of 0, even though they have
// access to the alloc-size information.
size_t mAllocSize;
// The memory mapping, if any.
UniqueMapping mMemory;
// The size of the region mapped in Map(), if successful. All
// SharedMemorys that are mapped have a non-zero mapped size.
size_t mMappedSize;
// Whether the handle held is freezable.
bool mFreezable = false;
// Whether the handle held is read-only.
bool mReadOnly = false;
// Whether the handle held is external (set with `SetHandle`).
bool mExternalHandle = false;
#if !defined(XP_DARWIN) && !defined(XP_WIN)
/// # Unix/POSIX-specific methods and members.
public:
// If named POSIX shm is being used, append the prefix (including
// the leading '/') that would be used by a process with the given
// pid to the given string and return true. If not, return false.
// (This is public so that the Linux sandboxing code can use it.)
static bool AppendPosixShmPrefix(std::string* str, pid_t pid);
// Similar, but simply returns whether POSIX shm is in use.
static bool UsingPosixShm();
# if !defined(ANDROID) && !defined(RUST_BINDGEN)
private:
mozilla::UniqueFileHandle mFrozenFile;
bool mIsMemfd = false;
# endif
#endif
};
} // namespace mozilla::ipc
#endif // ifndef mozilla_ipc_SharedMemory_h

View File

@@ -4,8 +4,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file, * 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/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/MathAlgorithms.h"
#include "nsDebug.h"
#include "SharedMemoryCursor.h" #include "SharedMemoryCursor.h"
namespace mozilla::ipc::shared_memory { namespace mozilla::ipc::shared_memory {
@@ -29,7 +27,7 @@ void Cursor::Seek(uint64_t aOffset) {
} }
} }
MutableHandle Cursor::TakeHandle() { Handle Cursor::TakeHandle() {
mMapping = nullptr; mMapping = nullptr;
return std::move(mHandle); return std::move(mHandle);
} }
@@ -64,7 +62,7 @@ bool Cursor::Consume(void* aBuffer, size_t aCount, bool aWriteToShmem) {
size_t mappingRemaining = mMapping.Size() - mappingOffset; size_t mappingRemaining = mMapping.Size() - mappingOffset;
size_t toCopy = std::min<size_t>(mappingRemaining, aCount - consumed); size_t toCopy = std::min<size_t>(mappingRemaining, aCount - consumed);
void* shmemPtr = mMapping.DataAs<char>() + mappingOffset; void* shmemPtr = static_cast<char*>(mMapping.Data()) + mappingOffset;
void* bufferPtr = static_cast<char*>(aBuffer) + consumed; void* bufferPtr = static_cast<char*>(aBuffer) + consumed;
if (aWriteToShmem) { if (aWriteToShmem) {
memcpy(shmemPtr, bufferPtr, toCopy); memcpy(shmemPtr, bufferPtr, toCopy);

View File

@@ -30,7 +30,7 @@ class Cursor {
// Construct a new Cursor which can be used to read from or write to the // Construct a new Cursor which can be used to read from or write to the
// shared memory region indicated by aHandle. // shared memory region indicated by aHandle.
explicit Cursor(MutableHandle&& aHandle) : mHandle(std::move(aHandle)) {} explicit Cursor(Handle&& aHandle) : mHandle(std::move(aHandle)) {}
bool IsValid() const { return mHandle.IsValid(); } bool IsValid() const { return mHandle.IsValid(); }
uint64_t Size() const { return mHandle.Size(); } uint64_t Size() const { return mHandle.Size(); }
@@ -50,7 +50,7 @@ class Cursor {
void Seek(uint64_t aOffset); void Seek(uint64_t aOffset);
// Invalidate the Cursor, and return the underlying handle. // Invalidate the Cursor, and return the underlying handle.
MutableHandle TakeHandle(); Handle TakeHandle();
// Set the ChunkSize for the shared memory regions in this chunk. This is // Set the ChunkSize for the shared memory regions in this chunk. This is
// intended to be used for testing purposes. // intended to be used for testing purposes.
@@ -76,9 +76,9 @@ class Cursor {
bool EnsureMapping(); bool EnsureMapping();
// Shared memory handle this Cursor allows accessing. // Shared memory handle this Cursor allows accessing.
MutableHandle mHandle; Handle mHandle;
// Memory map for the currently active chunk. Lazily initialized. // Memory map for the currently active chunk. Lazily initialized.
MutableMapping mMapping; Mapping mMapping;
// Absolute offset into the shared memory handle. // Absolute offset into the shared memory handle.
uint64_t mOffset = 0; uint64_t mOffset = 0;
// Current size of each chunk. Always a power of two. May be reduced in // Current size of each chunk. Always a power of two. May be reduced in

View File

@@ -45,27 +45,30 @@ Atomic<uint64_t> AllocationReporter::allocated;
NS_IMPL_ISUPPORTS(AllocationReporter, nsIMemoryReporter) NS_IMPL_ISUPPORTS(AllocationReporter, nsIMemoryReporter)
static void RegisterAllocationMemoryReporter() { static void RegisterMemoryReporter() {
static Atomic<bool> registered; static Atomic<bool> registered;
if (registered.compareExchange(false, true)) { if (registered.compareExchange(false, true)) {
RegisterStrongMemoryReporter(new AllocationReporter()); RegisterStrongMemoryReporter(new AllocationReporter());
} }
} }
HandleBase::HandleBase() = default; HandleBase::HandleBase() { RegisterMemoryReporter(); }
HandleBase::~HandleBase() { HandleBase::~HandleBase() {
if (mSize > 0) { MOZ_ASSERT(AllocationReporter::allocated >= mSize,
MOZ_ASSERT(AllocationReporter::allocated >= mSize, "Can't destroy more than allocated");
"Can't destroy more than allocated"); AllocationReporter::allocated -= mSize;
SetSize(0);
}
mHandle = nullptr; mHandle = nullptr;
mSize = 0;
} }
HandleBase& HandleBase::operator=(HandleBase&& aOther) { HandleBase& HandleBase::operator=(HandleBase&& aOther) {
MOZ_ASSERT(AllocationReporter::allocated >= mSize,
"Can't destroy more than allocated");
AllocationReporter::allocated -= mSize;
mHandle = std::move(aOther.mHandle); mHandle = std::move(aOther.mHandle);
SetSize(std::exchange(aOther.mSize, 0)); mSize = std::exchange(aOther.mSize, 0);
return *this; return *this;
} }
@@ -73,71 +76,45 @@ HandleBase HandleBase::Clone() const {
HandleBase hb; HandleBase hb;
hb.mHandle = Platform::CloneHandle(mHandle); hb.mHandle = Platform::CloneHandle(mHandle);
if (hb.mHandle) { if (hb.mHandle) {
// TODO more intelligently handle clones to not count as additional hb.mSize = mSize;
// TODO more intelligently handle clones to not count as addition
// allocations? // allocations?
hb.SetSize(mSize); AllocationReporter::allocated += mSize;
} }
return hb; return hb;
} }
void HandleBase::ToMessageWriter(IPC::MessageWriter* aWriter) && { void HandleBase::ToMessageWriter(IPC::MessageWriter* aWriter) && {
MOZ_ASSERT(AllocationReporter::allocated >= mSize,
"Can't destroy more than allocated");
AllocationReporter::allocated -= mSize;
WriteParam(aWriter, std::move(mHandle)); WriteParam(aWriter, std::move(mHandle));
WriteParam(aWriter, mSize); WriteParam(aWriter, std::exchange(mSize, 0));
SetSize(0);
} }
bool HandleBase::FromMessageReader(IPC::MessageReader* aReader) { bool HandleBase::FromMessageReader(IPC::MessageReader* aReader) {
mozilla::ipc::shared_memory::PlatformHandle handle; mozilla::ipc::shared_memory::PlatformHandle handle;
if (!ReadParam(aReader, &handle)) { if (!ReadParam(aReader, &handle)) {
aReader->FatalError("Failed to read shared memory PlatformHandle");
return false; return false;
} }
if (handle && !Platform::IsSafeToMap(handle)) { 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; return false;
} }
mHandle = std::move(handle); mHandle = std::move(handle);
SetSize(size); if (!ReadParam(aReader, &mSize)) {
return false;
}
mozilla::ipc::shared_memory::AllocationReporter::allocated += mSize;
return true; return true;
} }
void HandleBase::SetSize(uint64_t aSize) { Mapping Handle::Map(void* aFixedAddress) const {
RegisterAllocationMemoryReporter(); return Mapping(*this, aFixedAddress);
mozilla::ipc::shared_memory::AllocationReporter::allocated -= mSize;
mSize = aSize;
mozilla::ipc::shared_memory::AllocationReporter::allocated += mSize;
} }
MutableMapping MutableHandle::Map(void* aFixedAddress) const { Mapping Handle::MapSubregion(uint64_t aOffset, size_t aSize,
return MutableMapping(*this, aFixedAddress); void* aFixedAddress) const {
} return Mapping(*this, aOffset, aSize, 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 { ReadOnlyMapping ReadOnlyHandle::Map(void* aFixedAddress) const {
@@ -149,24 +126,19 @@ ReadOnlyMapping ReadOnlyHandle::MapSubregion(uint64_t aOffset, size_t aSize,
return ReadOnlyMapping(*this, aOffset, aSize, aFixedAddress); return ReadOnlyMapping(*this, aOffset, aSize, aFixedAddress);
} }
ReadOnlyMappingWithHandle ReadOnlyHandle::MapWithHandle( FreezableHandle::~FreezableHandle() {
void* aFixedAddress) && {
return ReadOnlyMappingWithHandle(std::move(*this), aFixedAddress);
}
FreezableHandle::~Handle() {
NS_WARNING_ASSERTION(!IsValid(), "freezable shared memory was never frozen"); NS_WARNING_ASSERTION(!IsValid(), "freezable shared memory was never frozen");
} }
MutableHandle FreezableHandle::WontFreeze() && { Handle FreezableHandle::WontFreeze() && {
return std::move(*this).ConvertTo<Type::Mutable>(); return std::move(*this).ConvertTo<Handle>();
} }
ReadOnlyHandle FreezableHandle::Freeze() && { ReadOnlyHandle FreezableHandle::Freeze() && {
DebugOnly<const uint64_t> previous_size = Size(); DebugOnly<const uint64_t> previous_size = Size();
if (Platform::Freeze(*this)) { if (Platform::Freeze(*this)) {
MOZ_ASSERT(Size() == previous_size); MOZ_ASSERT(Size() == previous_size);
return std::move(*this).ConvertTo<Type::ReadOnly>(); return std::move(*this).ConvertTo<ReadOnlyHandle>();
} }
return nullptr; return nullptr;
} }
@@ -180,12 +152,13 @@ FreezableMapping FreezableHandle::MapSubregion(uint64_t aOffset, size_t aSize,
return FreezableMapping(std::move(*this), aOffset, aSize, aFixedAddress); return FreezableMapping(std::move(*this), aOffset, aSize, aFixedAddress);
} }
MutableHandle Create(uint64_t aSize) { Handle Create(uint64_t aSize) {
MutableHandle h; Handle h;
const auto success = Platform::Create(h, aSize); const auto success = Platform::Create(h, aSize);
MOZ_ASSERT(success == h.IsValid()); MOZ_ASSERT(success == h.IsValid());
if (success) { if (success) {
MOZ_ASSERT(aSize == h.Size()); MOZ_ASSERT(aSize == h.Size());
AllocationReporter::allocated += h.Size();
} }
return h; return h;
} }
@@ -196,6 +169,7 @@ FreezableHandle CreateFreezable(uint64_t aSize) {
MOZ_ASSERT(success == h.IsValid()); MOZ_ASSERT(success == h.IsValid());
if (success) { if (success) {
MOZ_ASSERT(aSize == h.Size()); MOZ_ASSERT(aSize == h.Size());
AllocationReporter::allocated += h.Size();
} }
return h; return h;
} }
@@ -204,15 +178,13 @@ FreezableHandle CreateFreezable(uint64_t aSize) {
namespace IPC { namespace IPC {
void ParamTraits<mozilla::ipc::shared_memory::MutableHandle>::Write( void ParamTraits<mozilla::ipc::shared_memory::Handle>::Write(
MessageWriter* aWriter, MessageWriter* aWriter, mozilla::ipc::shared_memory::Handle&& aParam) {
mozilla::ipc::shared_memory::MutableHandle&& aParam) {
std::move(aParam).ToMessageWriter(aWriter); std::move(aParam).ToMessageWriter(aWriter);
} }
bool ParamTraits<mozilla::ipc::shared_memory::MutableHandle>::Read( bool ParamTraits<mozilla::ipc::shared_memory::Handle>::Read(
MessageReader* aReader, MessageReader* aReader, mozilla::ipc::shared_memory::Handle* aResult) {
mozilla::ipc::shared_memory::MutableHandle* aResult) {
return aResult->FromMessageReader(aReader); return aResult->FromMessageReader(aReader);
} }

View File

@@ -9,31 +9,13 @@
#include <utility> #include <utility>
#include "chrome/common/ipc_message_utils.h"
#include "mozilla/UniquePtrExtensions.h" #include "mozilla/UniquePtrExtensions.h"
namespace IPC {
template <class P>
struct ParamTraits;
class MessageWriter;
class MessageReader;
} // namespace IPC
namespace mozilla::geckoargs {
template <typename T>
struct CommandLineArg;
}
namespace mozilla::ipc { namespace mozilla::ipc {
namespace shared_memory { namespace shared_memory {
enum class Type {
Mutable,
ReadOnly,
MutableOrReadOnly,
Freezable,
};
// Rust Bindgen code doesn't actually use these types, but `UniqueFileHandle` // Rust Bindgen code doesn't actually use these types, but `UniqueFileHandle`
// and `UniqueMachSendRight` aren't defined and some headers need to type check, // and `UniqueMachSendRight` aren't defined and some headers need to type check,
// so we define a dummy pointer type. // so we define a dummy pointer type.
@@ -45,23 +27,8 @@ using PlatformHandle = mozilla::UniqueMachSendRight;
using PlatformHandle = mozilla::UniqueFileHandle; using PlatformHandle = mozilla::UniqueFileHandle;
#endif #endif
template <Type T>
struct Handle; struct Handle;
struct ReadOnlyHandle;
template <Type T, bool WithHandle = false>
struct Mapping;
using MutableHandle = Handle<Type::Mutable>;
using ReadOnlyHandle = Handle<Type::ReadOnly>;
using FreezableHandle = Handle<Type::Freezable>;
using MutableMapping = Mapping<Type::Mutable>;
using ReadOnlyMapping = Mapping<Type::ReadOnly>;
using MutableOrReadOnlyMapping = Mapping<Type::MutableOrReadOnly>;
using FreezableMapping = Mapping<Type::Freezable>;
using MutableMappingWithHandle = Mapping<Type::Mutable, true>;
using ReadOnlyMappingWithHandle = Mapping<Type::ReadOnly, true>;
class HandleBase { class HandleBase {
public: public:
@@ -80,19 +47,9 @@ class HandleBase {
*/ */
explicit operator bool() const { return (bool)mHandle; } explicit operator bool() const { return (bool)mHandle; }
/**
* Take the platform handle.
*
* This should be used with caution, as it drops all of the guarantees of the
* shared memory handle classes.
*/
PlatformHandle TakePlatformHandle() && { return std::move(mHandle); }
friend class Platform; friend class Platform;
friend struct IPC::ParamTraits<mozilla::ipc::shared_memory::MutableHandle>; friend struct IPC::ParamTraits<mozilla::ipc::shared_memory::Handle>;
friend struct IPC::ParamTraits<mozilla::ipc::shared_memory::ReadOnlyHandle>; friend struct IPC::ParamTraits<mozilla::ipc::shared_memory::ReadOnlyHandle>;
friend struct mozilla::geckoargs::CommandLineArg<
mozilla::ipc::shared_memory::ReadOnlyHandle>;
protected: protected:
HandleBase(); HandleBase();
@@ -110,14 +67,14 @@ class HandleBase {
HandleBase Clone() const; HandleBase Clone() const;
template <Type T> template <typename Derived>
Handle<T> CloneAs() const { Derived CloneAs() const {
return Clone().ConvertTo<T>(); return Clone().ConvertTo<Derived>();
} }
template <Type T> template <typename Derived>
Handle<T> ConvertTo() && { Derived ConvertTo() && {
Handle<T> d; Derived d;
static_cast<HandleBase&>(d) = std::move(*this); static_cast<HandleBase&>(d) = std::move(*this);
return d; return d;
} }
@@ -126,14 +83,6 @@ class HandleBase {
bool FromMessageReader(IPC::MessageReader* aReader); bool FromMessageReader(IPC::MessageReader* aReader);
private: private:
/**
* Set the size of the handle.
*
* This method must be used rather than setting `mSize` directly, as there is
* additional bookkeeping that goes along with this value.
*/
void SetSize(uint64_t aSize);
PlatformHandle mHandle = nullptr; PlatformHandle mHandle = nullptr;
uint64_t mSize = 0; uint64_t mSize = 0;
}; };
@@ -141,8 +90,7 @@ class HandleBase {
/** /**
* A handle to a shared memory region. * A handle to a shared memory region.
*/ */
template <> struct Handle : HandleBase {
struct Handle<Type::Mutable> : HandleBase {
/** /**
* Create an empty Handle. * Create an empty Handle.
*/ */
@@ -152,72 +100,45 @@ struct Handle<Type::Mutable> : HandleBase {
/** /**
* Clone the handle. * Clone the handle.
*/ */
Handle Clone() const { return CloneAs<Type::Mutable>(); } Handle Clone() const { return CloneAs<Handle>(); }
/**
* Convert the handle to a read-only handle.
*
* Note that this doesn't enforce any sort of security or guarantees on the
* underlying shared memory.
*/
ReadOnlyHandle ToReadOnly() &&;
/**
* Use the handle as a read-only handle.
*
* Note that this doesn't enforce any sort of security or guarantees on the
* underlying shared memory.
*/
const ReadOnlyHandle& AsReadOnly() const;
/** /**
* Map the shared memory region into memory. * Map the shared memory region into memory.
*/ */
MutableMapping Map(void* aFixedAddress = nullptr) const; struct Mapping Map(void* aFixedAddress = nullptr) const;
/** /**
* Map a subregion of the shared memory region into memory. * Map a subregion of the shared memory region into memory.
*/ */
MutableMapping MapSubregion(uint64_t aOffset, size_t aSize, struct Mapping MapSubregion(uint64_t aOffset, size_t aSize,
void* aFixedAddress = nullptr) const; void* aFixedAddress = nullptr) const;
/**
* Map the shared memory region into memory, keeping the handle with it.
*/
MutableMappingWithHandle MapWithHandle(void* aFixedAddress = nullptr) &&;
}; };
/** /**
* A read-only handle to a shared memory region. * A read-only handle to a shared memory region.
*/ */
template <> struct ReadOnlyHandle : HandleBase {
struct Handle<Type::ReadOnly> : HandleBase {
/** /**
* Create an empty ReadOnlyHandle. * Create an empty ReadOnlyHandle.
*/ */
Handle() = default; ReadOnlyHandle() = default;
MOZ_IMPLICIT Handle(std::nullptr_t) {} MOZ_IMPLICIT ReadOnlyHandle(std::nullptr_t) {}
/** /**
* Clone the handle. * Clone the handle.
*/ */
Handle Clone() const { return CloneAs<Type::ReadOnly>(); } ReadOnlyHandle Clone() const { return CloneAs<ReadOnlyHandle>(); }
/** /**
* Map the shared memory region into memory. * Map the shared memory region into memory.
*/ */
ReadOnlyMapping Map(void* aFixedAddress = nullptr) const; struct ReadOnlyMapping Map(void* aFixedAddress = nullptr) const;
/** /**
* Map a subregion of the shared memory region into memory. * Map a subregion of the shared memory region into memory.
*/ */
ReadOnlyMapping MapSubregion(uint64_t aOffset, size_t aSize, struct ReadOnlyMapping MapSubregion(uint64_t aOffset, size_t aSize,
void* aFixedAddress = nullptr) const; void* aFixedAddress = nullptr) const;
/**
* Map the shared memory region into memory, keeping the handle with it.
*/
ReadOnlyMappingWithHandle MapWithHandle(void* aFixedAddress = nullptr) &&;
}; };
/** /**
@@ -226,22 +147,21 @@ struct Handle<Type::ReadOnly> : HandleBase {
* One cannot clone this handle, ensuring that at most one writable mapping * One cannot clone this handle, ensuring that at most one writable mapping
* exists. After freezing, no new writable mappings can be created. * exists. After freezing, no new writable mappings can be created.
*/ */
template <> struct FreezableHandle : HandleBase {
struct Handle<Type::Freezable> : HandleBase {
/** /**
* Create an empty FreezableHandle. * Create an empty FreezableHandle.
*/ */
Handle() = default; FreezableHandle() = default;
MOZ_IMPLICIT Handle(std::nullptr_t) {} MOZ_IMPLICIT FreezableHandle(std::nullptr_t) {}
~Handle(); ~FreezableHandle();
Handle(Handle&&) = default; FreezableHandle(FreezableHandle&&) = default;
Handle& operator=(Handle&&) = default; FreezableHandle& operator=(FreezableHandle&&) = default;
/** /**
* Convert to a normal handle if we will not freeze this handle. * Convert to a normal handle if we will not freeze this handle.
*/ */
MutableHandle WontFreeze() &&; Handle WontFreeze() &&;
/** /**
* Freeze this handle, returning a read-only handle. * Freeze this handle, returning a read-only handle.
@@ -251,13 +171,13 @@ struct Handle<Type::Freezable> : HandleBase {
/** /**
* Map the shared memory region into memory. * Map the shared memory region into memory.
*/ */
FreezableMapping Map(void* aFixedAddress = nullptr) &&; struct FreezableMapping Map(void* aFixedAddress = nullptr) &&;
/** /**
* Map a subregion of the shared memory region into memory. * Map a subregion of the shared memory region into memory.
*/ */
FreezableMapping MapSubregion(uint64_t aOffset, size_t aSize, struct FreezableMapping MapSubregion(uint64_t aOffset, size_t aSize,
void* aFixedAddress = nullptr) &&; void* aFixedAddress = nullptr) &&;
friend class Platform; friend class Platform;
#if !defined(XP_DARWIN) && !defined(XP_WIN) && !defined(ANDROID) #if !defined(XP_DARWIN) && !defined(XP_WIN) && !defined(ANDROID)
@@ -269,7 +189,7 @@ struct Handle<Type::Freezable> : HandleBase {
/** /**
* Create a new shared memory region. * Create a new shared memory region.
*/ */
MutableHandle Create(uint64_t aSize); Handle Create(uint64_t aSize);
/** /**
* Create a new freezable shared memory region. * Create a new freezable shared memory region.
@@ -283,20 +203,9 @@ MutableHandle Create(uint64_t aSize);
*/ */
FreezableHandle CreateFreezable(uint64_t aSize); FreezableHandle CreateFreezable(uint64_t aSize);
#if defined(XP_LINUX)
// If named POSIX shm is being used, append the prefix (including
// the leading '/') that would be used by a process with the given
// pid to the given string and return true. If not, return false.
// (This is public so that the Linux sandboxing code can use it.)
bool AppendPosixShmPrefix(std::string* str, pid_t pid);
// Returns whether POSIX shm is in use.
bool UsingPosixShm();
#endif
} // namespace shared_memory } // namespace shared_memory
using MutableSharedMemoryHandle = shared_memory::MutableHandle; using MutableSharedMemoryHandle = shared_memory::Handle;
using ReadOnlySharedMemoryHandle = shared_memory::ReadOnlyHandle; using ReadOnlySharedMemoryHandle = shared_memory::ReadOnlyHandle;
using FreezableSharedMemoryHandle = shared_memory::FreezableHandle; using FreezableSharedMemoryHandle = shared_memory::FreezableHandle;
@@ -305,11 +214,11 @@ using FreezableSharedMemoryHandle = shared_memory::FreezableHandle;
namespace IPC { namespace IPC {
template <> template <>
struct ParamTraits<mozilla::ipc::shared_memory::MutableHandle> { struct ParamTraits<mozilla::ipc::shared_memory::Handle> {
static void Write(MessageWriter* aWriter, static void Write(MessageWriter* aWriter,
mozilla::ipc::shared_memory::MutableHandle&& aParam); mozilla::ipc::shared_memory::Handle&& aParam);
static bool Read(MessageReader* aReader, static bool Read(MessageReader* aReader,
mozilla::ipc::shared_memory::MutableHandle* aResult); mozilla::ipc::shared_memory::Handle* aResult);
}; };
template <> template <>

View File

@@ -45,14 +45,14 @@ Atomic<size_t> MappingReporter::mapped;
NS_IMPL_ISUPPORTS(MappingReporter, nsIMemoryReporter) NS_IMPL_ISUPPORTS(MappingReporter, nsIMemoryReporter)
static void RegisterMappingMemoryReporter() { static void RegisterMemoryReporter() {
static Atomic<bool> registered; static Atomic<bool> registered;
if (registered.compareExchange(false, true)) { if (registered.compareExchange(false, true)) {
RegisterStrongMemoryReporter(new MappingReporter()); RegisterStrongMemoryReporter(new MappingReporter());
} }
} }
MappingBase::MappingBase() = default; MappingBase::MappingBase() { RegisterMemoryReporter(); }
MappingBase& MappingBase::operator=(MappingBase&& aOther) { MappingBase& MappingBase::operator=(MappingBase&& aOther) {
// Swap members with `aOther`, and unmap that mapping. // Swap members with `aOther`, and unmap that mapping.
@@ -62,7 +62,7 @@ MappingBase& MappingBase::operator=(MappingBase&& aOther) {
return *this; return *this;
} }
void* MappingBase::Address() const { void* MappingBase::Data() const {
#ifdef FUZZING #ifdef FUZZING
return SharedMemoryFuzzer::MutateSharedMemory(mMemory, mSize); return SharedMemoryFuzzer::MutateSharedMemory(mMemory, mSize);
#else #else
@@ -70,12 +70,15 @@ void* MappingBase::Address() const {
#endif #endif
} }
LeakedMapping MappingBase::release() && {
// NOTE: this doesn't reduce gShmemMapped since it _is_ still mapped memory
// (and will be until the process terminates).
return LeakedMapping{static_cast<uint8_t*>(std::exchange(mMemory, nullptr)),
std::exchange(mSize, 0)};
}
bool MappingBase::Map(const HandleBase& aHandle, void* aFixedAddress, bool MappingBase::Map(const HandleBase& aHandle, void* aFixedAddress,
bool aReadOnly) { bool aReadOnly) {
// Invalid handles will fail and result in an invalid mapping.
if (!aHandle) {
return false;
}
// Verify that the handle size can be stored as a mapping size first // Verify that the handle size can be stored as a mapping size first
// (otherwise it won't be possible to map in the address space and the Map // (otherwise it won't be possible to map in the address space and the Map
// call will fail). // call will fail).
@@ -101,8 +104,6 @@ bool MappingBase::MapSubregion(const HandleBase& aHandle, uint64_t aOffset,
return false; return false;
} }
RegisterMappingMemoryReporter();
if (auto mem = if (auto mem =
Platform::Map(aHandle, aOffset, aSize, aFixedAddress, aReadOnly)) { Platform::Map(aHandle, aOffset, aSize, aFixedAddress, aReadOnly)) {
mMemory = *mem; mMemory = *mem;
@@ -125,48 +126,43 @@ void MappingBase::Unmap() {
mSize = 0; mSize = 0;
} }
std::tuple<void*, size_t> MappingBase::Release() && { Mapping::Mapping(const Handle& aHandle, void* aFixedAddress) {
// NOTE: this doesn't reduce gShmemMapped since it _is_ still mapped memory
// (and will be until the process terminates).
return std::make_tuple(std::exchange(mMemory, nullptr),
std::exchange(mSize, 0));
}
MutableOrReadOnlyMapping::Mapping(const MutableHandle& aHandle,
void* aFixedAddress)
: mReadOnly(false) {
Map(aHandle, aFixedAddress, false); Map(aHandle, aFixedAddress, false);
} }
MutableOrReadOnlyMapping::Mapping(const ReadOnlyHandle& aHandle, Mapping::Mapping(const Handle& aHandle, uint64_t aOffset, size_t aSize,
void* aFixedAddress) void* aFixedAddress) {
: mReadOnly(true) { MapSubregion(aHandle, aOffset, aSize, aFixedAddress, false);
}
ReadOnlyMapping::ReadOnlyMapping(const ReadOnlyHandle& aHandle,
void* aFixedAddress) {
Map(aHandle, aFixedAddress, true); Map(aHandle, aFixedAddress, true);
} }
MutableOrReadOnlyMapping::Mapping(MutableMapping&& aMapping) ReadOnlyMapping::ReadOnlyMapping(const ReadOnlyHandle& aHandle,
: MappingData(std::move(aMapping)), mReadOnly(false) {} uint64_t aOffset, size_t aSize,
void* aFixedAddress) {
MutableOrReadOnlyMapping::Mapping(ReadOnlyMapping&& aMapping) MapSubregion(aHandle, aOffset, aSize, aFixedAddress, true);
: MappingData(std::move(aMapping)), mReadOnly(true) {}
// We still store the handle if `Map` fails: the user may want to get it back
// (for instance, if fixed-address mapping doesn't work they may try mapping
// without one).
FreezableMapping::Mapping(FreezableHandle&& aHandle, void* aFixedAddress)
: mHandle(std::move(aHandle)) {
Map(mHandle, aFixedAddress, false);
} }
FreezableMapping::Mapping(FreezableHandle&& aHandle, uint64_t aOffset, FreezableMapping::FreezableMapping(FreezableHandle&& aHandle,
size_t aSize, void* aFixedAddress) void* aFixedAddress) {
: mHandle(std::move(aHandle)) { if (Map(aHandle, aFixedAddress, false)) {
MapSubregion(mHandle, aOffset, aSize, aFixedAddress, false); mHandle = std::move(aHandle);
}
} }
std::tuple<MutableMapping, ReadOnlyHandle> FreezableMapping::Freeze() && { FreezableMapping::FreezableMapping(FreezableHandle&& aHandle, uint64_t aOffset,
size_t aSize, void* aFixedAddress) {
if (MapSubregion(aHandle, aOffset, aSize, aFixedAddress, false)) {
mHandle = std::move(aHandle);
}
}
std::tuple<Mapping, ReadOnlyHandle> FreezableMapping::Freeze() && {
auto handle = std::move(mHandle); auto handle = std::move(mHandle);
return std::make_tuple(ConvertMappingTo<Type::Mutable>(std::move(*this)), return std::make_tuple(std::move(*this).ConvertTo<Mapping>(),
std::move(handle).Freeze()); std::move(handle).Freeze());
} }
@@ -176,10 +172,6 @@ FreezableHandle FreezableMapping::Unmap() && {
return handle; return handle;
} }
bool LocalProtect(char* aAddr, size_t aSize, Access aAccess) {
return Platform::Protect(aAddr, aSize, aAccess);
}
void* FindFreeAddressSpace(size_t aSize) { void* FindFreeAddressSpace(size_t aSize) {
return Platform::FindFreeAddressSpace(aSize); return Platform::FindFreeAddressSpace(aSize);
} }
@@ -196,4 +188,8 @@ size_t PageAlignedSize(size_t aMinimum) {
return pageSize * nPagesNeeded; return pageSize * nPagesNeeded;
} }
bool Protect(char* aAddr, size_t aSize, Access aAccess) {
return Platform::Protect(aAddr, aSize, aAccess);
}
} // namespace mozilla::ipc::shared_memory } // namespace mozilla::ipc::shared_memory

View File

@@ -8,7 +8,6 @@
#define mozilla_ipc_SharedMemoryMapping_h #define mozilla_ipc_SharedMemoryMapping_h
#include <tuple> #include <tuple>
#include <type_traits>
#include <utility> #include <utility>
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/Span.h" #include "mozilla/Span.h"
@@ -23,19 +22,10 @@ namespace shared_memory {
* *
* This memory will never be unmapped. * This memory will never be unmapped.
*/ */
template <Type T>
struct LeakedMapping : Span<uint8_t> { struct LeakedMapping : Span<uint8_t> {
using Span::Span; using Span::Span;
}; };
template <>
struct LeakedMapping<Type::ReadOnly> : Span<const uint8_t> {
using Span::Span;
};
using LeakedMutableMapping = LeakedMapping<Type::Mutable>;
using LeakedReadOnlyMapping = LeakedMapping<Type::ReadOnly>;
class MappingBase { class MappingBase {
public: public:
/** /**
@@ -46,7 +36,24 @@ class MappingBase {
/** /**
* The pointer to the mapping in memory. * The pointer to the mapping in memory.
*/ */
void* Address() const; void* Data() const;
/**
* Get a `Span<T>` over the mapping.
*
* The mapping data must meet the alignment requirements of @p T.
*
* @tparam T The type of data in the mapping.
*
* @return A span of type @p T covering as much of the mapping as possible.
*/
template <typename T>
Span<T> DataAsSpan() const {
MOZ_ASSERT((reinterpret_cast<uintptr_t>(Data()) % alignof(T)) == 0,
"memory map does not meet alignment requirements of type");
size_t count = Size() / sizeof(T);
return {static_cast<T*>(Data()), count};
}
/** /**
* Whether this shared memory mapping is valid. * Whether this shared memory mapping is valid.
@@ -83,82 +90,11 @@ class MappingBase {
void* aFixedAddress, bool aReadOnly); void* aFixedAddress, bool aReadOnly);
void Unmap(); void Unmap();
template <Type T, Type S> template <typename Derived>
static Mapping<T> ConvertMappingTo(Mapping<S>&& from) { Derived ConvertTo() && {
Mapping<T> to; Derived d;
static_cast<MappingBase&>(to) = std::move(from); static_cast<MappingBase&>(d) = std::move(*this);
return to; return d;
}
std::tuple<void*, size_t> Release() &&;
private:
void* mMemory = nullptr;
size_t mSize = 0;
};
template <bool CONST_MEMORY>
struct MappingData : MappingBase {
private:
template <typename T>
using DataType =
std::conditional_t<CONST_MEMORY, std::add_const_t<std::remove_const_t<T>>,
T>;
protected:
MappingData() = default;
explicit MappingData(MappingBase&& aOther) : MappingBase(std::move(aOther)) {}
public:
/**
* Get a pointer to the data in the mapping as a type T.
*
* The mapping data must meet the alignment requirements of @p T.
*
* @tparam T The type of data in the mapping.
*
* @return A pointer of type @p T*.
*/
template <typename T>
DataType<T>* DataAs() const {
MOZ_ASSERT((reinterpret_cast<uintptr_t>(Address()) % alignof(T)) == 0,
"memory map does not meet alignment requirements of type");
return static_cast<DataType<T>*>(Address());
}
/**
* Get a `Span<T>` over the mapping.
*
* The mapping data must meet the alignment requirements of @p T.
*
* @tparam T The type of data in the mapping.
*
* @return A span of type @p T covering as much of the mapping as possible.
*/
template <typename T>
Span<DataType<T>> DataAsSpan() const {
return {DataAs<T>(), Size() / sizeof(T)};
}
};
/**
* A shared memory mapping.
*/
template <Type T>
struct Mapping<T> : MappingData<T == Type::ReadOnly> {
/**
* Create an empty Mapping.
*/
Mapping() = default;
MOZ_IMPLICIT Mapping(std::nullptr_t) {}
explicit Mapping(const Handle<T>& aHandle, void* aFixedAddress = nullptr) {
MappingBase::Map(aHandle, aFixedAddress, T == Type::ReadOnly);
}
Mapping(const Handle<T>& aHandle, uint64_t aOffset, size_t aSize,
void* aFixedAddress = nullptr) {
MappingBase::MapSubregion(aHandle, aOffset, aSize, aFixedAddress,
T == Type::ReadOnly);
} }
/** /**
@@ -166,49 +102,55 @@ struct Mapping<T> : MappingData<T == Type::ReadOnly> {
* *
* This will cause the memory to be mapped until the process exits. * This will cause the memory to be mapped until the process exits.
*/ */
LeakedMapping<T> Release() && { LeakedMapping release() &&;
auto [ptr, size] = std::move(*this).MappingBase::Release();
return LeakedMapping<T>{ private:
static_cast<typename LeakedMapping<T>::pointer>(ptr), size}; void* mMemory = nullptr;
} size_t mSize = 0;
}; };
/** /**
* A shared memory mapping which has runtime-stored mutability. * A shared memory mapping.
*/ */
template <> struct Mapping : MappingBase {
struct Mapping<Type::MutableOrReadOnly> : MappingData<true> {
/** /**
* Create an empty MutableOrReadOnlyMapping. * Create an empty Mapping.
*/ */
Mapping() = default; Mapping() = default;
MOZ_IMPLICIT Mapping(std::nullptr_t) {} MOZ_IMPLICIT Mapping(std::nullptr_t) {}
explicit Mapping(const ReadOnlyHandle& aHandle, explicit Mapping(const Handle& aHandle, void* aFixedAddress = nullptr);
void* aFixedAddress = nullptr); Mapping(const Handle& aHandle, uint64_t aOffset, size_t aSize,
explicit Mapping(const MutableHandle& aHandle, void* aFixedAddress = nullptr); void* aFixedAddress = nullptr);
MOZ_IMPLICIT Mapping(ReadOnlyMapping&& aMapping);
MOZ_IMPLICIT Mapping(MutableMapping&& aMapping);
using MappingBase::release;
};
/**
* A read-only shared memory mapping.
*/
struct ReadOnlyMapping : MappingBase {
/** /**
* Return whether the mapping is read-only. * Create an empty ReadOnlyMapping.
*/ */
bool IsReadOnly() const { return mReadOnly; } ReadOnlyMapping() = default;
MOZ_IMPLICIT ReadOnlyMapping(std::nullptr_t) {}
private: explicit ReadOnlyMapping(const ReadOnlyHandle& aHandle,
bool mReadOnly = false; void* aFixedAddress = nullptr);
ReadOnlyMapping(const ReadOnlyHandle& aHandle, uint64_t aOffset, size_t aSize,
void* aFixedAddress = nullptr);
}; };
/** /**
* A freezable shared memory mapping. * A freezable shared memory mapping.
*/ */
template <> struct FreezableMapping : MappingBase {
struct Mapping<Type::Freezable> : MappingData<false> {
/** /**
* Create an empty FreezableMapping. * Create an empty FreezableMapping.
*/ */
Mapping() = default; FreezableMapping() = default;
MOZ_IMPLICIT Mapping(std::nullptr_t) {} MOZ_IMPLICIT FreezableMapping(std::nullptr_t) {}
/** /**
* Freezable mappings take ownership of a handle to ensure there is only one * Freezable mappings take ownership of a handle to ensure there is only one
@@ -216,9 +158,10 @@ struct Mapping<Type::Freezable> : MappingData<false> {
* *
* Call `Unmap()` to get the handle back. * Call `Unmap()` to get the handle back.
*/ */
explicit Mapping(FreezableHandle&& aHandle, void* aFixedAddress = nullptr); explicit FreezableMapping(FreezableHandle&& aHandle,
Mapping(FreezableHandle&& aHandle, uint64_t aOffset, size_t aSize, void* aFixedAddress = nullptr);
void* aFixedAddress = nullptr); FreezableMapping(FreezableHandle&& aHandle, uint64_t aOffset, size_t aSize,
void* aFixedAddress = nullptr);
/** /**
* Freeze the shared memory region. * Freeze the shared memory region.
@@ -226,7 +169,7 @@ struct Mapping<Type::Freezable> : MappingData<false> {
* The returned Mapping will still be valid and writable until it is deleted, * The returned Mapping will still be valid and writable until it is deleted,
* however no new writable mappings can be created. * however no new writable mappings can be created.
*/ */
std::tuple<MutableMapping, ReadOnlyHandle> Freeze() &&; std::tuple<Mapping, ReadOnlyHandle> Freeze() &&;
/** /**
* Unmap the shared memory, returning the freezable handle. * Unmap the shared memory, returning the freezable handle.
@@ -236,35 +179,10 @@ struct Mapping<Type::Freezable> : MappingData<false> {
*/ */
FreezableHandle Unmap() &&; FreezableHandle Unmap() &&;
protected: private:
FreezableHandle mHandle; FreezableHandle mHandle;
}; };
template <Type T>
struct Mapping<T, true> : public Mapping<T> {
Mapping() {}
MOZ_IMPLICIT Mapping(std::nullptr_t) : Mapping<T>(nullptr) {}
explicit Mapping(Handle<T>&& aHandle, void* aFixedAddress = nullptr)
: Mapping<T>(aHandle, aFixedAddress), mHandle(std::move(aHandle)) {}
const Handle<T>& Handle() const { return mHandle; };
std::tuple<shared_memory::Handle<T>, Mapping<T>> Split() && {
auto handle = std::move(mHandle);
return std::make_tuple(std::move(handle), std::move(*this));
}
private:
shared_memory::Handle<T> mHandle;
};
// To uphold the guarantees of freezable mappings, we do not allow access to the
// handle (and since this should never be used in this way, we make it a useless
// type).
template <>
struct Mapping<Type::Freezable, true>;
// The access level permitted for memory protection. // The access level permitted for memory protection.
enum Access { enum Access {
AccessNone = 0, AccessNone = 0,
@@ -320,16 +238,10 @@ size_t PageAlignedSize(size_t aMinimum);
} // namespace shared_memory } // namespace shared_memory
using SharedMemoryMapping = shared_memory::MutableMapping; using SharedMemoryMapping = shared_memory::Mapping;
using ReadOnlySharedMemoryMapping = shared_memory::ReadOnlyMapping; using ReadOnlySharedMemoryMapping = shared_memory::ReadOnlyMapping;
using MutableOrReadOnlySharedMemoryMapping =
shared_memory::MutableOrReadOnlyMapping;
using FreezableSharedMemoryMapping = shared_memory::FreezableMapping; using FreezableSharedMemoryMapping = shared_memory::FreezableMapping;
using SharedMemoryMappingWithHandle = shared_memory::MutableMappingWithHandle;
using ReadOnlySharedMemoryMappingWithHandle =
shared_memory::ReadOnlyMappingWithHandle;
} // namespace mozilla::ipc } // namespace mozilla::ipc
#endif #endif

View File

@@ -10,7 +10,6 @@
#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/ipc/SharedMemoryHandle.h"
#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/ipc/SharedMemoryMapping.h"
#include "mozilla/Logging.h" #include "mozilla/Logging.h"
#include "mozilla/Maybe.h"
namespace mozilla::ipc::shared_memory { namespace mozilla::ipc::shared_memory {
@@ -34,7 +33,7 @@ class Platform {
* *
* @returns Whether the handle was successfully created. * @returns Whether the handle was successfully created.
*/ */
static bool Create(MutableHandle& aHandle, size_t aSize); static bool Create(Handle& aHandle, size_t aSize);
/** /**
* Create a new freezable shared memory handle. * Create a new freezable shared memory handle.

View File

@@ -41,13 +41,10 @@ static Maybe<PlatformHandle> CreateImpl(size_t aSize, bool aFreezable) {
return Some(fd); return Some(fd);
} }
bool AppendPosixShmPrefix(std::string* str, pid_t pid) { return false; } bool Platform::Create(Handle& aHandle, size_t aSize) {
bool UsingPosixShm() { return false; }
bool Platform::Create(MutableHandle& aHandle, size_t aSize) {
if (auto ph = CreateImpl(aSize, false)) { if (auto ph = CreateImpl(aSize, false)) {
aHandle.mHandle = std::move(*ph); aHandle.mHandle = std::move(*ph);
aHandle.SetSize(aSize); aHandle.mSize = aSize;
return true; return true;
} }
return false; return false;
@@ -56,7 +53,7 @@ bool Platform::Create(MutableHandle& aHandle, size_t aSize) {
bool Platform::CreateFreezable(FreezableHandle& aHandle, size_t aSize) { bool Platform::CreateFreezable(FreezableHandle& aHandle, size_t aSize) {
if (auto ph = CreateImpl(aSize, true)) { if (auto ph = CreateImpl(aSize, true)) {
aHandle.mHandle = std::move(*ph); aHandle.mHandle = std::move(*ph);
aHandle.SetSize(aSize); aHandle.mSize = aSize;
return true; return true;
} }
return false; return false;

View File

@@ -30,7 +30,6 @@
#include "mozilla/IntegerPrintfMacros.h" #include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Printf.h" #include "mozilla/Printf.h"
#include "nsDebug.h"
#ifdef DEBUG #ifdef DEBUG
# define LOG_ERROR(str, args...) \ # define LOG_ERROR(str, args...) \
@@ -70,10 +69,10 @@ static Maybe<PlatformHandle> CreateImpl(size_t aSize, bool aFreezable) {
return Some(std::move(handle)); return Some(std::move(handle));
} }
bool Platform::Create(MutableHandle& aHandle, size_t aSize) { bool Platform::Create(Handle& aHandle, size_t aSize) {
if (auto ph = CreateImpl(aSize, false)) { if (auto ph = CreateImpl(aSize, false)) {
aHandle.mHandle = std::move(*ph); aHandle.mHandle = std::move(*ph);
aHandle.SetSize(aSize); aHandle.mSize = aSize;
return true; return true;
} }
return false; return false;
@@ -82,7 +81,7 @@ bool Platform::Create(MutableHandle& aHandle, size_t aSize) {
bool Platform::CreateFreezable(FreezableHandle& aHandle, size_t aSize) { bool Platform::CreateFreezable(FreezableHandle& aHandle, size_t aSize) {
if (auto ph = CreateImpl(aSize, true)) { if (auto ph = CreateImpl(aSize, true)) {
aHandle.mHandle = std::move(*ph); aHandle.mHandle = std::move(*ph);
aHandle.SetSize(aSize); aHandle.mSize = aSize;
return true; return true;
} }
return false; return false;

Some files were not shown because too many files have changed in this diff Show More