diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index c150bca11772..50fbd368f9b3 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -220,7 +220,6 @@ #include "mozilla/gfx/Rect.h" #include "mozilla/gfx/Types.h" #include "mozilla/ipc/ProtocolUtils.h" -#include "mozilla/ipc/SharedMemory.h" #include "mozilla/net/UrlClassifierCommon.h" #include "mozilla/Tokenizer.h" #include "mozilla/widget/IMEData.h" diff --git a/dom/canvas/DrawTargetWebgl.cpp b/dom/canvas/DrawTargetWebgl.cpp index 8cb34c8464bf..2d554f169643 100644 --- a/dom/canvas/DrawTargetWebgl.cpp +++ b/dom/canvas/DrawTargetWebgl.cpp @@ -443,25 +443,28 @@ bool DrawTargetWebgl::Init(const IntSize& size, const SurfaceFormat format, return false; } - size_t shmemSize = mozilla::ipc::SharedMemory::PageAlignedSize(byteSize); + size_t shmemSize = mozilla::ipc::shared_memory::PageAlignedSize(byteSize); if (NS_WARN_IF(shmemSize > UINT32_MAX)) { MOZ_ASSERT_UNREACHABLE("Buffer too big?"); return false; } - auto shmem = MakeRefPtr(); - if (NS_WARN_IF(!shmem->Create(shmemSize)) || - NS_WARN_IF(!shmem->Map(shmemSize))) { + auto handle = mozilla::ipc::shared_memory::Create(shmemSize); + if (NS_WARN_IF(!handle)) { + return false; + } + auto mapping = handle.Map(); + if (NS_WARN_IF(!mapping)) { return false; } - mShmem = std::move(shmem); - mShmemSize = shmemSize; + mShmemHandle = std::move(handle).ToReadOnly(); + mShmem = std::move(mapping); mSkia = new DrawTargetSkia; auto stride = layers::ImageDataSerializer::ComputeRGBStride( SurfaceFormat::B8G8R8A8, size.width); - if (!mSkia->Init(reinterpret_cast(mShmem->Memory()), size, stride, + if (!mSkia->Init(mShmem.DataAs(), size, stride, SurfaceFormat::B8G8R8A8, true)) { return false; } diff --git a/dom/canvas/DrawTargetWebgl.h b/dom/canvas/DrawTargetWebgl.h index a063487069f2..21364c5ca585 100644 --- a/dom/canvas/DrawTargetWebgl.h +++ b/dom/canvas/DrawTargetWebgl.h @@ -14,7 +14,8 @@ #include "mozilla/LinkedList.h" #include "mozilla/WeakPtr.h" #include "mozilla/ThreadLocal.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/layers/LayersTypes.h" #include @@ -381,12 +382,13 @@ class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr { RefPtr mSkia; // Skia DT pointing to the same pixel data, but without any applied clips. RefPtr 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. - RefPtr mShmem; + mozilla::ipc::SharedMemoryMapping mShmem; // The currently cached snapshot of the WebGL context RefPtr mSnapshot; - // The mappable size of mShmem. - uint32_t mShmemSize = 0; // Whether the framebuffer is still in the initially clear state. bool mIsClear = true; // Whether or not the Skia target has valid contents and is being drawn to @@ -605,13 +607,10 @@ class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr { return stream.str(); } - mozilla::ipc::SharedMemory::Handle TakeShmemHandle() const { - return mShmem ? mShmem->TakeHandle() - : mozilla::ipc::SharedMemory::NULLHandle(); + mozilla::ipc::ReadOnlySharedMemoryHandle TakeShmemHandle() { + return std::move(mShmemHandle); } - uint32_t GetShmemSize() const { return mShmemSize; } - private: bool SupportsPattern(const Pattern& aPattern) { return mSharedContext->SupportsPattern(aPattern); diff --git a/dom/canvas/QueueParamTraits.h b/dom/canvas/QueueParamTraits.h index a8a0b43510ea..3bb89a719a1d 100644 --- a/dom/canvas/QueueParamTraits.h +++ b/dom/canvas/QueueParamTraits.h @@ -13,7 +13,6 @@ #include "mozilla/Assertions.h" #include "mozilla/IntegerRange.h" #include "mozilla/ipc/ProtocolUtils.h" -#include "mozilla/ipc/SharedMemory.h" #include "mozilla/Logging.h" #include "mozilla/TimeStamp.h" #include "nsExceptionHandler.h" diff --git a/dom/canvas/WebGLTypes.h b/dom/canvas/WebGLTypes.h index 75479f027d1a..8e721f6d51f8 100644 --- a/dom/canvas/WebGLTypes.h +++ b/dom/canvas/WebGLTypes.h @@ -41,7 +41,6 @@ #include "nsTArray.h" #include "nsString.h" #include "mozilla/dom/WebGLRenderingContextBinding.h" -#include "mozilla/ipc/SharedMemory.h" // Manual reflection of WebIDL typedefs that are different from their // OpenGL counterparts. diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index d320185ab898..c85cff8b5294 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -652,9 +652,9 @@ NS_INTERFACE_MAP_END mozilla::ipc::IPCResult ContentChild::RecvSetXPCOMProcessAttributes( XPCOMInitData&& aXPCOMInit, const StructuredCloneData& aInitialData, FullLookAndFeel&& aLookAndFeelData, dom::SystemFontList&& aFontList, - Maybe&& aSharedUASheetHandle, + Maybe&& aSharedUASheetHandle, const uintptr_t& aSharedUASheetAddress, - nsTArray&& aSharedFontListBlocks, + nsTArray&& aSharedFontListBlocks, const bool& aIsReadyForBackgroundProcessing) { if (!sShutdownCanary) { return IPC_OK(); @@ -1332,8 +1332,9 @@ void ContentChild::InitGraphicsDeviceData(const ContentDeviceData& aData) { gfxPlatform::InitChild(aData); } -void ContentChild::InitSharedUASheets(Maybe&& aHandle, - uintptr_t aAddress) { +void ContentChild::InitSharedUASheets( + Maybe&& aHandle, + uintptr_t aAddress) { MOZ_ASSERT_IF(!aHandle, !aAddress); if (!aAddress) { @@ -2349,7 +2350,7 @@ mozilla::ipc::IPCResult ContentChild::RecvRegisterStringBundles( for (auto& descriptor : aDescriptors) { stringBundleService->RegisterContentBundle( - descriptor.bundleURL(), descriptor.mapHandle(), descriptor.mapSize()); + descriptor.bundleURL(), std::move(descriptor.mapHandle())); } return IPC_OK(); @@ -2369,7 +2370,7 @@ mozilla::ipc::IPCResult ContentChild::RecvUpdateL10nFileSources( } mozilla::ipc::IPCResult ContentChild::RecvUpdateSharedData( - SharedMemoryHandle&& aMapHandle, const uint32_t& aMapSize, + mozilla::ipc::ReadOnlySharedMemoryHandle&& aMapHandle, nsTArray&& aBlobs, nsTArray&& aChangedKeys) { nsTArray> blobImpls(aBlobs.Length()); for (auto& ipcBlob : aBlobs) { @@ -2377,12 +2378,12 @@ mozilla::ipc::IPCResult ContentChild::RecvUpdateSharedData( } if (mSharedData) { - mSharedData->Update(std::move(aMapHandle), aMapSize, std::move(blobImpls), + mSharedData->Update(std::move(aMapHandle), std::move(blobImpls), std::move(aChangedKeys)); } else { mSharedData = new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(), - std::move(aMapHandle), aMapSize, std::move(blobImpls)); + std::move(aMapHandle), std::move(blobImpls)); } return IPC_OK(); @@ -2443,7 +2444,7 @@ mozilla::ipc::IPCResult ContentChild::RecvRebuildFontList( mozilla::ipc::IPCResult ContentChild::RecvFontListShmBlockAdded( const uint32_t& aGeneration, const uint32_t& aIndex, - SharedMemoryHandle&& aHandle) { + mozilla::ipc::ReadOnlySharedMemoryHandle&& aHandle) { if (gfxPlatform::Initialized()) { gfxPlatformFontList::PlatformFontList()->ShmBlockAdded(aGeneration, aIndex, std::move(aHandle)); diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index d557ef39e40b..f2251570c573 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -17,6 +17,7 @@ #include "mozilla/Hal.h" #include "mozilla/ipc/InputStreamUtils.h" #include "mozilla/ipc/ProtocolUtils.h" +#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/StaticPtr.h" #include "mozilla/UniquePtr.h" #include "nsClassHashtable.h" @@ -119,8 +120,9 @@ class ContentChild final : public PContentChild, const mozilla::dom::ipc::StructuredCloneData& aInitialData, bool aIsReadyForBackgroundProcessing); - void InitSharedUASheets(Maybe&& aHandle, - uintptr_t aAddress); + void InitSharedUASheets( + Maybe&& aHandle, + uintptr_t aAddress); void InitGraphicsDeviceData(const ContentDeviceData& aData); @@ -309,7 +311,7 @@ class ContentChild final : public PContentChild, nsTArray&& aDescriptors); mozilla::ipc::IPCResult RecvUpdateSharedData( - SharedMemoryHandle&& aMapHandle, const uint32_t& aMapSize, + mozilla::ipc::ReadOnlySharedMemoryHandle&& aMapHandle, nsTArray&& aBlobs, nsTArray&& aChangedKeys); mozilla::ipc::IPCResult RecvForceGlobalReflow( @@ -329,7 +331,7 @@ class ContentChild final : public PContentChild, mozilla::ipc::IPCResult RecvRebuildFontList(const bool& aFullRebuild); mozilla::ipc::IPCResult RecvFontListShmBlockAdded( const uint32_t& aGeneration, const uint32_t& aIndex, - SharedMemoryHandle&& aHandle); + mozilla::ipc::ReadOnlySharedMemoryHandle&& aHandle); mozilla::ipc::IPCResult RecvUpdateAppLocales( nsTArray&& aAppLocales); @@ -503,9 +505,10 @@ class ContentChild final : public PContentChild, mozilla::ipc::IPCResult RecvSetXPCOMProcessAttributes( XPCOMInitData&& aXPCOMInit, const StructuredCloneData& aInitialData, FullLookAndFeel&& aLookAndFeelData, SystemFontList&& aFontList, - Maybe&& aSharedUASheetHandle, + Maybe&& aSharedUASheetHandle, const uintptr_t& aSharedUASheetAddress, - nsTArray&& aSharedFontListBlocks, + nsTArray&& + aSharedFontListBlocks, const bool& aIsReadyForBackgroundProcessing); mozilla::ipc::IPCResult RecvProvideAnonymousTemporaryFile( @@ -535,7 +538,7 @@ class ContentChild final : public PContentChild, // for use during gfx initialization. SystemFontList& SystemFontList() { return mFontList; } - nsTArray& SharedFontListBlocks() { + nsTArray& SharedFontListBlocks() { return mSharedFontListBlocks; } @@ -834,7 +837,7 @@ class ContentChild final : public PContentChild, // Temporary storage for look and feel data. FullLookAndFeel mLookAndFeelData; // Temporary storage for list of shared-fontlist memory blocks. - nsTArray mSharedFontListBlocks; + nsTArray mSharedFontListBlocks; AppInfo mAppInfo; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index b553d6bad93b..061bebee9f87 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -152,7 +152,7 @@ #include "mozilla/ipc/Endpoint.h" #include "mozilla/ipc/FileDescriptorUtils.h" #include "mozilla/ipc/IPCStreamUtils.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/ipc/TestShellParent.h" #include "mozilla/layers/CompositorThread.h" #include "mozilla/layers/ImageBridgeParent.h" @@ -1536,9 +1536,8 @@ void ContentParent::BroadcastStringBundle( const StringBundleDescriptor& aBundle) { for (auto* cp : AllProcesses(eLive)) { AutoTArray array; - array.AppendElement(StringBundleDescriptor( - aBundle.bundleURL(), SharedMemory::CloneHandle(aBundle.mapHandle()), - aBundle.mapSize())); + array.AppendElement(StringBundleDescriptor(aBundle.bundleURL(), + aBundle.mapHandle().Clone())); Unused << cp->SendRegisterStringBundles(std::move(array)); } } @@ -1547,9 +1546,9 @@ void ContentParent::BroadcastShmBlockAdded(uint32_t aGeneration, uint32_t aIndex) { auto* pfl = gfxPlatformFontList::PlatformFontList(); for (auto* cp : AllProcesses(eLive)) { - SharedMemory::Handle handle = + ReadOnlySharedMemoryHandle handle = pfl->ShareShmBlockToProcess(aIndex, cp->Pid()); - if (handle == SharedMemory::NULLHandle()) { + if (!handle.IsValid()) { // If something went wrong here, we just skip it; the child will need to // request the block as needed, at some performance cost. continue; @@ -2811,7 +2810,7 @@ bool ContentParent::InitInternal(ProcessPriority aInitialPriority) { // If the shared fontlist is in use, collect its shmem block handles to pass // to the child. - nsTArray sharedFontListBlocks; + nsTArray sharedFontListBlocks; gfxPlatformFontList::PlatformFontList()->ShareFontListToProcess( &sharedFontListBlocks, OtherPid()); @@ -2850,10 +2849,10 @@ bool ContentParent::InitInternal(ProcessPriority aInitialPriority) { screenManager.CopyScreensToRemote(this); // Send the UA sheet shared memory buffer and the address it is mapped at. - Maybe sharedUASheetHandle; + Maybe sharedUASheetHandle; uintptr_t sharedUASheetAddress = sheetCache->GetSharedMemoryAddress(); - if (SharedMemoryHandle handle = sheetCache->CloneHandle()) { + if (ReadOnlySharedMemoryHandle handle = sheetCache->CloneHandle()) { sharedUASheetHandle.emplace(std::move(handle)); } else { sharedUASheetAddress = 0; @@ -5628,7 +5627,7 @@ mozilla::ipc::IPCResult ContentParent::RecvShutdownPerfStats( mozilla::ipc::IPCResult ContentParent::RecvGetFontListShmBlock( const uint32_t& aGeneration, const uint32_t& aIndex, - SharedMemory::Handle* aOut) { + ReadOnlySharedMemoryHandle* aOut) { auto* fontList = gfxPlatformFontList::PlatformFontList(); MOZ_RELEASE_ASSERT(fontList, "gfxPlatformFontList not initialized?"); fontList->ShareFontListShmBlockToProcess(aGeneration, aIndex, Pid(), aOut); @@ -5680,12 +5679,12 @@ mozilla::ipc::IPCResult ContentParent::RecvStartCmapLoading( } mozilla::ipc::IPCResult ContentParent::RecvGetHyphDict( - nsIURI* aURI, SharedMemory::Handle* aOutHandle, uint32_t* aOutSize) { + nsIURI* aURI, ReadOnlySharedMemoryHandle* aOutHandle) { if (!aURI) { return IPC_FAIL(this, "aURI must not be null."); } - nsHyphenationManager::Instance()->ShareHyphDictToProcess( - aURI, Pid(), aOutHandle, aOutSize); + nsHyphenationManager::Instance()->ShareHyphDictToProcess(aURI, Pid(), + aOutHandle); return IPC_OK(); } diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 675c8a9635f4..f2fb07368546 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -22,7 +22,7 @@ #include "mozilla/ipc/BackgroundUtils.h" #include "mozilla/ipc/GeckoChildProcessHost.h" #include "mozilla/ipc/InputStreamUtils.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/Attributes.h" #include "mozilla/DataMutex.h" #include "mozilla/HalTypes.h" @@ -1125,7 +1125,7 @@ class ContentParent final : public PContentParent, mozilla::ipc::IPCResult RecvGetFontListShmBlock( const uint32_t& aGeneration, const uint32_t& aIndex, - mozilla::ipc::SharedMemory::Handle* aOut); + mozilla::ipc::ReadOnlySharedMemoryHandle* aOut); mozilla::ipc::IPCResult RecvInitializeFamily(const uint32_t& aGeneration, const uint32_t& aFamilyIndex, @@ -1149,8 +1149,7 @@ class ContentParent final : public PContentParent, const uint32_t& aStartIndex); mozilla::ipc::IPCResult RecvGetHyphDict( - nsIURI* aURIParams, mozilla::ipc::SharedMemory::Handle* aOutHandle, - uint32_t* aOutSize); + nsIURI* aURIParams, mozilla::ipc::ReadOnlySharedMemoryHandle* aOutHandle); mozilla::ipc::IPCResult RecvNotifyBenchmarkResult(const nsAString& aCodecName, const uint32_t& aDecodeFPS); diff --git a/dom/ipc/ContentProcess.cpp b/dom/ipc/ContentProcess.cpp index 70b765c686c4..087a4c21149c 100644 --- a/dom/ipc/ContentProcess.cpp +++ b/dom/ipc/ContentProcess.cpp @@ -72,10 +72,9 @@ void ContentProcess::InfallibleInit(int aArgc, char* aArgv[]) { Maybe parentBuildID = geckoargs::sParentBuildID.Get(aArgc, aArgv); - // command line: -jsInitHandle handle -jsInitLen length - Maybe jsInitHandle = + // command line: -jsInitHandle handle + Maybe jsInitHandle = geckoargs::sJsInitHandle.Get(aArgc, aArgv); - Maybe jsInitLen = geckoargs::sJsInitLen.Get(aArgc, aArgv); nsCOMPtr appDirArg; Maybe appDir = geckoargs::sAppDir.Get(aArgc, aArgv); @@ -131,8 +130,8 @@ void ContentProcess::InfallibleInit(int aArgc, char* aArgv[]) { MOZ_CRASH("InitPrefs failed"); } - if (jsInitHandle && jsInitLen && - !::mozilla::ipc::ImportSharedJSInit(jsInitHandle.extract(), *jsInitLen)) { + if (jsInitHandle && + !::mozilla::ipc::ImportSharedJSInit(jsInitHandle.extract())) { MOZ_CRASH("ImportSharedJSInit failed"); } diff --git a/dom/ipc/MemMapSnapshot.cpp b/dom/ipc/MemMapSnapshot.cpp index cc0bf83ed076..3a27ff6e673a 100644 --- a/dom/ipc/MemMapSnapshot.cpp +++ b/dom/ipc/MemMapSnapshot.cpp @@ -7,40 +7,36 @@ #include "MemMapSnapshot.h" #include "mozilla/ResultExtensions.h" +#include "mozilla/ipc/SharedMemoryHandle.h" namespace mozilla::ipc { Result MemMapSnapshot::Init(size_t aSize) { MOZ_ASSERT(!mMem); - auto aMem = MakeRefPtr(); - if (NS_WARN_IF(!aMem->CreateFreezable(aSize))) { - return Err(NS_ERROR_FAILURE); - } - if (NS_WARN_IF(!aMem->Map(aSize))) { + auto handle = shared_memory::CreateFreezable(aSize); + if (NS_WARN_IF(!handle)) { return Err(NS_ERROR_FAILURE); } - mMem = std::move(aMem); + auto mem = std::move(handle).Map(); + if (NS_WARN_IF(!mem)) { + return Err(NS_ERROR_FAILURE); + } + + mMem = std::move(mem); return Ok(); } -Result MemMapSnapshot::Finalize(RefPtr& aMem) { +Result MemMapSnapshot::Finalize() { MOZ_ASSERT(mMem); - auto size = mMem->Size(); - if (NS_WARN_IF(!mMem->Freeze())) { + auto [_, readOnlyHandle] = std::move(mMem).Freeze(); + if (NS_WARN_IF(!readOnlyHandle)) { return Err(NS_ERROR_FAILURE); } - 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(); + return std::move(readOnlyHandle); } } // namespace mozilla::ipc diff --git a/dom/ipc/MemMapSnapshot.h b/dom/ipc/MemMapSnapshot.h index d04d0db24235..f855a68e78a4 100644 --- a/dom/ipc/MemMapSnapshot.h +++ b/dom/ipc/MemMapSnapshot.h @@ -12,7 +12,7 @@ #include "mozilla/RefPtr.h" #include "mozilla/RangedPtr.h" #include "mozilla/Result.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "ErrorList.h" namespace mozilla::ipc { @@ -23,7 +23,7 @@ namespace mozilla::ipc { * The Init() method initializes a read-write memory mapped region of the given * 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 - * descriptor), and initializes an AutoMemMap with the new contents. + * descriptor), and returns a handle to it. * * The file descriptor for the resulting AutoMemMap can be shared among * processes, to safely access a shared, read-only copy of the data snapshot. @@ -31,16 +31,17 @@ namespace mozilla::ipc { class MOZ_RAII MemMapSnapshot { public: Result Init(size_t aSize); - Result Finalize(RefPtr& aMem); + Result Finalize(); template RangedPtr Get() { MOZ_ASSERT(mMem); - return {static_cast(mMem->Memory()), mMem->MaxSize() / sizeof(T)}; + auto span = mMem.DataAsSpan(); + return {span.data(), span.size()}; } private: - RefPtr mMem; + FreezableSharedMemoryMapping mMem; }; } // namespace mozilla::ipc diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index fab4e9005a69..8f5abbb469d5 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -139,7 +139,7 @@ using mozilla::dom::BrowsingContextInitializer from "mozilla/dom/BrowsingContext using mozilla::dom::PermitUnloadResult from "nsIDocumentViewer.h"; using mozilla::dom::MaybeDiscardedWindowContext from "mozilla/dom/WindowContext.h"; using mozilla::dom::WindowContextTransaction from "mozilla/dom/WindowContext.h"; -[MoveOnly] using mozilla::ipc::SharedMemoryHandle from "mozilla/ipc/SharedMemory.h"; +[MoveOnly] using mozilla::ipc::ReadOnlySharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h"; using gfxSparseBitSet from "gfxFontUtils.h"; using FontVisibility from "gfxFontEntry.h"; using mozilla::dom::MediaControlAction from "mozilla/dom/MediaControlKeySource.h"; @@ -400,8 +400,7 @@ struct VisitedQueryResult struct StringBundleDescriptor { nsCString bundleURL; - SharedMemoryHandle mapHandle; - uint32_t mapSize; + ReadOnlySharedMemoryHandle mapHandle; }; struct IPCURLClassifierFeature @@ -715,7 +714,7 @@ child: * should map the new block and add to its index. */ async FontListShmBlockAdded(uint32_t aGeneration, uint32_t aIndex, - SharedMemoryHandle aHandle); + ReadOnlySharedMemoryHandle aHandle); async UpdateAppLocales(nsCString[] appLocales); async UpdateRequestedLocales(nsCString[] requestedLocales); @@ -732,7 +731,7 @@ child: async SimpleURIUnknownRemoteSchemes(nsCString[] remoteSchemes); - async UpdateSharedData(SharedMemoryHandle aMapHandle, uint32_t aSize, + async UpdateSharedData(ReadOnlySharedMemoryHandle aMapHandle, IPCBlob[] blobs, nsCString[] changedKeys); @@ -803,9 +802,9 @@ child: FullLookAndFeel lookAndFeeldata, /* used on MacOSX/Linux/Android only: */ SystemFontList systemFontList, - SharedMemoryHandle? sharedUASheetHandle, + ReadOnlySharedMemoryHandle? sharedUASheetHandle, uintptr_t sharedUASheetAddress, - SharedMemoryHandle[] sharedFontListBlocks, + ReadOnlySharedMemoryHandle[] sharedFontListBlocks, bool aIsStartingUp); // Notify child that last-pb-context-exited notification was observed @@ -1377,7 +1376,7 @@ parent: * until it has mapped the font-list memory. */ sync GetFontListShmBlock(uint32_t aGeneration, uint32_t aIndex) - returns (SharedMemoryHandle aHandle); + returns (ReadOnlySharedMemoryHandle aHandle); /** * Ask the parent to initialize a given font family, so that face metadata @@ -1495,7 +1494,7 @@ parent: * @param aLoaded * Returns the size in bytes of the resource. */ - sync GetHyphDict(nullable nsIURI aURI) returns (SharedMemoryHandle aHandle, uint32_t aSize); + sync GetHyphDict(nullable nsIURI aURI) returns (ReadOnlySharedMemoryHandle aHandle); async CreateWindow(PBrowser aThisTab, MaybeDiscardedBrowsingContext aParent, diff --git a/dom/ipc/SharedMap.cpp b/dom/ipc/SharedMap.cpp index f11cf52ecd13..45c87e70b99b 100644 --- a/dom/ipc/SharedMap.cpp +++ b/dom/ipc/SharedMap.cpp @@ -43,11 +43,10 @@ static inline void AlignTo(size_t* aOffset, size_t aAlign) { SharedMap::SharedMap() = default; SharedMap::SharedMap(nsIGlobalObject* aGlobal, SharedMemoryHandle&& aMapHandle, - size_t aMapSize, nsTArray>&& aBlobs) + nsTArray>&& aBlobs) : DOMEventTargetHelper(aGlobal), mBlobImpls(std::move(aBlobs)), - mMapHandle(std::move(aMapHandle)), - mMapSize(aMapSize) {} + mHandle(std::move(aMapHandle)) {} bool SharedMap::Has(const nsACString& aName) { Unused << MaybeRebuild(); @@ -97,21 +96,13 @@ void SharedMap::Entry::Read(JSContext* aCx, holder.Read(aCx, aRetVal, aRv); } -SharedMap::SharedMemoryHandle SharedMap::CloneHandle() const { - if (mMap->IsValid()) { - return mMap->CloneHandle(); - } - return SharedMemory::CloneHandle(mMapHandle); -} - -void SharedMap::Update(SharedMemoryHandle&& aMapHandle, size_t aMapSize, +void SharedMap::Update(SharedMemoryHandle&& aMapHandle, nsTArray>&& aBlobs, nsTArray&& aChangedKeys) { MOZ_DIAGNOSTIC_ASSERT(!mWritable); - mMap->TakeHandleAndUnmap(); - mMapHandle = std::move(aMapHandle); - mMapSize = aMapSize; + mMapping = nullptr; + mHandle = std::move(aMapHandle); mEntries.Clear(); mEntryArray.reset(); @@ -191,10 +182,12 @@ void SharedMap::Entry::ExtractData(char* aDestPtr, uint32_t aNewOffset, } Result SharedMap::MaybeRebuild() { - if (!SharedMemory::IsHandleValid(mMapHandle)) { + if (mMapping || !mHandle) { return Ok(); } + MOZ_DIAGNOSTIC_ASSERT(!mWritable); + // This function maps a shared memory region created by Serialize() and reads // its header block to build a new mEntries hashtable of its contents. // @@ -203,24 +196,20 @@ Result SharedMap::MaybeRebuild() { // its shared memory region. When needed, that structured clone data is // retrieved directly as indexes into the SharedMap's shared memory region. - if (!mMap->SetHandle(SharedMemory::CloneHandle(mMapHandle), - SharedMemory::OpenRights::RightsReadOnly)) { - return Err(NS_ERROR_FAILURE); - } - mMapHandle = SharedMemory::NULLHandle(); - if (!mMap->Map(mMapSize)) { + mMapping = mHandle.Map(); + if (!mMapping) { return Err(NS_ERROR_FAILURE); } + mHandle = nullptr; - // We should be able to pass this range as an initializer list or an immediate - // param, but gcc currently chokes on that if optimization is enabled, and - // initializes everything to 0. - Range range((uint8_t*)mMap->Memory(), mMap->Size()); - InputBuffer buffer(range); + Range inputRange(mMapping.DataAsSpan()); + InputBuffer buffer(inputRange); uint32_t count; buffer.codeUint32(count); + MOZ_ASSERT(mEntries.IsEmpty()); + MOZ_ASSERT(mEntryArray.isNothing()); for (uint32_t i = 0; i < count; i++) { auto entry = MakeUnique(*this); entry->Code(buffer); @@ -246,9 +235,9 @@ void SharedMap::MaybeRebuild() const { WritableSharedMap::WritableSharedMap() { mWritable = true; // Serialize the initial empty contents of the map immediately so that we - // always have a file descriptor to send to callers of CloneMapFile(). + // always have a file descriptor to send. Unused << Serialize(); - MOZ_RELEASE_ASSERT(mMap->IsValid()); + MOZ_RELEASE_ASSERT(mHandle.IsValid() && mMapping.IsValid()); } SharedMap* WritableSharedMap::GetReadOnly() { @@ -256,7 +245,7 @@ SharedMap* WritableSharedMap::GetReadOnly() { nsTArray> blobs(mBlobImpls.Clone()); mReadOnly = new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(), - CloneHandle(), MapSize(), std::move(blobs)); + mHandle.Clone(), std::move(blobs)); } return mReadOnly; } @@ -339,8 +328,11 @@ Result WritableSharedMap::Serialize() { memcpy(ptr.get(), header.Get(), header.cursor()); // We've already updated offsets at this point. We need this to succeed. - mMap->TakeHandleAndUnmap(); - MOZ_RELEASE_ASSERT(mem.Finalize(mMap).isOk()); + auto result = mem.Finalize(); + MOZ_RELEASE_ASSERT(result.isOk()); + mHandle = result.unwrap(); + mMapping = mHandle.Map(); + MOZ_RELEASE_ASSERT(mMapping.IsValid()); return Ok(); } @@ -355,8 +347,7 @@ void WritableSharedMap::SendTo(ContentParent* aParent) const { } } - Unused << aParent->SendUpdateSharedData(CloneHandle(), mMap->Size(), blobs, - mChangedKeys); + Unused << aParent->SendUpdateSharedData(mHandle.Clone(), blobs, mChangedKeys); } void WritableSharedMap::BroadcastChanges() { @@ -376,7 +367,7 @@ void WritableSharedMap::BroadcastChanges() { if (mReadOnly) { nsTArray> blobImpls(mBlobImpls.Clone()); - mReadOnly->Update(CloneHandle(), mMap->Size(), std::move(blobImpls), + mReadOnly->Update(mHandle.Clone(), std::move(blobImpls), std::move(mChangedKeys)); } diff --git a/dom/ipc/SharedMap.h b/dom/ipc/SharedMap.h index cfbc1e10d905..59e1e8a5d315 100644 --- a/dom/ipc/SharedMap.h +++ b/dom/ipc/SharedMap.h @@ -10,7 +10,8 @@ #include "mozilla/dom/MozSharedMapBinding.h" #include "mozilla/dom/ipc/StructuredCloneData.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/Maybe.h" #include "mozilla/UniquePtr.h" @@ -53,13 +54,14 @@ namespace ipc { * WritableSharedMap instances. */ class SharedMap : public DOMEventTargetHelper { - using SharedMemory = mozilla::ipc::SharedMemory; - using SharedMemoryHandle = mozilla::ipc::SharedMemoryHandle; + protected: + using SharedMemoryMapping = mozilla::ipc::ReadOnlySharedMemoryMapping; + using SharedMemoryHandle = mozilla::ipc::ReadOnlySharedMemoryHandle; public: SharedMap(); - SharedMap(nsIGlobalObject* aGlobal, SharedMemoryHandle&&, size_t, + SharedMap(nsIGlobalObject* aGlobal, SharedMemoryHandle&&, nsTArray>&& aBlobs); // Returns true if the map contains the given (UTF-8) key. @@ -93,26 +95,16 @@ class SharedMap : public DOMEventTargetHelper { JS::MutableHandle aResult) const; /** - * 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. + * Returns the size of the memory mapped region that backs this map. */ - 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(); } + size_t MapSize() const { return mMapping.Size(); } /** * 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 * changed (UTF-8-encoded) keys. */ - void Update(SharedMemoryHandle&& aMapHandle, size_t aMapSize, + void Update(SharedMemoryHandle&& aMapHandle, nsTArray>&& aBlobs, nsTArray&& aChangedKeys); @@ -263,24 +255,20 @@ class SharedMap : public DOMEventTargetHelper { Result MaybeRebuild(); void MaybeRebuild() const; - SharedMemoryHandle mMapHandle; - // The size of the memory-mapped region backed by mMap, in bytes. - size_t mMapSize = 0; - mutable nsClassHashtable mEntries; mutable Maybe> mEntryArray; // Manages the memory mapping of the current snapshot. This is initialized - // lazily after each SharedMap construction or updated, based on the values in - // mMapFile and mMapSize. - RefPtr mMap = MakeRefPtr(); + // lazily after each SharedMap construction or update. + SharedMemoryHandle mHandle; + SharedMemoryMapping mMapping; bool mWritable = false; // Returns a pointer to the beginning of the memory mapped snapshot. Entry // offsets are relative to this pointer, and Entry objects access their // structured clone data by indexing this pointer. - char* Data() { return static_cast(mMap->Memory()); } + const char* Data() { return mMapping.DataAs(); } }; class WritableSharedMap final : public SharedMap { diff --git a/dom/ipc/SharedStringMap.cpp b/dom/ipc/SharedStringMap.cpp index 648dc9da2272..afd08f18543f 100644 --- a/dom/ipc/SharedStringMap.cpp +++ b/dom/ipc/SharedStringMap.cpp @@ -27,42 +27,36 @@ static inline size_t GetAlignmentOffset(size_t aOffset, size_t aAlign) { return mod ? aAlign - mod : 0; } -SharedStringMap::SharedStringMap(const SharedMemoryHandle& aMapHandle, - size_t aMapSize) { - auto map = MakeRefPtr(); - { - auto result = map->SetHandle(SharedMemory::CloneHandle(aMapHandle), - SharedMemory::OpenRights::RightsReadOnly); - MOZ_RELEASE_ASSERT(result); - } - { - auto result = map->Map(aMapSize); - MOZ_RELEASE_ASSERT(result); - } +SharedStringMap::SharedStringMap(const ReadOnlySharedMemoryHandle& aMapHandle) { + mHandle = aMapHandle.Clone(); + MOZ_RELEASE_ASSERT(mHandle.IsValid()); + auto mapping = aMapHandle.Map(); + MOZ_RELEASE_ASSERT(mapping.IsValid()); // We return literal nsStrings and nsCStrings pointing to the mapped data, // 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 // mapping alive until process shutdown, in order to be safe. - mMappedMemory = map->TakeMapping(); - mHandle = map->TakeHandle(); + mMappedMemory = std::move(mapping).Release(); MOZ_RELEASE_ASSERT(GetHeader().mMagic == kSharedStringMapMagic); } SharedStringMap::SharedStringMap(SharedStringMapBuilder&& aBuilder) { - RefPtr map; - auto result = aBuilder.Finalize(map); - MOZ_RELEASE_ASSERT(result.isOk() && map); + ReadOnlySharedMemoryMappingWithHandle mappingWithHandle; + auto result = aBuilder.Finalize(); + MOZ_RELEASE_ASSERT(result.isOk()); + mHandle = result.unwrap(); + auto mapping = mHandle.Map(); + MOZ_RELEASE_ASSERT(mapping.IsValid()); - mMappedMemory = map->TakeMapping(); - mHandle = map->TakeHandle(); + mMappedMemory = std::move(mapping).Release(); MOZ_RELEASE_ASSERT(GetHeader().mMagic == kSharedStringMapMagic); } -mozilla::ipc::SharedMemoryHandle SharedStringMap::CloneHandle() const { - return SharedMemory::CloneHandle(mHandle); +mozilla::ipc::ReadOnlySharedMemoryHandle SharedStringMap::CloneHandle() const { + return mHandle.Clone(); } bool SharedStringMap::Has(const nsCString& aKey) { @@ -97,8 +91,8 @@ void SharedStringMapBuilder::Add(const nsCString& aKey, Entry{mKeyTable.Add(aKey), mValueTable.Add(aValue)}); } -Result SharedStringMapBuilder::Finalize( - RefPtr& aMap) { +Result +SharedStringMapBuilder::Finalize() { using Header = SharedStringMap::Header; MOZ_ASSERT(mEntries.Count() == mKeyTable.Count()); @@ -147,7 +141,7 @@ Result SharedStringMapBuilder::Finalize( mValueTable.Clear(); mEntries.Clear(); - return mem.Finalize(aMap); + return mem.Finalize(); } } // namespace dom::ipc diff --git a/dom/ipc/SharedStringMap.h b/dom/ipc/SharedStringMap.h index ca90cf1f33f6..04627f7d4aac 100644 --- a/dom/ipc/SharedStringMap.h +++ b/dom/ipc/SharedStringMap.h @@ -9,7 +9,8 @@ #include "mozilla/Result.h" #include "mozilla/dom/ipc/StringTable.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "nsTHashMap.h" namespace mozilla::dom::ipc { @@ -88,7 +89,7 @@ class SharedStringMap { // Note: These constructors are infallible on the premise that this class // is used primarily in cases where it is critical to platform // functionality. - explicit SharedStringMap(const mozilla::ipc::SharedMemoryHandle&, size_t); + explicit SharedStringMap(const mozilla::ipc::ReadOnlySharedMemoryHandle&); explicit SharedStringMap(SharedStringMapBuilder&&); /** @@ -151,7 +152,7 @@ class SharedStringMap { * used to construct new instances of SharedStringMap with the same data as * this instance. */ - mozilla::ipc::SharedMemoryHandle CloneHandle() const; + mozilla::ipc::ReadOnlySharedMemoryHandle CloneHandle() const; size_t MapSize() const { return mMappedMemory.size(); } @@ -172,21 +173,23 @@ class SharedStringMap { StringTable KeyTable() const { const auto& header = GetHeader(); - return {{&mMappedMemory.data()[header.mKeyStringsOffset], - header.mKeyStringsSize}}; + return { + {const_cast(&mMappedMemory.data()[header.mKeyStringsOffset]), + header.mKeyStringsSize}}; } StringTable ValueTable() const { const auto& header = GetHeader(); - return {{&mMappedMemory.data()[header.mValueStringsOffset], + return {{const_cast( + &mMappedMemory.data()[header.mValueStringsOffset]), header.mValueStringsSize}}; } - mozilla::ipc::SharedMemoryHandle mHandle; + mozilla::ipc::ReadOnlySharedMemoryHandle mHandle; // This is a leaked shared memory mapping (see the constructor definition for // an explanation). It replaces AutoMemMap::setPersistent behavior as part of // bug 1454816. - Span mMappedMemory; + mozilla::ipc::shared_memory::LeakedReadOnlyMapping mMappedMemory; }; /** @@ -205,10 +208,9 @@ class MOZ_RAII SharedStringMapBuilder { /** * Finalizes the binary representation of the map, writes it to a shared - * memory region, and then initializes the given SharedMemory with a reference - * to the read-only copy of it. + * memory region, and then returns a read-only handle to it. */ - Result Finalize(RefPtr& aMap); + Result Finalize(); private: using Entry = SharedStringMap::Entry; diff --git a/dom/media/gmp/GMPParent.cpp b/dom/media/gmp/GMPParent.cpp index 73059ed7ccab..c035d275e350 100644 --- a/dom/media/gmp/GMPParent.cpp +++ b/dom/media/gmp/GMPParent.cpp @@ -22,7 +22,7 @@ #include "mozilla/ipc/GeckoChildProcessHost.h" #if defined(XP_LINUX) && defined(MOZ_SANDBOX) # include "mozilla/SandboxInfo.h" -# include "mozilla/ipc/SharedMemory.h" +# include "mozilla/ipc/SharedMemoryHandle.h" #endif #include "mozilla/Services.h" #include "mozilla/SSE.h" @@ -303,7 +303,7 @@ class NotifyGMPProcessLoadedTask : public Runnable { #if defined(XP_LINUX) && defined(MOZ_SANDBOX) if (SandboxInfo::Get().Test(SandboxInfo::kEnabledForMedia) && - ipc::SharedMemory::UsingPosixShm()) { + ipc::shared_memory::UsingPosixShm()) { canProfile = false; } #endif diff --git a/dom/media/gmp/GMPProcessChild.cpp b/dom/media/gmp/GMPProcessChild.cpp index 921c8e49334d..7c468cb5d1ab 100644 --- a/dom/media/gmp/GMPProcessChild.cpp +++ b/dom/media/gmp/GMPProcessChild.cpp @@ -18,11 +18,9 @@ void GMPProcessChild::InitStatics(int aArgc, char* aArgv[]) { Maybe nativeEvent = geckoargs::sPluginNativeEvent.Get(aArgc, aArgv); sUseNativeEventProcessing = nativeEvent.isSome() && *nativeEvent; - Maybe prefsLen = - geckoargs::sPrefsLen.Get(aArgc, aArgv, CheckArgFlag::None); - Maybe prefMapSize = - geckoargs::sPrefMapSize.Get(aArgc, aArgv, CheckArgFlag::None); - sUseXpcom = prefsLen.isSome() && prefMapSize.isSome(); + auto prefsHandlePresent = geckoargs::sPrefsHandle.IsPresent(aArgc, aArgv); + auto prefMapHandlePresent = geckoargs::sPrefMapHandle.IsPresent(aArgc, aArgv); + sUseXpcom = prefsHandlePresent && prefMapHandlePresent; } GMPProcessChild::~GMPProcessChild() = default; diff --git a/dom/media/gmp/GMPSharedMemManager.cpp b/dom/media/gmp/GMPSharedMemManager.cpp index e1231684866f..c33393ba1fb1 100644 --- a/dom/media/gmp/GMPSharedMemManager.cpp +++ b/dom/media/gmp/GMPSharedMemManager.cpp @@ -4,7 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GMPSharedMemManager.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryMapping.h" namespace mozilla::gmp { @@ -49,7 +49,7 @@ bool GMPSharedMemManager::MgrTakeShmem(GMPSharedMemClass aClass, size_t aSize, MOZ_ASSERT(MgrIsOnOwningThread()); auto& pool = mPool[size_t(aClass)]; - size_t alignedSize = ipc::SharedMemory::PageAlignedSize(aSize); + size_t alignedSize = ipc::shared_memory::PageAlignedSize(aSize); PurgeSmallerShmem(pool, alignedSize); if (pool.IsEmpty()) { return MgrAllocShmem(alignedSize, aMem); diff --git a/gfx/2d/RecordedEvent.h b/gfx/2d/RecordedEvent.h index c81db670be2e..b3c4b67bf981 100644 --- a/gfx/2d/RecordedEvent.h +++ b/gfx/2d/RecordedEvent.h @@ -239,7 +239,7 @@ struct MemWriter { // An istream like class for reading from memory struct MemReader { - constexpr MemReader(char* aData, size_t aLen) + constexpr MemReader(const char* aData, size_t aLen) : mData(aData), mEnd(aData + aLen) {} void read(char* s, std::streamsize n) { if (n <= (mEnd - mData)) { @@ -255,8 +255,8 @@ struct MemReader { bool good() { return !eof(); } void SetIsBad() { mData = mEnd + 1; } - char* mData; - char* mEnd; + const char* mData; + const char* mEnd; }; class ContiguousBuffer { diff --git a/gfx/layers/BufferTexture.h b/gfx/layers/BufferTexture.h index a306e4dfeb42..cdb2545c568c 100644 --- a/gfx/layers/BufferTexture.h +++ b/gfx/layers/BufferTexture.h @@ -10,7 +10,6 @@ #include "mozilla/RefPtr.h" #include "mozilla/gfx/2D.h" #include "mozilla/gfx/Types.h" -#include "mozilla/ipc/SharedMemory.h" #include "mozilla/layers/TextureClient.h" namespace mozilla { diff --git a/gfx/layers/CanvasDrawEventRecorder.cpp b/gfx/layers/CanvasDrawEventRecorder.cpp index 59e70dba7020..ece5f111e963 100644 --- a/gfx/layers/CanvasDrawEventRecorder.cpp +++ b/gfx/layers/CanvasDrawEventRecorder.cpp @@ -21,28 +21,27 @@ namespace mozilla { namespace layers { struct ShmemAndHandle { - RefPtr shmem; - Handle handle; + ipc::SharedMemoryMapping shmem; + ipc::MutableSharedMemoryHandle handle; }; static Maybe CreateAndMapShmem(size_t aSize) { - auto shmem = MakeRefPtr(); - if (!shmem->Create(aSize) || !shmem->Map(aSize)) { + auto handle = ipc::shared_memory::Create(aSize); + if (!handle) { + return Nothing(); + } + auto mapping = handle.Map(); + if (!mapping) { return Nothing(); } - auto shmemHandle = shmem->TakeHandle(); - if (!shmemHandle) { - return Nothing(); - } - - return Some(ShmemAndHandle{shmem.forget(), std::move(shmemHandle)}); + return Some(ShmemAndHandle{std::move(mapping), std::move(handle)}); } CanvasDrawEventRecorder::CanvasDrawEventRecorder( dom::ThreadSafeWorkerRef* aWorkerRef) : mWorkerRef(aWorkerRef), mIsOnWorker(!!aWorkerRef) { - mDefaultBufferSize = ipc::SharedMemory::PageAlignedSize( + mDefaultBufferSize = ipc::shared_memory::PageAlignedSize( StaticPrefs::gfx_canvas_remote_default_buffer_size()); mMaxDefaultBuffers = StaticPrefs::gfx_canvas_remote_max_default_buffers(); mMaxSpinCount = StaticPrefs::gfx_canvas_remote_max_spin_count(); @@ -66,7 +65,7 @@ bool CanvasDrawEventRecorder::Init(TextureType aTextureType, return false; } - mHeader = static_cast(header->shmem->Memory()); + mHeader = header->shmem.DataAs
(); mHeader->eventCount = 0; mHeader->writerWaitCount = 0; mHeader->writerState = State::Processing; @@ -76,20 +75,20 @@ bool CanvasDrawEventRecorder::Init(TextureType aTextureType, // 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 // translating while the handle is sent over. - AutoTArray bufferHandles; + AutoTArray bufferHandles; auto buffer = CreateAndMapShmem(mDefaultBufferSize); if (NS_WARN_IF(buffer.isNothing())) { return false; } mCurrentBuffer = CanvasBuffer(std::move(buffer->shmem)); - bufferHandles.AppendElement(std::move(buffer->handle)); + bufferHandles.AppendElement(std::move(buffer->handle).ToReadOnly()); buffer = CreateAndMapShmem(mDefaultBufferSize); if (NS_WARN_IF(buffer.isNothing())) { return false; } - mRecycledBuffers.emplace(buffer->shmem.forget(), 0); - bufferHandles.AppendElement(std::move(buffer->handle)); + mRecycledBuffers.emplace(std::move(buffer->shmem), 0); + bufferHandles.AppendElement(std::move(buffer->handle).ToReadOnly()); mWriterSemaphore.reset(CrossProcessSemaphore::Create("CanvasRecorder", 0)); auto writerSem = mWriterSemaphore->CloneHandle(); @@ -107,13 +106,13 @@ bool CanvasDrawEventRecorder::Init(TextureType aTextureType, if (!mHelpers->InitTranslator(aTextureType, aWebglTextureType, aBackendType, std::move(header->handle), - std::move(bufferHandles), mDefaultBufferSize, - std::move(readerSem), std::move(writerSem))) { + std::move(bufferHandles), std::move(readerSem), + std::move(writerSem))) { return false; } mTextureType = aTextureType; - mHeaderShmem = header->shmem; + mHeaderShmem = std::move(header->shmem); return true; } @@ -246,7 +245,7 @@ gfx::ContiguousBuffer& CanvasDrawEventRecorder::GetContiguousBuffer( } size_t bufferSize = std::max(mDefaultBufferSize, - ipc::SharedMemory::PageAlignedSize(aSize + 1)); + ipc::shared_memory::PageAlignedSize(aSize + 1)); auto newBuffer = CreateAndMapShmem(bufferSize); if (NS_WARN_IF(newBuffer.isNothing())) { mHeader->writerState = State::Failed; @@ -254,7 +253,7 @@ gfx::ContiguousBuffer& CanvasDrawEventRecorder::GetContiguousBuffer( return mCurrentBuffer; } - if (!mHelpers->AddBuffer(std::move(newBuffer->handle), bufferSize)) { + if (!mHelpers->AddBuffer(std::move(newBuffer->handle).ToReadOnly())) { mHeader->writerState = State::Failed; mCurrentBuffer = CanvasBuffer(); return mCurrentBuffer; diff --git a/gfx/layers/CanvasDrawEventRecorder.h b/gfx/layers/CanvasDrawEventRecorder.h index b0d5b0ef32e7..eeafb3785baf 100644 --- a/gfx/layers/CanvasDrawEventRecorder.h +++ b/gfx/layers/CanvasDrawEventRecorder.h @@ -12,7 +12,7 @@ #include "mozilla/Atomics.h" #include "mozilla/gfx/DrawEventRecorder.h" #include "mozilla/ipc/CrossProcessSemaphore.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/layers/LayersTypes.h" #include "mozilla/RefPtr.h" #include "mozilla/UniquePtr.h" @@ -27,7 +27,6 @@ class ThreadSafeWorkerRef; namespace layers { -typedef mozilla::ipc::SharedMemory::Handle Handle; typedef mozilla::CrossProcessSemaphoreHandle CrossProcessSemaphoreHandle; class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate, @@ -72,16 +71,15 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate, public: virtual ~Helpers() = default; - virtual bool InitTranslator(TextureType aTextureType, - TextureType aWebglTextureType, - gfx::BackendType aBackendType, - Handle&& aReadHandle, - nsTArray&& aBufferHandles, - uint64_t aBufferSize, - CrossProcessSemaphoreHandle&& aReaderSem, - CrossProcessSemaphoreHandle&& aWriterSem) = 0; + virtual bool InitTranslator( + TextureType aTextureType, TextureType aWebglTextureType, + gfx::BackendType aBackendType, + ipc::MutableSharedMemoryHandle&& aReadHandle, + nsTArray&& aBufferHandles, + CrossProcessSemaphoreHandle&& aReaderSem, + CrossProcessSemaphoreHandle&& aWriterSem) = 0; - virtual bool AddBuffer(Handle&& aBufferHandle, uint64_t aBufferSize) = 0; + virtual bool AddBuffer(ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) = 0; /** * @returns true if the reader of the CanvasEventRingBuffer has permanently @@ -163,29 +161,28 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate, UniquePtr mHelpers; TextureType mTextureType = TextureType::Unknown; - RefPtr mHeaderShmem; + ipc::SharedMemoryMapping mHeaderShmem; Header* mHeader = nullptr; struct CanvasBuffer : public gfx::ContiguousBuffer { - RefPtr shmem; + ipc::SharedMemoryMapping shmem; CanvasBuffer() : ContiguousBuffer(nullptr) {} - explicit CanvasBuffer(RefPtr&& aShmem) - : ContiguousBuffer(static_cast(aShmem->Memory()), - aShmem->Size()), + explicit CanvasBuffer(ipc::SharedMemoryMapping&& aShmem) + : ContiguousBuffer(aShmem.DataAs(), aShmem.Size()), shmem(std::move(aShmem)) {} - size_t Capacity() { return shmem ? shmem->Size() : 0; } + size_t Capacity() { return shmem ? shmem.Size() : 0; } }; struct RecycledBuffer { - RefPtr shmem; + ipc::SharedMemoryMapping shmem; int64_t eventCount = 0; - explicit RecycledBuffer(RefPtr&& aShmem, + explicit RecycledBuffer(ipc::SharedMemoryMapping&& aShmem, int64_t aEventCount) : shmem(std::move(aShmem)), eventCount(aEventCount) {} - size_t Capacity() { return shmem->Size(); } + size_t Capacity() { return shmem.Size(); } }; CanvasBuffer mCurrentBuffer; diff --git a/gfx/layers/RecordedCanvasEventImpl.h b/gfx/layers/RecordedCanvasEventImpl.h index d14b4ebf3622..536d28566582 100644 --- a/gfx/layers/RecordedCanvasEventImpl.h +++ b/gfx/layers/RecordedCanvasEventImpl.h @@ -26,7 +26,6 @@ using gfx::ReadElement; using gfx::ReferencePtr; using gfx::SurfaceFormat; using gfx::WriteElement; -using ipc::SharedMemory; const EventType CANVAS_BEGIN_TRANSACTION = EventType::LAST; const EventType CANVAS_END_TRANSACTION = EventType(EventType::LAST + 1); diff --git a/gfx/layers/SourceSurfaceSharedData.cpp b/gfx/layers/SourceSurfaceSharedData.cpp index 793b6bfa9c7a..10498c0230ef 100644 --- a/gfx/layers/SourceSurfaceSharedData.cpp +++ b/gfx/layers/SourceSurfaceSharedData.cpp @@ -9,6 +9,7 @@ #include "mozilla/Likely.h" #include "mozilla/StaticPrefs_image.h" #include "mozilla/Types.h" // for decltype +#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/layers/SharedSurfacesChild.h" #include "mozilla/layers/SharedSurfacesParent.h" #include "nsDebug.h" // for NS_ABORT_OOM @@ -30,10 +31,9 @@ using namespace mozilla::layers; namespace mozilla { namespace gfx { -void SourceSurfaceSharedDataWrapper::Init(const IntSize& aSize, int32_t aStride, - SurfaceFormat aFormat, - SharedMemory::Handle aHandle, - base::ProcessId aCreatorPid) { +void SourceSurfaceSharedDataWrapper::Init( + const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat, + ipc::ReadOnlySharedMemoryHandle aHandle, base::ProcessId aCreatorPid) { MOZ_ASSERT(!mBuf); mSize = aSize; mStride = aStride; @@ -41,8 +41,8 @@ void SourceSurfaceSharedDataWrapper::Init(const IntSize& aSize, int32_t aStride, mCreatorPid = aCreatorPid; size_t len = GetAlignedDataLength(); - mBuf = MakeAndAddRef(); - if (!mBuf->SetHandle(std::move(aHandle), ipc::SharedMemory::RightsReadOnly)) { + mBufHandle = std::move(aHandle); + if (!mBufHandle) { MOZ_CRASH("Invalid shared memory handle!"); } @@ -63,7 +63,7 @@ void SourceSurfaceSharedDataWrapper::Init(const IntSize& aSize, int32_t aStride, // We don't support unmapping for this surface, and we failed to map it. NS_ABORT_OOM(len); } else { - mBuf->CloseHandle(); + mBufHandle = nullptr; } } @@ -80,15 +80,20 @@ void SourceSurfaceSharedDataWrapper::Init(SourceSurfaceSharedData* aSurface) { bool SourceSurfaceSharedDataWrapper::EnsureMapped(size_t aLength) { MOZ_ASSERT(!GetData()); - while (!mBuf->Map(aLength)) { + auto mapping = mBufHandle.Map(); + while (!mapping) { nsTArray> expired; if (!SharedSurfacesParent::AgeOneGeneration(expired)) { return false; } MOZ_ASSERT(!expired.Contains(this)); SharedSurfacesParent::ExpireMap(expired); + mapping = mBufHandle.Map(); } + mBuf = std::make_shared( + std::move(mapping)); + return true; } @@ -143,7 +148,8 @@ void SourceSurfaceSharedDataWrapper::Unmap() { void SourceSurfaceSharedDataWrapper::ExpireMap() { MutexAutoLock lock(*mHandleLock); if (mMapCount == 0) { - mBuf->Unmap(); + // This unmaps the stored memory mapping. + *mBuf = nullptr; } } @@ -155,9 +161,10 @@ bool SourceSurfaceSharedData::Init(const IntSize& aSize, int32_t aStride, mFormat = aFormat; size_t len = GetAlignedDataLength(); - mBuf = new SharedMemory(); - if (NS_WARN_IF(!mBuf->Create(len)) || NS_WARN_IF(!mBuf->Map(len))) { - mBuf = nullptr; + mBufHandle = ipc::shared_memory::Create(len); + mBuf = std::make_shared( + mBufHandle.Map()); + if (NS_WARN_IF(!mBufHandle) || NS_WARN_IF(!mBuf || !*mBuf)) { return false; } @@ -187,17 +194,23 @@ void SourceSurfaceSharedData::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf, uint8_t* SourceSurfaceSharedData::GetDataInternal() const { 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 // get a new handle to share, but there were still active mappings. if (MOZ_UNLIKELY(mOldBuf)) { MOZ_ASSERT(mMapCount > 0); MOZ_ASSERT(mFinalized); - return static_cast(mOldBuf->Memory()); + return const_cast(mOldBuf->DataAs()); } - return static_cast(mBuf->Memory()); + // Const cast to match `GetData()`. + return const_cast(mBuf->DataAs()); } -nsresult SourceSurfaceSharedData::CloneHandle(SharedMemory::Handle& aHandle) { +nsresult SourceSurfaceSharedData::CloneHandle( + ipc::ReadOnlySharedMemoryHandle& aHandle) { MutexAutoLock lock(mMutex); MOZ_ASSERT(mHandleCount > 0); @@ -205,7 +218,7 @@ nsresult SourceSurfaceSharedData::CloneHandle(SharedMemory::Handle& aHandle) { return NS_ERROR_NOT_AVAILABLE; } - aHandle = mBuf->CloneHandle(); + aHandle = mBufHandle.Clone().ToReadOnly(); if (MOZ_UNLIKELY(!aHandle)) { return NS_ERROR_FAILURE; } @@ -223,7 +236,7 @@ void SourceSurfaceSharedData::CloseHandleInternal() { } if (mShared) { - mBuf->CloseHandle(); + mBufHandle = nullptr; mClosed = true; } } @@ -242,21 +255,25 @@ bool SourceSurfaceSharedData::ReallocHandle() { } size_t len = GetAlignedDataLength(); - RefPtr buf = new SharedMemory(); - if (NS_WARN_IF(!buf->Create(len)) || NS_WARN_IF(!buf->Map(len))) { + auto handle = ipc::shared_memory::Create(len); + auto mapping = handle.Map(); + if (NS_WARN_IF(!handle) || NS_WARN_IF(!mapping)) { return false; } size_t copyLen = GetDataLength(); - memcpy(buf->Memory(), mBuf->Memory(), copyLen); + memcpy(mapping.Address(), mBuf->Address(), copyLen); #ifdef SHARED_SURFACE_PROTECT_FINALIZED - buf->Protect(static_cast(buf->Memory()), len, RightsRead); + ipc::shared_memory::LocalProtect(mapping.DataAs(), len, + ipc::shared_memory::AccessRead); #endif if (mMapCount > 0 && !mOldBuf) { mOldBuf = std::move(mBuf); } - mBuf = std::move(buf); + mBufHandle = std::move(handle); + mBuf = std::make_shared( + std::move(mapping)); mClosed = false; mShared = false; return true; @@ -268,7 +285,10 @@ void SourceSurfaceSharedData::Finalize() { #ifdef SHARED_SURFACE_PROTECT_FINALIZED size_t len = GetAlignedDataLength(); - mBuf->Protect(static_cast(mBuf->Memory()), len, RightsRead); + // This class's mappings are always mutable, so we can safely cast away the + // const (see the comment above the `mBuf` declaration). + ipc::shared_memory::LocalProtect(const_cast(mBuf->DataAs()), len, + ipc::shared_memory::AccessRead); #endif mFinalized = true; diff --git a/gfx/layers/SourceSurfaceSharedData.h b/gfx/layers/SourceSurfaceSharedData.h index b17d6c4fed60..d442c009301c 100644 --- a/gfx/layers/SourceSurfaceSharedData.h +++ b/gfx/layers/SourceSurfaceSharedData.h @@ -10,7 +10,8 @@ #include "base/process.h" #include "mozilla/gfx/2D.h" #include "mozilla/Mutex.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "nsExpirationTracker.h" namespace mozilla { @@ -34,8 +35,6 @@ class SourceSurfaceSharedData; * mapped in the given shared memory handle as read only memory. */ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface { - typedef mozilla::ipc::SharedMemory SharedMemory; - public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceSharedDataWrapper, override) @@ -43,7 +42,8 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface { SourceSurfaceSharedDataWrapper() = default; void Init(const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat, - SharedMemory::Handle aHandle, base::ProcessId aCreatorPid); + mozilla::ipc::ReadOnlySharedMemoryHandle aHandle, + base::ProcessId aCreatorPid); void Init(SourceSurfaceSharedData* aSurface); @@ -57,7 +57,11 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface { IntSize GetSize() const override { return mSize; } SurfaceFormat GetFormat() const override { return mFormat; } - uint8_t* GetData() override { return static_cast(mBuf->Memory()); } + uint8_t* GetData() override { + // Cast away const-ness of shared memory to match the + // `DataSourceSurface::GetData` interface. The data will not be written to. + return mBuf ? const_cast(mBuf->DataAs()) : nullptr; + } bool OnHeap() const override { return false; } @@ -97,7 +101,7 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface { } size_t GetAlignedDataLength() const { - return mozilla::ipc::SharedMemory::PageAlignedSize(GetDataLength()); + return mozilla::ipc::shared_memory::PageAlignedSize(GetDataLength()); } bool EnsureMapped(size_t aLength); @@ -108,7 +112,9 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface { int32_t mStride = 0; uint32_t mConsumers = 1; IntSize mSize; - RefPtr mBuf; + // This is only used to support EnsureMapped if we fail initially. + mozilla::ipc::ReadOnlySharedMemoryHandle mBufHandle; + std::shared_ptr mBuf; SurfaceFormat mFormat = SurfaceFormat::UNKNOWN; base::ProcessId mCreatorPid = 0; bool mCreatorRef = true; @@ -119,8 +125,6 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface { * source surface. */ class SourceSurfaceSharedData : public DataSourceSurface { - typedef mozilla::ipc::SharedMemory SharedMemory; - public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceSharedData, override) @@ -197,7 +201,7 @@ class SourceSurfaceSharedData : public DataSourceSurface { * NS_ERROR_NOT_AVAILABLE -- handle was closed, need to reallocate. * NS_ERROR_FAILURE -- failed to create a handle to share. */ - nsresult CloneHandle(SharedMemory::Handle& aHandle); + nsresult CloneHandle(mozilla::ipc::ReadOnlySharedMemoryHandle& aHandle); /** * Indicates the buffer is not expected to be shared with any more processes. @@ -314,7 +318,7 @@ class SourceSurfaceSharedData : public DataSourceSurface { } size_t GetAlignedDataLength() const { - return mozilla::ipc::SharedMemory::PageAlignedSize(GetDataLength()); + return mozilla::ipc::shared_memory::PageAlignedSize(GetDataLength()); } /** @@ -328,8 +332,11 @@ class SourceSurfaceSharedData : public DataSourceSurface { int32_t mHandleCount; Maybe mDirtyRect; IntSize mSize; - RefPtr mBuf; - RefPtr mOldBuf; + mozilla::ipc::MutableSharedMemoryHandle mBufHandle; + // This class always has mutable mappings, however we need to share them with + // the wrapper which may be read-only, so we use MutableOrReadOnly. + std::shared_ptr mBuf; + std::shared_ptr mOldBuf; SurfaceFormat mFormat; bool mClosed : 1; bool mFinalized : 1; diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 160780bd3997..1287043dd36b 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -86,9 +86,8 @@ #include "nsThreadUtils.h" // for NS_IsMainThread #include "nsViewportInfo.h" // for ViewportMinScale(), ViewportMaxScale() #include "prsystem.h" // for PR_GetPhysicalMemorySize -#include "mozilla/ipc/SharedMemory.h" // for SharedMemory -#include "ScrollSnap.h" // for ScrollSnapUtils -#include "ScrollAnimationPhysics.h" // for ComputeAcceleratedWheelDelta +#include "ScrollSnap.h" // for ScrollSnapUtils +#include "ScrollAnimationPhysics.h" // for ComputeAcceleratedWheelDelta #include "SmoothMsdScrollAnimation.h" #include "SmoothScrollAnimation.h" #include "WheelScrollAnimation.h" diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index 448123256d68..b4a22e5f48fd 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -26,7 +26,6 @@ #include "mozilla/gfx/Logging.h" // for gfxDebug #include "mozilla/gfx/gfxVars.h" #include "mozilla/ipc/CrossProcessSemaphore.h" -#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc #include "mozilla/layers/CanvasRenderer.h" #include "mozilla/layers/CompositableForwarder.h" #include "mozilla/layers/ISurfaceAllocator.h" diff --git a/gfx/layers/ipc/CanvasChild.cpp b/gfx/layers/ipc/CanvasChild.cpp index 2562576fb81c..c6bdd9693e40 100644 --- a/gfx/layers/ipc/CanvasChild.cpp +++ b/gfx/layers/ipc/CanvasChild.cpp @@ -18,6 +18,7 @@ #include "mozilla/gfx/Point.h" #include "mozilla/ipc/Endpoint.h" #include "mozilla/ipc/ProcessChild.h" +#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/layers/CanvasDrawEventRecorder.h" #include "mozilla/layers/ImageDataSerializer.h" #include "mozilla/layers/SourceSurfaceSharedData.h" @@ -39,27 +40,29 @@ class RecorderHelpers final : public CanvasDrawEventRecorder::Helpers { ~RecorderHelpers() override = default; - bool InitTranslator(TextureType aTextureType, TextureType aWebglTextureType, - gfx::BackendType aBackendType, Handle&& aReadHandle, - nsTArray&& aBufferHandles, uint64_t aBufferSize, - CrossProcessSemaphoreHandle&& aReaderSem, - CrossProcessSemaphoreHandle&& aWriterSem) override { + bool InitTranslator( + TextureType aTextureType, TextureType aWebglTextureType, + gfx::BackendType aBackendType, + ipc::MutableSharedMemoryHandle&& aReadHandle, + nsTArray&& aBufferHandles, + CrossProcessSemaphoreHandle&& aReaderSem, + CrossProcessSemaphoreHandle&& aWriterSem) override { NS_ASSERT_OWNINGTHREAD(RecorderHelpers); if (NS_WARN_IF(!mCanvasChild)) { return false; } return mCanvasChild->SendInitTranslator( aTextureType, aWebglTextureType, aBackendType, std::move(aReadHandle), - std::move(aBufferHandles), aBufferSize, std::move(aReaderSem), + std::move(aBufferHandles), std::move(aReaderSem), std::move(aWriterSem)); } - bool AddBuffer(Handle&& aBufferHandle, uint64_t aBufferSize) override { + bool AddBuffer(ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) override { NS_ASSERT_OWNINGTHREAD(RecorderHelpers); if (!mCanvasChild) { return false; } - return mCanvasChild->SendAddBuffer(std::move(aBufferHandle), aBufferSize); + return mCanvasChild->SendAddBuffer(std::move(aBufferHandle)); } bool ReaderClosed() override { @@ -192,7 +195,9 @@ class SourceSurfaceCanvasRecording final : public gfx::SourceSurface { class CanvasDataShmemHolder { public: - CanvasDataShmemHolder(ipc::SharedMemory* aShmem, CanvasChild* aCanvasChild) + CanvasDataShmemHolder( + const std::shared_ptr& aShmem, + CanvasChild* aCanvasChild) : mMutex("CanvasChild::DataShmemHolder::mMutex"), mShmem(aShmem), mCanvasChild(aCanvasChild) {} @@ -259,7 +264,7 @@ class CanvasDataShmemHolder { return; } - mCanvasChild->ReturnDataSurfaceShmem(mShmem.forget()); + mCanvasChild->ReturnDataSurfaceShmem(std::move(mShmem)); mCanvasChild = nullptr; mWorkerRef = nullptr; } @@ -276,7 +281,7 @@ class CanvasDataShmemHolder { private: Mutex mMutex; - RefPtr mShmem; + std::shared_ptr mShmem; RefPtr mCanvasChild MOZ_GUARDED_BY(mMutex); RefPtr mWorkerRef MOZ_GUARDED_BY(mMutex); }; @@ -489,26 +494,26 @@ bool CanvasChild::EnsureDataSurfaceShmem(gfx::IntSize aSize, if (!sizeRequired) { return false; } - sizeRequired = ipc::SharedMemory::PageAlignedSize(sizeRequired); + sizeRequired = ipc::shared_memory::PageAlignedSize(sizeRequired); if (!mDataSurfaceShmemAvailable || mDataSurfaceShmem->Size() < sizeRequired) { RecordEvent(RecordedPauseTranslation()); - auto dataSurfaceShmem = MakeRefPtr(); - if (!dataSurfaceShmem->Create(sizeRequired) || - !dataSurfaceShmem->Map(sizeRequired)) { - return false; - } - - auto shmemHandle = dataSurfaceShmem->TakeHandle(); + auto shmemHandle = ipc::shared_memory::Create(sizeRequired); if (!shmemHandle) { return false; } - if (!SendSetDataSurfaceBuffer(std::move(shmemHandle), sizeRequired)) { + auto roMapping = shmemHandle.AsReadOnly().Map(); + if (!roMapping) { return false; } - mDataSurfaceShmem = dataSurfaceShmem.forget(); + if (!SendSetDataSurfaceBuffer(std::move(shmemHandle))) { + return false; + } + + mDataSurfaceShmem = std::make_shared( + std::move(roMapping)); mDataSurfaceShmemAvailable = true; } @@ -560,8 +565,7 @@ already_AddRefed CanvasChild::GetDataSurface( // use that directly without having to allocate a new shmem for retrieval. auto it = mTextureInfo.find(aTextureOwnerId); if (it != mTextureInfo.end() && it->second.mSnapshotShmem) { - const auto shmemPtr = - reinterpret_cast(it->second.mSnapshotShmem->Memory()); + const auto* shmemPtr = it->second.mSnapshotShmem->DataAs(); MOZ_ASSERT(shmemPtr); mRecorder->RecordEvent(RecordedPrepareShmem(aTextureOwnerId)); auto checkpoint = CreateCheckpoint(); @@ -574,10 +578,12 @@ already_AddRefed CanvasChild::GetDataSurface( delete closure; return nullptr; } + // We can cast away the const of `shmemPtr` to match the call because the + // DataSourceSurface will not be written to. RefPtr dataSurface = gfx::Factory::CreateWrappingDataSourceSurface( - shmemPtr, stride, ssSize, ssFormat, ReleaseDataShmemHolder, - closure); + const_cast(shmemPtr), stride, ssSize, ssFormat, + ReleaseDataShmemHolder, closure); aMayInvalidate = true; return dataSurface.forget(); } @@ -603,11 +609,14 @@ already_AddRefed CanvasChild::GetDataSurface( mDataSurfaceShmemAvailable = false; - auto* data = static_cast(mDataSurfaceShmem->Memory()); + const auto* data = mDataSurfaceShmem->DataAs(); + // We can cast away the const of `data` to match the call because the + // DataSourceSurface will not be written to. RefPtr dataSurface = gfx::Factory::CreateWrappingDataSourceSurface( - data, stride, ssSize, ssFormat, ReleaseDataShmemHolder, closure); + const_cast(data), stride, ssSize, ssFormat, + ReleaseDataShmemHolder, closure); aMayInvalidate = false; return dataSurface.forget(); } @@ -631,10 +640,9 @@ already_AddRefed CanvasChild::WrapSurface( } void CanvasChild::ReturnDataSurfaceShmem( - already_AddRefed aDataSurfaceShmem) { - RefPtr data = aDataSurfaceShmem; + std::shared_ptr&& aDataSurfaceShmem) { // We can only reuse the latest data surface shmem. - if (data == mDataSurfaceShmem) { + if (aDataSurfaceShmem == mDataSurfaceShmem) { MOZ_ASSERT(!mDataSurfaceShmemAvailable); mDataSurfaceShmemAvailable = true; } @@ -680,17 +688,17 @@ bool CanvasChild::RequiresRefresh( } ipc::IPCResult CanvasChild::RecvSnapshotShmem( - const RemoteTextureOwnerId aTextureOwnerId, Handle&& aShmemHandle, - uint32_t aShmemSize, SnapshotShmemResolver&& aResolve) { + const RemoteTextureOwnerId aTextureOwnerId, + ipc::ReadOnlySharedMemoryHandle&& aShmemHandle, + SnapshotShmemResolver&& aResolve) { auto it = mTextureInfo.find(aTextureOwnerId); if (it != mTextureInfo.end()) { - auto shmem = MakeRefPtr(); - if (NS_WARN_IF(!shmem->SetHandle(std::move(aShmemHandle), - ipc::SharedMemory::RightsReadOnly)) || - NS_WARN_IF(!shmem->Map(aShmemSize))) { + auto shmem = aShmemHandle.Map(); + if (NS_WARN_IF(!shmem)) { shmem = nullptr; } else { - it->second.mSnapshotShmem = std::move(shmem); + it->second.mSnapshotShmem = + std::make_shared(std::move(shmem)); } aResolve(true); } else { diff --git a/gfx/layers/ipc/CanvasChild.h b/gfx/layers/ipc/CanvasChild.h index 698111b47570..771f492d530b 100644 --- a/gfx/layers/ipc/CanvasChild.h +++ b/gfx/layers/ipc/CanvasChild.h @@ -9,6 +9,7 @@ #include "mozilla/gfx/RecordedEvent.h" #include "mozilla/ipc/CrossProcessSemaphore.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/layers/PCanvasChild.h" #include "mozilla/layers/SourceSurfaceSharedData.h" #include "mozilla/WeakPtr.h" @@ -56,9 +57,10 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr { ipc::IPCResult RecvNotifyRequiresRefresh( const RemoteTextureOwnerId aTextureOwnerId); - ipc::IPCResult RecvSnapshotShmem(const RemoteTextureOwnerId aTextureOwnerId, - Handle&& aShmemHandle, uint32_t aShmemSize, - SnapshotShmemResolver&& aResolve); + ipc::IPCResult RecvSnapshotShmem( + const RemoteTextureOwnerId aTextureOwnerId, + ipc::ReadOnlySharedMemoryHandle&& aShmemHandle, + SnapshotShmemResolver&& aResolve); ipc::IPCResult RecvNotifyTextureDestruction( const RemoteTextureOwnerId aTextureOwnerId); @@ -162,7 +164,7 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr { bool RequiresRefresh(const RemoteTextureOwnerId aTextureOwnerId) const; void ReturnDataSurfaceShmem( - already_AddRefed aDataSurfaceShmem); + std::shared_ptr&& aDataSurfaceShmem); protected: void ActorDestroy(ActorDestroyReason aWhy) final; @@ -185,12 +187,12 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr { RefPtr mWorkerRef; RefPtr mRecorder; - RefPtr mDataSurfaceShmem; + std::shared_ptr mDataSurfaceShmem; bool mDataSurfaceShmemAvailable = false; int64_t mLastWriteLockCheckpoint = 0; uint32_t mTransactionsSinceGetDataSurface = kCacheDataSurfaceThreshold; struct TextureInfo { - RefPtr mSnapshotShmem; + std::shared_ptr mSnapshotShmem; bool mRequiresRefresh = false; }; std::unordered_map& aShmem, - Handle&& aHandle, - ipc::SharedMemory::OpenRights aOpenRights, - size_t aSize) { - auto shmem = MakeRefPtr(); - if (!shmem->SetHandle(std::move(aHandle), aOpenRights) || - !shmem->Map(aSize)) { - return false; - } - - shmem->CloseHandle(); - aShmem = shmem.forget(); - return true; -} - StaticRefPtr CanvasTranslator::sSharedContext; bool CanvasTranslator::EnsureSharedContextWebgl() { @@ -154,8 +140,8 @@ void CanvasTranslator::Shutdown() { mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator( TextureType aTextureType, TextureType aWebglTextureType, - gfx::BackendType aBackendType, Handle&& aReadHandle, - nsTArray&& aBufferHandles, uint64_t aBufferSize, + gfx::BackendType aBackendType, ipc::MutableSharedMemoryHandle&& aReadHandle, + nsTArray&& aBufferHandles, CrossProcessSemaphoreHandle&& aReaderSem, CrossProcessSemaphoreHandle&& aWriterSem) { if (mHeaderShmem) { @@ -167,14 +153,13 @@ mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator( mBackendType = aBackendType; mOtherPid = OtherPid(); - mHeaderShmem = MakeAndAddRef(); - if (!CreateAndMapShmem(mHeaderShmem, std::move(aReadHandle), - ipc::SharedMemory::RightsReadWrite, sizeof(Header))) { + mHeaderShmem = aReadHandle.Map(); + if (!mHeaderShmem) { Deactivate(); return IPC_FAIL(this, "Failed to map canvas header shared memory."); } - mHeader = static_cast(mHeaderShmem->Memory()); + mHeader = mHeaderShmem.DataAs
(); mWriterSemaphore.reset(CrossProcessSemaphore::Create(std::move(aWriterSem))); mWriterSemaphore->CloseHandle(); @@ -193,10 +178,10 @@ mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator( } // Use the first buffer as our current buffer. - mDefaultBufferSize = aBufferSize; + mDefaultBufferSize = aBufferHandles[0].Size(); auto handleIter = aBufferHandles.begin(); - if (!CreateAndMapShmem(mCurrentShmem.shmem, std::move(*handleIter), - ipc::SharedMemory::RightsReadOnly, aBufferSize)) { + mCurrentShmem.shmem = std::move(*handleIter).Map(); + if (!mCurrentShmem.shmem) { Deactivate(); return IPC_FAIL(this, "Failed to map canvas buffer shared memory."); } @@ -205,8 +190,8 @@ mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator( // Add all other buffers to our recycled CanvasShmems. for (handleIter++; handleIter < aBufferHandles.end(); handleIter++) { CanvasShmem newShmem; - if (!CreateAndMapShmem(newShmem.shmem, std::move(*handleIter), - ipc::SharedMemory::RightsReadOnly, aBufferSize)) { + newShmem.shmem = std::move(*handleIter).Map(); + if (!newShmem.shmem) { Deactivate(); return IPC_FAIL(this, "Failed to map canvas buffer shared memory."); } @@ -247,7 +232,7 @@ ipc::IPCResult CanvasTranslator::RecvRestartTranslation() { } ipc::IPCResult CanvasTranslator::RecvAddBuffer( - ipc::SharedMemory::Handle&& aBufferHandle, uint64_t aBufferSize) { + ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) { if (mDeactivated) { // The other side might have sent a resume message before we deactivated. return IPC_OK(); @@ -255,20 +240,20 @@ ipc::IPCResult CanvasTranslator::RecvAddBuffer( if (UsePendingCanvasTranslatorEvents()) { MutexAutoLock lock(mCanvasTranslatorEventsLock); - mPendingCanvasTranslatorEvents.push_back(CanvasTranslatorEvent::AddBuffer( - std::move(aBufferHandle), aBufferSize)); + mPendingCanvasTranslatorEvents.push_back( + CanvasTranslatorEvent::AddBuffer(std::move(aBufferHandle))); PostCanvasTranslatorEvents(lock); } else { - DispatchToTaskQueue(NewRunnableMethod( + DispatchToTaskQueue(NewRunnableMethod( "CanvasTranslator::AddBuffer", this, &CanvasTranslator::AddBuffer, - std::move(aBufferHandle), aBufferSize)); + std::move(aBufferHandle))); } return IPC_OK(); } -bool CanvasTranslator::AddBuffer(ipc::SharedMemory::Handle&& aBufferHandle, - size_t aBufferSize) { +bool CanvasTranslator::AddBuffer( + ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) { MOZ_ASSERT(IsInTaskQueue()); if (mHeader->readerState == State::Failed) { // We failed before we got to the pause event. @@ -297,8 +282,8 @@ bool CanvasTranslator::AddBuffer(ipc::SharedMemory::Handle&& aBufferHandle, } CanvasShmem newShmem; - if (!CreateAndMapShmem(newShmem.shmem, std::move(aBufferHandle), - ipc::SharedMemory::RightsReadOnly, aBufferSize)) { + newShmem.shmem = aBufferHandle.Map(); + if (!newShmem.shmem) { return false; } @@ -309,7 +294,7 @@ bool CanvasTranslator::AddBuffer(ipc::SharedMemory::Handle&& aBufferHandle, } ipc::IPCResult CanvasTranslator::RecvSetDataSurfaceBuffer( - ipc::SharedMemory::Handle&& aBufferHandle, uint64_t aBufferSize) { + ipc::MutableSharedMemoryHandle&& aBufferHandle) { if (mDeactivated) { // The other side might have sent a resume message before we deactivated. return IPC_OK(); @@ -318,21 +303,19 @@ ipc::IPCResult CanvasTranslator::RecvSetDataSurfaceBuffer( if (UsePendingCanvasTranslatorEvents()) { MutexAutoLock lock(mCanvasTranslatorEventsLock); mPendingCanvasTranslatorEvents.push_back( - CanvasTranslatorEvent::SetDataSurfaceBuffer(std::move(aBufferHandle), - aBufferSize)); + CanvasTranslatorEvent::SetDataSurfaceBuffer(std::move(aBufferHandle))); PostCanvasTranslatorEvents(lock); } else { - DispatchToTaskQueue(NewRunnableMethod( + DispatchToTaskQueue(NewRunnableMethod( "CanvasTranslator::SetDataSurfaceBuffer", this, - &CanvasTranslator::SetDataSurfaceBuffer, std::move(aBufferHandle), - aBufferSize)); + &CanvasTranslator::SetDataSurfaceBuffer, std::move(aBufferHandle))); } return IPC_OK(); } bool CanvasTranslator::SetDataSurfaceBuffer( - ipc::SharedMemory::Handle&& aBufferHandle, size_t aBufferSize) { + ipc::MutableSharedMemoryHandle&& aBufferHandle) { MOZ_ASSERT(IsInTaskQueue()); if (mHeader->readerState == State::Failed) { // We failed before we got to the pause event. @@ -349,8 +332,8 @@ bool CanvasTranslator::SetDataSurfaceBuffer( return false; } - if (!CreateAndMapShmem(mDataSurfaceShmem, std::move(aBufferHandle), - ipc::SharedMemory::RightsReadWrite, aBufferSize)) { + mDataSurfaceShmem = aBufferHandle.Map(); + if (!mDataSurfaceShmem) { return false; } @@ -385,11 +368,11 @@ void CanvasTranslator::GetDataSurface(uint64_t aSurfaceRef) { ImageDataSerializer::ComputeRGBStride(format, dstSize.width); auto requiredSize = ImageDataSerializer::ComputeRGBBufferSize(dstSize, format); - if (requiredSize <= 0 || size_t(requiredSize) > mDataSurfaceShmem->Size()) { + if (requiredSize <= 0 || size_t(requiredSize) > mDataSurfaceShmem.Size()) { return; } - uint8_t* dst = static_cast(mDataSurfaceShmem->Memory()); + uint8_t* dst = mDataSurfaceShmem.DataAs(); const uint8_t* src = map->GetData(); const uint8_t* endSrc = src + (srcSize.height * srcStride); while (src < endSrc) { @@ -795,12 +778,11 @@ void CanvasTranslator::HandleCanvasTranslatorEvents() { dispatchTranslate = TranslateRecording(); break; case CanvasTranslatorEvent::Tag::AddBuffer: - dispatchTranslate = - AddBuffer(event->TakeBufferHandle(), event->BufferSize()); + dispatchTranslate = AddBuffer(event->TakeBufferHandle()); break; case CanvasTranslatorEvent::Tag::SetDataSurfaceBuffer: - dispatchTranslate = SetDataSurfaceBuffer(event->TakeBufferHandle(), - event->BufferSize()); + dispatchTranslate = + SetDataSurfaceBuffer(event->TakeDataSurfaceBufferHandle()); break; case CanvasTranslatorEvent::Tag::ClearCachedResources: ClearCachedResources(); @@ -1071,8 +1053,7 @@ void CanvasTranslator::CacheSnapshotShmem( nsCOMPtr thread = gfx::CanvasRenderThread::GetCanvasRenderThread(); RefPtr translator = this; - SendSnapshotShmem(aTextureOwnerId, std::move(shmemHandle), - webgl->GetShmemSize()) + SendSnapshotShmem(aTextureOwnerId, std::move(shmemHandle)) ->Then( thread, __func__, [=](bool) { translator->RemoveTexture(aTextureOwnerId); }, diff --git a/gfx/layers/ipc/CanvasTranslator.h b/gfx/layers/ipc/CanvasTranslator.h index 82cd36abba33..738ce02e2536 100644 --- a/gfx/layers/ipc/CanvasTranslator.h +++ b/gfx/layers/ipc/CanvasTranslator.h @@ -15,13 +15,16 @@ #include "mozilla/gfx/InlineTranslator.h" #include "mozilla/gfx/RecordedEvent.h" #include "CanvasChild.h" +#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/layers/CanvasDrawEventRecorder.h" #include "mozilla/layers/LayersSurfaces.h" #include "mozilla/layers/PCanvasParent.h" #include "mozilla/layers/RemoteTextureMap.h" #include "mozilla/ipc/CrossProcessSemaphore.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/Monitor.h" #include "mozilla/UniquePtr.h" +#include "mozilla/Variant.h" namespace mozilla { @@ -81,14 +84,13 @@ class CanvasTranslator final : public gfx::InlineTranslator, * @param aReaderSem reading blocked semaphore for the CanvasEventRingBuffer * @param aWriterSem writing blocked semaphore for the CanvasEventRingBuffer */ - ipc::IPCResult RecvInitTranslator(TextureType aTextureType, - TextureType aWebglTextureType, - gfx::BackendType aBackendType, - Handle&& aReadHandle, - nsTArray&& aBufferHandles, - uint64_t aBufferSize, - CrossProcessSemaphoreHandle&& aReaderSem, - CrossProcessSemaphoreHandle&& aWriterSem); + ipc::IPCResult RecvInitTranslator( + TextureType aTextureType, TextureType aWebglTextureType, + gfx::BackendType aBackendType, + ipc::MutableSharedMemoryHandle&& aReadHandle, + nsTArray&& aBufferHandles, + CrossProcessSemaphoreHandle&& aReaderSem, + CrossProcessSemaphoreHandle&& aWriterSem); /** * Restart the translation from a Stopped state. @@ -99,13 +101,13 @@ class CanvasTranslator final : public gfx::InlineTranslator, * 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. */ - ipc::IPCResult RecvAddBuffer(Handle&& aBufferHandle, uint64_t aBufferSize); + ipc::IPCResult RecvAddBuffer(ipc::ReadOnlySharedMemoryHandle&& aBufferHandle); /** * Sets the shared memory to be used for readback. */ - ipc::IPCResult RecvSetDataSurfaceBuffer(Handle&& aBufferHandle, - uint64_t aBufferSize); + ipc::IPCResult RecvSetDataSurfaceBuffer( + ipc::MutableSharedMemoryHandle&& aBufferHandle); ipc::IPCResult RecvClearCachedResources(); @@ -316,23 +318,25 @@ class CanvasTranslator final : public gfx::InlineTranslator, const Tag mTag; private: - ipc::SharedMemory::Handle mBufferHandle; - const size_t mBufferSize; + Variant + mBufferHandle; public: explicit CanvasTranslatorEvent(const Tag aTag) - : mTag(aTag), mBufferSize(0) { + : mTag(aTag), mBufferHandle(ipc::ReadOnlySharedMemoryHandle()) { MOZ_ASSERT(mTag == Tag::TranslateRecording || mTag == Tag::ClearCachedResources || mTag == Tag::DropFreeBuffersWhenDormant); } CanvasTranslatorEvent(const Tag aTag, - ipc::SharedMemory::Handle&& aBufferHandle, - size_t aBufferSize) - : mTag(aTag), - mBufferHandle(std::move(aBufferHandle)), - mBufferSize(aBufferSize) { - MOZ_ASSERT(mTag == Tag::AddBuffer || mTag == Tag::SetDataSurfaceBuffer); + ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) + : mTag(aTag), mBufferHandle(std::move(aBufferHandle)) { + MOZ_ASSERT(mTag == Tag::AddBuffer); + } + CanvasTranslatorEvent(const Tag aTag, + ipc::MutableSharedMemoryHandle&& aBufferHandle) + : mTag(aTag), mBufferHandle(std::move(aBufferHandle)) { + MOZ_ASSERT(mTag == Tag::SetDataSurfaceBuffer); } static UniquePtr TranslateRecording() { @@ -340,15 +344,15 @@ class CanvasTranslator final : public gfx::InlineTranslator, } static UniquePtr AddBuffer( - ipc::SharedMemory::Handle&& aBufferHandle, size_t aBufferSize) { - return MakeUnique( - Tag::AddBuffer, std::move(aBufferHandle), aBufferSize); + ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) { + return MakeUnique(Tag::AddBuffer, + std::move(aBufferHandle)); } static UniquePtr SetDataSurfaceBuffer( - ipc::SharedMemory::Handle&& aBufferHandle, size_t aBufferSize) { - return MakeUnique( - Tag::SetDataSurfaceBuffer, std::move(aBufferHandle), aBufferSize); + ipc::MutableSharedMemoryHandle&& aBufferHandle) { + return MakeUnique(Tag::SetDataSurfaceBuffer, + std::move(aBufferHandle)); } static UniquePtr ClearCachedResources() { @@ -359,20 +363,20 @@ class CanvasTranslator final : public gfx::InlineTranslator, return MakeUnique(Tag::DropFreeBuffersWhenDormant); } - ipc::SharedMemory::Handle TakeBufferHandle() { - if (mTag == Tag::AddBuffer || mTag == Tag::SetDataSurfaceBuffer) { - return std::move(mBufferHandle); + ipc::ReadOnlySharedMemoryHandle TakeBufferHandle() { + if (mTag == Tag::AddBuffer) { + return std::move(mBufferHandle).as(); } MOZ_ASSERT_UNREACHABLE("unexpected to be called"); - return mozilla::ipc::SharedMemory::NULLHandle(); + return nullptr; } - size_t BufferSize() { - if (mTag == Tag::AddBuffer || mTag == Tag::SetDataSurfaceBuffer) { - return mBufferSize; + ipc::MutableSharedMemoryHandle TakeDataSurfaceBufferHandle() { + if (mTag == Tag::SetDataSurfaceBuffer) { + return std::move(mBufferHandle).as(); } MOZ_ASSERT_UNREACHABLE("unexpected to be called"); - return 0; + return nullptr; } }; @@ -380,13 +384,13 @@ class CanvasTranslator final : public gfx::InlineTranslator, * @returns true if next HandleCanvasTranslatorEvents() needs to call * TranslateRecording(). */ - bool AddBuffer(Handle&& aBufferHandle, size_t aBufferSize); + bool AddBuffer(ipc::ReadOnlySharedMemoryHandle&& aBufferHandle); /* * @returns true if next HandleCanvasTranslatorEvents() needs to call * TranslateRecording(). */ - bool SetDataSurfaceBuffer(Handle&& aBufferHandle, size_t aBufferSize); + bool SetDataSurfaceBuffer(ipc::MutableSharedMemoryHandle&& aBufferHandle); bool ReadNextEvent(EventType& aEventType); @@ -470,7 +474,7 @@ class CanvasTranslator final : public gfx::InlineTranslator, using State = CanvasDrawEventRecorder::State; using Header = CanvasDrawEventRecorder::Header; - RefPtr mHeaderShmem; + ipc::SharedMemoryMapping mHeaderShmem; Header* mHeader = nullptr; // Limit event processing to stop at the designated checkpoint, rather than // proceed beyond it. This also forces processing to continue, even when it @@ -479,20 +483,20 @@ class CanvasTranslator final : public gfx::InlineTranslator, int64_t mFlushCheckpoint = 0; struct CanvasShmem { - RefPtr shmem; - bool IsValid() const { return !!shmem; } - auto Size() { return shmem ? shmem->Size() : 0; } + ipc::ReadOnlySharedMemoryMapping shmem; + bool IsValid() const { return shmem.IsValid(); } + auto Size() { return shmem ? shmem.Size() : 0; } gfx::MemReader CreateMemReader() { if (!shmem) { return {nullptr, 0}; } - return {static_cast(shmem->Memory()), Size()}; + return {shmem.DataAs(), Size()}; } }; std::queue mCanvasShmems; CanvasShmem mCurrentShmem; gfx::MemReader mCurrentMemReader{0, 0}; - RefPtr mDataSurfaceShmem; + ipc::SharedMemoryMapping mDataSurfaceShmem; UniquePtr mWriterSemaphore; UniquePtr mReaderSemaphore; TextureType mTextureType = TextureType::Unknown; diff --git a/gfx/layers/ipc/CompositorBridgeParent.h b/gfx/layers/ipc/CompositorBridgeParent.h index 404aa48b8a1d..735aa743bdf1 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.h +++ b/gfx/layers/ipc/CompositorBridgeParent.h @@ -17,7 +17,6 @@ #include "mozilla/TimeStamp.h" // for TimeStamp #include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/ipc/ProtocolUtils.h" -#include "mozilla/ipc/SharedMemory.h" #include "mozilla/layers/CompositorController.h" #include "mozilla/layers/CompositorVsyncSchedulerOwner.h" #include "mozilla/layers/FocusTarget.h" diff --git a/gfx/layers/ipc/ISurfaceAllocator.h b/gfx/layers/ipc/ISurfaceAllocator.h index ea8019a182da..cd79d1a8f06a 100644 --- a/gfx/layers/ipc/ISurfaceAllocator.h +++ b/gfx/layers/ipc/ISurfaceAllocator.h @@ -11,8 +11,7 @@ #include // for uint32_t #include "gfxTypes.h" #include "mozilla/dom/ipc/IdType.h" -#include "mozilla/gfx/Point.h" // for IntSize -#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc +#include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/RefPtr.h" #include "nsIMemoryReporter.h" // for nsIMemoryReporter #include "mozilla/Atomics.h" // for Atomic diff --git a/gfx/layers/ipc/ImageBridgeChild.h b/gfx/layers/ipc/ImageBridgeChild.h index d5a8b7199ded..9e01138c1e9a 100644 --- a/gfx/layers/ipc/ImageBridgeChild.h +++ b/gfx/layers/ipc/ImageBridgeChild.h @@ -13,8 +13,7 @@ #include "mozilla/Attributes.h" // for override #include "mozilla/Atomics.h" -#include "mozilla/RefPtr.h" // for already_AddRefed -#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc +#include "mozilla/RefPtr.h" // for already_AddRefed #include "mozilla/layers/CompositableForwarder.h" #include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/PImageBridgeChild.h" diff --git a/gfx/layers/ipc/ImageBridgeParent.h b/gfx/layers/ipc/ImageBridgeParent.h index c8d5ea4a736f..22ca4df93ce2 100644 --- a/gfx/layers/ipc/ImageBridgeParent.h +++ b/gfx/layers/ipc/ImageBridgeParent.h @@ -14,7 +14,6 @@ #include "mozilla/Attributes.h" // for override #include "mozilla/dom/ipc/IdType.h" #include "mozilla/ipc/ProtocolUtils.h" -#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc #include "mozilla/layers/CompositorThread.h" #include "mozilla/layers/PImageBridgeParent.h" #include "nsISupportsImpl.h" diff --git a/gfx/layers/ipc/LayersSurfaces.ipdlh b/gfx/layers/ipc/LayersSurfaces.ipdlh index 841973e973ad..af4350807526 100644 --- a/gfx/layers/ipc/LayersSurfaces.ipdlh +++ b/gfx/layers/ipc/LayersSurfaces.ipdlh @@ -24,7 +24,6 @@ using mozilla::gfx::IntSize from "mozilla/gfx/Point.h"; using mozilla::gfx::Matrix4x4 from "mozilla/gfx/Matrix.h"; using mozilla::gfx::FenceInfo 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 mozilla::layers::MaybeVideoBridgeSource from "mozilla/layers/VideoBridgeUtils.h"; using mozilla::layers::RemoteTextureId from "mozilla/layers/LayersTypes.h"; @@ -35,6 +34,7 @@ using mozilla::layers::GpuProcessQueryId from "mozilla/layers/LayersTypes.h"; using mozilla::wr::ExternalImageSource from "mozilla/webrender/WebRenderTypes.h"; using mozilla::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h"; using mozilla::layers::SurfaceDescriptorRemoteDecoderId from "mozilla/layers/LayersTypes.h"; +[MoveOnly] using mozilla::ipc::ReadOnlySharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h"; namespace mozilla { namespace layers { @@ -186,12 +186,12 @@ namespace layers { MemoryOrShmem data; }; -[Comparable] struct SurfaceDescriptorShared +struct SurfaceDescriptorShared { IntSize size; int32_t stride; SurfaceFormat format; - Handle handle; + ReadOnlySharedMemoryHandle handle; }; [Comparable] struct SurfaceDescriptorExternalImage diff --git a/gfx/layers/ipc/PCanvas.ipdl b/gfx/layers/ipc/PCanvas.ipdl index 368e8283463b..6e31fe568187 100644 --- a/gfx/layers/ipc/PCanvas.ipdl +++ b/gfx/layers/ipc/PCanvas.ipdl @@ -11,8 +11,9 @@ include "mozilla/layers/CanvasTranslator.h"; [MoveOnly] using mozilla::CrossProcessSemaphoreHandle from "mozilla/ipc/CrossProcessSemaphore.h"; using mozilla::layers::RemoteTextureOwnerId 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"; +[MoveOnly] using mozilla::ipc::ReadOnlySharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h"; +[MoveOnly] using mozilla::ipc::MutableSharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h"; namespace mozilla { namespace layers { @@ -34,8 +35,8 @@ parent: * are handles for the semaphores to handle waiting on either side. */ async InitTranslator(TextureType aTextureType, TextureType aWebglTextureType, - BackendType aBackendType, Handle aHeaderHandle, - Handle[] aBufferHandles, uint64_t aBufferSize, + BackendType aBackendType, MutableSharedMemoryHandle aHeaderHandle, + ReadOnlySharedMemoryHandle[] aBufferHandles, CrossProcessSemaphoreHandle aReaderSem, CrossProcessSemaphoreHandle aWriterSem); @@ -48,12 +49,12 @@ parent: * 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. */ - async AddBuffer(Handle aBufferHandle, uint64_t aBufferSize); + async AddBuffer(ReadOnlySharedMemoryHandle aBufferHandle); /** * Sets the shared memory to be used for readback. */ - async SetDataSurfaceBuffer(Handle aBufferHandle, uint64_t aBufferSize); + async SetDataSurfaceBuffer(MutableSharedMemoryHandle aBufferHandle); /** * Notify CanvasTranslator it is about to be minimized. @@ -97,7 +98,7 @@ child: /** * Cache the shmem of the framebuffer for snapshotting. */ - async SnapshotShmem(RemoteTextureOwnerId aTextureOwnerId, Handle aShmemHandle, uint32_t aShmemSize) returns (bool aSuccess); + async SnapshotShmem(RemoteTextureOwnerId aTextureOwnerId, ReadOnlySharedMemoryHandle aShmemHandle) returns (bool aSuccess); async NotifyTextureDestruction(RemoteTextureOwnerId aTextureOwnerId); }; diff --git a/gfx/layers/ipc/PCompositorManager.ipdl b/gfx/layers/ipc/PCompositorManager.ipdl index b60b9994182b..8290ae698e79 100644 --- a/gfx/layers/ipc/PCompositorManager.ipdl +++ b/gfx/layers/ipc/PCompositorManager.ipdl @@ -14,7 +14,6 @@ include "mozilla/layers/WebRenderMessageUtils.h"; using mozilla::TimeDuration from "mozilla/TimeStamp.h"; using mozilla::CSSToLayoutDeviceScale from "Units.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::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h"; using mozilla::wr::MemoryReport from "mozilla/webrender/WebRenderTypes.h"; diff --git a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp index 0757d1e22b4f..c4b361b15312 100644 --- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp +++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp @@ -5,13 +5,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "SharedPlanarYCbCrImage.h" -#include // for size_t -#include // for printf -#include "gfx2DGlue.h" // for Moz2D transition helpers -#include "ISurfaceAllocator.h" // for ISurfaceAllocator, etc -#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc -#include "mozilla/gfx/Types.h" // for SurfaceFormat::SurfaceFormat::YUV -#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc +#include // for size_t +#include // for printf +#include "gfx2DGlue.h" // for Moz2D transition helpers +#include "ISurfaceAllocator.h" // for ISurfaceAllocator, etc +#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc +#include "mozilla/gfx/Types.h" // for SurfaceFormat::SurfaceFormat::YUV #include "mozilla/layers/ImageClient.h" // for ImageClient #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc #include "mozilla/layers/TextureClient.h" diff --git a/gfx/layers/ipc/SharedSurfacesChild.cpp b/gfx/layers/ipc/SharedSurfacesChild.cpp index feb7ef2ecb67..c05c71633e63 100644 --- a/gfx/layers/ipc/SharedSurfacesChild.cpp +++ b/gfx/layers/ipc/SharedSurfacesChild.cpp @@ -220,7 +220,7 @@ nsresult SharedSurfacesChild::ShareInternal(SourceSurfaceSharedData* aSurface, // 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 // and/or if it has been finalized but never used for drawing in process. - ipc::SharedMemory::Handle handle = ipc::SharedMemory::NULLHandle(); + ipc::ReadOnlySharedMemoryHandle handle; nsresult rv = aSurface->CloneHandle(handle); if (rv == NS_ERROR_NOT_AVAILABLE) { // It is at least as expensive to copy the image to the GPU process if we diff --git a/gfx/layers/ipc/SharedSurfacesParent.h b/gfx/layers/ipc/SharedSurfacesParent.h index b62c4a5d8197..c13f953211c0 100644 --- a/gfx/layers/ipc/SharedSurfacesParent.h +++ b/gfx/layers/ipc/SharedSurfacesParent.h @@ -12,7 +12,6 @@ #include "mozilla/StaticMutex.h" // for StaticMutex #include "mozilla/StaticPtr.h" // for StaticAutoPtr #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/Point.h" // for IntSize #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptorShared diff --git a/gfx/layers/wr/IpcResourceUpdateQueue.cpp b/gfx/layers/wr/IpcResourceUpdateQueue.cpp index d19dc7f2f9ca..470649882e8f 100644 --- a/gfx/layers/wr/IpcResourceUpdateQueue.cpp +++ b/gfx/layers/wr/IpcResourceUpdateQueue.cpp @@ -8,7 +8,6 @@ #include #include #include "mozilla/Maybe.h" -#include "mozilla/ipc/SharedMemory.h" #include "mozilla/layers/PTextureChild.h" #include "mozilla/layers/WebRenderBridgeChild.h" diff --git a/gfx/thebes/SharedFontList-impl.h b/gfx/thebes/SharedFontList-impl.h index 4fd57df4925a..f968249daf5b 100644 --- a/gfx/thebes/SharedFontList-impl.h +++ b/gfx/thebes/SharedFontList-impl.h @@ -14,15 +14,13 @@ #include "nsXULAppAPI.h" #include "mozilla/RefPtr.h" #include "mozilla/UniquePtr.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryMapping.h" // This is split out from SharedFontList.h because that header is included -// quite widely (via gfxPlatformFontList.h, gfxTextRun.h, etc), and other code -// such as the generated DOM bindings code gets upset at (indirect) inclusion -// of via SharedMemory.h. So this header, which defines the actual -// 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. +// quite widely (via gfxPlatformFontList.h, gfxTextRun.h, etc). This header, +// which defines the actual 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 fontlist { @@ -243,14 +241,14 @@ class FontList { * list has changed/grown since the child was first initialized). */ void ShareShmBlockToProcess(uint32_t aIndex, base::ProcessId aPid, - ipc::SharedMemory::Handle* aOut) { + ipc::ReadOnlySharedMemoryHandle* aOut) { MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length()); if (aIndex >= mReadOnlyShmems.Length()) { // Block index out of range - *aOut = ipc::SharedMemory::NULLHandle(); + *aOut = nullptr; return; } - *aOut = mReadOnlyShmems[aIndex]->CloneHandle(); + *aOut = mReadOnlyShmems[aIndex].Clone(); if (!*aOut) { MOZ_CRASH("failed to share block"); } @@ -261,14 +259,14 @@ class FontList { * shared to the given process. This is used at child process startup * to pass the complete list at once. */ - void ShareBlocksToProcess(nsTArray* aBlocks, + void ShareBlocksToProcess(nsTArray* aBlocks, base::ProcessId aPid); - ipc::SharedMemory::Handle ShareBlockToProcess(uint32_t aIndex, - base::ProcessId aPid); + ipc::ReadOnlySharedMemoryHandle ShareBlockToProcess(uint32_t aIndex, + base::ProcessId aPid); void ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex, - ipc::SharedMemory::Handle aHandle); + ipc::ReadOnlySharedMemoryHandle aHandle); /** * Support for memory reporter. */ @@ -298,13 +296,22 @@ class FontList { private: struct ShmBlock { - // Takes ownership of aShmem. Note that in a child process, aShmem will be - // mapped as read-only. - explicit ShmBlock(RefPtr&& aShmem) - : mShmem(std::move(aShmem)) {} + // Takes ownership of aShmem. In a child process, aShmem will be mapped as + // read-only. + explicit ShmBlock(ipc::ReadOnlySharedMemoryMapping&& 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. - void* Memory() const { return mShmem->Memory(); } + void* Memory() const { return mShmem.Address(); } + + void Clear() { mShmem = nullptr; } // Only the parent process does allocation, so only it will update this // field. Content processes read the value when checking Pointer validity. @@ -326,7 +333,8 @@ class FontList { return static_cast(Memory())->mBlockSize; } - RefPtr mShmem; + private: + ipc::MutableOrReadOnlySharedMemoryMapping mShmem; }; Header& GetHeader() const; @@ -369,10 +377,10 @@ class FontList { nsTArray> mBlocks; /** - * Auxiliary array, used only in the parent process; holds read-only copies - * of the shmem blocks; these are what will be shared to child processes. + * Auxiliary array, used only in the parent process; holds read-only handles + * for the shmem blocks; these are what will be shared to child processes. */ - nsTArray> mReadOnlyShmems; + nsTArray mReadOnlyShmems; #ifdef XP_WIN // Bool array to track whether we have read face names from the name table. diff --git a/gfx/thebes/SharedFontList.cpp b/gfx/thebes/SharedFontList.cpp index c6b3a408fdd5..da2744fcee21 100644 --- a/gfx/thebes/SharedFontList.cpp +++ b/gfx/thebes/SharedFontList.cpp @@ -6,7 +6,6 @@ #include "gfxPlatformFontList.h" #include "gfxFontUtils.h" #include "gfxFont.h" -#include "mozilla/ipc/SharedMemory.h" #include "nsReadableUtils.h" #include "prerror.h" #include "mozilla/dom/ContentChild.h" @@ -741,25 +740,21 @@ FontList::FontList(uint32_t aGeneration) { // SetXPCOMProcessAttributes. auto& blocks = dom::ContentChild::GetSingleton()->SharedFontListBlocks(); for (auto& handle : blocks) { - auto newShm = MakeRefPtr(); - if (!newShm->IsHandleValid(handle)) { + if (!handle) { // Bail out and let UpdateShmBlocks try to do its thing below. break; } - 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()) { + if (handle.Size() < SHM_BLOCK_SIZE) { MOZ_CRASH("failed to map shared memory"); } - uint32_t size = static_cast(newShm->Memory())->mBlockSize; + auto newShm = handle.Map(); + if (!newShm || !newShm.Address()) { + MOZ_CRASH("failed to map shared memory"); + } + uint32_t size = newShm.DataAs()->mBlockSize; MOZ_ASSERT(size >= SHM_BLOCK_SIZE); - if (size != SHM_BLOCK_SIZE) { - newShm->Unmap(); - if (!newShm->Map(size) || !newShm->Memory()) { - MOZ_CRASH("failed to map shared memory"); - } + if (newShm.Size() < size) { + MOZ_CRASH("failed to map shared memory"); } mBlocks.AppendElement(new ShmBlock(std::move(newShm))); } @@ -804,17 +799,17 @@ FontList::Header& FontList::GetHeader() const MOZ_NO_THREAD_SAFETY_ANALYSIS { bool FontList::AppendShmBlock(uint32_t aSizeNeeded) { MOZ_ASSERT(XRE_IsParentProcess()); uint32_t size = std::max(aSizeNeeded, SHM_BLOCK_SIZE); - auto newShm = MakeRefPtr(); - if (!newShm->CreateFreezable(size)) { + auto handle = ipc::shared_memory::CreateFreezable(size); + if (!handle) { MOZ_CRASH("failed to create shared memory"); return false; } - if (!newShm->Map(size) || !newShm->Memory()) { + auto [newShm, readOnly] = std::move(handle).Map().Freeze(); + if (!newShm || !newShm.Address()) { MOZ_CRASH("failed to map shared memory"); return false; } - auto readOnly = MakeRefPtr(); - if (!newShm->ReadOnlyCopy(readOnly.get())) { + if (!readOnly) { MOZ_CRASH("failed to create read-only copy"); return false; } @@ -848,19 +843,13 @@ bool FontList::AppendShmBlock(uint32_t aSizeNeeded) { } void FontList::ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex, - ipc::SharedMemory::Handle aHandle) { + ipc::ReadOnlySharedMemoryHandle aHandle) { MOZ_ASSERT(!XRE_IsParentProcess()); MOZ_ASSERT(mBlocks.Length() > 0); - auto newShm = MakeRefPtr(); - if (!newShm->IsHandleValid(aHandle)) { + if (!aHandle) { return; } - if (!newShm->SetHandle(std::move(aHandle), - ipc::SharedMemory::RightsReadOnly)) { - MOZ_CRASH("failed to set shm handle"); - } - if (aIndex != mBlocks.Length()) { return; } @@ -868,17 +857,15 @@ void FontList::ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex, return; } - if (!newShm->Map(SHM_BLOCK_SIZE) || !newShm->Memory()) { + auto newShm = aHandle.Map(); + if (!newShm || !newShm.Address() || newShm.Size() < SHM_BLOCK_SIZE) { MOZ_CRASH("failed to map shared memory"); } - uint32_t size = static_cast(newShm->Memory())->mBlockSize; + uint32_t size = newShm.DataAs()->mBlockSize; MOZ_ASSERT(size >= SHM_BLOCK_SIZE); - if (size != SHM_BLOCK_SIZE) { - newShm->Unmap(); - if (!newShm->Map(size) || !newShm->Memory()) { - MOZ_CRASH("failed to map shared memory"); - } + if (newShm.Size() < size) { + MOZ_CRASH("failed to map shared memory"); } mBlocks.AppendElement(new ShmBlock(std::move(newShm))); @@ -886,7 +873,7 @@ void FontList::ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex, void FontList::DetachShmBlocks() { for (auto& i : mBlocks) { - i->mShmem = nullptr; + i->Clear(); } mBlocks.Clear(); mReadOnlyShmems.Clear(); @@ -897,29 +884,22 @@ FontList::ShmBlock* FontList::GetBlockFromParent(uint32_t aIndex) { // 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 uint32_t generation = aIndex == 0 ? 0 : GetGeneration(); - ipc::SharedMemory::Handle handle = ipc::SharedMemory::NULLHandle(); + ipc::ReadOnlySharedMemoryHandle handle; if (!dom::ContentChild::GetSingleton()->SendGetFontListShmBlock( generation, aIndex, &handle)) { return nullptr; } - auto newShm = MakeRefPtr(); - if (!newShm->IsHandleValid(handle)) { + if (!handle) { return nullptr; } - if (!newShm->SetHandle(std::move(handle), - ipc::SharedMemory::RightsReadOnly)) { - MOZ_CRASH("failed to set shm handle"); - } - if (!newShm->Map(SHM_BLOCK_SIZE) || !newShm->Memory()) { + auto newShm = handle.Map(); + if (!newShm || !newShm.Address() || newShm.Size() < SHM_BLOCK_SIZE) { MOZ_CRASH("failed to map shared memory"); } - uint32_t size = static_cast(newShm->Memory())->mBlockSize; + uint32_t size = newShm.DataAs()->mBlockSize; MOZ_ASSERT(size >= SHM_BLOCK_SIZE); - if (size != SHM_BLOCK_SIZE) { - newShm->Unmap(); - if (!newShm->Map(size) || !newShm->Memory()) { - MOZ_CRASH("failed to map shared memory"); - } + if (newShm.Size() < size) { + MOZ_CRASH("failed to map shared memory"); } return new ShmBlock(std::move(newShm)); } @@ -947,10 +927,10 @@ bool FontList::UpdateShmBlocks(bool aMustLock) MOZ_NO_THREAD_SAFETY_ANALYSIS { } void FontList::ShareBlocksToProcess( - nsTArray* aBlocks, base::ProcessId aPid) { + nsTArray* aBlocks, base::ProcessId aPid) { MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length()); for (auto& shmem : mReadOnlyShmems) { - auto handle = shmem->CloneHandle(); + auto handle = shmem.Clone(); if (!handle) { // 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 @@ -963,13 +943,13 @@ void FontList::ShareBlocksToProcess( } } -ipc::SharedMemory::Handle FontList::ShareBlockToProcess(uint32_t aIndex, - base::ProcessId aPid) { +ipc::ReadOnlySharedMemoryHandle FontList::ShareBlockToProcess( + uint32_t aIndex, base::ProcessId aPid) { MOZ_RELEASE_ASSERT(XRE_IsParentProcess()); MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length()); MOZ_RELEASE_ASSERT(aIndex < mReadOnlyShmems.Length()); - return mReadOnlyShmems[aIndex]->CloneHandle(); + return mReadOnlyShmems[aIndex].Clone(); } Pointer FontList::Alloc(uint32_t aSize) { @@ -1410,7 +1390,7 @@ size_t FontList::SizeOfExcludingThis( mozilla::MallocSizeOf aMallocSizeOf) const { size_t result = mBlocks.ShallowSizeOfExcludingThis(aMallocSizeOf); for (const auto& b : mBlocks) { - result += aMallocSizeOf(b.get()) + aMallocSizeOf(b->mShmem.get()); + result += aMallocSizeOf(b.get()); } return result; } diff --git a/gfx/thebes/gfxBaseSharedMemorySurface.h b/gfx/thebes/gfxBaseSharedMemorySurface.h index bf211edab51c..663b11a09907 100644 --- a/gfx/thebes/gfxBaseSharedMemorySurface.h +++ b/gfx/thebes/gfxBaseSharedMemorySurface.h @@ -9,7 +9,6 @@ #include "mozilla/gfx/2D.h" #include "mozilla/ipc/Shmem.h" -#include "mozilla/ipc/SharedMemory.h" #include "gfxASurface.h" #include "gfxImageSurface.h" @@ -33,7 +32,6 @@ extern const cairo_user_data_key_t SHM_KEY; template class gfxBaseSharedMemorySurface : public Base { - typedef mozilla::ipc::SharedMemory SharedMemory; typedef mozilla::ipc::Shmem Shmem; protected: diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp index b593e031b9eb..aa200ceb0dcb 100644 --- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -3111,7 +3111,7 @@ void gfxPlatformFontList::CancelInitOtherFamilyNamesTask() { void gfxPlatformFontList::ShareFontListShmBlockToProcess( uint32_t aGeneration, uint32_t aIndex, base::ProcessId aPid, - mozilla::ipc::SharedMemory::Handle* aOut) { + mozilla::ipc::ReadOnlySharedMemoryHandle* aOut) { auto list = SharedFontList(); if (!list) { return; @@ -3119,12 +3119,12 @@ void gfxPlatformFontList::ShareFontListShmBlockToProcess( if (!aGeneration || list->GetGeneration() == aGeneration) { list->ShareShmBlockToProcess(aIndex, aPid, aOut); } else { - *aOut = mozilla::ipc::SharedMemory::NULLHandle(); + *aOut = nullptr; } } void gfxPlatformFontList::ShareFontListToProcess( - nsTArray* aBlocks, + nsTArray* aBlocks, base::ProcessId aPid) { auto list = SharedFontList(); if (list) { @@ -3132,15 +3132,16 @@ void gfxPlatformFontList::ShareFontListToProcess( } } -mozilla::ipc::SharedMemory::Handle gfxPlatformFontList::ShareShmBlockToProcess( - uint32_t aIndex, base::ProcessId aPid) { +mozilla::ipc::ReadOnlySharedMemoryHandle +gfxPlatformFontList::ShareShmBlockToProcess(uint32_t aIndex, + base::ProcessId aPid) { MOZ_RELEASE_ASSERT(SharedFontList()); return SharedFontList()->ShareBlockToProcess(aIndex, aPid); } void gfxPlatformFontList::ShmBlockAdded( uint32_t aGeneration, uint32_t aIndex, - mozilla::ipc::SharedMemory::Handle aHandle) { + mozilla::ipc::ReadOnlySharedMemoryHandle aHandle) { if (SharedFontList()) { AutoLock lock(mLock); SharedFontList()->ShmBlockAdded(aGeneration, aIndex, std::move(aHandle)); diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h index a732707f936a..0b1efc4cc341 100644 --- a/gfx/thebes/gfxPlatformFontList.h +++ b/gfx/thebes/gfxPlatformFontList.h @@ -27,7 +27,7 @@ #include "mozilla/MemoryReporting.h" #include "mozilla/RangedArray.h" #include "mozilla/RecursiveMutex.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" #include "nsLanguageAtomService.h" namespace mozilla { @@ -353,20 +353,20 @@ class gfxPlatformFontList : public gfxFontInfoLoader { // Create a handle for a single shmem block (identified by index) ready to // be shared to the given processId. - void ShareFontListShmBlockToProcess(uint32_t aGeneration, uint32_t aIndex, - base::ProcessId aPid, - mozilla::ipc::SharedMemory::Handle* aOut); + void ShareFontListShmBlockToProcess( + uint32_t aGeneration, uint32_t aIndex, base::ProcessId aPid, + mozilla::ipc::ReadOnlySharedMemoryHandle* aOut); // Populate the array aBlocks with the complete list of shmem handles ready // to be shared to the given processId. void ShareFontListToProcess( - nsTArray* aBlocks, + nsTArray* aBlocks, base::ProcessId aPid); void ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex, - mozilla::ipc::SharedMemory::Handle aHandle); + mozilla::ipc::ReadOnlySharedMemoryHandle aHandle); - mozilla::ipc::SharedMemory::Handle ShareShmBlockToProcess( + mozilla::ipc::ReadOnlySharedMemoryHandle ShareShmBlockToProcess( uint32_t aIndex, base::ProcessId aPid); void SetCharacterMap(uint32_t aGeneration, uint32_t aFamilyIndex, bool aAlias, diff --git a/gfx/vr/ipc/VRManagerChild.h b/gfx/vr/ipc/VRManagerChild.h index 7448007c0711..18935c9693cb 100644 --- a/gfx/vr/ipc/VRManagerChild.h +++ b/gfx/vr/ipc/VRManagerChild.h @@ -13,7 +13,6 @@ #include "mozilla/dom/WebXRBinding.h" #include "mozilla/dom/XRFrame.h" #include "mozilla/gfx/PVRManagerChild.h" -#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc #include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator #include "mozilla/layers/LayersTypes.h" // for LayersBackend diff --git a/image/ImageMemoryReporter.cpp b/image/ImageMemoryReporter.cpp index 0afb890d00b9..1f785cb27bd8 100644 --- a/image/ImageMemoryReporter.cpp +++ b/image/ImageMemoryReporter.cpp @@ -7,6 +7,7 @@ #include "ImageMemoryReporter.h" #include "Image.h" #include "base/process_util.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/layers/SharedSurfacesParent.h" #include "mozilla/StaticPrefs_image.h" #include "nsIMemoryReporter.h" @@ -113,7 +114,7 @@ void ImageMemoryReporter::ReportSharedSurface( path.AppendInt(aEntry.mCreatorRef); path.AppendLiteral(")/decoded-"); - size_t surfaceSize = mozilla::ipc::SharedMemory::PageAlignedSize( + size_t surfaceSize = mozilla::ipc::shared_memory::PageAlignedSize( aEntry.mSize.height * aEntry.mStride); // If this memory has already been reported elsewhere (e.g. as part of our diff --git a/intl/hyphenation/glue/nsHyphenationManager.cpp b/intl/hyphenation/glue/nsHyphenationManager.cpp index 01839373189a..f1541e7f723a 100644 --- a/intl/hyphenation/glue/nsHyphenationManager.cpp +++ b/intl/hyphenation/glue/nsHyphenationManager.cpp @@ -331,11 +331,10 @@ void nsHyphenationManager::LoadAliases() { void nsHyphenationManager::ShareHyphDictToProcess( nsIURI* aURI, base::ProcessId aPid, - mozilla::ipc::SharedMemory::Handle* aOutHandle, uint32_t* aOutSize) { + mozilla::ipc::ReadOnlySharedMemoryHandle* aOutHandle) { MOZ_ASSERT(XRE_IsParentProcess()); // aURI will be referring to an omnijar resource (otherwise just bail). - *aOutHandle = mozilla::ipc::SharedMemory::NULLHandle(); - *aOutSize = 0; + *aOutHandle = nullptr; // Extract the locale code from the URI, and get the corresponding // hyphenator (loading it into shared memory if necessary). @@ -358,7 +357,7 @@ void nsHyphenationManager::ShareHyphDictToProcess( return; } - hyph->CloneHandle(aOutHandle, aOutSize); + *aOutHandle = hyph->CloneHandle(); } size_t nsHyphenationManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) { diff --git a/intl/hyphenation/glue/nsHyphenationManager.h b/intl/hyphenation/glue/nsHyphenationManager.h index 1565e2fd3e7d..0a4b57bf122d 100644 --- a/intl/hyphenation/glue/nsHyphenationManager.h +++ b/intl/hyphenation/glue/nsHyphenationManager.h @@ -8,7 +8,7 @@ #include "base/process.h" #include "mozilla/Omnijar.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" #include "nsHashKeys.h" #include "nsAtomHashKeys.h" #include "nsInterfaceHashtable.h" @@ -27,9 +27,9 @@ class nsHyphenationManager : public nsIObserver { already_AddRefed GetHyphenator(nsAtom* aLocale); - void ShareHyphDictToProcess(nsIURI* aURI, base::ProcessId aPid, - mozilla::ipc::SharedMemory::Handle* aOutHandle, - uint32_t* aOutSize); + void ShareHyphDictToProcess( + nsIURI* aURI, base::ProcessId aPid, + mozilla::ipc::ReadOnlySharedMemoryHandle* aOutHandle); static nsHyphenationManager* Instance(); diff --git a/intl/hyphenation/glue/nsHyphenator.cpp b/intl/hyphenation/glue/nsHyphenator.cpp index 40ce45018b9f..46e4038dd3f3 100644 --- a/intl/hyphenation/glue/nsHyphenator.cpp +++ b/intl/hyphenation/glue/nsHyphenator.cpp @@ -7,6 +7,8 @@ #include "mozilla/dom/ContentChild.h" #include "mozilla/Omnijar.h" +#include "mozilla/ipc/SharedMemoryHandle.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "nsContentUtils.h" #include "nsIChannel.h" #include "nsIFile.h" @@ -32,7 +34,7 @@ void DefaultDelete::operator()( mapped_hyph_free_compiled_data(const_cast(aData)); } -static const void* GetItemPtrFromJarURI(nsIJARURI* aJAR, uint32_t* aLength) { +static const uint8_t* GetItemPtrFromJarURI(nsIJARURI* aJAR, uint32_t* aLength) { // Try to get the jarfile's nsZipArchive, find the relevant item, and return // a pointer to its data provided it is stored uncompressed. nsCOMPtr jarFile; @@ -66,63 +68,53 @@ static const void* GetItemPtrFromJarURI(nsIJARURI* aJAR, uint32_t* aLength) { return nullptr; } -static RefPtr GetHyphDictFromParent(nsIURI* aURI, - uint32_t* aLength) { +static ipc::ReadOnlySharedMemoryMapping GetHyphDictFromParent(nsIURI* aURI) { MOZ_ASSERT(!XRE_IsParentProcess()); - ipc::SharedMemory::Handle handle = ipc::SharedMemory::NULLHandle(); - uint32_t size; + ipc::ReadOnlySharedMemoryHandle handle; MOZ_ASSERT(aURI); - if (!dom::ContentChild::GetSingleton()->SendGetHyphDict(aURI, &handle, - &size)) { + if (!dom::ContentChild::GetSingleton()->SendGetHyphDict(aURI, &handle)) { return nullptr; } - RefPtr shm = MakeRefPtr(); - if (!shm->IsHandleValid(handle)) { + if (!handle.IsValid()) { return nullptr; } - if (!shm->SetHandle(std::move(handle), ipc::SharedMemory::RightsReadOnly)) { + auto map = handle.Map(); + if (!map) { return nullptr; } - if (!shm->Map(size)) { + if (!map.Address()) { return nullptr; } - char* addr = static_cast(shm->Memory()); - if (!addr) { - return nullptr; - } - *aLength = size; - return shm; + return map; } -static RefPtr CopyToShmem(const CompiledData* aData) { +static ipc::ReadOnlySharedMemoryHandle CopyToShmem(const CompiledData* aData) { MOZ_ASSERT(XRE_IsParentProcess()); // 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 // without hyphenation. uint32_t size = mapped_hyph_compiled_data_size(aData); - RefPtr shm = MakeRefPtr(); - if (!shm->CreateFreezable(size)) { + auto handle = ipc::shared_memory::CreateFreezable(size); + if (!handle) { return nullptr; } - if (!shm->Map(size)) { + auto map = std::move(handle).Map(); + if (!map) { return nullptr; } - char* buffer = static_cast(shm->Memory()); + char* buffer = map.DataAs(); if (!buffer) { return nullptr; } memcpy(buffer, mapped_hyph_compiled_data_ptr(aData), size); - if (!shm->Freeze()) { - return nullptr; - } - - return shm; + auto [_, readOnlyHandle] = std::move(map).Freeze(); + return std::move(readOnlyHandle); } -static RefPtr LoadFromURI(nsIURI* aURI, uint32_t* aLength, - bool aPrecompiled) { +static ipc::ReadOnlySharedMemoryHandle LoadFromURI(nsIURI* aURI, + bool aPrecompiled) { MOZ_ASSERT(XRE_IsParentProcess()); nsCOMPtr channel; if (NS_FAILED(NS_NewChannel( @@ -145,14 +137,15 @@ static RefPtr LoadFromURI(nsIURI* aURI, uint32_t* aLength, } if (aPrecompiled) { - RefPtr shm = MakeRefPtr(); - if (!shm->CreateFreezable(available)) { + auto handle = ipc::shared_memory::CreateFreezable(available); + if (!handle) { return nullptr; } - if (!shm->Map(available)) { + auto map = std::move(handle).Map(); + if (!map) { return nullptr; } - char* buffer = static_cast(shm->Memory()); + char* buffer = map.DataAs(); if (!buffer) { return nullptr; } @@ -168,12 +161,13 @@ static RefPtr LoadFromURI(nsIURI* aURI, uint32_t* aLength, return nullptr; } - if (!shm->Freeze()) { + auto [_, readOnlyHandle] = std::move(map).Freeze(); + + if (!readOnlyHandle) { return nullptr; } - *aLength = bytesRead; - return shm; + return std::move(readOnlyHandle); } // Read from the URI into a temporary buffer, compile it, then copy the @@ -188,7 +182,6 @@ static RefPtr LoadFromURI(nsIURI* aURI, uint32_t* aLength, UniquePtr data(mapped_hyph_compile_buffer( reinterpret_cast(buffer.get()), bytesRead, false)); if (data) { - *aLength = mapped_hyph_compiled_data_size(data.get()); return CopyToShmem(data.get()); } @@ -196,8 +189,7 @@ static RefPtr LoadFromURI(nsIURI* aURI, uint32_t* aLength, } nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized) - : mDict(static_cast(nullptr)), - mDictSize(0), + : mDict(Span()), mHyphenateCapitalized(aHyphenateCapitalized) { // Files with extension ".hyf" are expected to be precompiled mapped_hyph // tables; we also support uncompiled ".dic" files, but they are more @@ -210,13 +202,11 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized) // them a compiled version of the resource, so that we only pay the cost of // compilation once per language per session. if (!precompiled && !XRE_IsParentProcess()) { - uint32_t length; - RefPtr shm = GetHyphDictFromParent(aURI, &length); + auto shm = GetHyphDictFromParent(aURI); if (shm) { // We don't need to validate mDict because the parent process // will have done so. - mDictSize = length; - mDict = AsVariant(std::move(shm)); + mDict.emplace(std::move(shm)); } return; } @@ -226,15 +216,13 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized) // 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! uint32_t length; - const void* ptr = GetItemPtrFromJarURI(jar, &length); + const uint8_t* ptr = GetItemPtrFromJarURI(jar, &length); if (ptr) { if (precompiled) { // The data should be directly usable by mapped_hyph; validate that it // looks correct, and save the pointer. - if (mapped_hyph_is_valid_hyphenator(static_cast(ptr), - length)) { - mDictSize = length; - mDict = AsVariant(ptr); + if (mapped_hyph_is_valid_hyphenator(ptr, length)) { + mDict.emplace>(ptr, length); return; } } else { @@ -242,13 +230,12 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized) // We then move it to shared memory so we can expose it to content // processes. MOZ_ASSERT(XRE_IsParentProcess()); - UniquePtr data(mapped_hyph_compile_buffer( - static_cast(ptr), length, false)); + UniquePtr data( + mapped_hyph_compile_buffer(ptr, length, false)); if (data) { - RefPtr shm = CopyToShmem(data.get()); + auto shm = CopyToShmem(data.get()); if (shm) { - mDictSize = mapped_hyph_compiled_data_size(data.get()); - mDict = AsVariant(std::move(shm)); + mDict.emplace(std::move(shm)); return; } } @@ -259,19 +246,17 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized) // 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). if (XRE_IsParentProcess()) { - RefPtr shm = LoadFromURI(aURI, &length, precompiled); + auto shm = LoadFromURI(aURI, precompiled); if (shm) { - mDictSize = length; - mDict = AsVariant(std::move(shm)); + mDict.emplace(std::move(shm)); return; } } else { - RefPtr shm = GetHyphDictFromParent(aURI, &length); + auto shm = GetHyphDictFromParent(aURI); if (shm) { // We don't need to validate mDict because the parent process // will have done so. - mDictSize = length; - mDict = AsVariant(std::move(shm)); + mDict.emplace(std::move(shm)); return; } } @@ -312,10 +297,9 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized) UniquePtr data( mapped_hyph_compile_file(path.get(), false)); if (data) { - RefPtr shm = CopyToShmem(data.get()); + auto shm = CopyToShmem(data.get()); if (shm) { - mDictSize = mapped_hyph_compiled_data_size(data.get()); - mDict = AsVariant(std::move(shm)); + mDict.emplace(std::move(shm)); return; } } @@ -333,8 +317,9 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized) bool nsHyphenator::IsValid() { return mDict.match( - [](const void*& ptr) { return ptr != nullptr; }, - [](RefPtr& shm) { return shm != nullptr; }, + [](Span& span) { return span.data() != nullptr; }, + [](ipc::ReadOnlySharedMemoryHandle& shm) { return shm.IsValid(); }, + [](ipc::ReadOnlySharedMemoryMapping& shm) { return shm.IsValid(); }, [](UniquePtr& hyph) { return hyph != nullptr; }); } @@ -441,16 +426,21 @@ void nsHyphenator::HyphenateWord(const nsAString& aString, uint32_t aStart, AutoTArray hyphenValues; hyphenValues.SetLength(utf8.Length()); int32_t result = mDict.match( - [&](const void*& ptr) { + [&](Span& span) { return mapped_hyph_find_hyphen_values_raw( - static_cast(ptr), mDictSize, utf8.BeginReading(), - utf8.Length(), hyphenValues.Elements(), hyphenValues.Length()); + span.data(), span.size(), utf8.BeginReading(), utf8.Length(), + hyphenValues.Elements(), hyphenValues.Length()); }, - [&](RefPtr& shm) { + [&](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( - static_cast(shm->Memory()), mDictSize, - utf8.BeginReading(), utf8.Length(), hyphenValues.Elements(), - hyphenValues.Length()); + shm.DataAs(), shm.Size(), utf8.BeginReading(), + utf8.Length(), hyphenValues.Elements(), hyphenValues.Length()); }, [&](UniquePtr& hyph) { return mapped_hyph_find_hyphen_values_dic( @@ -486,14 +476,11 @@ void nsHyphenator::HyphenateWord(const nsAString& aString, uint32_t aStart, } } -void nsHyphenator::CloneHandle(ipc::SharedMemory::Handle* aOutHandle, - uint32_t* aOutSize) { - // If the resource is invalid, or if we fail to share it to the child - // process, we'll just bail out and continue without hyphenation; no need - // for this to be a fatal error. - if (!mDict.is>()) { - return; +ipc::ReadOnlySharedMemoryHandle nsHyphenator::CloneHandle() { + MOZ_ASSERT(XRE_IsParentProcess()); + + if (mDict.is()) { + return mDict.as().Clone(); } - *aOutHandle = mDict.as>()->CloneHandle(); - *aOutSize = mDictSize; + return nullptr; } diff --git a/intl/hyphenation/glue/nsHyphenator.h b/intl/hyphenation/glue/nsHyphenator.h index 25473b8c1e47..0b8cbae3a73d 100644 --- a/intl/hyphenation/glue/nsHyphenator.h +++ b/intl/hyphenation/glue/nsHyphenator.h @@ -6,8 +6,10 @@ #ifndef nsHyphenator_h__ #define nsHyphenator_h__ -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/RefPtr.h" +#include "mozilla/Span.h" #include "mozilla/UniquePtr.h" #include "mozilla/Variant.h" #include "nsCOMPtr.h" @@ -42,8 +44,7 @@ class nsHyphenator { nsresult Hyphenate(const nsAString& aText, nsTArray& aHyphens); - void CloneHandle(mozilla::ipc::SharedMemory::Handle* aOutHandle, - uint32_t* aOutSize); + mozilla::ipc::ReadOnlySharedMemoryHandle CloneHandle(); private: ~nsHyphenator() = default; @@ -51,12 +52,13 @@ class nsHyphenator { void HyphenateWord(const nsAString& aString, uint32_t aStart, uint32_t aLimit, nsTArray& aHyphens); - mozilla::Variant, // shmem block - mozilla::UniquePtr // loaded by mapped_hyph - > + mozilla::Variant< + mozilla::Span, // raw pointer to uncompressed omnijar data + mozilla::ipc::ReadOnlySharedMemoryHandle, // shmem handle, in the parent + mozilla::ipc::ReadOnlySharedMemoryMapping, // mapped shmem, in the child + mozilla::UniquePtr // loaded by mapped_hyph + > mDict; - uint32_t mDictSize; // size of mDict data (not used if type is HyphDic) bool mHyphenateCapitalized; }; diff --git a/intl/strres/nsIStringBundle.idl b/intl/strres/nsIStringBundle.idl index fef8859c2b6a..83711696cf86 100644 --- a/intl/strres/nsIStringBundle.idl +++ b/intl/strres/nsIStringBundle.idl @@ -8,7 +8,7 @@ %{C++ #include "mozilla/MemoryReporting.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" namespace mozilla { namespace dom { @@ -27,7 +27,7 @@ class ContentParent; %} [ptr] native ContentParent(mozilla::dom::ContentParent); -[ref] native SharedMemoryHandle(mozilla::ipc::SharedMemoryHandle); +native ReadOnlySharedMemoryHandle(mozilla::ipc::ReadOnlySharedMemoryHandle&&); native MallocSizeOf(mozilla::MallocSizeOf); [scriptable, builtinclass, uuid(D85A17C2-AA7C-11d2-9B8C-00805F8A16D9)] @@ -104,6 +104,5 @@ interface nsIStringBundleService : nsISupports [notxpcom, nostdcall] void sendContentBundles(in ContentParent aContentParent); [notxpcom, nostdcall] void registerContentBundle(in ACString aBundleURL, - [const] in SharedMemoryHandle aMapHandle, - in size_t aMapSize); + in ReadOnlySharedMemoryHandle aMapHandle); }; diff --git a/intl/strres/nsStringBundle.cpp b/intl/strres/nsStringBundle.cpp index 3fc821902913..fb1e8390ebd6 100644 --- a/intl/strres/nsStringBundle.cpp +++ b/intl/strres/nsStringBundle.cpp @@ -27,6 +27,7 @@ #include "nsSimpleEnumerator.h" #include "nsStringStream.h" #include "mozilla/dom/txXSLTMsgsURL.h" +#include "mozilla/ipc/SharedMemoryHandle.h" #include "mozilla/BinarySearch.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/ResultExtensions.h" @@ -93,12 +94,8 @@ static bool IsContentBundle(const nsCString& aUrl) { namespace { -#define STRINGBUNDLEPROXY_IID \ - { \ - 0x537cf21b, 0x99fc, 0x4002, { \ - 0x9e, 0xec, 0x97, 0xbe, 0x4d, 0xe0, 0xb3, 0xdc \ - } \ - } +#define STRINGBUNDLEPROXY_IID \ + {0x537cf21b, 0x99fc, 0x4002, {0x9e, 0xec, 0x97, 0xbe, 0x4d, 0xe0, 0xb3, 0xdc}} /** * A simple proxy class for a string bundle instance which will be replaced by @@ -186,12 +183,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(StringBundleProxy, STRINGBUNDLEPROXY_IID) NS_IMPL_ISUPPORTS(StringBundleProxy, nsIStringBundle, StringBundleProxy) -#define SHAREDSTRINGBUNDLE_IID \ - { \ - 0x7a8df5f7, 0x9e50, 0x44f6, { \ - 0xbf, 0x89, 0xc7, 0xad, 0x6c, 0x17, 0xf8, 0x5f \ - } \ - } +#define SHAREDSTRINGBUNDLE_IID \ + {0x7a8df5f7, 0x9e50, 0x44f6, {0xbf, 0x89, 0xc7, 0xad, 0x6c, 0x17, 0xf8, 0x5f}} /** * A string bundle backed by a read-only, shared memory buffer. This should @@ -209,8 +202,7 @@ class SharedStringBundle final : public nsStringBundleBase { * called in child processes, for bundles initially created in the parent * process. */ - void SetMapFile(const mozilla::ipc::SharedMemoryHandle& aHandle, - size_t aSize); + void SetMapFile(mozilla::ipc::ReadOnlySharedMemoryHandle&& aHandle); NS_DECL_ISUPPORTS_INHERITED NS_DECLARE_STATIC_IID_ACCESSOR(SHAREDSTRINGBUNDLE_IID) @@ -219,21 +211,21 @@ class SharedStringBundle final : public nsStringBundleBase { /** * Returns a copy of the file descriptor pointing to the shared memory - * key-values tore for this string bundle. This should only be called in the + * key-value store for this string bundle. This should only be called in the * parent process, and may be used to send shared string bundles to child * processes. */ - mozilla::ipc::SharedMemoryHandle CloneHandle() const { + mozilla::ipc::ReadOnlySharedMemoryHandle CloneHandle() const { MOZ_ASSERT(XRE_IsParentProcess()); if (mMapHandle.isSome()) { - return mozilla::ipc::SharedMemory::CloneHandle(mMapHandle.ref()); + return mMapHandle.ref().Clone(); } return mStringMap->CloneHandle(); } size_t MapSize() const { if (mMapHandle.isSome()) { - return mMapSize; + return mMapHandle->Size(); } if (mStringMap) { return mStringMap->MapSize(); @@ -249,7 +241,6 @@ class SharedStringBundle final : public nsStringBundleBase { StringBundleDescriptor descriptor; descriptor.bundleURL() = BundleURL(); descriptor.mapHandle() = CloneHandle(); - descriptor.mapSize() = MapSize(); return descriptor; } @@ -274,8 +265,7 @@ class SharedStringBundle final : public nsStringBundleBase { private: RefPtr mStringMap; - Maybe mMapHandle; - size_t mMapSize; + Maybe mMapHandle; }; NS_DEFINE_STATIC_IID_ACCESSOR(SharedStringBundle, SHAREDSTRINGBUNDLE_IID) @@ -523,8 +513,7 @@ nsresult SharedStringBundle::LoadProperties() { if (mStringMap) return NS_OK; if (mMapHandle.isSome()) { - mStringMap = new SharedStringMap(mMapHandle.ref(), mMapSize); - mMapHandle.reset(); + mStringMap = new SharedStringMap(mMapHandle.extract()); return NS_OK; } @@ -578,11 +567,10 @@ nsresult SharedStringBundle::LoadProperties() { } void SharedStringBundle::SetMapFile( - const mozilla::ipc::SharedMemoryHandle& aHandle, size_t aSize) { + mozilla::ipc::ReadOnlySharedMemoryHandle&& aHandle) { MOZ_ASSERT(XRE_IsContentProcess()); mStringMap = nullptr; - mMapHandle.emplace(mozilla::ipc::SharedMemory::CloneHandle(aHandle)); - mMapSize = aSize; + mMapHandle.emplace(std::move(aHandle)); } NS_IMETHODIMP @@ -830,7 +818,7 @@ void nsStringBundleService::SendContentBundles(ContentParent* aContentParent) { void nsStringBundleService::RegisterContentBundle( const nsACString& aBundleURL, - const mozilla::ipc::SharedMemoryHandle& aMapHandle, size_t aMapSize) { + mozilla::ipc::ReadOnlySharedMemoryHandle&& aMapHandle) { RefPtr proxy; bundleCacheEntry_t* cacheEntry = mBundleMap.Get(aBundleURL); @@ -848,7 +836,7 @@ void nsStringBundleService::RegisterContentBundle( auto bundle = MakeBundleRefPtr( PromiseFlatCString(aBundleURL).get()); - bundle->SetMapFile(aMapHandle, aMapSize); + bundle->SetMapFile(std::move(aMapHandle)); if (proxy) { proxy->Retarget(bundle); diff --git a/ipc/chromium/src/chrome/common/ipc_message_utils.cc b/ipc/chromium/src/chrome/common/ipc_message_utils.cc index 58d6bbd0fd95..0816ebbcf5dc 100644 --- a/ipc/chromium/src/chrome/common/ipc_message_utils.cc +++ b/ipc/chromium/src/chrome/common/ipc_message_utils.cc @@ -73,7 +73,7 @@ MessageBufferReader::MessageBufferReader(MessageReader* reader, return; } if (shmem_ok) { - mozilla::ipc::shared_memory::Handle handle; + mozilla::ipc::shared_memory::MutableHandle handle; if (!IPC::ReadParam(reader, &handle)) { reader->FatalError("failed to read shared memory handle"); return; diff --git a/ipc/chromium/src/chrome/common/ipc_message_utils.h b/ipc/chromium/src/chrome/common/ipc_message_utils.h index e5d676ee2369..210802c3996e 100644 --- a/ipc/chromium/src/chrome/common/ipc_message_utils.h +++ b/ipc/chromium/src/chrome/common/ipc_message_utils.h @@ -18,6 +18,7 @@ #include "base/pickle.h" #include "chrome/common/ipc_message.h" #include "mozilla/CheckedInt.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #if defined(XP_WIN) # include @@ -32,7 +33,6 @@ namespace mozilla::ipc { class IProtocol; template struct IPDLParamTraits; -class SharedMemory; namespace shared_memory { class Cursor; } diff --git a/ipc/glue/BigBuffer.cpp b/ipc/glue/BigBuffer.cpp index 2dbde130dba6..24ce8b6f6468 100644 --- a/ipc/glue/BigBuffer.cpp +++ b/ipc/glue/BigBuffer.cpp @@ -7,16 +7,15 @@ #include "mozilla/ipc/BigBuffer.h" #include "chrome/common/ipc_message_utils.h" -#include "mozilla/ipc/SharedMemory.h" #include "nsDebug.h" namespace mozilla::ipc { -BigBuffer::BigBuffer(Adopt, SharedMemory* aSharedMemory, size_t aSize) - : mSize(aSize), mData(AsVariant(RefPtr{aSharedMemory})) { - MOZ_RELEASE_ASSERT(aSharedMemory && aSharedMemory->Memory(), - "shared memory must be non-null and mapped"); - MOZ_RELEASE_ASSERT(mSize <= aSharedMemory->Size(), +BigBuffer::BigBuffer(Adopt, SharedMemoryMappingWithHandle&& aSharedMemory, + size_t aSize) + : mSize(aSize), mData(AsVariant(std::move(aSharedMemory))) { + MOZ_RELEASE_ASSERT(mData.as<1>(), "shared memory must be valid"); + MOZ_RELEASE_ASSERT(mSize <= mData.as<1>().Size(), "shared memory region isn't large enough"); } @@ -24,13 +23,11 @@ BigBuffer::BigBuffer(Adopt, uint8_t* aData, size_t aSize) : mSize(aSize), mData(AsVariant(UniqueFreePtr{aData})) {} uint8_t* BigBuffer::Data() { - return mData.is<0>() ? mData.as<0>().get() - : reinterpret_cast(mData.as<1>()->Memory()); + return mData.is<0>() ? mData.as<0>().get() : mData.as<1>().DataAs(); } const uint8_t* BigBuffer::Data() const { - return mData.is<0>() - ? mData.as<0>().get() - : reinterpret_cast(mData.as<1>()->Memory()); + return mData.is<0>() ? mData.as<0>().get() + : mData.as<1>().DataAs(); } auto BigBuffer::TryAllocBuffer(size_t aSize) -> Maybe { @@ -41,12 +38,12 @@ auto BigBuffer::TryAllocBuffer(size_t aSize) -> Maybe { return Some(AsVariant(std::move(mem))); } - RefPtr shmem = new SharedMemory(); - size_t capacity = SharedMemory::PageAlignedSize(aSize); - if (!shmem->Create(capacity) || !shmem->Map(capacity)) { + size_t capacity = shared_memory::PageAlignedSize(aSize); + auto mapping = shared_memory::Create(capacity).MapWithHandle(); + if (!mapping) { return {}; } - return Some(AsVariant(shmem)); + return Some(AsVariant(std::move(mapping))); } } // namespace mozilla::ipc @@ -62,8 +59,11 @@ void IPC::ParamTraits::Write(MessageWriter* aWriter, WriteParam(aWriter, isShmem); if (isShmem) { - if (!data.as<1>()->WriteHandle(aWriter)) { + auto handle = data.as<1>().Handle().Clone(); + if (!handle) { aWriter->FatalError("Failed to write data shmem"); + } else { + WriteParam(aWriter, std::move(handle)); } } else { aWriter->WriteBytes(data.as<0>().get(), size); @@ -81,13 +81,18 @@ bool IPC::ParamTraits::Read(MessageReader* aReader, } if (isShmem) { - RefPtr shmem = new SharedMemory(); - size_t capacity = SharedMemory::PageAlignedSize(size); - if (!shmem->ReadHandle(aReader) || !shmem->Map(capacity)) { + MutableSharedMemoryHandle handle; + size_t expected_size = shared_memory::PageAlignedSize(size); + if (!ReadParam(aReader, &handle) || !handle) { aReader->FatalError("Failed to read data shmem"); return false; } - *aResult = BigBuffer(BigBuffer::Adopt{}, shmem, size); + auto mapping = std::move(handle).MapWithHandle(); + 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; } diff --git a/ipc/glue/BigBuffer.h b/ipc/glue/BigBuffer.h index 7136b6c03c0d..47ba60564e21 100644 --- a/ipc/glue/BigBuffer.h +++ b/ipc/glue/BigBuffer.h @@ -9,9 +9,10 @@ #include #include +#include "mozilla/Maybe.h" #include "mozilla/Span.h" #include "mozilla/Variant.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryMapping.h" namespace mozilla::ipc { @@ -62,8 +63,8 @@ class BigBuffer { // Create a new BigBuffer from an existing shared memory region, taking // ownership of that shared memory region. The shared memory region must be - // non-null, mapped, and large enough to fit aSize bytes. - BigBuffer(Adopt, SharedMemory* aSharedMemory, size_t aSize); + // valid and large enough to fit aSize bytes. + BigBuffer(Adopt, SharedMemoryMappingWithHandle&& aSharedMemory, size_t aSize); // 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 @@ -87,14 +88,16 @@ class BigBuffer { // If the BigBuffer is backed by shared memory, returns a pointer to the // backing SharedMemory region. - SharedMemory* GetSharedMemory() const { - return mData.is<1>() ? mData.as<1>().get() : nullptr; + // This is only meant to be used in tests. + const SharedMemoryMappingWithHandle* GetSharedMemory() const { + return mData.is<1>() ? &mData.as<1>() : nullptr; } private: friend struct IPC::ParamTraits; - using Storage = Variant, RefPtr>; + using Storage = + Variant, SharedMemoryMappingWithHandle>; // Empty storage which holds no data. static Storage NoData() { return AsVariant(UniqueFreePtr{}); } diff --git a/ipc/glue/CrossProcessMutex.h b/ipc/glue/CrossProcessMutex.h index c49ae22d60a6..b65acd001df1 100644 --- a/ipc/glue/CrossProcessMutex.h +++ b/ipc/glue/CrossProcessMutex.h @@ -15,7 +15,7 @@ #endif #if !defined(XP_WIN) && !defined(XP_NETBSD) && !defined(XP_OPENBSD) # include -# include "mozilla/ipc/SharedMemory.h" +# include "mozilla/ipc/SharedMemoryMapping.h" # include "mozilla/Atomics.h" #endif @@ -39,7 +39,7 @@ namespace mozilla { #if defined(XP_WIN) typedef mozilla::UniqueFileHandle CrossProcessMutexHandle; #elif !defined(XP_NETBSD) && !defined(XP_OPENBSD) -typedef mozilla::ipc::SharedMemory::Handle CrossProcessMutexHandle; +typedef mozilla::ipc::MutableSharedMemoryHandle CrossProcessMutexHandle; #else // Stub for other platforms. We can't use uintptr_t here since different // processes could disagree on its size. @@ -104,7 +104,7 @@ class CrossProcessMutex { #if defined(XP_WIN) HANDLE mMutex; #elif !defined(XP_NETBSD) && !defined(XP_OPENBSD) - RefPtr mSharedBuffer; + mozilla::ipc::SharedMemoryMappingWithHandle mSharedBuffer; pthread_mutex_t* mMutex; mozilla::Atomic* mCount; #endif diff --git a/ipc/glue/CrossProcessMutex_posix.cpp b/ipc/glue/CrossProcessMutex_posix.cpp index b94c317a18ba..fabb766ff4c6 100644 --- a/ipc/glue/CrossProcessMutex_posix.cpp +++ b/ipc/glue/CrossProcessMutex_posix.cpp @@ -6,6 +6,7 @@ #include "CrossProcessMutex.h" #include "mozilla/Unused.h" +#include "mozilla/ipc/SharedMemoryHandle.h" #include "nsDebug.h" #include "nsISupportsImpl.h" @@ -43,16 +44,12 @@ CrossProcessMutex::CrossProcessMutex(const char*) // they specifically are not on Linux. MOZ_RELEASE_ASSERT(false); #endif - mSharedBuffer = new ipc::SharedMemory; - if (!mSharedBuffer->Create(sizeof(MutexData))) { + mSharedBuffer = ipc::shared_memory::Create(sizeof(MutexData)).MapWithHandle(); + if (!mSharedBuffer) { MOZ_CRASH(); } - if (!mSharedBuffer->Map(sizeof(MutexData))) { - MOZ_CRASH(); - } - - MutexData* data = static_cast(mSharedBuffer->Memory()); + MutexData* data = mSharedBuffer.DataAs(); if (!data) { MOZ_CRASH(); @@ -69,22 +66,12 @@ CrossProcessMutex::CrossProcessMutex(const char*) CrossProcessMutex::CrossProcessMutex(CrossProcessMutexHandle aHandle) : mMutex(nullptr), mCount(nullptr) { - mSharedBuffer = new ipc::SharedMemory; - - if (!mSharedBuffer->IsHandleValid(aHandle)) { + mSharedBuffer = std::move(aHandle).MapWithHandle(); + if (!mSharedBuffer) { MOZ_CRASH(); } - if (!mSharedBuffer->SetHandle(std::move(aHandle), - ipc::SharedMemory::RightsReadWrite)) { - MOZ_CRASH(); - } - - if (!mSharedBuffer->Map(sizeof(MutexData))) { - MOZ_CRASH(); - } - - MutexData* data = static_cast(mSharedBuffer->Memory()); + MutexData* data = mSharedBuffer.DataAs(); if (!data) { MOZ_CRASH(); @@ -125,16 +112,14 @@ void CrossProcessMutex::Unlock() { } CrossProcessMutexHandle CrossProcessMutex::CloneHandle() { - CrossProcessMutexHandle result = ipc::SharedMemory::NULLHandle(); - if (mSharedBuffer) { - result = mSharedBuffer->CloneHandle(); - if (!result) { + auto handle = mSharedBuffer.Handle().Clone(); + if (!handle) { MOZ_CRASH(); } + return handle; } - - return result; + return nullptr; } } // namespace mozilla diff --git a/ipc/glue/CrossProcessSemaphore.h b/ipc/glue/CrossProcessSemaphore.h index ca45b3226abb..8bb1716d8648 100644 --- a/ipc/glue/CrossProcessSemaphore.h +++ b/ipc/glue/CrossProcessSemaphore.h @@ -16,7 +16,7 @@ #else # include # include -# include "mozilla/ipc/SharedMemory.h" +# include "mozilla/ipc/SharedMemoryMapping.h" # include "mozilla/Atomics.h" #endif @@ -41,13 +41,7 @@ typedef mozilla::UniqueFileHandle CrossProcessSemaphoreHandle; #elif defined(XP_DARWIN) typedef mozilla::UniqueMachSendRight CrossProcessSemaphoreHandle; #else -typedef mozilla::ipc::SharedMemory::Handle CrossProcessSemaphoreHandle; - -template <> -inline bool IsHandleValid( - const CrossProcessSemaphoreHandle& handle) { - return !(handle == mozilla::ipc::SharedMemory::NULLHandle()); -} +typedef mozilla::ipc::MutableSharedMemoryHandle CrossProcessSemaphoreHandle; #endif class CrossProcessSemaphore { @@ -108,7 +102,8 @@ class CrossProcessSemaphore { CrossProcessSemaphoreHandle mSemaphore; #else - RefPtr mSharedBuffer; + mozilla::ipc::MutableSharedMemoryHandle mHandle; + mozilla::ipc::SharedMemoryMapping mSharedBuffer; sem_t* mSemaphore; mozilla::Atomic* mRefCount; #endif diff --git a/ipc/glue/CrossProcessSemaphore_posix.cpp b/ipc/glue/CrossProcessSemaphore_posix.cpp index e03768d4d2db..28587b12e014 100644 --- a/ipc/glue/CrossProcessSemaphore_posix.cpp +++ b/ipc/glue/CrossProcessSemaphore_posix.cpp @@ -28,16 +28,17 @@ namespace mozilla { /* static */ CrossProcessSemaphore* CrossProcessSemaphore::Create(const char*, uint32_t aInitialValue) { - RefPtr sharedBuffer = new ipc::SharedMemory; - if (!sharedBuffer->Create(sizeof(SemaphoreData))) { + auto handle = ipc::shared_memory::Create(sizeof(SemaphoreData)); + if (!handle) { return nullptr; } - if (!sharedBuffer->Map(sizeof(SemaphoreData))) { + auto mapping = handle.Map(); + if (!mapping) { return nullptr; } - SemaphoreData* data = static_cast(sharedBuffer->Memory()); + SemaphoreData* data = mapping.DataAs(); if (!data) { return nullptr; @@ -48,7 +49,8 @@ CrossProcessSemaphore* CrossProcessSemaphore::Create(const char*, } CrossProcessSemaphore* sem = new CrossProcessSemaphore; - sem->mSharedBuffer = sharedBuffer; + sem->mHandle = std::move(handle); + sem->mSharedBuffer = std::move(mapping); sem->mSemaphore = &data->mSemaphore; sem->mRefCount = &data->mRefCount; *sem->mRefCount = 1; @@ -61,24 +63,14 @@ CrossProcessSemaphore* CrossProcessSemaphore::Create(const char*, /* static */ CrossProcessSemaphore* CrossProcessSemaphore::Create( CrossProcessSemaphoreHandle aHandle) { - RefPtr sharedBuffer = new ipc::SharedMemory; - - if (!sharedBuffer->IsHandleValid(aHandle)) { + auto mapping = aHandle.Map(); + if (!mapping) { return nullptr; } - if (!sharedBuffer->SetHandle(std::move(aHandle), - ipc::SharedMemory::RightsReadWrite)) { - return nullptr; - } + aHandle = nullptr; - if (!sharedBuffer->Map(sizeof(SemaphoreData))) { - return nullptr; - } - - sharedBuffer->CloseHandle(); - - SemaphoreData* data = static_cast(sharedBuffer->Memory()); + SemaphoreData* data = mapping.DataAs(); if (!data) { return nullptr; @@ -95,7 +87,7 @@ CrossProcessSemaphore* CrossProcessSemaphore::Create( } CrossProcessSemaphore* sem = new CrossProcessSemaphore; - sem->mSharedBuffer = sharedBuffer; + sem->mSharedBuffer = std::move(mapping); sem->mSemaphore = &data->mSemaphore; sem->mRefCount = &data->mRefCount; return sem; @@ -147,18 +139,16 @@ void CrossProcessSemaphore::Signal() { } CrossProcessSemaphoreHandle CrossProcessSemaphore::CloneHandle() { - CrossProcessSemaphoreHandle result = ipc::SharedMemory::NULLHandle(); - if (mSharedBuffer) { - result = mSharedBuffer->CloneHandle(); - if (!result) { + auto handle = mHandle.Clone(); + if (!handle) { MOZ_CRASH(); } + return handle; } - - return result; + return nullptr; } -void CrossProcessSemaphore::CloseHandle() { mSharedBuffer->CloseHandle(); } +void CrossProcessSemaphore::CloseHandle() { mHandle = nullptr; } } // namespace mozilla diff --git a/ipc/glue/DataPipe.cpp b/ipc/glue/DataPipe.cpp index c12d17d0c2ae..5401b6065548 100644 --- a/ipc/glue/DataPipe.cpp +++ b/ipc/glue/DataPipe.cpp @@ -71,9 +71,10 @@ static void DoNotifyOnUnlock(DataPipeAutoLock& aLock, class DataPipeLink : public NodeController::PortObserver { public: DataPipeLink(bool aReceiverSide, std::shared_ptr aMutex, - ScopedPort aPort, SharedMemory::Handle aShmemHandle, - SharedMemory* aShmem, uint32_t aCapacity, nsresult aPeerStatus, - uint32_t aOffset, uint32_t aAvailable) + ScopedPort aPort, MutableSharedMemoryHandle&& aShmemHandle, + const std::shared_ptr aShmem, + uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset, + uint32_t aAvailable) : mMutex(std::move(aMutex)), mPort(std::move(aPort)), mShmemHandle(std::move(aShmemHandle)), @@ -165,8 +166,8 @@ class DataPipeLink : public NodeController::PortObserver { std::shared_ptr mMutex; ScopedPort mPort MOZ_GUARDED_BY(*mMutex); - SharedMemory::Handle mShmemHandle MOZ_GUARDED_BY(*mMutex); - const RefPtr mShmem; + MutableSharedMemoryHandle mShmemHandle MOZ_GUARDED_BY(*mMutex); + const std::shared_ptr mShmem; const uint32_t mCapacity; const bool mReceiverSide; @@ -245,10 +246,10 @@ DataPipeBase::DataPipeBase(bool aReceiverSide, nsresult aError) mStatus(NS_SUCCEEDED(aError) ? NS_BASE_STREAM_CLOSED : aError) {} DataPipeBase::DataPipeBase(bool aReceiverSide, ScopedPort aPort, - SharedMemory::Handle aShmemHandle, - SharedMemory* aShmem, uint32_t aCapacity, - nsresult aPeerStatus, uint32_t aOffset, - uint32_t aAvailable) + MutableSharedMemoryHandle&& aShmemHandle, + const std::shared_ptr& aShmem, + uint32_t aCapacity, nsresult aPeerStatus, + uint32_t aOffset, uint32_t aAvailable) : mMutex(std::make_shared(aReceiverSide ? "DataPipeReceiver" : "DataPipeSender")), mStatus(NS_OK), @@ -318,7 +319,7 @@ nsresult DataPipeBase::ProcessSegmentsInternal( // Extract an iterator over the next contiguous region of the shared memory // buffer which will be used . - char* start = static_cast(link->mShmem->Memory()) + link->mOffset; + char* start = link->mShmem->DataAs() + link->mOffset; char* iter = start; char* end = start + std::min({aCount - *aProcessedCount, link->mAvailable, link->mCapacity - link->mOffset}); @@ -480,21 +481,17 @@ bool DataPipeRead(IPC::MessageReader* aReader, RefPtr* aResult) { aReader->FatalError("failed to read DataPipe port"); return false; } - SharedMemory::Handle shmemHandle; + MutableSharedMemoryHandle shmemHandle; if (!ReadParam(aReader, &shmemHandle)) { aReader->FatalError("failed to read DataPipe shmem"); return false; } - // Due to the awkward shared memory API provided by SharedMemory, we need to - // transfer ownership into the `shmem` here, then steal it back later in the - // 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"); + + if (!shmemHandle) { + aReader->FatalError("failed to create DataPipe shmem handle"); return false; } + uint32_t capacity = 0; nsresult peerStatus = NS_OK; uint32_t offset = 0; @@ -508,12 +505,14 @@ bool DataPipeRead(IPC::MessageReader* aReader, RefPtr* aResult) { aReader->FatalError("received DataPipe state values are inconsistent"); return false; } - if (!shmem->Map(SharedMemory::PageAlignedSize(capacity))) { + auto mapping = std::make_shared(shmemHandle.Map()); + if (!*mapping || + mapping->Size() != shared_memory::PageAlignedSize(capacity)) { aReader->FatalError("failed to map DataPipe shared memory region"); return false; } - *aResult = new T(std::move(port), shmem->TakeHandle(), shmem, capacity, + *aResult = new T(std::move(port), std::move(shmemHandle), mapping, capacity, peerStatus, offset, available); if (MOZ_LOG_TEST(gDataPipeLog, LogLevel::Debug)) { DataPipeAutoLock lock(*(*aResult)->mMutex); @@ -588,7 +587,7 @@ NS_IMETHODIMP DataPipeSender::AsyncWait(nsIOutputStreamCallback* aCallback, nsIEventTarget* aTarget) { AsyncWaitInternal( aCallback ? NS_NewCancelableRunnableFunction( - "DataPipeReceiver::AsyncWait", + "DataPipeSender::AsyncWait", [self = RefPtr{this}, callback = RefPtr{aCallback}] { MOZ_LOG(gDataPipeLog, LogLevel::Debug, ("Calling OnOutputStreamReady(%p, %p)", @@ -717,27 +716,31 @@ nsresult NewDataPipe(uint32_t aCapacity, DataPipeSender** aSender, auto [senderPort, receiverPort] = controller->CreatePortPair(); // Create and allocate the shared memory region. - auto shmem = MakeRefPtr(); - size_t alignedCapacity = SharedMemory::PageAlignedSize(aCapacity); - if (!shmem->Create(alignedCapacity) || !shmem->Map(alignedCapacity)) { + size_t alignedCapacity = shared_memory::PageAlignedSize(aCapacity); + auto handle = shared_memory::Create(alignedCapacity); + if (!handle) { + return NS_ERROR_OUT_OF_MEMORY; + } + auto mapping = std::make_shared(handle.Map()); + if (!*mapping) { return NS_ERROR_OUT_OF_MEMORY; } // 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 // when serializing, when errors are non-recoverable. - SharedMemory::Handle senderShmemHandle = shmem->CloneHandle(); - SharedMemory::Handle receiverShmemHandle = shmem->TakeHandle(); + auto senderShmemHandle = handle.Clone(); + auto receiverShmemHandle = std::move(handle); if (!senderShmemHandle || !receiverShmemHandle) { return NS_ERROR_OUT_OF_MEMORY; } RefPtr sender = new DataPipeSender(std::move(senderPort), std::move(senderShmemHandle), - shmem, aCapacity, NS_OK, 0, aCapacity); + mapping, aCapacity, NS_OK, 0, aCapacity); RefPtr receiver = new DataPipeReceiver(std::move(receiverPort), - std::move(receiverShmemHandle), shmem, - aCapacity, NS_OK, 0, 0); + std::move(receiverShmemHandle), + mapping, aCapacity, NS_OK, 0, 0); sender.forget(aSender); receiver.forget(aReceiver); return NS_OK; diff --git a/ipc/glue/DataPipe.h b/ipc/glue/DataPipe.h index 18760d10932d..cfeb0fb69f2b 100644 --- a/ipc/glue/DataPipe.h +++ b/ipc/glue/DataPipe.h @@ -7,12 +7,14 @@ #ifndef mozilla_ipc_DataPipe_h #define mozilla_ipc_DataPipe_h -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/ipc/NodeController.h" #include "nsIAsyncInputStream.h" #include "nsIAsyncOutputStream.h" #include "nsIIPCSerializableInputStream.h" #include "nsISupports.h" +#include namespace mozilla { namespace ipc { @@ -30,7 +32,8 @@ class DataPipeBase { protected: explicit DataPipeBase(bool aReceiverSide, nsresult aError); DataPipeBase(bool aReceiverSide, ScopedPort aPort, - SharedMemory::Handle aShmemHandle, SharedMemory* aShmem, + MutableSharedMemoryHandle&& aShmemHandle, + const std::shared_ptr& aShmem, uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset, uint32_t aAvailable); @@ -78,12 +81,8 @@ bool DataPipeRead(IPC::MessageReader* aReader, RefPtr* aResult); class DataPipeSender; class DataPipeReceiver; -#define NS_DATAPIPESENDER_IID \ - { \ - 0x6698ed77, 0x9fff, 0x425d, { \ - 0xb0, 0xa6, 0x1d, 0x30, 0x66, 0xee, 0xb8, 0x16 \ - } \ - } +#define NS_DATAPIPESENDER_IID \ + {0x6698ed77, 0x9fff, 0x425d, {0xb0, 0xa6, 0x1d, 0x30, 0x66, 0xee, 0xb8, 0x16}} // Helper class for streaming data to another process. class DataPipeSender final : public nsIAsyncOutputStream, @@ -103,9 +102,10 @@ class DataPipeSender final : public nsIAsyncOutputStream, explicit DataPipeSender(nsresult aError) : data_pipe_detail::DataPipeBase(/* aReceiverSide */ false, aError) {} - DataPipeSender(ScopedPort aPort, SharedMemory::Handle aShmemHandle, - SharedMemory* aShmem, uint32_t aCapacity, nsresult aPeerStatus, - uint32_t aOffset, uint32_t aAvailable) + DataPipeSender(ScopedPort aPort, MutableSharedMemoryHandle&& aShmemHandle, + const std::shared_ptr& aShmem, + uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset, + uint32_t aAvailable) : data_pipe_detail::DataPipeBase( /* aReceiverSide */ false, std::move(aPort), std::move(aShmemHandle), aShmem, aCapacity, aPeerStatus, aOffset, @@ -116,12 +116,8 @@ class DataPipeSender final : public nsIAsyncOutputStream, NS_DEFINE_STATIC_IID_ACCESSOR(DataPipeSender, NS_DATAPIPESENDER_IID) -#define NS_DATAPIPERECEIVER_IID \ - { \ - 0x0a185f83, 0x499e, 0x450c, { \ - 0x95, 0x82, 0x27, 0x67, 0xad, 0x6d, 0x64, 0xb5 \ - } \ - } +#define NS_DATAPIPERECEIVER_IID \ + {0x0a185f83, 0x499e, 0x450c, {0x95, 0x82, 0x27, 0x67, 0xad, 0x6d, 0x64, 0xb5}} // Helper class for streaming data from another process. class DataPipeReceiver final : public nsIAsyncInputStream, @@ -143,9 +139,10 @@ class DataPipeReceiver final : public nsIAsyncInputStream, explicit DataPipeReceiver(nsresult aError) : data_pipe_detail::DataPipeBase(/* aReceiverSide */ true, aError) {} - DataPipeReceiver(ScopedPort aPort, SharedMemory::Handle aShmemHandle, - SharedMemory* aShmem, uint32_t aCapacity, - nsresult aPeerStatus, uint32_t aOffset, uint32_t aAvailable) + DataPipeReceiver(ScopedPort aPort, MutableSharedMemoryHandle&& aShmemHandle, + const std::shared_ptr& aShmem, + uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset, + uint32_t aAvailable) : data_pipe_detail::DataPipeBase( /* aReceiverSide */ true, std::move(aPort), std::move(aShmemHandle), aShmem, aCapacity, aPeerStatus, aOffset, aAvailable) {} diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp index 7872a19ce0eb..b0c74483ac4f 100644 --- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -15,7 +15,6 @@ #include "chrome/common/process_watcher.h" #ifdef XP_DARWIN # include -# include "SharedMemory.h" # include "base/rand_util.h" # include "chrome/common/mach_ipc_mac.h" # include "mozilla/StaticPrefs_media.h" diff --git a/ipc/glue/IdleSchedulerChild.cpp b/ipc/glue/IdleSchedulerChild.cpp index 9a094c395f3a..bda159a2c547 100644 --- a/ipc/glue/IdleSchedulerChild.cpp +++ b/ipc/glue/IdleSchedulerChild.cpp @@ -29,18 +29,16 @@ void IdleSchedulerChild::Init(IdlePeriodState* aIdlePeriodState) { mIdlePeriodState = aIdlePeriodState; RefPtr scheduler = this; - auto resolve = - [&](std::tuple, uint32_t>&& aResult) { - if (std::get<0>(aResult)) { - mActiveCounter->SetHandle(std::move(*std::get<0>(aResult)), - SharedMemory::RightsReadWrite); - mActiveCounter->Map(sizeof(int32_t)); - mChildId = std::get<1>(aResult); - if (mChildId && mIdlePeriodState && mIdlePeriodState->IsActive()) { - SetActive(); - } - } - }; + auto resolve = [&](std::tuple, + uint32_t>&& aResult) { + if (auto& handle = std::get<0>(aResult)) { + mActiveCounter = handle->Map(); + mChildId = std::get<1>(aResult); + if (mChildId && mIdlePeriodState && mIdlePeriodState->IsActive()) { + SetActive(); + } + } + }; auto reject = [&](ResponseRejectReason) {}; SendInitForIdleUse(std::move(resolve), std::move(reject)); @@ -54,23 +52,21 @@ IPCResult IdleSchedulerChild::RecvIdleTime(uint64_t aId, TimeDuration aBudget) { } void IdleSchedulerChild::SetActive() { - if (mChildId && CanSend() && mActiveCounter->Memory()) { - ++(static_cast*>( - mActiveCounter->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]); - ++(static_cast*>(mActiveCounter->Memory())[mChildId]); + if (mChildId && CanSend() && mActiveCounter) { + auto counters = mActiveCounter.DataAsSpan>(); + ++counters[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]; + ++counters[mChildId]; } } bool IdleSchedulerChild::SetPaused() { - if (mChildId && CanSend() && mActiveCounter->Memory()) { - --(static_cast*>(mActiveCounter->Memory())[mChildId]); + if (mChildId && CanSend() && mActiveCounter) { + auto counters = mActiveCounter.DataAsSpan>(); + --counters[mChildId]; // The following expression reduces the global activity count and checks if // it drops below the cpu counter limit. - return (static_cast*>(mActiveCounter->Memory()) - [NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER])-- == - static_cast*>( - mActiveCounter - ->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER]; + return counters[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]-- == + counters[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER]; } return false; diff --git a/ipc/glue/IdleSchedulerChild.h b/ipc/glue/IdleSchedulerChild.h index ce06eec6176f..67ee242cce4b 100644 --- a/ipc/glue/IdleSchedulerChild.h +++ b/ipc/glue/IdleSchedulerChild.h @@ -11,7 +11,7 @@ #include "mozilla/Attributes.h" #include "mozilla/RefPtr.h" #include "mozilla/ipc/PIdleSchedulerChild.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryMapping.h" class nsIIdlePeriod; @@ -58,7 +58,7 @@ class IdleSchedulerChild final : public PIdleSchedulerChild { friend class BackgroundChildImpl; // See IdleScheduleParent::sActiveChildCounter - RefPtr mActiveCounter = MakeRefPtr(); + SharedMemoryMapping mActiveCounter; IdlePeriodState* mIdlePeriodState = nullptr; diff --git a/ipc/glue/IdleSchedulerParent.cpp b/ipc/glue/IdleSchedulerParent.cpp index a0c02a167127..2faa80b6c5c4 100644 --- a/ipc/glue/IdleSchedulerParent.cpp +++ b/ipc/glue/IdleSchedulerParent.cpp @@ -9,7 +9,10 @@ #include "mozilla/Unused.h" #include "mozilla/ipc/IdleSchedulerParent.h" #include "mozilla/AppShutdown.h" +#include "mozilla/NeverDestroyed.h" #include "mozilla/Telemetry.h" +#include "mozilla/ipc/SharedMemoryHandle.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "nsSystemInfo.h" #include "nsThreadUtils.h" #include "nsITimer.h" @@ -17,8 +20,18 @@ namespace mozilla::ipc { -MOZ_RUNINIT RefPtr IdleSchedulerParent::sActiveChildCounter = - nullptr; +// 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 SharedMemoryMappingWithHandle& sActiveChildCounter() { + static NeverDestroyed mapping; + return *mapping; +} + std::bitset IdleSchedulerParent::sInUseChildCounters; MOZ_RUNINIT LinkedList @@ -108,9 +121,9 @@ void IdleSchedulerParent::CalculateNumIdleTasks() { sMaxConcurrentGCs = std::clamp(sNumCPUs / sPrefConcurrentGCsCPUDivisor, 1u, sPrefConcurrentGCsMax); - if (sActiveChildCounter && sActiveChildCounter->Memory()) { - static_cast*>( - sActiveChildCounter->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] = + if (sActiveChildCounter()) { + sActiveChildCounter() + .DataAsSpan>()[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] = static_cast(sMaxConcurrentIdleTasksInChildProcesses); } IdleSchedulerParent::Schedule(nullptr); @@ -121,14 +134,12 @@ IdleSchedulerParent::~IdleSchedulerParent() { // that is the case. if (mChildId) { sInUseChildCounters[mChildId] = false; - if (sActiveChildCounter && sActiveChildCounter->Memory() && - static_cast*>( - sActiveChildCounter->Memory())[mChildId]) { - --static_cast*>( - sActiveChildCounter - ->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]; - static_cast*>(sActiveChildCounter->Memory())[mChildId] = - 0; + if (sActiveChildCounter()) { + auto counters = sActiveChildCounter().DataAsSpan>(); + if (counters[mChildId]) { + --counters[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]; + counters[mChildId] = 0; + } } } @@ -155,7 +166,7 @@ IdleSchedulerParent::~IdleSchedulerParent() { sChildProcessesAlive--; if (sChildProcessesAlive == 0) { MOZ_ASSERT(sIdleAndGCRequests.isEmpty()); - sActiveChildCounter = nullptr; + sActiveChildCounter() = nullptr; if (sStarvationPreventer) { sStarvationPreventer->Cancel(); @@ -177,27 +188,22 @@ IPCResult IdleSchedulerParent::RecvInitForIdleUse( // Create a shared memory object which is shared across all the relevant // processes. - if (!sActiveChildCounter) { - sActiveChildCounter = MakeRefPtr(); + if (!sActiveChildCounter()) { size_t shmemSize = NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT * sizeof(int32_t); - if (sActiveChildCounter->Create(shmemSize) && - sActiveChildCounter->Map(shmemSize)) { - memset(sActiveChildCounter->Memory(), 0, shmemSize); + sActiveChildCounter() = shared_memory::Create(shmemSize).MapWithHandle(); + if (sActiveChildCounter()) { + memset(sActiveChildCounter().Address(), 0, shmemSize); sInUseChildCounters[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER] = true; sInUseChildCounters[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] = true; - static_cast*>( - sActiveChildCounter - ->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] = + sActiveChildCounter().DataAsSpan>() + [NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] = static_cast(sMaxConcurrentIdleTasksInChildProcesses); } else { - sActiveChildCounter = nullptr; + sActiveChildCounter() = nullptr; } } - Maybe activeCounter; - if (SharedMemory::Handle handle = - sActiveChildCounter ? sActiveChildCounter->CloneHandle() : nullptr) { - activeCounter.emplace(std::move(handle)); - } + MutableSharedMemoryHandle activeCounter = + sActiveChildCounter() ? sActiveChildCounter().Handle().Clone() : nullptr; uint32_t unusedId = 0; for (uint32_t i = 0; i < NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT; ++i) { @@ -211,8 +217,9 @@ IPCResult IdleSchedulerParent::RecvInitForIdleUse( // If there wasn't an empty item, we'll fallback to 0. mChildId = unusedId; - aResolve(std::tuple&&, const uint32_t&>( - std::move(activeCounter), mChildId)); + aResolve( + std::tuple&&, const uint32_t&>( + Some(std::move(activeCounter)), mChildId)); return IPC_OK(); } @@ -318,10 +325,9 @@ IPCResult IdleSchedulerParent::RecvDoneGC() { } int32_t IdleSchedulerParent::ActiveCount() { - if (sActiveChildCounter) { - return (static_cast*>( - sActiveChildCounter - ->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]); + if (sActiveChildCounter()) { + return sActiveChildCounter().DataAsSpan>() + [NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]; } return 0; } diff --git a/ipc/glue/IdleSchedulerParent.h b/ipc/glue/IdleSchedulerParent.h index 5f57487e588c..40c6c934f551 100644 --- a/ipc/glue/IdleSchedulerParent.h +++ b/ipc/glue/IdleSchedulerParent.h @@ -13,7 +13,7 @@ #include "mozilla/LinkedList.h" #include "mozilla/RefPtr.h" #include "mozilla/ipc/PIdleSchedulerParent.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include #define NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT 1024 @@ -82,14 +82,6 @@ class IdleSchedulerParent final bool IsDoingIdleTask() const { return !isInList() && 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 sActiveChildCounter; // 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 // sActiveChildCounter. diff --git a/ipc/glue/PIdleScheduler.ipdl b/ipc/glue/PIdleScheduler.ipdl index d0b94abaa2ca..b37639aea075 100644 --- a/ipc/glue/PIdleScheduler.ipdl +++ b/ipc/glue/PIdleScheduler.ipdl @@ -5,7 +5,7 @@ include protocol PBackground; using mozilla::TimeDuration from "mozilla/TimeStamp.h"; -[MoveOnly] using mozilla::ipc::SharedMemoryHandle from "mozilla/ipc/SharedMemory.h"; +[MoveOnly] using mozilla::ipc::MutableSharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h"; namespace mozilla { namespace ipc { @@ -39,7 +39,7 @@ child: async IdleTime(uint64_t id, TimeDuration budget); parent: - async InitForIdleUse() returns (SharedMemoryHandle? state, uint32_t childId); + async InitForIdleUse() returns (MutableSharedMemoryHandle? state, uint32_t childId); async RequestIdleTime(uint64_t id, TimeDuration budget); async IdleTimeUsed(uint64_t id); diff --git a/ipc/glue/ProcessChild.cpp b/ipc/glue/ProcessChild.cpp index 44ee401fde77..f218dbb35361 100644 --- a/ipc/glue/ProcessChild.cpp +++ b/ipc/glue/ProcessChild.cpp @@ -55,22 +55,18 @@ void ProcessChild::AddPlatformBuildID(geckoargs::ChildProcessArgs& aExtraArgs) { /* static */ bool ProcessChild::InitPrefs(int aArgc, char* aArgv[]) { - Maybe prefsHandle = + Maybe prefsHandle = geckoargs::sPrefsHandle.Get(aArgc, aArgv); - Maybe prefMapHandle = + Maybe prefMapHandle = geckoargs::sPrefMapHandle.Get(aArgc, aArgv); - Maybe prefsLen = geckoargs::sPrefsLen.Get(aArgc, aArgv); - Maybe prefMapSize = geckoargs::sPrefMapSize.Get(aArgc, aArgv); - if (prefsLen.isNothing() || prefMapSize.isNothing() || - prefsHandle.isNothing() || prefMapHandle.isNothing()) { + if (prefsHandle.isNothing() || prefMapHandle.isNothing()) { return false; } SharedPreferenceDeserializer deserializer; return deserializer.DeserializeFromSharedMemory(std::move(*prefsHandle), - std::move(*prefMapHandle), - *prefsLen, *prefMapSize); + std::move(*prefMapHandle)); } #ifdef ENABLE_TESTS diff --git a/ipc/glue/ProcessUtils.h b/ipc/glue/ProcessUtils.h index 7049eae49054..bb3b78d28981 100644 --- a/ipc/glue/ProcessUtils.h +++ b/ipc/glue/ProcessUtils.h @@ -12,7 +12,8 @@ #include "mozilla/GeckoArgs.h" #include "mozilla/ipc/FileDescriptor.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/Maybe.h" #include "mozilla/Preferences.h" #include "mozilla/RefPtr.h" @@ -36,22 +37,21 @@ class SharedPreferenceSerializer final { bool SerializeToSharedMemory(const GeckoProcessType aDestinationProcessType, const nsACString& aDestinationRemoteType); - size_t GetPrefMapSize() const { return mPrefMapSize; } - size_t GetPrefsLength() const { return mPrefsLength; } + const ReadOnlySharedMemoryHandle& GetPrefsHandle() const { + return mPrefsHandle; + } - const SharedMemoryHandle& GetPrefsHandle() const { return mPrefsHandle; } - - const SharedMemoryHandle& GetPrefMapHandle() const { return mPrefMapHandle; } + const ReadOnlySharedMemoryHandle& GetPrefMapHandle() const { + return mPrefMapHandle; + } void AddSharedPrefCmdLineArgs(GeckoChildProcessHost& procHost, geckoargs::ChildProcessArgs& aExtraOpts) const; private: DISALLOW_COPY_AND_ASSIGN(SharedPreferenceSerializer); - size_t mPrefMapSize; - size_t mPrefsLength; - SharedMemoryHandle mPrefMapHandle; - SharedMemoryHandle mPrefsHandle; + ReadOnlySharedMemoryHandle mPrefMapHandle; + ReadOnlySharedMemoryHandle mPrefsHandle; }; class SharedPreferenceDeserializer final { @@ -59,18 +59,13 @@ class SharedPreferenceDeserializer final { SharedPreferenceDeserializer(); ~SharedPreferenceDeserializer(); - bool DeserializeFromSharedMemory(SharedMemoryHandle aPrefsHandle, - SharedMemoryHandle aPrefMapHandle, - uint64_t aPrefsLen, uint64_t aPrefMapSize); - - const SharedMemoryHandle& GetPrefMapHandle() const; + bool DeserializeFromSharedMemory(ReadOnlySharedMemoryHandle&& aPrefsHandle, + ReadOnlySharedMemoryHandle&& aPrefMapHandle); private: DISALLOW_COPY_AND_ASSIGN(SharedPreferenceDeserializer); - Maybe mPrefMapHandle; - Maybe mPrefsLen; - Maybe mPrefMapSize; - RefPtr mShmem = MakeRefPtr(); + ReadOnlySharedMemoryHandle mPrefMapHandle; + ReadOnlySharedMemoryMapping mShmem; }; // Generate command line argument to spawn a child process. If the shared memory @@ -80,7 +75,7 @@ void ExportSharedJSInit(GeckoChildProcessHost& procHost, // Initialize the content used by the JS engine during the initialization of a // JS::Runtime. -bool ImportSharedJSInit(SharedMemoryHandle aJsInitHandle, uint64_t aJsInitLen); +bool ImportSharedJSInit(ReadOnlySharedMemoryHandle&& aJsInitHandle); } // namespace ipc } // namespace mozilla diff --git a/ipc/glue/ProcessUtils_common.cpp b/ipc/glue/ProcessUtils_common.cpp index 3de385ef0127..75bc1205453d 100644 --- a/ipc/glue/ProcessUtils_common.cpp +++ b/ipc/glue/ProcessUtils_common.cpp @@ -19,8 +19,7 @@ namespace mozilla { namespace ipc { -SharedPreferenceSerializer::SharedPreferenceSerializer() - : mPrefMapSize(0), mPrefsLength(0) { +SharedPreferenceSerializer::SharedPreferenceSerializer() { MOZ_COUNT_CTOR(SharedPreferenceSerializer); } @@ -30,9 +29,7 @@ SharedPreferenceSerializer::~SharedPreferenceSerializer() { SharedPreferenceSerializer::SharedPreferenceSerializer( SharedPreferenceSerializer&& aOther) - : mPrefMapSize(aOther.mPrefMapSize), - mPrefsLength(aOther.mPrefsLength), - mPrefMapHandle(std::move(aOther.mPrefMapHandle)), + : mPrefMapHandle(std::move(aOther.mPrefMapHandle)), mPrefsHandle(std::move(aOther.mPrefsHandle)) { MOZ_COUNT_CTOR(SharedPreferenceSerializer); } @@ -40,7 +37,7 @@ SharedPreferenceSerializer::SharedPreferenceSerializer( bool SharedPreferenceSerializer::SerializeToSharedMemory( const GeckoProcessType aDestinationProcessType, const nsACString& aDestinationRemoteType) { - mPrefMapHandle = Preferences::EnsureSnapshot(&mPrefMapSize); + mPrefMapHandle = Preferences::EnsureSnapshot(); bool destIsWebContent = aDestinationProcessType == GeckoProcessType_Content && @@ -50,40 +47,38 @@ bool SharedPreferenceSerializer::SerializeToSharedMemory( // Serialize the early prefs. nsAutoCStringN<1024> prefs; Preferences::SerializePreferences(prefs, destIsWebContent); - mPrefsLength = prefs.Length(); + auto prefsLength = prefs.Length(); - RefPtr shm = MakeRefPtr(); // Set up the shared memory. - if (!shm->Create(prefs.Length())) { + auto handle = shared_memory::Create(prefsLength); + if (!handle) { NS_ERROR("failed to create shared memory in the parent"); return false; } - if (!shm->Map(prefs.Length())) { + auto mapping = handle.Map(); + if (!mapping) { NS_ERROR("failed to map shared memory in the parent"); return false; } // Copy the serialized prefs into the shared memory. - memcpy(static_cast(shm->Memory()), prefs.get(), mPrefsLength); + memcpy(mapping.DataAs(), prefs.get(), prefsLength); - mPrefsHandle = shm->TakeHandleAndUnmap(); + mPrefsHandle = std::move(handle).ToReadOnly(); return true; } void SharedPreferenceSerializer::AddSharedPrefCmdLineArgs( mozilla::ipc::GeckoChildProcessHost& procHost, geckoargs::ChildProcessArgs& aExtraOpts) const { - SharedMemoryHandle prefsHandle = SharedMemory::CloneHandle(GetPrefsHandle()); - MOZ_RELEASE_ASSERT(prefsHandle, "failed to duplicate prefs handle"); - SharedMemoryHandle prefMapHandle = - SharedMemory::CloneHandle(GetPrefMapHandle()); - MOZ_RELEASE_ASSERT(prefMapHandle, "failed to duplicate pref map handle"); + auto prefsHandle = GetPrefsHandle().Clone(); + MOZ_RELEASE_ASSERT(prefsHandle, "failed to clone prefs handle"); + auto prefMapHandle = GetPrefMapHandle().Clone(); + MOZ_RELEASE_ASSERT(prefMapHandle, "failed to clone pref map handle"); - // Pass the handles and lengths via command line flags. + // Pass the handles via command line flags. geckoargs::sPrefsHandle.Put(std::move(prefsHandle), aExtraOpts); - geckoargs::sPrefsLen.Put((uintptr_t)(GetPrefsLength()), aExtraOpts); geckoargs::sPrefMapHandle.Put(std::move(prefMapHandle), aExtraOpts); - geckoargs::sPrefMapSize.Put((uintptr_t)(GetPrefMapSize()), aExtraOpts); } SharedPreferenceDeserializer::SharedPreferenceDeserializer() { @@ -95,79 +90,56 @@ SharedPreferenceDeserializer::~SharedPreferenceDeserializer() { } bool SharedPreferenceDeserializer::DeserializeFromSharedMemory( - SharedMemoryHandle aPrefsHandle, SharedMemoryHandle aPrefMapHandle, - uint64_t aPrefsLen, uint64_t aPrefMapSize) { - if (!aPrefsHandle || !aPrefMapHandle || !aPrefsLen || !aPrefMapSize) { + ReadOnlySharedMemoryHandle&& aPrefsHandle, + ReadOnlySharedMemoryHandle&& aPrefMapHandle) { + if (!aPrefsHandle || !aPrefMapHandle) { return false; } - mPrefMapHandle.emplace(std::move(aPrefMapHandle)); - - mPrefsLen = Some((uintptr_t)(aPrefsLen)); - - mPrefMapSize = Some((uintptr_t)(aPrefMapSize)); + mPrefMapHandle = std::move(aPrefMapHandle); // Init the shared-memory base preference mapping first, so that only changed // preferences wind up in heap memory. - Preferences::InitSnapshot(mPrefMapHandle.ref(), *mPrefMapSize); + Preferences::InitSnapshot(mPrefMapHandle); // Set up early prefs from the shared memory. - if (!mShmem->SetHandle(std::move(aPrefsHandle), - SharedMemory::RightsReadOnly)) { - NS_ERROR("failed to open shared memory in the child"); - return false; - } - if (!mShmem->Map(*mPrefsLen)) { + mShmem = aPrefsHandle.Map(); + if (!mShmem) { NS_ERROR("failed to map shared memory in the child"); return false; } - Preferences::DeserializePreferences(static_cast(mShmem->Memory()), - *mPrefsLen); + Preferences::DeserializePreferences(mShmem.DataAs(), mShmem.Size()); return true; } -const SharedMemoryHandle& SharedPreferenceDeserializer::GetPrefMapHandle() - const { - MOZ_ASSERT(mPrefMapHandle.isSome()); - - return mPrefMapHandle.ref(); -} - void ExportSharedJSInit(mozilla::ipc::GeckoChildProcessHost& procHost, geckoargs::ChildProcessArgs& aExtraOpts) { auto& shmem = xpc::SelfHostedShmem::GetSingleton(); - SharedMemoryHandle handle = SharedMemory::CloneHandle(shmem.Handle()); - size_t len = shmem.Content().Length(); + auto handle = shmem.Handle().Clone(); // If the file is not found or the content is empty, then we would start the // content process without this optimization. - if (!SharedMemory::IsHandleValid(handle) || !len) { + if (!handle) { NS_ERROR("Can't use SelfHosted shared memory handle."); return; } - // command line: -jsInitHandle handle -jsInitLen length + // command line: -jsInitHandle handle geckoargs::sJsInitHandle.Put(std::move(handle), aExtraOpts); - geckoargs::sJsInitLen.Put((uintptr_t)(len), aExtraOpts); } -bool ImportSharedJSInit(SharedMemoryHandle aJsInitHandle, uint64_t aJsInitLen) { +bool ImportSharedJSInit(ReadOnlySharedMemoryHandle&& aJsInitHandle) { // This is an optimization, and as such we can safely recover if the command // line argument are not provided. - if (!aJsInitLen || !aJsInitHandle) { + if (!aJsInitHandle) { 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 // of the self-hosted Xdr. auto& shmem = xpc::SelfHostedShmem::GetSingleton(); - if (!shmem.InitFromChild(std::move(aJsInitHandle), len)) { + if (!shmem.InitFromChild(std::move(aJsInitHandle))) { NS_ERROR("failed to open shared memory in the child"); return false; } diff --git a/ipc/glue/ProtocolUtils.h b/ipc/glue/ProtocolUtils.h index 9b8a199166c4..8037eefe4f6f 100644 --- a/ipc/glue/ProtocolUtils.h +++ b/ipc/glue/ProtocolUtils.h @@ -26,7 +26,6 @@ #include "mozilla/UniquePtr.h" #include "mozilla/ipc/MessageChannel.h" #include "mozilla/ipc/MessageLink.h" -#include "mozilla/ipc/SharedMemory.h" #include "mozilla/ipc/Shmem.h" #include "nsPrintfCString.h" #include "nsTHashMap.h" diff --git a/ipc/glue/SharedMemory.cpp b/ipc/glue/SharedMemory.cpp deleted file mode 100644 index 689fffff5901..000000000000 --- a/ipc/glue/SharedMemory.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* 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 - -#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 gShmemAllocated; -static Atomic 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 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 SharedMemory::TakeMapping() { - // NOTE: this doesn't reduce gShmemMapped since it _is_ still mapped memory - // (and will be until the process terminates). - return {static_cast(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(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 diff --git a/ipc/glue/SharedMemory.h b/ipc/glue/SharedMemory.h deleted file mode 100644 index cf7e9098f679..000000000000 --- a/ipc/glue/SharedMemory.h +++ /dev/null @@ -1,190 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* 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 - -#include "mozilla/Maybe.h" -#include "mozilla/UniquePtrExtensions.h" -#include "nsISupportsImpl.h" // NS_INLINE_DECL_REFCOUNTING - -#if !(defined(XP_DARWIN) || defined(XP_WIN)) -# include -#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 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 MapImpl(size_t nBytes, void* fixedAddress); - static void UnmapImpl(size_t nBytes, void* address); - Maybe 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; -#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 diff --git a/ipc/glue/SharedMemory_android.cpp b/ipc/glue/SharedMemory_android.cpp deleted file mode 100644 index 04f24167af59..000000000000 --- a/ipc/glue/SharedMemory_android.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* 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 -#include -#include -#include -#include - -#include "mozilla/Ashmem.h" - -#ifdef MOZ_VALGRIND -# include -#endif - -#include "base/eintr_wrapper.h" -#include "base/logging.h" -#include "base/string_util.h" -#include "mozilla/Atomics.h" -#include "mozilla/Maybe.h" -#include "mozilla/ProfilerThreadSleep.h" -#include "mozilla/UniquePtrExtensions.h" -#include "prenv.h" - -namespace mozilla::ipc { - -void SharedMemory::ResetImpl() {}; - -SharedMemory::Handle SharedMemory::CloneHandle(const Handle& aHandle) { - const int new_fd = dup(aHandle.get()); - if (new_fd < 0) { - CHROMIUM_LOG(WARNING) << "failed to duplicate file descriptor: " - << strerror(errno); - return nullptr; - } - return mozilla::UniqueFileHandle(new_fd); -} - -void* SharedMemory::FindFreeAddressSpace(size_t size) { - void* memory = mmap(nullptr, size, PROT_NONE, - MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE, -1, 0); - if (memory == MAP_FAILED) { - return nullptr; - } - munmap(memory, size); - return memory; -} - -Maybe SharedMemory::MapImpl(size_t nBytes, void* fixedAddress) { - // Don't use MAP_FIXED when a fixed_address was specified, since that can - // replace pages that are alread mapped at that address. - void* mem = - mmap(fixedAddress, nBytes, PROT_READ | (mReadOnly ? 0 : PROT_WRITE), - MAP_SHARED, mHandle.get(), 0); - - if (mem == MAP_FAILED) { - CHROMIUM_LOG(WARNING) << "Call to mmap failed: " << strerror(errno); - return Nothing(); - } - - if (fixedAddress && mem != fixedAddress) { - bool munmap_succeeded = munmap(mem, nBytes) == 0; - DCHECK(munmap_succeeded) << "Call to munmap failed, errno=" << errno; - return Nothing(); - } - - return Some(mem); -} - -void SharedMemory::UnmapImpl(size_t nBytes, void* address) { - munmap(address, nBytes); -} - -// Android has its own shared memory API, ashmem. It doesn't support POSIX -// shm_open, and the memfd support (see posix impl) also doesn't work because -// its SELinux policy prevents the procfs operations we'd use (see bug 1670277 -// for more details). - -bool SharedMemory::AppendPosixShmPrefix(std::string* str, pid_t pid) { - return false; -} - -bool SharedMemory::UsingPosixShm() { return false; } - -bool SharedMemory::CreateImpl(size_t size, bool freezable) { - DCHECK(size > 0); - DCHECK(!mHandle); - - int fd = mozilla::android::ashmem_create(nullptr, size); - if (fd < 0) { - CHROMIUM_LOG(WARNING) << "failed to open shm: " << strerror(errno); - return false; - } - - mHandle.reset(fd); - return true; -} - -Maybe SharedMemory::ReadOnlyCopyImpl() { - if (mozilla::android::ashmem_setProt(mHandle.get(), PROT_READ) != 0) { - CHROMIUM_LOG(WARNING) << "failed to set ashmem read-only: " - << strerror(errno); - return Nothing(); - } - - mozilla::UniqueFileHandle ro_file = std::move(mHandle); - - return Some(std::move(ro_file)); -} - -void SharedMemory::SystemProtect(char* aAddr, size_t aSize, int aRights) { - if (!SystemProtectFallible(aAddr, aSize, aRights)) { - MOZ_CRASH("can't mprotect()"); - } -} - -bool SharedMemory::SystemProtectFallible(char* aAddr, size_t aSize, - int aRights) { - int flags = 0; - if (aRights & RightsRead) flags |= PROT_READ; - if (aRights & RightsWrite) flags |= PROT_WRITE; - if (RightsNone == aRights) flags = PROT_NONE; - - return 0 == mprotect(aAddr, aSize, flags); -} - -size_t SharedMemory::SystemPageSize() { return sysconf(_SC_PAGESIZE); } - -} // namespace mozilla::ipc diff --git a/ipc/glue/SharedMemory_mach.cpp b/ipc/glue/SharedMemory_mach.cpp deleted file mode 100644 index 610b7318cb05..000000000000 --- a/ipc/glue/SharedMemory_mach.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/ipc/SharedMemory.h" - -#include - -#include -#include -#if defined(XP_IOS) -# include -# define mach_vm_address_t vm_address_t -# define mach_vm_map vm_map -# define mach_vm_read vm_read -# define mach_vm_region_recurse vm_region_recurse_64 -# define mach_vm_size_t vm_size_t -#else -# include -#endif -#include -#include // mprotect -#include - -#if defined(XP_MACOSX) && defined(__x86_64__) -# include "prenv.h" -#endif - -#include "mozilla/IntegerPrintfMacros.h" -#include "mozilla/Printf.h" -#include "mozilla/StaticMutex.h" - -#ifdef DEBUG -# define LOG_ERROR(str, args...) \ - PR_BEGIN_MACRO \ - mozilla::SmprintfPointer msg = mozilla::Smprintf(str, ##args); \ - NS_WARNING(msg.get()); \ - PR_END_MACRO -#else -# define LOG_ERROR(str, args...) \ - do { /* nothing */ \ - } while (0) -#endif - -namespace mozilla::ipc { - -static inline void* toPointer(mach_vm_address_t address) { - return reinterpret_cast(static_cast(address)); -} - -static inline mach_vm_address_t toVMAddress(void* pointer) { - return static_cast(reinterpret_cast(pointer)); -} - -void SharedMemory::ResetImpl() {}; - -bool SharedMemory::CreateImpl(size_t size, bool freezable) { - memory_object_size_t memoryObjectSize = round_page(size); - - kern_return_t kr = - mach_make_memory_entry_64(mach_task_self(), &memoryObjectSize, 0, - MAP_MEM_NAMED_CREATE | VM_PROT_DEFAULT, - getter_Transfers(mHandle), MACH_PORT_NULL); - if (kr != KERN_SUCCESS || memoryObjectSize < round_page(size)) { - LOG_ERROR("Failed to make memory entry (%zu bytes). %s (%x)\n", size, - mach_error_string(kr), kr); - TakeHandle(); - return false; - } - return true; -} - -Maybe MapMemory(size_t size, void* fixedAddress, - const mozilla::UniqueMachSendRight& port, - bool readOnly) { - kern_return_t kr; - mach_vm_address_t address = toVMAddress(fixedAddress); - - vm_prot_t vmProtection = VM_PROT_READ; - if (!readOnly) { - vmProtection |= VM_PROT_WRITE; - } - - kr = - mach_vm_map(mach_task_self(), &address, round_page(size), 0, - fixedAddress ? VM_FLAGS_FIXED : VM_FLAGS_ANYWHERE, port.get(), - 0, false, vmProtection, vmProtection, VM_INHERIT_NONE); - if (kr != KERN_SUCCESS) { - if (!fixedAddress) { - LOG_ERROR( - "Failed to map shared memory (%zu bytes) into %x, port %x. %s (%x)\n", - size, mach_task_self(), mach_port_t(port.get()), - mach_error_string(kr), kr); - } - return Nothing(); - } - - if (fixedAddress && fixedAddress != toPointer(address)) { - kr = vm_deallocate(mach_task_self(), address, size); - if (kr != KERN_SUCCESS) { - LOG_ERROR( - "Failed to unmap shared memory at unsuitable address " - "(%zu bytes) from %x, port %x. %s (%x)\n", - size, mach_task_self(), mach_port_t(port.get()), - mach_error_string(kr), kr); - } - return Nothing(); - } - - return Some(toPointer(address)); -} - -Maybe SharedMemory::MapImpl(size_t size, void* fixedAddress) { - return MapMemory(size, fixedAddress, mHandle, mReadOnly); -} - -void* SharedMemory::FindFreeAddressSpace(size_t size) { - mach_vm_address_t address = 0; - size = round_page(size); - if (mach_vm_map(mach_task_self(), &address, size, 0, VM_FLAGS_ANYWHERE, - MEMORY_OBJECT_NULL, 0, false, VM_PROT_NONE, VM_PROT_NONE, - VM_INHERIT_NONE) != KERN_SUCCESS || - vm_deallocate(mach_task_self(), address, size) != KERN_SUCCESS) { - return nullptr; - } - return toPointer(address); -} - -auto SharedMemory::CloneHandle(const Handle& aHandle) -> Handle { - return mozilla::RetainMachSendRight(aHandle.get()); -} - -void SharedMemory::UnmapImpl(size_t nBytes, void* address) { - vm_address_t vm_address = toVMAddress(address); - kern_return_t kr = - vm_deallocate(mach_task_self(), vm_address, round_page(nBytes)); - if (kr != KERN_SUCCESS) { - LOG_ERROR("Failed to deallocate shared memory. %s (%x)\n", - mach_error_string(kr), kr); - } -} - -Maybe SharedMemory::ReadOnlyCopyImpl() { - memory_object_size_t memoryObjectSize = round_page(mAllocSize); - - mozilla::UniqueMachSendRight port; - - void* address = mMemory.get(); - bool unmap = false; - - if (!address) { - // Temporarily map memory (as readonly) to get an address. - if (auto memory = MapMemory(memoryObjectSize, nullptr, mHandle, true)) { - address = *memory; - unmap = true; - } else { - return Nothing(); - } - } - - kern_return_t kr = mach_make_memory_entry_64( - mach_task_self(), &memoryObjectSize, - static_cast(reinterpret_cast(address)), - VM_PROT_READ, getter_Transfers(port), MACH_PORT_NULL); - - if (unmap) { - kern_return_t kr = - vm_deallocate(mach_task_self(), toVMAddress(address), memoryObjectSize); - if (kr != KERN_SUCCESS) { - LOG_ERROR("Failed to deallocate shared memory. %s (%x)\n", - mach_error_string(kr), kr); - } - } - - if (kr != KERN_SUCCESS || memoryObjectSize < round_page(mAllocSize)) { - LOG_ERROR("Failed to make memory entry (%zu bytes). %s (%x)\n", mAllocSize, - mach_error_string(kr), kr); - return Nothing(); - } - - return Some(std::move(port)); -} - -void SharedMemory::SystemProtect(char* aAddr, size_t aSize, int aRights) { - if (!SystemProtectFallible(aAddr, aSize, aRights)) { - MOZ_CRASH("can't mprotect()"); - } -} - -bool SharedMemory::SystemProtectFallible(char* aAddr, size_t aSize, - int aRights) { - int flags = 0; - if (aRights & RightsRead) flags |= PROT_READ; - if (aRights & RightsWrite) flags |= PROT_WRITE; - if (RightsNone == aRights) flags = PROT_NONE; - - return 0 == mprotect(aAddr, aSize, flags); -} - -#if defined(XP_MACOSX) && defined(__x86_64__) -std::atomic sPageSizeOverride = 0; -#endif - -size_t SharedMemory::SystemPageSize() { -#if defined(XP_MACOSX) && defined(__x86_64__) - if (sPageSizeOverride == 0) { - if (PR_GetEnv("MOZ_SHMEM_PAGESIZE_16K")) { - sPageSizeOverride = 16 * 1024; - } else { - sPageSizeOverride = sysconf(_SC_PAGESIZE); - } - } - return sPageSizeOverride; -#else - return sysconf(_SC_PAGESIZE); -#endif -} - -} // namespace mozilla::ipc diff --git a/ipc/glue/SharedMemory_posix.cpp b/ipc/glue/SharedMemory_posix.cpp deleted file mode 100644 index da279f469237..000000000000 --- a/ipc/glue/SharedMemory_posix.cpp +++ /dev/null @@ -1,458 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* 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 -#include -#include -#include -#include - -#ifdef XP_LINUX -# include "base/linux_memfd_defs.h" -#endif -#ifdef MOZ_WIDGET_GTK -# include "mozilla/WidgetUtilsGtk.h" -#endif - -#ifdef __FreeBSD__ -# include -#endif - -#ifdef MOZ_VALGRIND -# include -#endif - -#include "base/eintr_wrapper.h" -#include "base/logging.h" -#include "base/string_util.h" -#include "mozilla/Atomics.h" -#include "mozilla/Maybe.h" -#include "mozilla/ProfilerThreadSleep.h" -#include "mozilla/UniquePtrExtensions.h" -#include "prenv.h" -#include "nsXULAppAPI.h" // for XRE_IsParentProcess - -namespace mozilla::ipc { - -void SharedMemory::ResetImpl() { - if (mFrozenFile) { - CHROMIUM_LOG(WARNING) << "freezable shared memory was never frozen"; - mFrozenFile = nullptr; - } - mIsMemfd = false; -}; - -SharedMemory::Handle SharedMemory::CloneHandle(const Handle& aHandle) { - const int new_fd = dup(aHandle.get()); - if (new_fd < 0) { - CHROMIUM_LOG(WARNING) << "failed to duplicate file descriptor: " - << strerror(errno); - return nullptr; - } - return mozilla::UniqueFileHandle(new_fd); -} - -void* SharedMemory::FindFreeAddressSpace(size_t size) { - void* memory = mmap(nullptr, size, PROT_NONE, - MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE, -1, 0); - if (memory == MAP_FAILED) { - return nullptr; - } - munmap(memory, size); - return memory; -} - -Maybe SharedMemory::MapImpl(size_t nBytes, void* fixedAddress) { - // Don't use MAP_FIXED when a fixed_address was specified, since that can - // replace pages that are alread mapped at that address. - void* mem = - mmap(fixedAddress, nBytes, PROT_READ | (mReadOnly ? 0 : PROT_WRITE), - MAP_SHARED, mHandle.get(), 0); - - if (mem == MAP_FAILED) { - CHROMIUM_LOG(WARNING) << "Call to mmap failed: " << strerror(errno); - return Nothing(); - } - - if (fixedAddress && mem != fixedAddress) { - bool munmap_succeeded = munmap(mem, nBytes) == 0; - DCHECK(munmap_succeeded) << "Call to munmap failed, errno=" << errno; - return Nothing(); - } - - return Some(mem); -} - -void SharedMemory::UnmapImpl(size_t nBytes, void* address) { - munmap(address, nBytes); -} - -// memfd_create is a nonstandard interface for creating anonymous -// shared memory accessible as a file descriptor but not tied to any -// filesystem. It first appeared in Linux 3.17, and was adopted by -// FreeBSD in version 13. - -#if !defined(HAVE_MEMFD_CREATE) && defined(XP_LINUX) && \ - defined(SYS_memfd_create) - -// Older libc versions (e.g., glibc before 2.27) don't have the -// wrapper, but we can supply our own; see `linux_memfd_defs.h`. - -static int memfd_create(const char* name, unsigned int flags) { - return syscall(SYS_memfd_create, name, flags); -} - -# define HAVE_MEMFD_CREATE 1 -#endif - -// memfd supports having "seals" applied to the file, to prevent -// various types of changes (which apply to all fds referencing the -// file). Unfortunately, we can't rely on F_SEAL_WRITE to implement -// Freeze(); see the comments in ReadOnlyCopy() below. -// -// Instead, to prevent a child process from regaining write access to -// a read-only copy, the OS must also provide a way to remove write -// permissions at the file descriptor level. This next section -// attempts to accomplish that. - -#ifdef HAVE_MEMFD_CREATE -# ifdef XP_LINUX -# define USE_MEMFD_CREATE 1 - -// To create a read-only duplicate of an fd, we can use procfs; the -// same operation could restore write access, but sandboxing prevents -// child processes from accessing /proc. -// -// (Note: if this ever changes to not use /proc, also reconsider how -// and if HaveMemfd should check whether this works.) - -static int DupReadOnly(int fd) { - MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess()); - std::string path = StringPrintf("/proc/self/fd/%d", fd); - // procfs opens probably won't EINTR, but checking for it can't hurt - return HANDLE_EINTR(open(path.c_str(), O_RDONLY | O_CLOEXEC)); -} - -# elif defined(__FreeBSD__) -# define USE_MEMFD_CREATE 1 - -// FreeBSD's Capsicum framework allows irrevocably restricting the -// operations permitted on a file descriptor. - -static int DupReadOnly(int fd) { - int rofd = dup(fd); - if (rofd < 0) { - return -1; - } - - cap_rights_t rights; - cap_rights_init(&rights, CAP_FSTAT, CAP_MMAP_R); - if (cap_rights_limit(rofd, &rights) < 0) { - int err = errno; - close(rofd); - errno = err; - return -1; - } - - return rofd; -} - -# else // unhandled OS -# warning "OS has memfd_create but no DupReadOnly implementation" -# endif // OS selection -#endif // HAVE_MEMFD_CREATE - -// Runtime detection for memfd support. Returns `Nothing()` if not -// supported, or `Some(flags)` if supported, where `flags` contains -// flags like `MFD_CLOEXEC` that should be passed to all calls. -static Maybe HaveMemfd() { -#ifdef USE_MEMFD_CREATE - static const Maybe kHave = []() -> Maybe { - unsigned flags = MFD_CLOEXEC | MFD_ALLOW_SEALING; -# ifdef MFD_NOEXEC_SEAL - flags |= MFD_NOEXEC_SEAL; -# endif - - mozilla::UniqueFileHandle fd(memfd_create("mozilla-ipc-test", flags)); - -# ifdef MFD_NOEXEC_SEAL - if (!fd && errno == EINVAL) { - flags &= ~MFD_NOEXEC_SEAL; - fd.reset(memfd_create("mozilla-ipc-test", flags)); - } -# endif - - if (!fd) { - DCHECK_EQ(errno, ENOSYS); - return Nothing(); - } - - // Verify that DupReadOnly works; on Linux it's known to fail if: - // - // * SELinux assigns the memfd a type for which this process's - // domain doesn't have "open" permission; this is always the - // case on Android but could occur on desktop as well - // - // * /proc (used by the DupReadOnly implementation) isn't mounted, - // which is a configuration that the Tor Browser project is - // interested in as a way to reduce fingerprinting risk - // - // Sandboxed processes on Linux also can't use it if sandboxing - // has already been started, but that's expected. It should be - // safe for sandboxed child processes to use memfd even if an - // unsandboxed process couldn't freeze them, because freezing - // isn't allowed (or meaningful) for memory created by another - // process. - - if (XRE_IsParentProcess()) { - mozilla::UniqueFileHandle rofd(DupReadOnly(fd.get())); - if (!rofd) { - CHROMIUM_LOG(WARNING) << "read-only dup failed (" << strerror(errno) - << "); not using memfd"; - return Nothing(); - } - } - return Some(flags); - }(); - return kHave; -#else - return Nothing(); -#endif // USE_MEMFD_CREATE -} - -// static -bool SharedMemory::AppendPosixShmPrefix(std::string* str, pid_t pid) { - if (HaveMemfd()) { - return false; - } - *str += '/'; -#ifdef MOZ_WIDGET_GTK - // The Snap package environment doesn't provide a private /dev/shm - // (it's used for communication with services like PulseAudio); - // instead AppArmor is used to restrict access to it. Anything with - // this prefix is allowed: - if (const char* snap = mozilla::widget::GetSnapInstanceName()) { - StringAppendF(str, "snap.%s.", snap); - } -#endif // XP_LINUX - // Hopefully the "implementation defined" name length limit is long - // enough for this. - StringAppendF(str, "org.mozilla.ipc.%d.", static_cast(pid)); - return true; -} - -bool SharedMemory::CreateImpl(size_t size, bool freezable) { - DCHECK(size > 0); - DCHECK(!mHandle); - DCHECK(!mFrozenFile); - - MOZ_DIAGNOSTIC_ASSERT( - !freezable || XRE_IsParentProcess(), - "Child processes may not create freezable shared memory"); - - mozilla::UniqueFileHandle fd; - mozilla::UniqueFileHandle frozen_fd; - bool is_memfd = false; - -#ifdef USE_MEMFD_CREATE - if (auto flags = HaveMemfd()) { - fd.reset(memfd_create("mozilla-ipc", *flags)); - if (!fd) { - // In general it's too late to fall back here -- in a sandboxed - // child process, shm_open is already blocked. And it shouldn't - // be necessary. - CHROMIUM_LOG(WARNING) << "failed to create memfd: " << strerror(errno); - return false; - } - is_memfd = true; - if (freezable) { - frozen_fd.reset(DupReadOnly(fd.get())); - if (!frozen_fd) { - CHROMIUM_LOG(WARNING) - << "failed to create read-only memfd: " << strerror(errno); - return false; - } - } - } -#endif - - if (!fd) { - // Generic Unix: shm_open + shm_unlink - do { - // The names don't need to be unique, but it saves time if they - // usually are. - static mozilla::Atomic sNameCounter; - std::string name; - CHECK(AppendPosixShmPrefix(&name, getpid())); - StringAppendF(&name, "%zu", sNameCounter++); - // O_EXCL means the names being predictable shouldn't be a problem. - fd.reset(HANDLE_EINTR( - shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600))); - if (fd) { - if (freezable) { - frozen_fd.reset(HANDLE_EINTR(shm_open(name.c_str(), O_RDONLY, 0400))); - if (!frozen_fd) { - int open_err = errno; - shm_unlink(name.c_str()); - DLOG(FATAL) << "failed to re-open freezable shm: " - << strerror(open_err); - return false; - } - } - if (shm_unlink(name.c_str()) != 0) { - // This shouldn't happen, but if it does: assume the file is - // in fact leaked, and bail out now while it's still 0-length. - DLOG(FATAL) << "failed to unlink shm: " << strerror(errno); - return false; - } - } - } while (!fd && errno == EEXIST); - } - - if (!fd) { - CHROMIUM_LOG(WARNING) << "failed to open shm: " << strerror(errno); - return false; - } - - mozilla::Maybe fallocateError; -#if defined(HAVE_POSIX_FALLOCATE) - // Using posix_fallocate will ensure that there's actually space for this - // file. Otherwise we end up with a sparse file that can give SIGBUS if we - // run out of space while writing to it. (This doesn't apply to memfd.) - if (!is_memfd) { - int rv; - // Avoid repeated interruptions of posix_fallocate by the profiler's - // SIGPROF sampling signal. Indicating "thread sleep" here means we'll - // get up to one interruption but not more. See bug 1658847 for more. - // This has to be scoped outside the HANDLE_RV_EINTR retry loop. - { - AUTO_PROFILER_THREAD_SLEEP; - - rv = HANDLE_RV_EINTR( - posix_fallocate(fd.get(), 0, static_cast(size))); - } - - // Some filesystems have trouble with posix_fallocate. For now, we must - // fallback ftruncate and accept the allocation failures like we do - // without posix_fallocate. - // See https://bugzilla.mozilla.org/show_bug.cgi?id=1618914 - if (rv != 0 && rv != EOPNOTSUPP && rv != EINVAL && rv != ENODEV) { - CHROMIUM_LOG(WARNING) - << "fallocate failed to set shm size: " << strerror(rv); - return false; - } - fallocateError = mozilla::Some(rv); - } -#endif - - // If posix_fallocate isn't supported / relevant for this type of - // file (either failed with an expected error, or wasn't attempted), - // then set the size with ftruncate: - if (fallocateError != mozilla::Some(0)) { - int rv = HANDLE_EINTR(ftruncate(fd.get(), static_cast(size))); - if (rv != 0) { - int ftruncate_errno = errno; - if (fallocateError) { - CHROMIUM_LOG(WARNING) << "fallocate failed to set shm size: " - << strerror(*fallocateError); - } - CHROMIUM_LOG(WARNING) - << "ftruncate failed to set shm size: " << strerror(ftruncate_errno); - return false; - } - } - - mHandle = std::move(fd); - mFrozenFile = std::move(frozen_fd); - mIsMemfd = is_memfd; - return true; -} - -Maybe SharedMemory::ReadOnlyCopyImpl() { -#ifdef USE_MEMFD_CREATE -# ifdef MOZ_VALGRIND - // Valgrind allows memfd_create but doesn't understand F_ADD_SEALS. - static const bool haveSeals = RUNNING_ON_VALGRIND == 0; -# else - static const bool haveSeals = true; -# endif - static const bool useSeals = !PR_GetEnv("MOZ_SHM_NO_SEALS"); - if (mIsMemfd && haveSeals && useSeals) { - // Seals are added to the file as defense-in-depth. The primary - // method of access control is creating a read-only fd (using - // procfs in this case) and requiring that sandboxes processes not - // have access to /proc/self/fd to regain write permission; this - // is the same as with shm_open. - // - // Unfortunately, F_SEAL_WRITE is unreliable: if the process - // forked while there was a writeable mapping, it will inherit a - // copy of the mapping, which causes the seal to fail. - // - // (Also, in the future we may want to split this into separate - // classes for mappings and shared memory handles, which would - // complicate identifying the case where `F_SEAL_WRITE` would be - // possible even in the absence of races with fork.) - // - // However, Linux 5.1 added F_SEAL_FUTURE_WRITE, which prevents - // write operations afterwards, but existing writeable mappings - // are unaffected (similar to ashmem protection semantics). - - const int seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL; - int sealError = EINVAL; - -# ifdef F_SEAL_FUTURE_WRITE - sealError = - fcntl(mHandle.get(), F_ADD_SEALS, seals | F_SEAL_FUTURE_WRITE) == 0 - ? 0 - : errno; -# endif // F_SEAL_FUTURE_WRITE - if (sealError == EINVAL) { - sealError = fcntl(mHandle.get(), F_ADD_SEALS, seals) == 0 ? 0 : errno; - } - if (sealError != 0) { - CHROMIUM_LOG(WARNING) << "failed to seal memfd: " << strerror(errno); - return Nothing(); - } - } -#else // !USE_MEMFD_CREATE - DCHECK(!mIsMemfd); -#endif - - DCHECK(mFrozenFile); - DCHECK(mHandle); - mozilla::UniqueFileHandle ro_file = std::move(mFrozenFile); - - DCHECK(ro_file); - - return Some(std::move(ro_file)); -} - -void SharedMemory::SystemProtect(char* aAddr, size_t aSize, int aRights) { - if (!SystemProtectFallible(aAddr, aSize, aRights)) { - MOZ_CRASH("can't mprotect()"); - } -} - -bool SharedMemory::SystemProtectFallible(char* aAddr, size_t aSize, - int aRights) { - int flags = 0; - if (aRights & RightsRead) flags |= PROT_READ; - if (aRights & RightsWrite) flags |= PROT_WRITE; - if (RightsNone == aRights) flags = PROT_NONE; - - return 0 == mprotect(aAddr, aSize, flags); -} - -size_t SharedMemory::SystemPageSize() { return sysconf(_SC_PAGESIZE); } - -bool SharedMemory::UsingPosixShm() { return !HaveMemfd(); } - -} // namespace mozilla::ipc diff --git a/ipc/glue/SharedMemory_windows.cpp b/ipc/glue/SharedMemory_windows.cpp deleted file mode 100644 index 3684e2b3ac54..000000000000 --- a/ipc/glue/SharedMemory_windows.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* 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 - -#include "base/logging.h" -#include "base/win_util.h" -#include "base/string_util.h" -#include "mozilla/ipc/ProtocolUtils.h" -#include "mozilla/RandomNum.h" -#include "nsDebug.h" -#include "nsString.h" -#ifdef MOZ_MEMORY -# include "mozmemory_utils.h" -#endif - -namespace { -// NtQuerySection is an internal (but believed to be stable) API and the -// structures it uses are defined in nt_internals.h. -// So we have to define them ourselves. -typedef enum _SECTION_INFORMATION_CLASS { - SectionBasicInformation, -} SECTION_INFORMATION_CLASS; - -typedef struct _SECTION_BASIC_INFORMATION { - PVOID BaseAddress; - ULONG Attributes; - LARGE_INTEGER Size; -} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION; - -typedef ULONG(__stdcall* NtQuerySectionType)( - HANDLE SectionHandle, SECTION_INFORMATION_CLASS SectionInformationClass, - PVOID SectionInformation, ULONG SectionInformationLength, - PULONG ResultLength); - -// Checks if the section object is safe to map. At the moment this just means -// it's not an image section. -bool IsSectionSafeToMap(HANDLE handle) { - static NtQuerySectionType nt_query_section_func = - reinterpret_cast( - ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), "NtQuerySection")); - DCHECK(nt_query_section_func); - - // The handle must have SECTION_QUERY access for this to succeed. - SECTION_BASIC_INFORMATION basic_information = {}; - ULONG status = - nt_query_section_func(handle, SectionBasicInformation, &basic_information, - sizeof(basic_information), nullptr); - if (status) { - return false; - } - - return (basic_information.Attributes & SEC_IMAGE) != SEC_IMAGE; -} - -} // namespace - -namespace mozilla::ipc { - -void SharedMemory::ResetImpl() {}; - -SharedMemory::Handle SharedMemory::CloneHandle(const Handle& aHandle) { - HANDLE handle = INVALID_HANDLE_VALUE; - if (DuplicateHandle(GetCurrentProcess(), aHandle.get(), GetCurrentProcess(), - &handle, 0, false, DUPLICATE_SAME_ACCESS)) { - return SharedMemoryHandle(handle); - } - NS_WARNING("DuplicateHandle Failed!"); - return nullptr; -} - -void* SharedMemory::FindFreeAddressSpace(size_t size) { - void* memory = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS); - if (memory) { - VirtualFree(memory, 0, MEM_RELEASE); - } - return memory; -} - -Maybe SharedMemory::MapImpl(size_t nBytes, void* fixedAddress) { - if (mExternalHandle && !IsSectionSafeToMap(mHandle.get())) { - return Nothing(); - } - - void* mem = MapViewOfFileEx( - mHandle.get(), mReadOnly ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, - 0, 0, nBytes, fixedAddress); - if (mem) { - MOZ_ASSERT(!fixedAddress || mem == fixedAddress, - "MapViewOfFileEx returned an expected address"); - return Some(mem); - } - return Nothing(); -} - -void SharedMemory::UnmapImpl(size_t nBytes, void* address) { - UnmapViewOfFile(address); -} - -// Wrapper around CreateFileMappingW for pagefile-backed regions. When out of -// memory, may attempt to stall and retry rather than returning immediately, in -// hopes that the page file is about to be expanded by Windows. (bug 1822383, -// bug 1716727) -// -// This method is largely a copy of the MozVirtualAlloc method from -// mozjemalloc.cpp, which implements this strategy for VirtualAlloc calls, -// except re-purposed to handle CreateFileMapping. -static HANDLE MozCreateFileMappingW( - LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, - DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCWSTR lpName) { -#ifdef MOZ_MEMORY - constexpr auto IsOOMError = [] { - return ::GetLastError() == ERROR_COMMITMENT_LIMIT; - }; - - { - HANDLE handle = ::CreateFileMappingW( - INVALID_HANDLE_VALUE, lpFileMappingAttributes, flProtect, - dwMaximumSizeHigh, dwMaximumSizeLow, lpName); - if (MOZ_LIKELY(handle)) { - MOZ_DIAGNOSTIC_ASSERT(handle != INVALID_HANDLE_VALUE, - "::CreateFileMapping should return NULL, not " - "INVALID_HANDLE_VALUE, on failure"); - return handle; - } - - // We can't do anything for errors other than OOM. - if (!IsOOMError()) { - return nullptr; - } - } - - // Retry as many times as desired (possibly zero). - const mozilla::StallSpecs stallSpecs = mozilla::GetAllocatorStallSpecs(); - - const auto ret = - stallSpecs.StallAndRetry(&::Sleep, [&]() -> std::optional { - HANDLE handle = ::CreateFileMappingW( - INVALID_HANDLE_VALUE, lpFileMappingAttributes, flProtect, - dwMaximumSizeHigh, dwMaximumSizeLow, lpName); - - if (handle) { - MOZ_DIAGNOSTIC_ASSERT(handle != INVALID_HANDLE_VALUE, - "::CreateFileMapping should return NULL, not " - "INVALID_HANDLE_VALUE, on failure"); - return handle; - } - - // Failure for some reason other than OOM. - if (!IsOOMError()) { - return nullptr; - } - - return std::nullopt; - }); - - return ret.value_or(nullptr); -#else - return ::CreateFileMappingW(INVALID_HANDLE_VALUE, lpFileMappingAttributes, - flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, - lpName); -#endif -} - -bool SharedMemory::CreateImpl(size_t size, bool freezable) { - // If the shared memory object has no DACL, any process can - // duplicate its handles with any access rights; e.g., re-add write - // access to a read-only handle. To prevent that, we give it an - // empty DACL, so that no process can do that. - SECURITY_ATTRIBUTES sa, *psa = nullptr; - SECURITY_DESCRIPTOR sd; - ACL dacl; - - if (freezable) { - psa = &sa; - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = &sd; - sa.bInheritHandle = FALSE; - - if (NS_WARN_IF(!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION)) || - NS_WARN_IF( - !InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) || - NS_WARN_IF(!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE))) { - return false; - } - } - - mHandle.reset(MozCreateFileMappingW(psa, PAGE_READWRITE, 0, - static_cast(size), nullptr)); - return (bool)mHandle; -} - -Maybe SharedMemory::ReadOnlyCopyImpl() { - HANDLE ro_handle; - if (!::DuplicateHandle(GetCurrentProcess(), mHandle.get(), - GetCurrentProcess(), &ro_handle, - GENERIC_READ | FILE_MAP_READ, false, 0)) { - return Nothing(); - } - - return Some(ro_handle); -} - -void SharedMemory::SystemProtect(char* aAddr, size_t aSize, int aRights) { - if (!SystemProtectFallible(aAddr, aSize, aRights)) { - MOZ_CRASH("can't VirtualProtect()"); - } -} - -bool SharedMemory::SystemProtectFallible(char* aAddr, size_t aSize, - int aRights) { - DWORD flags; - if ((aRights & RightsRead) && (aRights & RightsWrite)) - flags = PAGE_READWRITE; - else if (aRights & RightsRead) - flags = PAGE_READONLY; - else - flags = PAGE_NOACCESS; - - DWORD oldflags; - return VirtualProtect(aAddr, aSize, flags, &oldflags); -} - -size_t SharedMemory::SystemPageSize() { - SYSTEM_INFO si; - GetSystemInfo(&si); - return si.dwPageSize; -} - -} // namespace mozilla::ipc diff --git a/ipc/glue/moz.build b/ipc/glue/moz.build index e5166b0df946..3ee354d54d67 100644 --- a/ipc/glue/moz.build +++ b/ipc/glue/moz.build @@ -55,7 +55,6 @@ EXPORTS.mozilla.ipc += [ "RustMessageUtils.h", "ScopedPort.h", "SerializedStructuredCloneBuffer.h", - "SharedMemory.h", "SharedMemoryCursor.h", "SharedMemoryHandle.h", "SharedMemoryMapping.h", @@ -108,19 +107,14 @@ else: "CrossProcessSemaphore_posix.cpp", ] -# TODO change to UNIFIED_SOURCES when old shared memory impl removed if CONFIG["OS_ARCH"] == "Darwin": - SOURCES += ["SharedMemory_mach.cpp"] - SOURCES += ["SharedMemoryPlatform_mach.cpp"] + UNIFIED_SOURCES += ["SharedMemoryPlatform_mach.cpp"] elif CONFIG["OS_ARCH"] == "WINNT": - SOURCES += ["SharedMemory_windows.cpp"] - SOURCES += ["SharedMemoryPlatform_windows.cpp"] + UNIFIED_SOURCES += ["SharedMemoryPlatform_windows.cpp"] elif CONFIG["OS_TARGET"] == "Android": - SOURCES += ["SharedMemory_android.cpp"] - SOURCES += ["SharedMemoryPlatform_android.cpp"] + UNIFIED_SOURCES += ["SharedMemoryPlatform_android.cpp"] else: - SOURCES += ["SharedMemory_posix.cpp"] - SOURCES += ["SharedMemoryPlatform_posix.cpp"] + UNIFIED_SOURCES += ["SharedMemoryPlatform_posix.cpp"] if CONFIG["OS_ARCH"] == "Linux": @@ -195,7 +189,9 @@ UNIFIED_SOURCES += [ "RandomAccessStreamUtils.cpp", "ScopedPort.cpp", "SerializedStructuredCloneBuffer.cpp", - "SharedMemory.cpp", + "SharedMemoryCursor.cpp", + "SharedMemoryHandle.cpp", + "SharedMemoryMapping.cpp", "Shmem.cpp", "StringUtil.cpp", "TransportSecurityInfoUtils.cpp", @@ -214,10 +210,6 @@ UNIFIED_SOURCES += [ SOURCES += [ "BackgroundChildImpl.cpp", "BackgroundParentImpl.cpp", - # TODO move to UNIFIED_SOURCES when old shared memory impl is removed - "SharedMemoryCursor.cpp", - "SharedMemoryHandle.cpp", - "SharedMemoryMapping.cpp", ] if CONFIG["OS_ARCH"] == "Darwin": diff --git a/ipc/ipdl/ipdl/lower.py b/ipc/ipdl/ipdl/lower.py index 328b90a5f7bd..57f99e39c36c 100644 --- a/ipc/ipdl/ipdl/lower.py +++ b/ipc/ipdl/ipdl/lower.py @@ -3378,7 +3378,6 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor): Typedef(Type("IPC::Message"), "Message"), Typedef(Type("base::ProcessHandle"), "ProcessHandle"), Typedef(Type("mozilla::ipc::MessageChannel"), "MessageChannel"), - Typedef(Type("mozilla::ipc::SharedMemory"), "SharedMemory"), ] def visitTranslationUnit(self, tu): diff --git a/js/xpconnect/loader/IOBuffers.h b/js/xpconnect/loader/IOBuffers.h index e26b0c3bca82..281f554ffefb 100644 --- a/js/xpconnect/loader/IOBuffers.h +++ b/js/xpconnect/loader/IOBuffers.h @@ -66,12 +66,18 @@ class OutputBuffer { class InputBuffer { public: - explicit InputBuffer(const Range& buffer) : data(buffer) {} + explicit InputBuffer(const Range& buffer) : data(buffer) {} + + // Since the other constructor stores `buffer` by reference, we must ensure + // no implicit conversions occur (which would result in a reference to a + // temporary being stored). + template + explicit InputBuffer(T) = delete; const uint8_t* read(size_t size) { MOZ_ASSERT(checkCapacity(size)); - auto buf = &data[cursor_]; + const auto* buf = &data[cursor_]; cursor_ += size; return buf; } @@ -138,7 +144,7 @@ class InputBuffer { bool error_ = false; public: - const Range& data; + const Range& data; size_t cursor_ = 0; }; diff --git a/js/xpconnect/loader/ScriptPreloader.cpp b/js/xpconnect/loader/ScriptPreloader.cpp index fe167cb8f247..d2dd4c0b6207 100644 --- a/js/xpconnect/loader/ScriptPreloader.cpp +++ b/js/xpconnect/loader/ScriptPreloader.cpp @@ -558,7 +558,7 @@ Result ScriptPreloader::InitCacheInternal( LinkedList scripts; - Range header(data, data + headerSize); + Range header(data, data + headerSize); data += headerSize; // Reconstruct alignment padding if required. diff --git a/js/xpconnect/loader/URLPreloader.cpp b/js/xpconnect/loader/URLPreloader.cpp index 6721cd047113..967bd4c17b6d 100644 --- a/js/xpconnect/loader/URLPreloader.cpp +++ b/js/xpconnect/loader/URLPreloader.cpp @@ -313,7 +313,7 @@ Result URLPreloader::ReadCache( mCachedURLs.Clear(); }); - Range header(data, data + headerSize); + Range header(data, data + headerSize); data += headerSize; InputBuffer buf(header); diff --git a/js/xpconnect/src/XPCSelfHostedShmem.cpp b/js/xpconnect/src/XPCSelfHostedShmem.cpp index abd7ca5b0ef7..f0ab36899ee7 100644 --- a/js/xpconnect/src/XPCSelfHostedShmem.cpp +++ b/js/xpconnect/src/XPCSelfHostedShmem.cpp @@ -40,64 +40,45 @@ void xpc::SelfHostedShmem::Shutdown() { void xpc::SelfHostedShmem::InitFromParent(ContentType aXdr) { MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!mLen, "Shouldn't call this more than once"); + MOZ_ASSERT(!mHandle && !mMem, "Shouldn't call this more than once"); size_t len = aXdr.Length(); - auto shm = mozilla::MakeRefPtr(); - if (NS_WARN_IF(!shm->CreateFreezable(len))) { + auto handle = mozilla::ipc::shared_memory::CreateFreezable(len); + if (NS_WARN_IF(!handle)) { return; } - if (NS_WARN_IF(!shm->Map(len))) { + auto mapping = std::move(handle).Map(); + if (NS_WARN_IF(!mapping)) { return; } - void* address = shm->Memory(); + void* address = mapping.Address(); memcpy(address, aXdr.Elements(), aXdr.LengthBytes()); - RefPtr roCopy = - mozilla::MakeRefPtr(); - if (NS_WARN_IF(!shm->ReadOnlyCopy(&*roCopy))) { - return; - } - - mMem = std::move(shm); - mHandle = roCopy->TakeHandleAndUnmap(); - mLen = len; + std::tie(std::ignore, mHandle) = std::move(mapping).Freeze(); + mMem = mHandle.Map(); } bool xpc::SelfHostedShmem::InitFromChild( - mozilla::ipc::SharedMemoryHandle aHandle, size_t aLen) { + mozilla::ipc::ReadOnlySharedMemoryHandle aHandle) { MOZ_ASSERT(!XRE_IsParentProcess()); MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!mLen, "Shouldn't call this more than once"); + MOZ_ASSERT(!mMem, "Shouldn't call this more than once"); - auto shm = mozilla::MakeRefPtr(); - if (NS_WARN_IF(!shm->SetHandle(std::move(aHandle), - mozilla::ipc::SharedMemory::RightsReadOnly))) { - return false; - } - - if (NS_WARN_IF(!shm->Map(aLen))) { - return false; - } - - // Note: mHandle remains empty, as content processes are not spawning more - // content processes. - mMem = std::move(shm); - mLen = aLen; - return true; + mMem = aHandle.Map(); + return mMem.IsValid(); } xpc::SelfHostedShmem::ContentType xpc::SelfHostedShmem::Content() const { if (!mMem) { - MOZ_ASSERT(mLen == 0); return ContentType(); } - return ContentType(reinterpret_cast(mMem->Memory()), mLen); + return mMem.DataAsSpan(); } -const mozilla::ipc::SharedMemoryHandle& xpc::SelfHostedShmem::Handle() const { +const mozilla::ipc::ReadOnlySharedMemoryHandle& xpc::SelfHostedShmem::Handle() + const { return mHandle; } @@ -110,7 +91,7 @@ xpc::SelfHostedShmem::CollectReports(nsIHandleReportCallback* aHandleReport, // This does not exactly report the amount of data mapped by the system, // but the space requested when creating the handle. MOZ_COLLECT_REPORT("explicit/js-non-window/shared-memory/self-hosted-xdr", - KIND_NONHEAP, UNITS_BYTES, mLen, + KIND_NONHEAP, UNITS_BYTES, mMem.Size(), "Memory used to initialize the JS engine with the " "self-hosted code encoded by the parent process."); } diff --git a/js/xpconnect/src/XPCSelfHostedShmem.h b/js/xpconnect/src/XPCSelfHostedShmem.h index 01359f2e6184..35b8fc36ee86 100644 --- a/js/xpconnect/src/XPCSelfHostedShmem.h +++ b/js/xpconnect/src/XPCSelfHostedShmem.h @@ -12,7 +12,8 @@ #include "mozilla/RefPtr.h" #include "mozilla/Span.h" #include "mozilla/StaticPtr.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "nsIMemoryReporter.h" #include "nsIObserver.h" #include "nsIThread.h" @@ -48,14 +49,14 @@ class SelfHostedShmem final : public nsIMemoryReporter { // // This function is not thread-safe and should be call at most once and from // the main thread. - [[nodiscard]] bool InitFromChild(mozilla::ipc::SharedMemoryHandle aHandle, - size_t aLen); + [[nodiscard]] bool InitFromChild( + mozilla::ipc::ReadOnlySharedMemoryHandle aHandle); // Return a span over the read-only XDR content of the self-hosted stencil. ContentType Content() const; // Return the file handle which is under which the content is mapped. - const mozilla::ipc::SharedMemoryHandle& Handle() const; + const mozilla::ipc::ReadOnlySharedMemoryHandle& Handle() const; // Register this class to the memory reporter service. void InitMemoryReporter(); @@ -74,15 +75,9 @@ class SelfHostedShmem final : public nsIMemoryReporter { static mozilla::StaticRefPtr sSelfHostedXdr; - // read-only file Handle used to transfer from the parent process to content - // processes. - mozilla::ipc::SharedMemoryHandle mHandle; - - // Shared memory used by JS runtime initialization. - RefPtr mMem; - - // Length of the content within the shared memory. - size_t mLen = 0; + // Read-only shared memory used by JS runtime initialization. + mozilla::ipc::ReadOnlySharedMemoryHandle mHandle; + mozilla::ipc::ReadOnlySharedMemoryMapping mMem; }; } // namespace xpc diff --git a/layout/style/GlobalStyleSheetCache.cpp b/layout/style/GlobalStyleSheetCache.cpp index 13d65c2d3ed3..416b5972eb1f 100644 --- a/layout/style/GlobalStyleSheetCache.cpp +++ b/layout/style/GlobalStyleSheetCache.cpp @@ -17,7 +17,8 @@ #include "mozilla/css/Loader.h" #include "mozilla/dom/ReferrerInfo.h" #include "mozilla/dom/SRIMetadata.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "MainThreadUtils.h" #include "nsContentUtils.h" #include "nsIConsoleService.h" @@ -105,8 +106,8 @@ namespace mozilla { using namespace mozilla; using namespace css; -mozilla::ipc::SharedMemoryHandle& sSharedMemoryHandle() { - static NeverDestroyed handle; +mozilla::ipc::ReadOnlySharedMemoryHandle& sSharedMemoryHandle() { + static NeverDestroyed handle; return *handle; } @@ -265,7 +266,8 @@ GlobalStyleSheetCache::GlobalStyleSheetCache() { // non-shared sheets in the mFooSheet fields. In a content process, we'll // lazily load our own copies of the sheets later. if (!sSharedMemory.IsEmpty()) { - if (auto* header = reinterpret_cast(sSharedMemory.data())) { + if (const auto* header = + reinterpret_cast(sSharedMemory.data())) { MOZ_RELEASE_ASSERT(header->mMagic == Header::kMagic); #define STYLE_SHEET(identifier_, url_, shared_) \ @@ -282,7 +284,7 @@ GlobalStyleSheetCache::GlobalStyleSheetCache() { void GlobalStyleSheetCache::LoadSheetFromSharedMemory( const char* aURL, RefPtr* aSheet, SheetParsingMode aParsingMode, - Header* aHeader, UserAgentStyleSheetID aSheetID) { + const Header* aHeader, UserAgentStyleSheetID aSheetID) { auto i = size_t(aSheetID); auto sheet = @@ -307,8 +309,8 @@ void GlobalStyleSheetCache::InitSharedSheetsInParent() { MOZ_ASSERT(XRE_IsParentProcess()); MOZ_RELEASE_ASSERT(sSharedMemory.IsEmpty()); - auto shm = MakeRefPtr(); - if (NS_WARN_IF(!shm->CreateFreezable(kSharedMemorySize))) { + auto handle = ipc::shared_memory::CreateFreezable(kSharedMemorySize); + if (NS_WARN_IF(!handle)) { return; } @@ -340,19 +342,22 @@ void GlobalStyleSheetCache::InitSharedSheetsInParent() { #endif void* address = nullptr; - if (void* p = ipc::SharedMemory::FindFreeAddressSpace(2 * kOffset)) { + if (void* p = ipc::shared_memory::FindFreeAddressSpace(2 * kOffset)) { address = reinterpret_cast(uintptr_t(p) + kOffset); } - if (!shm->Map(kSharedMemorySize, address)) { + auto mapping = std::move(handle).Map(address); + if (!mapping) { // Failed to map at the address we computed for some reason. Fall back // to just allocating at a location of the OS's choosing, and hope that // it works in the content process. - if (NS_WARN_IF(!shm->Map(kSharedMemorySize))) { + auto handle = std::move(mapping).Unmap(); + mapping = std::move(handle).Map(); + if (NS_WARN_IF(!mapping)) { return; } } - address = shm->Memory(); + address = mapping.Address(); auto* header = static_cast(address); header->mMagic = Header::kMagic; @@ -388,16 +393,12 @@ void GlobalStyleSheetCache::InitSharedSheetsInParent() { // Finished writing into the shared memory. Freeze it, so that a process // can't confuse other processes by changing the UA style sheet contents. - if (NS_WARN_IF(!shm->Freeze())) { + auto [_, readOnlyHandle] = std::move(mapping).Freeze(); + if (NS_WARN_IF(!readOnlyHandle)) { return; } - // The Freeze() call unmaps the shared memory. Re-map it again as read only. - // If this fails, due to something else being mapped into the same place - // between the Freeze() and Map() call, we can just fall back to keeping our - // own copy of the UA style sheets in the parent, and still try sending the - // shared memory to the content processes. - shm->Map(kSharedMemorySize, address); + auto roMapping = readOnlyHandle.Map(address); // Record how must of the shared memory we have used, for memory reporting // later. We round up to the nearest page since the free space at the end @@ -406,13 +407,13 @@ void GlobalStyleSheetCache::InitSharedSheetsInParent() { // TODO(heycam): This won't be true on Windows unless we allow creating the // shared memory with SEC_RESERVE so that the pages are reserved but not // committed. - size_t pageSize = ipc::SharedMemory::SystemPageSize(); + size_t pageSize = ipc::shared_memory::SystemPageSize(); sUsedSharedMemory = (Servo_SharedMemoryBuilder_GetLength(builder.get()) + pageSize - 1) & ~(pageSize - 1); - sSharedMemory = shm->TakeMapping(); - sSharedMemoryHandle() = shm->TakeHandle(); + sSharedMemory = std::move(roMapping).Release(); + sSharedMemoryHandle() = std::move(readOnlyHandle); } GlobalStyleSheetCache::~GlobalStyleSheetCache() { @@ -539,26 +540,24 @@ RefPtr GlobalStyleSheetCache::LoadSheet( } /* static */ void GlobalStyleSheetCache::SetSharedMemory( - ipc::SharedMemory::Handle aHandle, uintptr_t aAddress) { + ipc::ReadOnlySharedMemoryHandle aHandle, uintptr_t aAddress) { MOZ_ASSERT(!XRE_IsParentProcess()); MOZ_ASSERT(!gStyleCache, "Too late, GlobalStyleSheetCache already created!"); MOZ_ASSERT(sSharedMemory.IsEmpty(), "Shouldn't call this more than once"); - auto shm = MakeRefPtr(); - if (!shm->SetHandle(std::move(aHandle), ipc::SharedMemory::RightsReadOnly)) { + auto mapping = aHandle.Map(reinterpret_cast(aAddress)); + if (!mapping) { return; } - if (shm->Map(kSharedMemorySize, reinterpret_cast(aAddress))) { - sSharedMemory = shm->TakeMapping(); - sSharedMemoryHandle() = shm->TakeHandle(); - } + sSharedMemory = std::move(mapping).Release(); + sSharedMemoryHandle() = std::move(aHandle); } -ipc::SharedMemoryHandle GlobalStyleSheetCache::CloneHandle() { +ipc::ReadOnlySharedMemoryHandle GlobalStyleSheetCache::CloneHandle() { MOZ_ASSERT(XRE_IsParentProcess()); - if (ipc::SharedMemory::IsHandleValid(sSharedMemoryHandle())) { - return ipc::SharedMemory::CloneHandle(sSharedMemoryHandle()); + if (sSharedMemoryHandle().IsValid()) { + return sSharedMemoryHandle().Clone(); } return nullptr; } @@ -567,7 +566,7 @@ StaticRefPtr GlobalStyleSheetCache::gStyleCache; StaticRefPtr GlobalStyleSheetCache::gCSSLoader; StaticRefPtr GlobalStyleSheetCache::gUserContentSheetURL; -Span GlobalStyleSheetCache::sSharedMemory; +ipc::shared_memory::LeakedReadOnlyMapping GlobalStyleSheetCache::sSharedMemory; size_t GlobalStyleSheetCache::sUsedSharedMemory; } // namespace mozilla diff --git a/layout/style/GlobalStyleSheetCache.h b/layout/style/GlobalStyleSheetCache.h index e4a75a8e8867..aff88d480f35 100644 --- a/layout/style/GlobalStyleSheetCache.h +++ b/layout/style/GlobalStyleSheetCache.h @@ -16,7 +16,8 @@ #include "mozilla/StaticPtr.h" #include "mozilla/UserAgentStyleSheetID.h" #include "mozilla/css/Loader.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" +#include "mozilla/ipc/SharedMemoryMapping.h" class nsIFile; class nsIURI; @@ -60,13 +61,13 @@ class GlobalStyleSheetCache final : public nsIObserver, // Called early on in a content process' life from // ContentChild::InitSharedUASheets, before the GlobalStyleSheetCache // singleton has been created. - static void SetSharedMemory(mozilla::ipc::SharedMemory::Handle aHandle, + static void SetSharedMemory(mozilla::ipc::ReadOnlySharedMemoryHandle aHandle, uintptr_t aAddress); // Obtain a shared memory handle for the shared UA sheets to pass into a // content process. Called by ContentParent::InitInternal shortly after // a content process has been created. - mozilla::ipc::SharedMemoryHandle CloneHandle(); + mozilla::ipc::ReadOnlySharedMemoryHandle CloneHandle(); // Returns the address of the shared memory segment that holds the shared UA // sheets. @@ -104,7 +105,7 @@ class GlobalStyleSheetCache final : public nsIObserver, RefPtr LoadSheet(nsIURI* aURI, css::SheetParsingMode aParsingMode, css::FailureAction aFailureAction); void LoadSheetFromSharedMemory(const char* aURL, RefPtr* aSheet, - css::SheetParsingMode, Header*, + css::SheetParsingMode, const Header*, UserAgentStyleSheetID); static StaticRefPtr gStyleCache; @@ -120,7 +121,7 @@ class GlobalStyleSheetCache final : public nsIObserver, RefPtr mUserContentSheet; // Shared memory segment storing shared style sheets. - static Span sSharedMemory; + static mozilla::ipc::shared_memory::LeakedReadOnlyMapping sSharedMemory; // How much of the shared memory buffer we ended up using. Used for memory // reporting in the parent process. diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp index 3c00aa8f1b59..1d15f82453c7 100644 --- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -176,9 +176,9 @@ static void SerializeAndAppendString(const nsCString& aChars, nsCString& aStr) { aStr.Append(aChars); } -static char* DeserializeString(char* aChars, nsCString& aStr) { - char* p = aChars; - uint32_t length = strtol(p, &p, 10); +static const char* DeserializeString(const char* aChars, nsCString& aStr) { + const char* p = aChars; + uint32_t length = strtol(p, const_cast(&p), 10); MOZ_ASSERT(p[0] == '/'); p++; // move past the '/' aStr.Assign(p, length); @@ -332,9 +332,9 @@ union PrefValue { } } - static char* Deserialize(PrefType aType, char* aStr, - Maybe* aDomValue) { - char* p = aStr; + static const char* Deserialize(PrefType aType, const char* aStr, + Maybe* aDomValue) { + const char* p = aStr; switch (aType) { case PrefType::Bool: @@ -350,7 +350,7 @@ union PrefValue { return p; case PrefType::Int: { - *aDomValue = Some(int32_t(strtol(p, &p, 10))); + *aDomValue = Some(int32_t(strtol(p, const_cast(&p), 10))); return p; } @@ -981,8 +981,8 @@ class Pref { aStr.Append('\n'); } - static char* Deserialize(char* aStr, dom::Pref* aDomPref) { - char* p = aStr; + static const char* Deserialize(const char* aStr, dom::Pref* aDomPref) { + const char* p = aStr; // The type. PrefType type; @@ -3796,13 +3796,13 @@ void Preferences::SerializePreferences(nsCString& aStr, } /* static */ -void Preferences::DeserializePreferences(char* aStr, size_t aPrefsLen) { +void Preferences::DeserializePreferences(const char* aStr, size_t aPrefsLen) { MOZ_ASSERT(!XRE_IsParentProcess()); MOZ_ASSERT(!gChangedDomPrefs); gChangedDomPrefs = new nsTArray(); - char* p = aStr; + const char* p = aStr; while (*p != '\0') { dom::Pref pref; p = Pref::Deserialize(p, &pref); @@ -3818,7 +3818,7 @@ void Preferences::DeserializePreferences(char* aStr, size_t aPrefsLen) { } /* static */ -mozilla::ipc::SharedMemoryHandle Preferences::EnsureSnapshot(size_t* aSize) { +mozilla::ipc::ReadOnlySharedMemoryHandle Preferences::EnsureSnapshot() { MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(NS_IsMainThread()); @@ -3867,17 +3867,16 @@ mozilla::ipc::SharedMemoryHandle Preferences::EnsureSnapshot(size_t* aSize) { } } - *aSize = gSharedMap->MapSize(); return gSharedMap->CloneHandle(); } /* static */ -void Preferences::InitSnapshot(const mozilla::ipc::SharedMemoryHandle& aHandle, - size_t aSize) { +void Preferences::InitSnapshot( + const mozilla::ipc::ReadOnlySharedMemoryHandle& aHandle) { MOZ_ASSERT(!XRE_IsParentProcess()); MOZ_ASSERT(!gSharedMap); - gSharedMap = new SharedPrefMap(aHandle, aSize); + gSharedMap = new SharedPrefMap(aHandle); StaticPrefs::InitStaticPrefsFromShared(); } diff --git a/modules/libpref/Preferences.h b/modules/libpref/Preferences.h index d789aecc9b5b..d52619abf7c2 100644 --- a/modules/libpref/Preferences.h +++ b/modules/libpref/Preferences.h @@ -17,7 +17,7 @@ #include "mozilla/MemoryReporting.h" #include "mozilla/MozPromise.h" #include "mozilla/StaticPtr.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" #include "nsCOMPtr.h" #include "nsIObserver.h" #include "nsIPrefBranch.h" @@ -408,13 +408,10 @@ class Preferences final : public nsIPrefService, // prefs in bulk from the parent process, via shared memory. static void SerializePreferences(nsCString& aStr, bool aIsDestinationWebContentProcess); - static void DeserializePreferences(char* aStr, size_t aPrefsLen); + static void DeserializePreferences(const char* aStr, size_t aPrefsLen); -#ifndef RUST_BINDGEN - static mozilla::ipc::SharedMemoryHandle EnsureSnapshot(size_t* aSize); - static void InitSnapshot(const mozilla::ipc::SharedMemoryHandle&, - size_t aSize); -#endif + static mozilla::ipc::ReadOnlySharedMemoryHandle EnsureSnapshot(); + static void InitSnapshot(const mozilla::ipc::ReadOnlySharedMemoryHandle&); // When a single pref is changed in the parent process, these methods are // used to pass the update to content processes. diff --git a/modules/libpref/SharedPrefMap.cpp b/modules/libpref/SharedPrefMap.cpp index 8119018efb93..72a19dd54b04 100644 --- a/modules/libpref/SharedPrefMap.cpp +++ b/modules/libpref/SharedPrefMap.cpp @@ -22,38 +22,31 @@ static inline size_t GetAlignmentOffset(size_t aOffset, size_t aAlign) { return mod ? aAlign - mod : 0; } -SharedPrefMap::SharedPrefMap(const SharedMemoryHandle& aMapHandle, - size_t aMapSize) { - auto map = MakeRefPtr(); - { - auto result = map->SetHandle(SharedMemory::CloneHandle(aMapHandle), - SharedMemory::OpenRights::RightsReadOnly); - MOZ_RELEASE_ASSERT(result); - } - { - auto result = map->Map(aMapSize); - MOZ_RELEASE_ASSERT(result); - } +SharedPrefMap::SharedPrefMap(const ReadOnlySharedMemoryHandle& aMapHandle) { + auto map = aMapHandle.Map(); + MOZ_RELEASE_ASSERT(map); + mHandle = aMapHandle.Clone(); // We return literal nsCStrings pointing to the mapped data for preference // names and string values, 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 mapping alive until process shutdown, in order to be safe. - mMappedMemory = map->TakeMapping(); - mHandle = map->TakeHandle(); + mMappedMemory = std::move(map).Release(); } SharedPrefMap::SharedPrefMap(SharedPrefMapBuilder&& aBuilder) { - RefPtr map; - auto result = aBuilder.Finalize(map); - MOZ_RELEASE_ASSERT(result.isOk() && map); - - mMappedMemory = map->TakeMapping(); - mHandle = map->TakeHandle(); + ReadOnlySharedMemoryMappingWithHandle mapWithHandle; + auto result = aBuilder.Finalize(); + MOZ_RELEASE_ASSERT(result.isOk()); + mHandle = result.unwrap(); + auto map = mHandle.Map(); + MOZ_RELEASE_ASSERT(map.IsValid()); + mMappedMemory = std::move(map).Release(); } -mozilla::ipc::SharedMemoryHandle SharedPrefMap::CloneHandle() const { - return SharedMemory::CloneHandle(mHandle); +mozilla::ipc::ReadOnlySharedMemoryHandle SharedPrefMap::CloneHandle() const { + MOZ_ASSERT(XRE_IsParentProcess()); + return mHandle.Clone(); } bool SharedPrefMap::Has(const char* aKey) const { @@ -148,8 +141,7 @@ void SharedPrefMapBuilder::Add(const nsCString& aKey, const Flags& aFlags, }); } -Result SharedPrefMapBuilder::Finalize( - RefPtr& aMap) { +Result SharedPrefMapBuilder::Finalize() { using Header = SharedPrefMap::Header; // Create an array of entry pointers for the entry array, and sort it by @@ -244,7 +236,7 @@ Result SharedPrefMapBuilder::Finalize( mStringValueTable.Clear(); mEntries.Clear(); - return mem.Finalize(aMap); + return mem.Finalize(); } } // namespace mozilla diff --git a/modules/libpref/SharedPrefMap.h b/modules/libpref/SharedPrefMap.h index ad99d331df23..cecf88d44746 100644 --- a/modules/libpref/SharedPrefMap.h +++ b/modules/libpref/SharedPrefMap.h @@ -11,7 +11,8 @@ #include "mozilla/Preferences.h" #include "mozilla/Result.h" #include "mozilla/dom/ipc/StringTable.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "nsTHashMap.h" namespace mozilla { @@ -419,7 +420,7 @@ class SharedPrefMap { // Note: These constructors are infallible, because the preference database is // critical to platform functionality, and we cannot operate without it. - SharedPrefMap(const mozilla::ipc::SharedMemoryHandle&, size_t); + explicit SharedPrefMap(const mozilla::ipc::ReadOnlySharedMemoryHandle&); explicit SharedPrefMap(SharedPrefMapBuilder&&); // Searches for the given preference in the map, and returns true if it @@ -502,7 +503,7 @@ class SharedPrefMap { // memory region for this map. The handle may be passed between processes, and // used to construct new instances of SharedPrefMap with the same data as this // instance. - mozilla::ipc::SharedMemoryHandle CloneHandle() const; + mozilla::ipc::ReadOnlySharedMemoryHandle CloneHandle() const; // Returns the size of the mapped memory region. This size must be passed to // the constructor when mapping the shared region in another process. @@ -528,8 +529,8 @@ class SharedPrefMap { template RangedPtr GetBlock(const DataBlock& aBlock) const { - return RangedPtr(&mMappedMemory.data()[aBlock.mOffset], - aBlock.mSize) + return RangedPtr(&mMappedMemory.data()[aBlock.mOffset], + aBlock.mSize) .ReinterpretCast(); } @@ -549,19 +550,19 @@ class SharedPrefMap { StringTable KeyTable() const { auto& block = GetHeader().mKeyStrings; - return {{&mMappedMemory.data()[block.mOffset], block.mSize}}; + return {{(uint8_t*)&mMappedMemory.data()[block.mOffset], block.mSize}}; } StringTable ValueTable() const { auto& block = GetHeader().mValueStrings; - return {{&mMappedMemory.data()[block.mOffset], block.mSize}}; + return {{(uint8_t*)&mMappedMemory.data()[block.mOffset], block.mSize}}; } - mozilla::ipc::SharedMemoryHandle mHandle; + mozilla::ipc::ReadOnlySharedMemoryHandle mHandle; // This is a leaked shared memory mapping (see the constructor definition for // an explanation). It replaces AutoMemMap::setPersistent behavior as part of // bug 1454816. - Span mMappedMemory; + mozilla::ipc::shared_memory::LeakedReadOnlyMapping mMappedMemory; }; // A helper class which builds the contiguous look-up table used by @@ -591,13 +592,13 @@ class MOZ_RAII SharedPrefMapBuilder { const nsCString& aDefaultValue, const nsCString& aUserValue); // Finalizes the binary representation of the map, writes it to a shared - // memory region, and then initializes the given SharedMemory with a reference - // to the read-only copy of it. + // memory region, and then initializes the given ReadOnlySharedMemoryMapping + // with a reference to the read-only copy of it. // // This should generally not be used directly by callers. The // SharedPrefMapBuilder instance should instead be passed to the SharedPrefMap // constructor as a move reference. - Result Finalize(RefPtr& aMap); + Result Finalize(); private: using StringTableEntry = mozilla::dom::ipc::StringTableEntry; diff --git a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp index 4eff5e671189..4777e1d26dbb 100644 --- a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp +++ b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp @@ -18,7 +18,7 @@ #include "mozilla/StaticMutex.h" #include "mozilla/UniquePtr.h" #include "mozilla/UniquePtrExtensions.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" #include "nsComponentManagerUtils.h" #include "nsPrintfCString.h" #include "nsString.h" @@ -320,7 +320,7 @@ static void AddLdLibraryEnvPaths(SandboxBroker::Policy* aPolicy) { static void AddSharedMemoryPaths(SandboxBroker::Policy* aPolicy, pid_t aPid) { std::string shmPath("/dev/shm"); - if (ipc::SharedMemory::AppendPosixShmPrefix(&shmPath, aPid)) { + if (ipc::shared_memory::AppendPosixShmPrefix(&shmPath, aPid)) { aPolicy->AddPrefix(rdwrcr, shmPath.c_str()); } } diff --git a/startupcache/StartupCache.cpp b/startupcache/StartupCache.cpp index 12a902152a31..38fc6152a428 100644 --- a/startupcache/StartupCache.cpp +++ b/startupcache/StartupCache.cpp @@ -294,7 +294,7 @@ Result StartupCache::LoadArchive() { return Err(NS_ERROR_UNEXPECTED); } - Range header(data, data + headerSize); + Range header(data, data + headerSize); data += headerSize; mCacheEntriesBaseOffset = sizeof(MAGIC) + sizeof(headerSize) + headerSize; diff --git a/toolkit/xre/GeckoArgs.h b/toolkit/xre/GeckoArgs.h index dfcd2c44464c..abadf8bfcec4 100644 --- a/toolkit/xre/GeckoArgs.h +++ b/toolkit/xre/GeckoArgs.h @@ -210,15 +210,12 @@ static CommandLineArg sProfile{"-profile", "profile"}; static CommandLineArg sIPCHandle{"-ipcHandle", "ipchandle"}; -static CommandLineArg sJsInitHandle{ +static CommandLineArg sJsInitHandle{ "-jsInitHandle", "jsinithandle"}; -static CommandLineArg sJsInitLen{"-jsInitLen", "jsinitlen"}; -static CommandLineArg sPrefsHandle{ +static CommandLineArg sPrefsHandle{ "-prefsHandle", "prefshandle"}; -static CommandLineArg sPrefsLen{"-prefsLen", "prefslen"}; -static CommandLineArg sPrefMapHandle{ +static CommandLineArg sPrefMapHandle{ "-prefMapHandle", "prefmaphandle"}; -static CommandLineArg sPrefMapSize{"-prefMapSize", "prefmapsize"}; static CommandLineArg sSandboxingKind{"-sandboxingKind", "sandboxingkind"}; diff --git a/widget/gtk/WaylandBuffer.cpp b/widget/gtk/WaylandBuffer.cpp index 3fa9c27cf7f4..7d42afae1fd4 100644 --- a/widget/gtk/WaylandBuffer.cpp +++ b/widget/gtk/WaylandBuffer.cpp @@ -16,6 +16,7 @@ #include "gfxPlatform.h" #include "mozilla/WidgetUtilsGtk.h" #include "mozilla/gfx/Tools.h" +#include "mozilla/ipc/SharedMemoryHandle.h" #include "nsGtkUtils.h" #include "nsPrintfCString.h" #include "prenv.h" // For PR_GetEnv @@ -54,15 +55,16 @@ RefPtr WaylandShmPool::Create(nsWaylandDisplay* aWaylandDisplay, RefPtr shmPool = new WaylandShmPool(); - shmPool->mShm = MakeRefPtr(); - if (!shmPool->mShm->Create(aSize)) { + auto handle = ipc::shared_memory::Create(aSize); + if (!handle) { NS_WARNING("WaylandShmPool: Unable to allocate shared memory!"); return nullptr; } - shmPool->mSize = aSize; - shmPool->mShmPool = wl_shm_create_pool( - aWaylandDisplay->GetShm(), shmPool->mShm->CloneHandle().get(), aSize); + shmPool->mShmHandle = handle.Clone(); + shmPool->mShmPool = + wl_shm_create_pool(aWaylandDisplay->GetShm(), + handle.Clone().TakePlatformHandle().get(), aSize); if (!shmPool->mShmPool) { NS_WARNING("WaylandShmPool: Unable to allocate shared memory pool!"); return nullptr; @@ -72,15 +74,14 @@ RefPtr WaylandShmPool::Create(nsWaylandDisplay* aWaylandDisplay, } void* WaylandShmPool::GetImageData() { - if (mImageData) { - return mImageData; + if (!mShm) { + mShm = mShmHandle.Map(); + if (!mShm) { + NS_WARNING("WaylandShmPool: Failed to map Shm!"); + return nullptr; + } } - if (!mShm->Map(mSize)) { - NS_WARNING("WaylandShmPool: Failed to map Shm!"); - return nullptr; - } - mImageData = mShm->Memory(); - return mImageData; + return mShm.Address(); } WaylandShmPool::~WaylandShmPool() { diff --git a/widget/gtk/WaylandBuffer.h b/widget/gtk/WaylandBuffer.h index 1a349b6fd7ab..0f7293f3d716 100644 --- a/widget/gtk/WaylandBuffer.h +++ b/widget/gtk/WaylandBuffer.h @@ -10,7 +10,8 @@ #include "DMABufSurface.h" #include "GLContext.h" #include "MozFramebuffer.h" -#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/ipc/SharedMemoryHandle.h" +#include "mozilla/ipc/SharedMemoryMapping.h" #include "mozilla/gfx/2D.h" #include "mozilla/gfx/Types.h" #include "mozilla/Mutex.h" @@ -37,9 +38,8 @@ class WaylandShmPool { ~WaylandShmPool(); wl_shm_pool* mShmPool = nullptr; - void* mImageData = nullptr; - RefPtr mShm; - int mSize = 0; + ipc::MutableSharedMemoryHandle mShmHandle; + ipc::SharedMemoryMapping mShm; }; class WaylandBuffer { diff --git a/widget/gtk/nsShmImage.cpp b/widget/gtk/nsShmImage.cpp index 7208b7075f11..8ec10abc5cdb 100644 --- a/widget/gtk/nsShmImage.cpp +++ b/widget/gtk/nsShmImage.cpp @@ -9,7 +9,7 @@ #ifdef MOZ_HAVE_SHMIMAGE # include "mozilla/X11Util.h" # include "mozilla/gfx/gfxVars.h" -# include "mozilla/ipc/SharedMemory.h" +# include "mozilla/ipc/SharedMemoryMapping.h" # include "gfxPlatform.h" # include "nsPrintfCString.h" # include "nsTArray.h" @@ -54,7 +54,7 @@ static bool gShmAvailable = true; bool nsShmImage::UseShm() { return gShmAvailable; } bool nsShmImage::CreateShmSegment() { - size_t size = SharedMemory::PageAlignedSize(mStride * mSize.height); + size_t size = shared_memory::PageAlignedSize(mStride * mSize.height); # if defined(__OpenBSD__) && defined(MOZ_SANDBOX) static mozilla::LazyLogModule sPledgeLog("SandboxPledge");