Bug 1942129 pt4 - Convert old shmem call sites to use the new shmem classes r=ipc-reviewers,media-playback-reviewers,padenot,lsalzman,aosmond,nika
While much of this is simply converting code (and removing extraneous
`size` parameters), toolkit/xre/GeckoArgs.{h,cpp} has some significant
changes to support sending read-only handles (which is all we need!).
Differential Revision: https://phabricator.services.mozilla.com/D236750
This commit is contained in:
@@ -220,7 +220,6 @@
|
|||||||
#include "mozilla/gfx/Rect.h"
|
#include "mozilla/gfx/Rect.h"
|
||||||
#include "mozilla/gfx/Types.h"
|
#include "mozilla/gfx/Types.h"
|
||||||
#include "mozilla/ipc/ProtocolUtils.h"
|
#include "mozilla/ipc/ProtocolUtils.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
|
||||||
#include "mozilla/net/UrlClassifierCommon.h"
|
#include "mozilla/net/UrlClassifierCommon.h"
|
||||||
#include "mozilla/Tokenizer.h"
|
#include "mozilla/Tokenizer.h"
|
||||||
#include "mozilla/widget/IMEData.h"
|
#include "mozilla/widget/IMEData.h"
|
||||||
|
|||||||
@@ -443,25 +443,28 @@ bool DrawTargetWebgl::Init(const IntSize& size, const SurfaceFormat format,
|
|||||||
return false;
|
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)) {
|
if (NS_WARN_IF(shmemSize > UINT32_MAX)) {
|
||||||
MOZ_ASSERT_UNREACHABLE("Buffer too big?");
|
MOZ_ASSERT_UNREACHABLE("Buffer too big?");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto shmem = MakeRefPtr<mozilla::ipc::SharedMemory>();
|
auto handle = mozilla::ipc::shared_memory::Create(shmemSize);
|
||||||
if (NS_WARN_IF(!shmem->Create(shmemSize)) ||
|
if (NS_WARN_IF(!handle)) {
|
||||||
NS_WARN_IF(!shmem->Map(shmemSize))) {
|
return false;
|
||||||
|
}
|
||||||
|
auto mapping = handle.Map();
|
||||||
|
if (NS_WARN_IF(!mapping)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mShmem = std::move(shmem);
|
mShmemHandle = std::move(handle).ToReadOnly();
|
||||||
mShmemSize = shmemSize;
|
mShmem = std::move(mapping);
|
||||||
|
|
||||||
mSkia = new DrawTargetSkia;
|
mSkia = new DrawTargetSkia;
|
||||||
auto stride = layers::ImageDataSerializer::ComputeRGBStride(
|
auto stride = layers::ImageDataSerializer::ComputeRGBStride(
|
||||||
SurfaceFormat::B8G8R8A8, size.width);
|
SurfaceFormat::B8G8R8A8, size.width);
|
||||||
if (!mSkia->Init(reinterpret_cast<uint8_t*>(mShmem->Memory()), size, stride,
|
if (!mSkia->Init(mShmem.DataAs<uint8_t>(), size, stride,
|
||||||
SurfaceFormat::B8G8R8A8, true)) {
|
SurfaceFormat::B8G8R8A8, true)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
#include "mozilla/LinkedList.h"
|
#include "mozilla/LinkedList.h"
|
||||||
#include "mozilla/WeakPtr.h"
|
#include "mozilla/WeakPtr.h"
|
||||||
#include "mozilla/ThreadLocal.h"
|
#include "mozilla/ThreadLocal.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
#include "mozilla/layers/LayersTypes.h"
|
#include "mozilla/layers/LayersTypes.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -381,12 +382,13 @@ class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr {
|
|||||||
RefPtr<DrawTargetSkia> mSkia;
|
RefPtr<DrawTargetSkia> mSkia;
|
||||||
// Skia DT pointing to the same pixel data, but without any applied clips.
|
// Skia DT pointing to the same pixel data, but without any applied clips.
|
||||||
RefPtr<DrawTargetSkia> mSkiaNoClip;
|
RefPtr<DrawTargetSkia> mSkiaNoClip;
|
||||||
|
// A Shmem read-only handle to the same memory as mShmem, to be consumed by
|
||||||
|
// TakeShmemHandle().
|
||||||
|
mozilla::ipc::ReadOnlySharedMemoryHandle mShmemHandle;
|
||||||
// The Shmem backing the Skia DT, if applicable.
|
// The Shmem backing the Skia DT, if applicable.
|
||||||
RefPtr<mozilla::ipc::SharedMemory> mShmem;
|
mozilla::ipc::SharedMemoryMapping mShmem;
|
||||||
// The currently cached snapshot of the WebGL context
|
// The currently cached snapshot of the WebGL context
|
||||||
RefPtr<SourceSurfaceWebgl> mSnapshot;
|
RefPtr<SourceSurfaceWebgl> mSnapshot;
|
||||||
// The mappable size of mShmem.
|
|
||||||
uint32_t mShmemSize = 0;
|
|
||||||
// Whether the framebuffer is still in the initially clear state.
|
// Whether the framebuffer is still in the initially clear state.
|
||||||
bool mIsClear = true;
|
bool mIsClear = true;
|
||||||
// Whether or not the Skia target has valid contents and is being drawn to
|
// Whether or not the Skia target has valid contents and is being drawn to
|
||||||
@@ -605,13 +607,10 @@ class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr {
|
|||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::SharedMemory::Handle TakeShmemHandle() const {
|
mozilla::ipc::ReadOnlySharedMemoryHandle TakeShmemHandle() {
|
||||||
return mShmem ? mShmem->TakeHandle()
|
return std::move(mShmemHandle);
|
||||||
: mozilla::ipc::SharedMemory::NULLHandle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t GetShmemSize() const { return mShmemSize; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool SupportsPattern(const Pattern& aPattern) {
|
bool SupportsPattern(const Pattern& aPattern) {
|
||||||
return mSharedContext->SupportsPattern(aPattern);
|
return mSharedContext->SupportsPattern(aPattern);
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include "mozilla/IntegerRange.h"
|
#include "mozilla/IntegerRange.h"
|
||||||
#include "mozilla/ipc/ProtocolUtils.h"
|
#include "mozilla/ipc/ProtocolUtils.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
|
||||||
#include "mozilla/Logging.h"
|
#include "mozilla/Logging.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "nsExceptionHandler.h"
|
#include "nsExceptionHandler.h"
|
||||||
|
|||||||
@@ -41,7 +41,6 @@
|
|||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
|
||||||
|
|
||||||
// Manual reflection of WebIDL typedefs that are different from their
|
// Manual reflection of WebIDL typedefs that are different from their
|
||||||
// OpenGL counterparts.
|
// OpenGL counterparts.
|
||||||
|
|||||||
@@ -652,9 +652,9 @@ NS_INTERFACE_MAP_END
|
|||||||
mozilla::ipc::IPCResult ContentChild::RecvSetXPCOMProcessAttributes(
|
mozilla::ipc::IPCResult ContentChild::RecvSetXPCOMProcessAttributes(
|
||||||
XPCOMInitData&& aXPCOMInit, const StructuredCloneData& aInitialData,
|
XPCOMInitData&& aXPCOMInit, const StructuredCloneData& aInitialData,
|
||||||
FullLookAndFeel&& aLookAndFeelData, dom::SystemFontList&& aFontList,
|
FullLookAndFeel&& aLookAndFeelData, dom::SystemFontList&& aFontList,
|
||||||
Maybe<SharedMemoryHandle>&& aSharedUASheetHandle,
|
Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aSharedUASheetHandle,
|
||||||
const uintptr_t& aSharedUASheetAddress,
|
const uintptr_t& aSharedUASheetAddress,
|
||||||
nsTArray<SharedMemoryHandle>&& aSharedFontListBlocks,
|
nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aSharedFontListBlocks,
|
||||||
const bool& aIsReadyForBackgroundProcessing) {
|
const bool& aIsReadyForBackgroundProcessing) {
|
||||||
if (!sShutdownCanary) {
|
if (!sShutdownCanary) {
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
@@ -1332,8 +1332,9 @@ void ContentChild::InitGraphicsDeviceData(const ContentDeviceData& aData) {
|
|||||||
gfxPlatform::InitChild(aData);
|
gfxPlatform::InitChild(aData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentChild::InitSharedUASheets(Maybe<SharedMemoryHandle>&& aHandle,
|
void ContentChild::InitSharedUASheets(
|
||||||
uintptr_t aAddress) {
|
Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aHandle,
|
||||||
|
uintptr_t aAddress) {
|
||||||
MOZ_ASSERT_IF(!aHandle, !aAddress);
|
MOZ_ASSERT_IF(!aHandle, !aAddress);
|
||||||
|
|
||||||
if (!aAddress) {
|
if (!aAddress) {
|
||||||
@@ -2349,7 +2350,7 @@ mozilla::ipc::IPCResult ContentChild::RecvRegisterStringBundles(
|
|||||||
|
|
||||||
for (auto& descriptor : aDescriptors) {
|
for (auto& descriptor : aDescriptors) {
|
||||||
stringBundleService->RegisterContentBundle(
|
stringBundleService->RegisterContentBundle(
|
||||||
descriptor.bundleURL(), descriptor.mapHandle(), descriptor.mapSize());
|
descriptor.bundleURL(), std::move(descriptor.mapHandle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
@@ -2369,7 +2370,7 @@ mozilla::ipc::IPCResult ContentChild::RecvUpdateL10nFileSources(
|
|||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult ContentChild::RecvUpdateSharedData(
|
mozilla::ipc::IPCResult ContentChild::RecvUpdateSharedData(
|
||||||
SharedMemoryHandle&& aMapHandle, const uint32_t& aMapSize,
|
mozilla::ipc::ReadOnlySharedMemoryHandle&& aMapHandle,
|
||||||
nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys) {
|
nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys) {
|
||||||
nsTArray<RefPtr<BlobImpl>> blobImpls(aBlobs.Length());
|
nsTArray<RefPtr<BlobImpl>> blobImpls(aBlobs.Length());
|
||||||
for (auto& ipcBlob : aBlobs) {
|
for (auto& ipcBlob : aBlobs) {
|
||||||
@@ -2377,12 +2378,12 @@ mozilla::ipc::IPCResult ContentChild::RecvUpdateSharedData(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mSharedData) {
|
if (mSharedData) {
|
||||||
mSharedData->Update(std::move(aMapHandle), aMapSize, std::move(blobImpls),
|
mSharedData->Update(std::move(aMapHandle), std::move(blobImpls),
|
||||||
std::move(aChangedKeys));
|
std::move(aChangedKeys));
|
||||||
} else {
|
} else {
|
||||||
mSharedData =
|
mSharedData =
|
||||||
new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(),
|
new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(),
|
||||||
std::move(aMapHandle), aMapSize, std::move(blobImpls));
|
std::move(aMapHandle), std::move(blobImpls));
|
||||||
}
|
}
|
||||||
|
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
@@ -2443,7 +2444,7 @@ mozilla::ipc::IPCResult ContentChild::RecvRebuildFontList(
|
|||||||
|
|
||||||
mozilla::ipc::IPCResult ContentChild::RecvFontListShmBlockAdded(
|
mozilla::ipc::IPCResult ContentChild::RecvFontListShmBlockAdded(
|
||||||
const uint32_t& aGeneration, const uint32_t& aIndex,
|
const uint32_t& aGeneration, const uint32_t& aIndex,
|
||||||
SharedMemoryHandle&& aHandle) {
|
mozilla::ipc::ReadOnlySharedMemoryHandle&& aHandle) {
|
||||||
if (gfxPlatform::Initialized()) {
|
if (gfxPlatform::Initialized()) {
|
||||||
gfxPlatformFontList::PlatformFontList()->ShmBlockAdded(aGeneration, aIndex,
|
gfxPlatformFontList::PlatformFontList()->ShmBlockAdded(aGeneration, aIndex,
|
||||||
std::move(aHandle));
|
std::move(aHandle));
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "mozilla/Hal.h"
|
#include "mozilla/Hal.h"
|
||||||
#include "mozilla/ipc/InputStreamUtils.h"
|
#include "mozilla/ipc/InputStreamUtils.h"
|
||||||
#include "mozilla/ipc/ProtocolUtils.h"
|
#include "mozilla/ipc/ProtocolUtils.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
#include "mozilla/StaticPtr.h"
|
#include "mozilla/StaticPtr.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "nsClassHashtable.h"
|
#include "nsClassHashtable.h"
|
||||||
@@ -119,8 +120,9 @@ class ContentChild final : public PContentChild,
|
|||||||
const mozilla::dom::ipc::StructuredCloneData& aInitialData,
|
const mozilla::dom::ipc::StructuredCloneData& aInitialData,
|
||||||
bool aIsReadyForBackgroundProcessing);
|
bool aIsReadyForBackgroundProcessing);
|
||||||
|
|
||||||
void InitSharedUASheets(Maybe<SharedMemoryHandle>&& aHandle,
|
void InitSharedUASheets(
|
||||||
uintptr_t aAddress);
|
Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aHandle,
|
||||||
|
uintptr_t aAddress);
|
||||||
|
|
||||||
void InitGraphicsDeviceData(const ContentDeviceData& aData);
|
void InitGraphicsDeviceData(const ContentDeviceData& aData);
|
||||||
|
|
||||||
@@ -309,7 +311,7 @@ class ContentChild final : public PContentChild,
|
|||||||
nsTArray<L10nFileSourceDescriptor>&& aDescriptors);
|
nsTArray<L10nFileSourceDescriptor>&& aDescriptors);
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvUpdateSharedData(
|
mozilla::ipc::IPCResult RecvUpdateSharedData(
|
||||||
SharedMemoryHandle&& aMapHandle, const uint32_t& aMapSize,
|
mozilla::ipc::ReadOnlySharedMemoryHandle&& aMapHandle,
|
||||||
nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys);
|
nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys);
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvForceGlobalReflow(
|
mozilla::ipc::IPCResult RecvForceGlobalReflow(
|
||||||
@@ -329,7 +331,7 @@ class ContentChild final : public PContentChild,
|
|||||||
mozilla::ipc::IPCResult RecvRebuildFontList(const bool& aFullRebuild);
|
mozilla::ipc::IPCResult RecvRebuildFontList(const bool& aFullRebuild);
|
||||||
mozilla::ipc::IPCResult RecvFontListShmBlockAdded(
|
mozilla::ipc::IPCResult RecvFontListShmBlockAdded(
|
||||||
const uint32_t& aGeneration, const uint32_t& aIndex,
|
const uint32_t& aGeneration, const uint32_t& aIndex,
|
||||||
SharedMemoryHandle&& aHandle);
|
mozilla::ipc::ReadOnlySharedMemoryHandle&& aHandle);
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvUpdateAppLocales(
|
mozilla::ipc::IPCResult RecvUpdateAppLocales(
|
||||||
nsTArray<nsCString>&& aAppLocales);
|
nsTArray<nsCString>&& aAppLocales);
|
||||||
@@ -503,9 +505,10 @@ class ContentChild final : public PContentChild,
|
|||||||
mozilla::ipc::IPCResult RecvSetXPCOMProcessAttributes(
|
mozilla::ipc::IPCResult RecvSetXPCOMProcessAttributes(
|
||||||
XPCOMInitData&& aXPCOMInit, const StructuredCloneData& aInitialData,
|
XPCOMInitData&& aXPCOMInit, const StructuredCloneData& aInitialData,
|
||||||
FullLookAndFeel&& aLookAndFeelData, SystemFontList&& aFontList,
|
FullLookAndFeel&& aLookAndFeelData, SystemFontList&& aFontList,
|
||||||
Maybe<SharedMemoryHandle>&& aSharedUASheetHandle,
|
Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aSharedUASheetHandle,
|
||||||
const uintptr_t& aSharedUASheetAddress,
|
const uintptr_t& aSharedUASheetAddress,
|
||||||
nsTArray<SharedMemoryHandle>&& aSharedFontListBlocks,
|
nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle>&&
|
||||||
|
aSharedFontListBlocks,
|
||||||
const bool& aIsReadyForBackgroundProcessing);
|
const bool& aIsReadyForBackgroundProcessing);
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvProvideAnonymousTemporaryFile(
|
mozilla::ipc::IPCResult RecvProvideAnonymousTemporaryFile(
|
||||||
@@ -535,7 +538,7 @@ class ContentChild final : public PContentChild,
|
|||||||
// for use during gfx initialization.
|
// for use during gfx initialization.
|
||||||
SystemFontList& SystemFontList() { return mFontList; }
|
SystemFontList& SystemFontList() { return mFontList; }
|
||||||
|
|
||||||
nsTArray<SharedMemoryHandle>& SharedFontListBlocks() {
|
nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle>& SharedFontListBlocks() {
|
||||||
return mSharedFontListBlocks;
|
return mSharedFontListBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -834,7 +837,7 @@ class ContentChild final : public PContentChild,
|
|||||||
// Temporary storage for look and feel data.
|
// Temporary storage for look and feel data.
|
||||||
FullLookAndFeel mLookAndFeelData;
|
FullLookAndFeel mLookAndFeelData;
|
||||||
// Temporary storage for list of shared-fontlist memory blocks.
|
// Temporary storage for list of shared-fontlist memory blocks.
|
||||||
nsTArray<SharedMemoryHandle> mSharedFontListBlocks;
|
nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle> mSharedFontListBlocks;
|
||||||
|
|
||||||
AppInfo mAppInfo;
|
AppInfo mAppInfo;
|
||||||
|
|
||||||
|
|||||||
@@ -152,7 +152,7 @@
|
|||||||
#include "mozilla/ipc/Endpoint.h"
|
#include "mozilla/ipc/Endpoint.h"
|
||||||
#include "mozilla/ipc/FileDescriptorUtils.h"
|
#include "mozilla/ipc/FileDescriptorUtils.h"
|
||||||
#include "mozilla/ipc/IPCStreamUtils.h"
|
#include "mozilla/ipc/IPCStreamUtils.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
#include "mozilla/ipc/TestShellParent.h"
|
#include "mozilla/ipc/TestShellParent.h"
|
||||||
#include "mozilla/layers/CompositorThread.h"
|
#include "mozilla/layers/CompositorThread.h"
|
||||||
#include "mozilla/layers/ImageBridgeParent.h"
|
#include "mozilla/layers/ImageBridgeParent.h"
|
||||||
@@ -1536,9 +1536,8 @@ void ContentParent::BroadcastStringBundle(
|
|||||||
const StringBundleDescriptor& aBundle) {
|
const StringBundleDescriptor& aBundle) {
|
||||||
for (auto* cp : AllProcesses(eLive)) {
|
for (auto* cp : AllProcesses(eLive)) {
|
||||||
AutoTArray<StringBundleDescriptor, 1> array;
|
AutoTArray<StringBundleDescriptor, 1> array;
|
||||||
array.AppendElement(StringBundleDescriptor(
|
array.AppendElement(StringBundleDescriptor(aBundle.bundleURL(),
|
||||||
aBundle.bundleURL(), SharedMemory::CloneHandle(aBundle.mapHandle()),
|
aBundle.mapHandle().Clone()));
|
||||||
aBundle.mapSize()));
|
|
||||||
Unused << cp->SendRegisterStringBundles(std::move(array));
|
Unused << cp->SendRegisterStringBundles(std::move(array));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1547,9 +1546,9 @@ void ContentParent::BroadcastShmBlockAdded(uint32_t aGeneration,
|
|||||||
uint32_t aIndex) {
|
uint32_t aIndex) {
|
||||||
auto* pfl = gfxPlatformFontList::PlatformFontList();
|
auto* pfl = gfxPlatformFontList::PlatformFontList();
|
||||||
for (auto* cp : AllProcesses(eLive)) {
|
for (auto* cp : AllProcesses(eLive)) {
|
||||||
SharedMemory::Handle handle =
|
ReadOnlySharedMemoryHandle handle =
|
||||||
pfl->ShareShmBlockToProcess(aIndex, cp->Pid());
|
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
|
// If something went wrong here, we just skip it; the child will need to
|
||||||
// request the block as needed, at some performance cost.
|
// request the block as needed, at some performance cost.
|
||||||
continue;
|
continue;
|
||||||
@@ -2811,7 +2810,7 @@ bool ContentParent::InitInternal(ProcessPriority aInitialPriority) {
|
|||||||
|
|
||||||
// If the shared fontlist is in use, collect its shmem block handles to pass
|
// If the shared fontlist is in use, collect its shmem block handles to pass
|
||||||
// to the child.
|
// to the child.
|
||||||
nsTArray<SharedMemoryHandle> sharedFontListBlocks;
|
nsTArray<ReadOnlySharedMemoryHandle> sharedFontListBlocks;
|
||||||
gfxPlatformFontList::PlatformFontList()->ShareFontListToProcess(
|
gfxPlatformFontList::PlatformFontList()->ShareFontListToProcess(
|
||||||
&sharedFontListBlocks, OtherPid());
|
&sharedFontListBlocks, OtherPid());
|
||||||
|
|
||||||
@@ -2850,10 +2849,10 @@ bool ContentParent::InitInternal(ProcessPriority aInitialPriority) {
|
|||||||
screenManager.CopyScreensToRemote(this);
|
screenManager.CopyScreensToRemote(this);
|
||||||
|
|
||||||
// Send the UA sheet shared memory buffer and the address it is mapped at.
|
// Send the UA sheet shared memory buffer and the address it is mapped at.
|
||||||
Maybe<SharedMemoryHandle> sharedUASheetHandle;
|
Maybe<ReadOnlySharedMemoryHandle> sharedUASheetHandle;
|
||||||
uintptr_t sharedUASheetAddress = sheetCache->GetSharedMemoryAddress();
|
uintptr_t sharedUASheetAddress = sheetCache->GetSharedMemoryAddress();
|
||||||
|
|
||||||
if (SharedMemoryHandle handle = sheetCache->CloneHandle()) {
|
if (ReadOnlySharedMemoryHandle handle = sheetCache->CloneHandle()) {
|
||||||
sharedUASheetHandle.emplace(std::move(handle));
|
sharedUASheetHandle.emplace(std::move(handle));
|
||||||
} else {
|
} else {
|
||||||
sharedUASheetAddress = 0;
|
sharedUASheetAddress = 0;
|
||||||
@@ -5628,7 +5627,7 @@ mozilla::ipc::IPCResult ContentParent::RecvShutdownPerfStats(
|
|||||||
|
|
||||||
mozilla::ipc::IPCResult ContentParent::RecvGetFontListShmBlock(
|
mozilla::ipc::IPCResult ContentParent::RecvGetFontListShmBlock(
|
||||||
const uint32_t& aGeneration, const uint32_t& aIndex,
|
const uint32_t& aGeneration, const uint32_t& aIndex,
|
||||||
SharedMemory::Handle* aOut) {
|
ReadOnlySharedMemoryHandle* aOut) {
|
||||||
auto* fontList = gfxPlatformFontList::PlatformFontList();
|
auto* fontList = gfxPlatformFontList::PlatformFontList();
|
||||||
MOZ_RELEASE_ASSERT(fontList, "gfxPlatformFontList not initialized?");
|
MOZ_RELEASE_ASSERT(fontList, "gfxPlatformFontList not initialized?");
|
||||||
fontList->ShareFontListShmBlockToProcess(aGeneration, aIndex, Pid(), aOut);
|
fontList->ShareFontListShmBlockToProcess(aGeneration, aIndex, Pid(), aOut);
|
||||||
@@ -5680,12 +5679,12 @@ mozilla::ipc::IPCResult ContentParent::RecvStartCmapLoading(
|
|||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult ContentParent::RecvGetHyphDict(
|
mozilla::ipc::IPCResult ContentParent::RecvGetHyphDict(
|
||||||
nsIURI* aURI, SharedMemory::Handle* aOutHandle, uint32_t* aOutSize) {
|
nsIURI* aURI, ReadOnlySharedMemoryHandle* aOutHandle) {
|
||||||
if (!aURI) {
|
if (!aURI) {
|
||||||
return IPC_FAIL(this, "aURI must not be null.");
|
return IPC_FAIL(this, "aURI must not be null.");
|
||||||
}
|
}
|
||||||
nsHyphenationManager::Instance()->ShareHyphDictToProcess(
|
nsHyphenationManager::Instance()->ShareHyphDictToProcess(aURI, Pid(),
|
||||||
aURI, Pid(), aOutHandle, aOutSize);
|
aOutHandle);
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#include "mozilla/ipc/BackgroundUtils.h"
|
#include "mozilla/ipc/BackgroundUtils.h"
|
||||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||||
#include "mozilla/ipc/InputStreamUtils.h"
|
#include "mozilla/ipc/InputStreamUtils.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/DataMutex.h"
|
#include "mozilla/DataMutex.h"
|
||||||
#include "mozilla/HalTypes.h"
|
#include "mozilla/HalTypes.h"
|
||||||
@@ -1125,7 +1125,7 @@ class ContentParent final : public PContentParent,
|
|||||||
|
|
||||||
mozilla::ipc::IPCResult RecvGetFontListShmBlock(
|
mozilla::ipc::IPCResult RecvGetFontListShmBlock(
|
||||||
const uint32_t& aGeneration, const uint32_t& aIndex,
|
const uint32_t& aGeneration, const uint32_t& aIndex,
|
||||||
mozilla::ipc::SharedMemory::Handle* aOut);
|
mozilla::ipc::ReadOnlySharedMemoryHandle* aOut);
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvInitializeFamily(const uint32_t& aGeneration,
|
mozilla::ipc::IPCResult RecvInitializeFamily(const uint32_t& aGeneration,
|
||||||
const uint32_t& aFamilyIndex,
|
const uint32_t& aFamilyIndex,
|
||||||
@@ -1149,8 +1149,7 @@ class ContentParent final : public PContentParent,
|
|||||||
const uint32_t& aStartIndex);
|
const uint32_t& aStartIndex);
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvGetHyphDict(
|
mozilla::ipc::IPCResult RecvGetHyphDict(
|
||||||
nsIURI* aURIParams, mozilla::ipc::SharedMemory::Handle* aOutHandle,
|
nsIURI* aURIParams, mozilla::ipc::ReadOnlySharedMemoryHandle* aOutHandle);
|
||||||
uint32_t* aOutSize);
|
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvNotifyBenchmarkResult(const nsAString& aCodecName,
|
mozilla::ipc::IPCResult RecvNotifyBenchmarkResult(const nsAString& aCodecName,
|
||||||
const uint32_t& aDecodeFPS);
|
const uint32_t& aDecodeFPS);
|
||||||
|
|||||||
@@ -72,10 +72,9 @@ void ContentProcess::InfallibleInit(int aArgc, char* aArgv[]) {
|
|||||||
Maybe<const char*> parentBuildID =
|
Maybe<const char*> parentBuildID =
|
||||||
geckoargs::sParentBuildID.Get(aArgc, aArgv);
|
geckoargs::sParentBuildID.Get(aArgc, aArgv);
|
||||||
|
|
||||||
// command line: -jsInitHandle handle -jsInitLen length
|
// command line: -jsInitHandle handle
|
||||||
Maybe<mozilla::ipc::SharedMemoryHandle> jsInitHandle =
|
Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle> jsInitHandle =
|
||||||
geckoargs::sJsInitHandle.Get(aArgc, aArgv);
|
geckoargs::sJsInitHandle.Get(aArgc, aArgv);
|
||||||
Maybe<uint64_t> jsInitLen = geckoargs::sJsInitLen.Get(aArgc, aArgv);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIFile> appDirArg;
|
nsCOMPtr<nsIFile> appDirArg;
|
||||||
Maybe<const char*> appDir = geckoargs::sAppDir.Get(aArgc, aArgv);
|
Maybe<const char*> appDir = geckoargs::sAppDir.Get(aArgc, aArgv);
|
||||||
@@ -131,8 +130,8 @@ void ContentProcess::InfallibleInit(int aArgc, char* aArgv[]) {
|
|||||||
MOZ_CRASH("InitPrefs failed");
|
MOZ_CRASH("InitPrefs failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsInitHandle && jsInitLen &&
|
if (jsInitHandle &&
|
||||||
!::mozilla::ipc::ImportSharedJSInit(jsInitHandle.extract(), *jsInitLen)) {
|
!::mozilla::ipc::ImportSharedJSInit(jsInitHandle.extract())) {
|
||||||
MOZ_CRASH("ImportSharedJSInit failed");
|
MOZ_CRASH("ImportSharedJSInit failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,40 +7,36 @@
|
|||||||
#include "MemMapSnapshot.h"
|
#include "MemMapSnapshot.h"
|
||||||
|
|
||||||
#include "mozilla/ResultExtensions.h"
|
#include "mozilla/ResultExtensions.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
|
|
||||||
namespace mozilla::ipc {
|
namespace mozilla::ipc {
|
||||||
|
|
||||||
Result<Ok, nsresult> MemMapSnapshot::Init(size_t aSize) {
|
Result<Ok, nsresult> MemMapSnapshot::Init(size_t aSize) {
|
||||||
MOZ_ASSERT(!mMem);
|
MOZ_ASSERT(!mMem);
|
||||||
|
|
||||||
auto aMem = MakeRefPtr<SharedMemory>();
|
auto handle = shared_memory::CreateFreezable(aSize);
|
||||||
if (NS_WARN_IF(!aMem->CreateFreezable(aSize))) {
|
if (NS_WARN_IF(!handle)) {
|
||||||
return Err(NS_ERROR_FAILURE);
|
|
||||||
}
|
|
||||||
if (NS_WARN_IF(!aMem->Map(aSize))) {
|
|
||||||
return Err(NS_ERROR_FAILURE);
|
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();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Ok, nsresult> MemMapSnapshot::Finalize(RefPtr<SharedMemory>& aMem) {
|
Result<ReadOnlySharedMemoryHandle, nsresult> MemMapSnapshot::Finalize() {
|
||||||
MOZ_ASSERT(mMem);
|
MOZ_ASSERT(mMem);
|
||||||
|
|
||||||
auto size = mMem->Size();
|
auto [_, readOnlyHandle] = std::move(mMem).Freeze();
|
||||||
if (NS_WARN_IF(!mMem->Freeze())) {
|
if (NS_WARN_IF(!readOnlyHandle)) {
|
||||||
return Err(NS_ERROR_FAILURE);
|
return Err(NS_ERROR_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
aMem = std::move(mMem);
|
return std::move(readOnlyHandle);
|
||||||
|
|
||||||
// We need to re-map the memory as `Freeze()` unmaps it.
|
|
||||||
if (NS_WARN_IF(!aMem->Map(size))) {
|
|
||||||
return Err(NS_ERROR_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla::ipc
|
} // namespace mozilla::ipc
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "mozilla/RangedPtr.h"
|
#include "mozilla/RangedPtr.h"
|
||||||
#include "mozilla/Result.h"
|
#include "mozilla/Result.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
#include "ErrorList.h"
|
#include "ErrorList.h"
|
||||||
|
|
||||||
namespace mozilla::ipc {
|
namespace mozilla::ipc {
|
||||||
@@ -23,7 +23,7 @@ namespace mozilla::ipc {
|
|||||||
* The Init() method initializes a read-write memory mapped region of the given
|
* The Init() method initializes a read-write memory mapped region of the given
|
||||||
* size, which can be initialized with arbitrary data. The Finalize() method
|
* size, which can be initialized with arbitrary data. The Finalize() method
|
||||||
* remaps that region as read-only (and backs it with a read-only file
|
* remaps that region as read-only (and backs it with a read-only file
|
||||||
* descriptor), and 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
|
* The file descriptor for the resulting AutoMemMap can be shared among
|
||||||
* processes, to safely access a shared, read-only copy of the data snapshot.
|
* processes, to safely access a shared, read-only copy of the data snapshot.
|
||||||
@@ -31,16 +31,17 @@ namespace mozilla::ipc {
|
|||||||
class MOZ_RAII MemMapSnapshot {
|
class MOZ_RAII MemMapSnapshot {
|
||||||
public:
|
public:
|
||||||
Result<Ok, nsresult> Init(size_t aSize);
|
Result<Ok, nsresult> Init(size_t aSize);
|
||||||
Result<Ok, nsresult> Finalize(RefPtr<SharedMemory>& aMem);
|
Result<ReadOnlySharedMemoryHandle, nsresult> Finalize();
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
RangedPtr<T> Get() {
|
RangedPtr<T> Get() {
|
||||||
MOZ_ASSERT(mMem);
|
MOZ_ASSERT(mMem);
|
||||||
return {static_cast<T*>(mMem->Memory()), mMem->MaxSize() / sizeof(T)};
|
auto span = mMem.DataAsSpan<T>();
|
||||||
|
return {span.data(), span.size()};
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RefPtr<SharedMemory> mMem;
|
FreezableSharedMemoryMapping mMem;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla::ipc
|
} // namespace mozilla::ipc
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ using mozilla::dom::BrowsingContextInitializer from "mozilla/dom/BrowsingContext
|
|||||||
using mozilla::dom::PermitUnloadResult from "nsIDocumentViewer.h";
|
using mozilla::dom::PermitUnloadResult from "nsIDocumentViewer.h";
|
||||||
using mozilla::dom::MaybeDiscardedWindowContext from "mozilla/dom/WindowContext.h";
|
using mozilla::dom::MaybeDiscardedWindowContext from "mozilla/dom/WindowContext.h";
|
||||||
using mozilla::dom::WindowContextTransaction from "mozilla/dom/WindowContext.h";
|
using mozilla::dom::WindowContextTransaction from "mozilla/dom/WindowContext.h";
|
||||||
[MoveOnly] using mozilla::ipc::SharedMemoryHandle from "mozilla/ipc/SharedMemory.h";
|
[MoveOnly] using mozilla::ipc::ReadOnlySharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h";
|
||||||
using gfxSparseBitSet from "gfxFontUtils.h";
|
using gfxSparseBitSet from "gfxFontUtils.h";
|
||||||
using FontVisibility from "gfxFontEntry.h";
|
using FontVisibility from "gfxFontEntry.h";
|
||||||
using mozilla::dom::MediaControlAction from "mozilla/dom/MediaControlKeySource.h";
|
using mozilla::dom::MediaControlAction from "mozilla/dom/MediaControlKeySource.h";
|
||||||
@@ -400,8 +400,7 @@ struct VisitedQueryResult
|
|||||||
struct StringBundleDescriptor
|
struct StringBundleDescriptor
|
||||||
{
|
{
|
||||||
nsCString bundleURL;
|
nsCString bundleURL;
|
||||||
SharedMemoryHandle mapHandle;
|
ReadOnlySharedMemoryHandle mapHandle;
|
||||||
uint32_t mapSize;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IPCURLClassifierFeature
|
struct IPCURLClassifierFeature
|
||||||
@@ -715,7 +714,7 @@ child:
|
|||||||
* should map the new block and add to its index.
|
* should map the new block and add to its index.
|
||||||
*/
|
*/
|
||||||
async FontListShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
|
async FontListShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
|
||||||
SharedMemoryHandle aHandle);
|
ReadOnlySharedMemoryHandle aHandle);
|
||||||
|
|
||||||
async UpdateAppLocales(nsCString[] appLocales);
|
async UpdateAppLocales(nsCString[] appLocales);
|
||||||
async UpdateRequestedLocales(nsCString[] requestedLocales);
|
async UpdateRequestedLocales(nsCString[] requestedLocales);
|
||||||
@@ -732,7 +731,7 @@ child:
|
|||||||
|
|
||||||
async SimpleURIUnknownRemoteSchemes(nsCString[] remoteSchemes);
|
async SimpleURIUnknownRemoteSchemes(nsCString[] remoteSchemes);
|
||||||
|
|
||||||
async UpdateSharedData(SharedMemoryHandle aMapHandle, uint32_t aSize,
|
async UpdateSharedData(ReadOnlySharedMemoryHandle aMapHandle,
|
||||||
IPCBlob[] blobs,
|
IPCBlob[] blobs,
|
||||||
nsCString[] changedKeys);
|
nsCString[] changedKeys);
|
||||||
|
|
||||||
@@ -803,9 +802,9 @@ child:
|
|||||||
FullLookAndFeel lookAndFeeldata,
|
FullLookAndFeel lookAndFeeldata,
|
||||||
/* used on MacOSX/Linux/Android only: */
|
/* used on MacOSX/Linux/Android only: */
|
||||||
SystemFontList systemFontList,
|
SystemFontList systemFontList,
|
||||||
SharedMemoryHandle? sharedUASheetHandle,
|
ReadOnlySharedMemoryHandle? sharedUASheetHandle,
|
||||||
uintptr_t sharedUASheetAddress,
|
uintptr_t sharedUASheetAddress,
|
||||||
SharedMemoryHandle[] sharedFontListBlocks,
|
ReadOnlySharedMemoryHandle[] sharedFontListBlocks,
|
||||||
bool aIsStartingUp);
|
bool aIsStartingUp);
|
||||||
|
|
||||||
// Notify child that last-pb-context-exited notification was observed
|
// Notify child that last-pb-context-exited notification was observed
|
||||||
@@ -1377,7 +1376,7 @@ parent:
|
|||||||
* until it has mapped the font-list memory.
|
* until it has mapped the font-list memory.
|
||||||
*/
|
*/
|
||||||
sync GetFontListShmBlock(uint32_t aGeneration, uint32_t aIndex)
|
sync GetFontListShmBlock(uint32_t aGeneration, uint32_t aIndex)
|
||||||
returns (SharedMemoryHandle aHandle);
|
returns (ReadOnlySharedMemoryHandle aHandle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ask the parent to initialize a given font family, so that face metadata
|
* Ask the parent to initialize a given font family, so that face metadata
|
||||||
@@ -1495,7 +1494,7 @@ parent:
|
|||||||
* @param aLoaded
|
* @param aLoaded
|
||||||
* Returns the size in bytes of the resource.
|
* Returns the size in bytes of the resource.
|
||||||
*/
|
*/
|
||||||
sync GetHyphDict(nullable nsIURI aURI) returns (SharedMemoryHandle aHandle, uint32_t aSize);
|
sync GetHyphDict(nullable nsIURI aURI) returns (ReadOnlySharedMemoryHandle aHandle);
|
||||||
|
|
||||||
async CreateWindow(PBrowser aThisTab,
|
async CreateWindow(PBrowser aThisTab,
|
||||||
MaybeDiscardedBrowsingContext aParent,
|
MaybeDiscardedBrowsingContext aParent,
|
||||||
|
|||||||
@@ -43,11 +43,10 @@ static inline void AlignTo(size_t* aOffset, size_t aAlign) {
|
|||||||
SharedMap::SharedMap() = default;
|
SharedMap::SharedMap() = default;
|
||||||
|
|
||||||
SharedMap::SharedMap(nsIGlobalObject* aGlobal, SharedMemoryHandle&& aMapHandle,
|
SharedMap::SharedMap(nsIGlobalObject* aGlobal, SharedMemoryHandle&& aMapHandle,
|
||||||
size_t aMapSize, nsTArray<RefPtr<BlobImpl>>&& aBlobs)
|
nsTArray<RefPtr<BlobImpl>>&& aBlobs)
|
||||||
: DOMEventTargetHelper(aGlobal),
|
: DOMEventTargetHelper(aGlobal),
|
||||||
mBlobImpls(std::move(aBlobs)),
|
mBlobImpls(std::move(aBlobs)),
|
||||||
mMapHandle(std::move(aMapHandle)),
|
mHandle(std::move(aMapHandle)) {}
|
||||||
mMapSize(aMapSize) {}
|
|
||||||
|
|
||||||
bool SharedMap::Has(const nsACString& aName) {
|
bool SharedMap::Has(const nsACString& aName) {
|
||||||
Unused << MaybeRebuild();
|
Unused << MaybeRebuild();
|
||||||
@@ -97,21 +96,13 @@ void SharedMap::Entry::Read(JSContext* aCx,
|
|||||||
holder.Read(aCx, aRetVal, aRv);
|
holder.Read(aCx, aRetVal, aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedMap::SharedMemoryHandle SharedMap::CloneHandle() const {
|
void SharedMap::Update(SharedMemoryHandle&& aMapHandle,
|
||||||
if (mMap->IsValid()) {
|
|
||||||
return mMap->CloneHandle();
|
|
||||||
}
|
|
||||||
return SharedMemory::CloneHandle(mMapHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedMap::Update(SharedMemoryHandle&& aMapHandle, size_t aMapSize,
|
|
||||||
nsTArray<RefPtr<BlobImpl>>&& aBlobs,
|
nsTArray<RefPtr<BlobImpl>>&& aBlobs,
|
||||||
nsTArray<nsCString>&& aChangedKeys) {
|
nsTArray<nsCString>&& aChangedKeys) {
|
||||||
MOZ_DIAGNOSTIC_ASSERT(!mWritable);
|
MOZ_DIAGNOSTIC_ASSERT(!mWritable);
|
||||||
|
|
||||||
mMap->TakeHandleAndUnmap();
|
mMapping = nullptr;
|
||||||
mMapHandle = std::move(aMapHandle);
|
mHandle = std::move(aMapHandle);
|
||||||
mMapSize = aMapSize;
|
|
||||||
mEntries.Clear();
|
mEntries.Clear();
|
||||||
mEntryArray.reset();
|
mEntryArray.reset();
|
||||||
|
|
||||||
@@ -191,10 +182,12 @@ void SharedMap::Entry::ExtractData(char* aDestPtr, uint32_t aNewOffset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result<Ok, nsresult> SharedMap::MaybeRebuild() {
|
Result<Ok, nsresult> SharedMap::MaybeRebuild() {
|
||||||
if (!SharedMemory::IsHandleValid(mMapHandle)) {
|
if (mMapping || !mHandle) {
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(!mWritable);
|
||||||
|
|
||||||
// This function maps a shared memory region created by Serialize() and reads
|
// This function maps a shared memory region created by Serialize() and reads
|
||||||
// its header block to build a new mEntries hashtable of its contents.
|
// its header block to build a new mEntries hashtable of its contents.
|
||||||
//
|
//
|
||||||
@@ -203,24 +196,20 @@ Result<Ok, nsresult> SharedMap::MaybeRebuild() {
|
|||||||
// its shared memory region. When needed, that structured clone data is
|
// its shared memory region. When needed, that structured clone data is
|
||||||
// retrieved directly as indexes into the SharedMap's shared memory region.
|
// retrieved directly as indexes into the SharedMap's shared memory region.
|
||||||
|
|
||||||
if (!mMap->SetHandle(SharedMemory::CloneHandle(mMapHandle),
|
mMapping = mHandle.Map();
|
||||||
SharedMemory::OpenRights::RightsReadOnly)) {
|
if (!mMapping) {
|
||||||
return Err(NS_ERROR_FAILURE);
|
|
||||||
}
|
|
||||||
mMapHandle = SharedMemory::NULLHandle();
|
|
||||||
if (!mMap->Map(mMapSize)) {
|
|
||||||
return Err(NS_ERROR_FAILURE);
|
return Err(NS_ERROR_FAILURE);
|
||||||
}
|
}
|
||||||
|
mHandle = nullptr;
|
||||||
|
|
||||||
// We should be able to pass this range as an initializer list or an immediate
|
Range<const uint8_t> inputRange(mMapping.DataAsSpan<uint8_t>());
|
||||||
// param, but gcc currently chokes on that if optimization is enabled, and
|
InputBuffer buffer(inputRange);
|
||||||
// initializes everything to 0.
|
|
||||||
Range<uint8_t> range((uint8_t*)mMap->Memory(), mMap->Size());
|
|
||||||
InputBuffer buffer(range);
|
|
||||||
|
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
buffer.codeUint32(count);
|
buffer.codeUint32(count);
|
||||||
|
|
||||||
|
MOZ_ASSERT(mEntries.IsEmpty());
|
||||||
|
MOZ_ASSERT(mEntryArray.isNothing());
|
||||||
for (uint32_t i = 0; i < count; i++) {
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
auto entry = MakeUnique<Entry>(*this);
|
auto entry = MakeUnique<Entry>(*this);
|
||||||
entry->Code(buffer);
|
entry->Code(buffer);
|
||||||
@@ -246,9 +235,9 @@ void SharedMap::MaybeRebuild() const {
|
|||||||
WritableSharedMap::WritableSharedMap() {
|
WritableSharedMap::WritableSharedMap() {
|
||||||
mWritable = true;
|
mWritable = true;
|
||||||
// Serialize the initial empty contents of the map immediately so that we
|
// Serialize the initial empty contents of the map immediately so that we
|
||||||
// always have a file descriptor to send to callers of CloneMapFile().
|
// always have a file descriptor to send.
|
||||||
Unused << Serialize();
|
Unused << Serialize();
|
||||||
MOZ_RELEASE_ASSERT(mMap->IsValid());
|
MOZ_RELEASE_ASSERT(mHandle.IsValid() && mMapping.IsValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedMap* WritableSharedMap::GetReadOnly() {
|
SharedMap* WritableSharedMap::GetReadOnly() {
|
||||||
@@ -256,7 +245,7 @@ SharedMap* WritableSharedMap::GetReadOnly() {
|
|||||||
nsTArray<RefPtr<BlobImpl>> blobs(mBlobImpls.Clone());
|
nsTArray<RefPtr<BlobImpl>> blobs(mBlobImpls.Clone());
|
||||||
mReadOnly =
|
mReadOnly =
|
||||||
new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(),
|
new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(),
|
||||||
CloneHandle(), MapSize(), std::move(blobs));
|
mHandle.Clone(), std::move(blobs));
|
||||||
}
|
}
|
||||||
return mReadOnly;
|
return mReadOnly;
|
||||||
}
|
}
|
||||||
@@ -339,8 +328,11 @@ Result<Ok, nsresult> WritableSharedMap::Serialize() {
|
|||||||
memcpy(ptr.get(), header.Get(), header.cursor());
|
memcpy(ptr.get(), header.Get(), header.cursor());
|
||||||
|
|
||||||
// We've already updated offsets at this point. We need this to succeed.
|
// We've already updated offsets at this point. We need this to succeed.
|
||||||
mMap->TakeHandleAndUnmap();
|
auto result = mem.Finalize();
|
||||||
MOZ_RELEASE_ASSERT(mem.Finalize(mMap).isOk());
|
MOZ_RELEASE_ASSERT(result.isOk());
|
||||||
|
mHandle = result.unwrap();
|
||||||
|
mMapping = mHandle.Map();
|
||||||
|
MOZ_RELEASE_ASSERT(mMapping.IsValid());
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
@@ -355,8 +347,7 @@ void WritableSharedMap::SendTo(ContentParent* aParent) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Unused << aParent->SendUpdateSharedData(CloneHandle(), mMap->Size(), blobs,
|
Unused << aParent->SendUpdateSharedData(mHandle.Clone(), blobs, mChangedKeys);
|
||||||
mChangedKeys);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WritableSharedMap::BroadcastChanges() {
|
void WritableSharedMap::BroadcastChanges() {
|
||||||
@@ -376,7 +367,7 @@ void WritableSharedMap::BroadcastChanges() {
|
|||||||
|
|
||||||
if (mReadOnly) {
|
if (mReadOnly) {
|
||||||
nsTArray<RefPtr<BlobImpl>> blobImpls(mBlobImpls.Clone());
|
nsTArray<RefPtr<BlobImpl>> blobImpls(mBlobImpls.Clone());
|
||||||
mReadOnly->Update(CloneHandle(), mMap->Size(), std::move(blobImpls),
|
mReadOnly->Update(mHandle.Clone(), std::move(blobImpls),
|
||||||
std::move(mChangedKeys));
|
std::move(mChangedKeys));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
#include "mozilla/dom/MozSharedMapBinding.h"
|
#include "mozilla/dom/MozSharedMapBinding.h"
|
||||||
|
|
||||||
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
#include "mozilla/DOMEventTargetHelper.h"
|
#include "mozilla/DOMEventTargetHelper.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
@@ -53,13 +54,14 @@ namespace ipc {
|
|||||||
* WritableSharedMap instances.
|
* WritableSharedMap instances.
|
||||||
*/
|
*/
|
||||||
class SharedMap : public DOMEventTargetHelper {
|
class SharedMap : public DOMEventTargetHelper {
|
||||||
using SharedMemory = mozilla::ipc::SharedMemory;
|
protected:
|
||||||
using SharedMemoryHandle = mozilla::ipc::SharedMemoryHandle;
|
using SharedMemoryMapping = mozilla::ipc::ReadOnlySharedMemoryMapping;
|
||||||
|
using SharedMemoryHandle = mozilla::ipc::ReadOnlySharedMemoryHandle;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SharedMap();
|
SharedMap();
|
||||||
|
|
||||||
SharedMap(nsIGlobalObject* aGlobal, SharedMemoryHandle&&, size_t,
|
SharedMap(nsIGlobalObject* aGlobal, SharedMemoryHandle&&,
|
||||||
nsTArray<RefPtr<BlobImpl>>&& aBlobs);
|
nsTArray<RefPtr<BlobImpl>>&& aBlobs);
|
||||||
|
|
||||||
// Returns true if the map contains the given (UTF-8) key.
|
// Returns true if the map contains the given (UTF-8) key.
|
||||||
@@ -93,26 +95,16 @@ class SharedMap : public DOMEventTargetHelper {
|
|||||||
JS::MutableHandle<JS::Value> aResult) const;
|
JS::MutableHandle<JS::Value> aResult) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a copy of the read-only file descriptor which backs the shared
|
* Returns the size of the memory mapped region that backs this map.
|
||||||
* memory region for this map. The file descriptor may be passed between
|
|
||||||
* processes, and used to update corresponding instances in child processes.
|
|
||||||
*/
|
*/
|
||||||
SharedMemoryHandle CloneHandle() const;
|
size_t MapSize() const { return mMapping.Size(); }
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the size of the memory mapped region that backs this map. Must be
|
|
||||||
* passed to the SharedMap() constructor or Update() method along with the
|
|
||||||
* descriptor returned by CloneMapFile() in order to initialize or update a
|
|
||||||
* child SharedMap.
|
|
||||||
*/
|
|
||||||
size_t MapSize() const { return mMap->Size(); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates this instance to reflect the contents of the shared memory region
|
* Updates this instance to reflect the contents of the shared memory region
|
||||||
* in the given map handle, and broadcasts a change event for the given set of
|
* in the given map handle, and broadcasts a change event for the given set of
|
||||||
* changed (UTF-8-encoded) keys.
|
* changed (UTF-8-encoded) keys.
|
||||||
*/
|
*/
|
||||||
void Update(SharedMemoryHandle&& aMapHandle, size_t aMapSize,
|
void Update(SharedMemoryHandle&& aMapHandle,
|
||||||
nsTArray<RefPtr<BlobImpl>>&& aBlobs,
|
nsTArray<RefPtr<BlobImpl>>&& aBlobs,
|
||||||
nsTArray<nsCString>&& aChangedKeys);
|
nsTArray<nsCString>&& aChangedKeys);
|
||||||
|
|
||||||
@@ -263,24 +255,20 @@ class SharedMap : public DOMEventTargetHelper {
|
|||||||
Result<Ok, nsresult> MaybeRebuild();
|
Result<Ok, nsresult> MaybeRebuild();
|
||||||
void MaybeRebuild() const;
|
void MaybeRebuild() const;
|
||||||
|
|
||||||
SharedMemoryHandle mMapHandle;
|
|
||||||
// The size of the memory-mapped region backed by mMap, in bytes.
|
|
||||||
size_t mMapSize = 0;
|
|
||||||
|
|
||||||
mutable nsClassHashtable<nsCStringHashKey, Entry> mEntries;
|
mutable nsClassHashtable<nsCStringHashKey, Entry> mEntries;
|
||||||
mutable Maybe<nsTArray<Entry*>> mEntryArray;
|
mutable Maybe<nsTArray<Entry*>> mEntryArray;
|
||||||
|
|
||||||
// Manages the memory mapping of the current snapshot. This is initialized
|
// Manages the memory mapping of the current snapshot. This is initialized
|
||||||
// lazily after each SharedMap construction or updated, based on the values in
|
// lazily after each SharedMap construction or update.
|
||||||
// mMapFile and mMapSize.
|
SharedMemoryHandle mHandle;
|
||||||
RefPtr<SharedMemory> mMap = MakeRefPtr<SharedMemory>();
|
SharedMemoryMapping mMapping;
|
||||||
|
|
||||||
bool mWritable = false;
|
bool mWritable = false;
|
||||||
|
|
||||||
// Returns a pointer to the beginning of the memory mapped snapshot. Entry
|
// Returns a pointer to the beginning of the memory mapped snapshot. Entry
|
||||||
// offsets are relative to this pointer, and Entry objects access their
|
// offsets are relative to this pointer, and Entry objects access their
|
||||||
// structured clone data by indexing this pointer.
|
// structured clone data by indexing this pointer.
|
||||||
char* Data() { return static_cast<char*>(mMap->Memory()); }
|
const char* Data() { return mMapping.DataAs<char>(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class WritableSharedMap final : public SharedMap {
|
class WritableSharedMap final : public SharedMap {
|
||||||
|
|||||||
@@ -27,42 +27,36 @@ static inline size_t GetAlignmentOffset(size_t aOffset, size_t aAlign) {
|
|||||||
return mod ? aAlign - mod : 0;
|
return mod ? aAlign - mod : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedStringMap::SharedStringMap(const SharedMemoryHandle& aMapHandle,
|
SharedStringMap::SharedStringMap(const ReadOnlySharedMemoryHandle& aMapHandle) {
|
||||||
size_t aMapSize) {
|
mHandle = aMapHandle.Clone();
|
||||||
auto map = MakeRefPtr<SharedMemory>();
|
MOZ_RELEASE_ASSERT(mHandle.IsValid());
|
||||||
{
|
auto mapping = aMapHandle.Map();
|
||||||
auto result = map->SetHandle(SharedMemory::CloneHandle(aMapHandle),
|
MOZ_RELEASE_ASSERT(mapping.IsValid());
|
||||||
SharedMemory::OpenRights::RightsReadOnly);
|
|
||||||
MOZ_RELEASE_ASSERT(result);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = map->Map(aMapSize);
|
|
||||||
MOZ_RELEASE_ASSERT(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We return literal nsStrings and nsCStrings pointing to the mapped data,
|
// We return literal nsStrings and nsCStrings pointing to the mapped data,
|
||||||
// which means that we may still have references to the mapped data even
|
// which means that we may still have references to the mapped data even
|
||||||
// after this instance is destroyed. That means that we need to keep the
|
// after this instance is destroyed. That means that we need to keep the
|
||||||
// mapping alive until process shutdown, in order to be safe.
|
// mapping alive until process shutdown, in order to be safe.
|
||||||
mMappedMemory = map->TakeMapping();
|
mMappedMemory = std::move(mapping).Release();
|
||||||
mHandle = map->TakeHandle();
|
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(GetHeader().mMagic == kSharedStringMapMagic);
|
MOZ_RELEASE_ASSERT(GetHeader().mMagic == kSharedStringMapMagic);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedStringMap::SharedStringMap(SharedStringMapBuilder&& aBuilder) {
|
SharedStringMap::SharedStringMap(SharedStringMapBuilder&& aBuilder) {
|
||||||
RefPtr<SharedMemory> map;
|
ReadOnlySharedMemoryMappingWithHandle mappingWithHandle;
|
||||||
auto result = aBuilder.Finalize(map);
|
auto result = aBuilder.Finalize();
|
||||||
MOZ_RELEASE_ASSERT(result.isOk() && map);
|
MOZ_RELEASE_ASSERT(result.isOk());
|
||||||
|
mHandle = result.unwrap();
|
||||||
|
auto mapping = mHandle.Map();
|
||||||
|
MOZ_RELEASE_ASSERT(mapping.IsValid());
|
||||||
|
|
||||||
mMappedMemory = map->TakeMapping();
|
mMappedMemory = std::move(mapping).Release();
|
||||||
mHandle = map->TakeHandle();
|
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(GetHeader().mMagic == kSharedStringMapMagic);
|
MOZ_RELEASE_ASSERT(GetHeader().mMagic == kSharedStringMapMagic);
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::SharedMemoryHandle SharedStringMap::CloneHandle() const {
|
mozilla::ipc::ReadOnlySharedMemoryHandle SharedStringMap::CloneHandle() const {
|
||||||
return SharedMemory::CloneHandle(mHandle);
|
return mHandle.Clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SharedStringMap::Has(const nsCString& aKey) {
|
bool SharedStringMap::Has(const nsCString& aKey) {
|
||||||
@@ -97,8 +91,8 @@ void SharedStringMapBuilder::Add(const nsCString& aKey,
|
|||||||
Entry{mKeyTable.Add(aKey), mValueTable.Add(aValue)});
|
Entry{mKeyTable.Add(aKey), mValueTable.Add(aValue)});
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Ok, nsresult> SharedStringMapBuilder::Finalize(
|
Result<ReadOnlySharedMemoryHandle, nsresult>
|
||||||
RefPtr<SharedMemory>& aMap) {
|
SharedStringMapBuilder::Finalize() {
|
||||||
using Header = SharedStringMap::Header;
|
using Header = SharedStringMap::Header;
|
||||||
|
|
||||||
MOZ_ASSERT(mEntries.Count() == mKeyTable.Count());
|
MOZ_ASSERT(mEntries.Count() == mKeyTable.Count());
|
||||||
@@ -147,7 +141,7 @@ Result<Ok, nsresult> SharedStringMapBuilder::Finalize(
|
|||||||
mValueTable.Clear();
|
mValueTable.Clear();
|
||||||
mEntries.Clear();
|
mEntries.Clear();
|
||||||
|
|
||||||
return mem.Finalize(aMap);
|
return mem.Finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dom::ipc
|
} // namespace dom::ipc
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
#include "mozilla/Result.h"
|
#include "mozilla/Result.h"
|
||||||
#include "mozilla/dom/ipc/StringTable.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"
|
#include "nsTHashMap.h"
|
||||||
|
|
||||||
namespace mozilla::dom::ipc {
|
namespace mozilla::dom::ipc {
|
||||||
@@ -88,7 +89,7 @@ class SharedStringMap {
|
|||||||
// Note: These constructors are infallible on the premise that this class
|
// Note: These constructors are infallible on the premise that this class
|
||||||
// is used primarily in cases where it is critical to platform
|
// is used primarily in cases where it is critical to platform
|
||||||
// functionality.
|
// functionality.
|
||||||
explicit SharedStringMap(const mozilla::ipc::SharedMemoryHandle&, size_t);
|
explicit SharedStringMap(const mozilla::ipc::ReadOnlySharedMemoryHandle&);
|
||||||
explicit SharedStringMap(SharedStringMapBuilder&&);
|
explicit SharedStringMap(SharedStringMapBuilder&&);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -151,7 +152,7 @@ class SharedStringMap {
|
|||||||
* used to construct new instances of SharedStringMap with the same data as
|
* used to construct new instances of SharedStringMap with the same data as
|
||||||
* this instance.
|
* this instance.
|
||||||
*/
|
*/
|
||||||
mozilla::ipc::SharedMemoryHandle CloneHandle() const;
|
mozilla::ipc::ReadOnlySharedMemoryHandle CloneHandle() const;
|
||||||
|
|
||||||
size_t MapSize() const { return mMappedMemory.size(); }
|
size_t MapSize() const { return mMappedMemory.size(); }
|
||||||
|
|
||||||
@@ -172,21 +173,23 @@ class SharedStringMap {
|
|||||||
|
|
||||||
StringTable<nsCString> KeyTable() const {
|
StringTable<nsCString> KeyTable() const {
|
||||||
const auto& header = GetHeader();
|
const auto& header = GetHeader();
|
||||||
return {{&mMappedMemory.data()[header.mKeyStringsOffset],
|
return {
|
||||||
header.mKeyStringsSize}};
|
{const_cast<uint8_t*>(&mMappedMemory.data()[header.mKeyStringsOffset]),
|
||||||
|
header.mKeyStringsSize}};
|
||||||
}
|
}
|
||||||
|
|
||||||
StringTable<nsString> ValueTable() const {
|
StringTable<nsString> ValueTable() const {
|
||||||
const auto& header = GetHeader();
|
const auto& header = GetHeader();
|
||||||
return {{&mMappedMemory.data()[header.mValueStringsOffset],
|
return {{const_cast<uint8_t*>(
|
||||||
|
&mMappedMemory.data()[header.mValueStringsOffset]),
|
||||||
header.mValueStringsSize}};
|
header.mValueStringsSize}};
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::SharedMemoryHandle mHandle;
|
mozilla::ipc::ReadOnlySharedMemoryHandle mHandle;
|
||||||
// This is a leaked shared memory mapping (see the constructor definition for
|
// This is a leaked shared memory mapping (see the constructor definition for
|
||||||
// an explanation). It replaces AutoMemMap::setPersistent behavior as part of
|
// an explanation). It replaces AutoMemMap::setPersistent behavior as part of
|
||||||
// bug 1454816.
|
// bug 1454816.
|
||||||
Span<uint8_t> 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
|
* Finalizes the binary representation of the map, writes it to a shared
|
||||||
* memory region, and then initializes the given SharedMemory with a reference
|
* memory region, and then returns a read-only handle to it.
|
||||||
* to the read-only copy of it.
|
|
||||||
*/
|
*/
|
||||||
Result<Ok, nsresult> Finalize(RefPtr<mozilla::ipc::SharedMemory>& aMap);
|
Result<mozilla::ipc::ReadOnlySharedMemoryHandle, nsresult> Finalize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Entry = SharedStringMap::Entry;
|
using Entry = SharedStringMap::Entry;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||||
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
||||||
# include "mozilla/SandboxInfo.h"
|
# include "mozilla/SandboxInfo.h"
|
||||||
# include "mozilla/ipc/SharedMemory.h"
|
# include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
#endif
|
#endif
|
||||||
#include "mozilla/Services.h"
|
#include "mozilla/Services.h"
|
||||||
#include "mozilla/SSE.h"
|
#include "mozilla/SSE.h"
|
||||||
@@ -303,7 +303,7 @@ class NotifyGMPProcessLoadedTask : public Runnable {
|
|||||||
|
|
||||||
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
||||||
if (SandboxInfo::Get().Test(SandboxInfo::kEnabledForMedia) &&
|
if (SandboxInfo::Get().Test(SandboxInfo::kEnabledForMedia) &&
|
||||||
ipc::SharedMemory::UsingPosixShm()) {
|
ipc::shared_memory::UsingPosixShm()) {
|
||||||
canProfile = false;
|
canProfile = false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -18,11 +18,9 @@ void GMPProcessChild::InitStatics(int aArgc, char* aArgv[]) {
|
|||||||
Maybe<bool> nativeEvent = geckoargs::sPluginNativeEvent.Get(aArgc, aArgv);
|
Maybe<bool> nativeEvent = geckoargs::sPluginNativeEvent.Get(aArgc, aArgv);
|
||||||
sUseNativeEventProcessing = nativeEvent.isSome() && *nativeEvent;
|
sUseNativeEventProcessing = nativeEvent.isSome() && *nativeEvent;
|
||||||
|
|
||||||
Maybe<uint64_t> prefsLen =
|
auto prefsHandlePresent = geckoargs::sPrefsHandle.IsPresent(aArgc, aArgv);
|
||||||
geckoargs::sPrefsLen.Get(aArgc, aArgv, CheckArgFlag::None);
|
auto prefMapHandlePresent = geckoargs::sPrefMapHandle.IsPresent(aArgc, aArgv);
|
||||||
Maybe<uint64_t> prefMapSize =
|
sUseXpcom = prefsHandlePresent && prefMapHandlePresent;
|
||||||
geckoargs::sPrefMapSize.Get(aArgc, aArgv, CheckArgFlag::None);
|
|
||||||
sUseXpcom = prefsLen.isSome() && prefMapSize.isSome();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GMPProcessChild::~GMPProcessChild() = default;
|
GMPProcessChild::~GMPProcessChild() = default;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "GMPSharedMemManager.h"
|
#include "GMPSharedMemManager.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
|
|
||||||
namespace mozilla::gmp {
|
namespace mozilla::gmp {
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ bool GMPSharedMemManager::MgrTakeShmem(GMPSharedMemClass aClass, size_t aSize,
|
|||||||
MOZ_ASSERT(MgrIsOnOwningThread());
|
MOZ_ASSERT(MgrIsOnOwningThread());
|
||||||
|
|
||||||
auto& pool = mPool[size_t(aClass)];
|
auto& pool = mPool[size_t(aClass)];
|
||||||
size_t alignedSize = ipc::SharedMemory::PageAlignedSize(aSize);
|
size_t alignedSize = ipc::shared_memory::PageAlignedSize(aSize);
|
||||||
PurgeSmallerShmem(pool, alignedSize);
|
PurgeSmallerShmem(pool, alignedSize);
|
||||||
if (pool.IsEmpty()) {
|
if (pool.IsEmpty()) {
|
||||||
return MgrAllocShmem(alignedSize, aMem);
|
return MgrAllocShmem(alignedSize, aMem);
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ struct MemWriter {
|
|||||||
|
|
||||||
// An istream like class for reading from memory
|
// An istream like class for reading from memory
|
||||||
struct MemReader {
|
struct MemReader {
|
||||||
constexpr MemReader(char* aData, size_t aLen)
|
constexpr MemReader(const char* aData, size_t aLen)
|
||||||
: mData(aData), mEnd(aData + aLen) {}
|
: mData(aData), mEnd(aData + aLen) {}
|
||||||
void read(char* s, std::streamsize n) {
|
void read(char* s, std::streamsize n) {
|
||||||
if (n <= (mEnd - mData)) {
|
if (n <= (mEnd - mData)) {
|
||||||
@@ -255,8 +255,8 @@ struct MemReader {
|
|||||||
bool good() { return !eof(); }
|
bool good() { return !eof(); }
|
||||||
void SetIsBad() { mData = mEnd + 1; }
|
void SetIsBad() { mData = mEnd + 1; }
|
||||||
|
|
||||||
char* mData;
|
const char* mData;
|
||||||
char* mEnd;
|
const char* mEnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ContiguousBuffer {
|
class ContiguousBuffer {
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
#include "mozilla/gfx/Types.h"
|
#include "mozilla/gfx/Types.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
|
||||||
#include "mozilla/layers/TextureClient.h"
|
#include "mozilla/layers/TextureClient.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|||||||
@@ -21,28 +21,27 @@ namespace mozilla {
|
|||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
struct ShmemAndHandle {
|
struct ShmemAndHandle {
|
||||||
RefPtr<ipc::SharedMemory> shmem;
|
ipc::SharedMemoryMapping shmem;
|
||||||
Handle handle;
|
ipc::MutableSharedMemoryHandle handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Maybe<ShmemAndHandle> CreateAndMapShmem(size_t aSize) {
|
static Maybe<ShmemAndHandle> CreateAndMapShmem(size_t aSize) {
|
||||||
auto shmem = MakeRefPtr<ipc::SharedMemory>();
|
auto handle = ipc::shared_memory::Create(aSize);
|
||||||
if (!shmem->Create(aSize) || !shmem->Map(aSize)) {
|
if (!handle) {
|
||||||
|
return Nothing();
|
||||||
|
}
|
||||||
|
auto mapping = handle.Map();
|
||||||
|
if (!mapping) {
|
||||||
return Nothing();
|
return Nothing();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto shmemHandle = shmem->TakeHandle();
|
return Some(ShmemAndHandle{std::move(mapping), std::move(handle)});
|
||||||
if (!shmemHandle) {
|
|
||||||
return Nothing();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Some(ShmemAndHandle{shmem.forget(), std::move(shmemHandle)});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CanvasDrawEventRecorder::CanvasDrawEventRecorder(
|
CanvasDrawEventRecorder::CanvasDrawEventRecorder(
|
||||||
dom::ThreadSafeWorkerRef* aWorkerRef)
|
dom::ThreadSafeWorkerRef* aWorkerRef)
|
||||||
: mWorkerRef(aWorkerRef), mIsOnWorker(!!aWorkerRef) {
|
: mWorkerRef(aWorkerRef), mIsOnWorker(!!aWorkerRef) {
|
||||||
mDefaultBufferSize = ipc::SharedMemory::PageAlignedSize(
|
mDefaultBufferSize = ipc::shared_memory::PageAlignedSize(
|
||||||
StaticPrefs::gfx_canvas_remote_default_buffer_size());
|
StaticPrefs::gfx_canvas_remote_default_buffer_size());
|
||||||
mMaxDefaultBuffers = StaticPrefs::gfx_canvas_remote_max_default_buffers();
|
mMaxDefaultBuffers = StaticPrefs::gfx_canvas_remote_max_default_buffers();
|
||||||
mMaxSpinCount = StaticPrefs::gfx_canvas_remote_max_spin_count();
|
mMaxSpinCount = StaticPrefs::gfx_canvas_remote_max_spin_count();
|
||||||
@@ -66,7 +65,7 @@ bool CanvasDrawEventRecorder::Init(TextureType aTextureType,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mHeader = static_cast<Header*>(header->shmem->Memory());
|
mHeader = header->shmem.DataAs<Header>();
|
||||||
mHeader->eventCount = 0;
|
mHeader->eventCount = 0;
|
||||||
mHeader->writerWaitCount = 0;
|
mHeader->writerWaitCount = 0;
|
||||||
mHeader->writerState = State::Processing;
|
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
|
// We always keep at least two buffers. This means that when we
|
||||||
// have to add a new buffer, there is at least a full buffer that requires
|
// have to add a new buffer, there is at least a full buffer that requires
|
||||||
// translating while the handle is sent over.
|
// translating while the handle is sent over.
|
||||||
AutoTArray<Handle, 2> bufferHandles;
|
AutoTArray<ipc::ReadOnlySharedMemoryHandle, 2> bufferHandles;
|
||||||
auto buffer = CreateAndMapShmem(mDefaultBufferSize);
|
auto buffer = CreateAndMapShmem(mDefaultBufferSize);
|
||||||
if (NS_WARN_IF(buffer.isNothing())) {
|
if (NS_WARN_IF(buffer.isNothing())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mCurrentBuffer = CanvasBuffer(std::move(buffer->shmem));
|
mCurrentBuffer = CanvasBuffer(std::move(buffer->shmem));
|
||||||
bufferHandles.AppendElement(std::move(buffer->handle));
|
bufferHandles.AppendElement(std::move(buffer->handle).ToReadOnly());
|
||||||
|
|
||||||
buffer = CreateAndMapShmem(mDefaultBufferSize);
|
buffer = CreateAndMapShmem(mDefaultBufferSize);
|
||||||
if (NS_WARN_IF(buffer.isNothing())) {
|
if (NS_WARN_IF(buffer.isNothing())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mRecycledBuffers.emplace(buffer->shmem.forget(), 0);
|
mRecycledBuffers.emplace(std::move(buffer->shmem), 0);
|
||||||
bufferHandles.AppendElement(std::move(buffer->handle));
|
bufferHandles.AppendElement(std::move(buffer->handle).ToReadOnly());
|
||||||
|
|
||||||
mWriterSemaphore.reset(CrossProcessSemaphore::Create("CanvasRecorder", 0));
|
mWriterSemaphore.reset(CrossProcessSemaphore::Create("CanvasRecorder", 0));
|
||||||
auto writerSem = mWriterSemaphore->CloneHandle();
|
auto writerSem = mWriterSemaphore->CloneHandle();
|
||||||
@@ -107,13 +106,13 @@ bool CanvasDrawEventRecorder::Init(TextureType aTextureType,
|
|||||||
|
|
||||||
if (!mHelpers->InitTranslator(aTextureType, aWebglTextureType, aBackendType,
|
if (!mHelpers->InitTranslator(aTextureType, aWebglTextureType, aBackendType,
|
||||||
std::move(header->handle),
|
std::move(header->handle),
|
||||||
std::move(bufferHandles), mDefaultBufferSize,
|
std::move(bufferHandles), std::move(readerSem),
|
||||||
std::move(readerSem), std::move(writerSem))) {
|
std::move(writerSem))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mTextureType = aTextureType;
|
mTextureType = aTextureType;
|
||||||
mHeaderShmem = header->shmem;
|
mHeaderShmem = std::move(header->shmem);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +245,7 @@ gfx::ContiguousBuffer& CanvasDrawEventRecorder::GetContiguousBuffer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t bufferSize = std::max(mDefaultBufferSize,
|
size_t bufferSize = std::max(mDefaultBufferSize,
|
||||||
ipc::SharedMemory::PageAlignedSize(aSize + 1));
|
ipc::shared_memory::PageAlignedSize(aSize + 1));
|
||||||
auto newBuffer = CreateAndMapShmem(bufferSize);
|
auto newBuffer = CreateAndMapShmem(bufferSize);
|
||||||
if (NS_WARN_IF(newBuffer.isNothing())) {
|
if (NS_WARN_IF(newBuffer.isNothing())) {
|
||||||
mHeader->writerState = State::Failed;
|
mHeader->writerState = State::Failed;
|
||||||
@@ -254,7 +253,7 @@ gfx::ContiguousBuffer& CanvasDrawEventRecorder::GetContiguousBuffer(
|
|||||||
return mCurrentBuffer;
|
return mCurrentBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mHelpers->AddBuffer(std::move(newBuffer->handle), bufferSize)) {
|
if (!mHelpers->AddBuffer(std::move(newBuffer->handle).ToReadOnly())) {
|
||||||
mHeader->writerState = State::Failed;
|
mHeader->writerState = State::Failed;
|
||||||
mCurrentBuffer = CanvasBuffer();
|
mCurrentBuffer = CanvasBuffer();
|
||||||
return mCurrentBuffer;
|
return mCurrentBuffer;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "mozilla/Atomics.h"
|
#include "mozilla/Atomics.h"
|
||||||
#include "mozilla/gfx/DrawEventRecorder.h"
|
#include "mozilla/gfx/DrawEventRecorder.h"
|
||||||
#include "mozilla/ipc/CrossProcessSemaphore.h"
|
#include "mozilla/ipc/CrossProcessSemaphore.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
#include "mozilla/layers/LayersTypes.h"
|
#include "mozilla/layers/LayersTypes.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
@@ -27,7 +27,6 @@ class ThreadSafeWorkerRef;
|
|||||||
|
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
typedef mozilla::ipc::SharedMemory::Handle Handle;
|
|
||||||
typedef mozilla::CrossProcessSemaphoreHandle CrossProcessSemaphoreHandle;
|
typedef mozilla::CrossProcessSemaphoreHandle CrossProcessSemaphoreHandle;
|
||||||
|
|
||||||
class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
|
class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
|
||||||
@@ -72,16 +71,15 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
|
|||||||
public:
|
public:
|
||||||
virtual ~Helpers() = default;
|
virtual ~Helpers() = default;
|
||||||
|
|
||||||
virtual bool InitTranslator(TextureType aTextureType,
|
virtual bool InitTranslator(
|
||||||
TextureType aWebglTextureType,
|
TextureType aTextureType, TextureType aWebglTextureType,
|
||||||
gfx::BackendType aBackendType,
|
gfx::BackendType aBackendType,
|
||||||
Handle&& aReadHandle,
|
ipc::MutableSharedMemoryHandle&& aReadHandle,
|
||||||
nsTArray<Handle>&& aBufferHandles,
|
nsTArray<ipc::ReadOnlySharedMemoryHandle>&& aBufferHandles,
|
||||||
uint64_t aBufferSize,
|
CrossProcessSemaphoreHandle&& aReaderSem,
|
||||||
CrossProcessSemaphoreHandle&& aReaderSem,
|
CrossProcessSemaphoreHandle&& aWriterSem) = 0;
|
||||||
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
|
* @returns true if the reader of the CanvasEventRingBuffer has permanently
|
||||||
@@ -163,29 +161,28 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
|
|||||||
UniquePtr<Helpers> mHelpers;
|
UniquePtr<Helpers> mHelpers;
|
||||||
|
|
||||||
TextureType mTextureType = TextureType::Unknown;
|
TextureType mTextureType = TextureType::Unknown;
|
||||||
RefPtr<ipc::SharedMemory> mHeaderShmem;
|
ipc::SharedMemoryMapping mHeaderShmem;
|
||||||
Header* mHeader = nullptr;
|
Header* mHeader = nullptr;
|
||||||
|
|
||||||
struct CanvasBuffer : public gfx::ContiguousBuffer {
|
struct CanvasBuffer : public gfx::ContiguousBuffer {
|
||||||
RefPtr<ipc::SharedMemory> shmem;
|
ipc::SharedMemoryMapping shmem;
|
||||||
|
|
||||||
CanvasBuffer() : ContiguousBuffer(nullptr) {}
|
CanvasBuffer() : ContiguousBuffer(nullptr) {}
|
||||||
|
|
||||||
explicit CanvasBuffer(RefPtr<ipc::SharedMemory>&& aShmem)
|
explicit CanvasBuffer(ipc::SharedMemoryMapping&& aShmem)
|
||||||
: ContiguousBuffer(static_cast<char*>(aShmem->Memory()),
|
: ContiguousBuffer(aShmem.DataAs<char>(), aShmem.Size()),
|
||||||
aShmem->Size()),
|
|
||||||
shmem(std::move(aShmem)) {}
|
shmem(std::move(aShmem)) {}
|
||||||
|
|
||||||
size_t Capacity() { return shmem ? shmem->Size() : 0; }
|
size_t Capacity() { return shmem ? shmem.Size() : 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RecycledBuffer {
|
struct RecycledBuffer {
|
||||||
RefPtr<ipc::SharedMemory> shmem;
|
ipc::SharedMemoryMapping shmem;
|
||||||
int64_t eventCount = 0;
|
int64_t eventCount = 0;
|
||||||
explicit RecycledBuffer(RefPtr<ipc::SharedMemory>&& aShmem,
|
explicit RecycledBuffer(ipc::SharedMemoryMapping&& aShmem,
|
||||||
int64_t aEventCount)
|
int64_t aEventCount)
|
||||||
: shmem(std::move(aShmem)), eventCount(aEventCount) {}
|
: shmem(std::move(aShmem)), eventCount(aEventCount) {}
|
||||||
size_t Capacity() { return shmem->Size(); }
|
size_t Capacity() { return shmem.Size(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
CanvasBuffer mCurrentBuffer;
|
CanvasBuffer mCurrentBuffer;
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ using gfx::ReadElement;
|
|||||||
using gfx::ReferencePtr;
|
using gfx::ReferencePtr;
|
||||||
using gfx::SurfaceFormat;
|
using gfx::SurfaceFormat;
|
||||||
using gfx::WriteElement;
|
using gfx::WriteElement;
|
||||||
using ipc::SharedMemory;
|
|
||||||
|
|
||||||
const EventType CANVAS_BEGIN_TRANSACTION = EventType::LAST;
|
const EventType CANVAS_BEGIN_TRANSACTION = EventType::LAST;
|
||||||
const EventType CANVAS_END_TRANSACTION = EventType(EventType::LAST + 1);
|
const EventType CANVAS_END_TRANSACTION = EventType(EventType::LAST + 1);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "mozilla/Likely.h"
|
#include "mozilla/Likely.h"
|
||||||
#include "mozilla/StaticPrefs_image.h"
|
#include "mozilla/StaticPrefs_image.h"
|
||||||
#include "mozilla/Types.h" // for decltype
|
#include "mozilla/Types.h" // for decltype
|
||||||
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
#include "mozilla/layers/SharedSurfacesChild.h"
|
#include "mozilla/layers/SharedSurfacesChild.h"
|
||||||
#include "mozilla/layers/SharedSurfacesParent.h"
|
#include "mozilla/layers/SharedSurfacesParent.h"
|
||||||
#include "nsDebug.h" // for NS_ABORT_OOM
|
#include "nsDebug.h" // for NS_ABORT_OOM
|
||||||
@@ -30,10 +31,9 @@ using namespace mozilla::layers;
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
|
|
||||||
void SourceSurfaceSharedDataWrapper::Init(const IntSize& aSize, int32_t aStride,
|
void SourceSurfaceSharedDataWrapper::Init(
|
||||||
SurfaceFormat aFormat,
|
const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat,
|
||||||
SharedMemory::Handle aHandle,
|
ipc::ReadOnlySharedMemoryHandle aHandle, base::ProcessId aCreatorPid) {
|
||||||
base::ProcessId aCreatorPid) {
|
|
||||||
MOZ_ASSERT(!mBuf);
|
MOZ_ASSERT(!mBuf);
|
||||||
mSize = aSize;
|
mSize = aSize;
|
||||||
mStride = aStride;
|
mStride = aStride;
|
||||||
@@ -41,8 +41,8 @@ void SourceSurfaceSharedDataWrapper::Init(const IntSize& aSize, int32_t aStride,
|
|||||||
mCreatorPid = aCreatorPid;
|
mCreatorPid = aCreatorPid;
|
||||||
|
|
||||||
size_t len = GetAlignedDataLength();
|
size_t len = GetAlignedDataLength();
|
||||||
mBuf = MakeAndAddRef<SharedMemory>();
|
mBufHandle = std::move(aHandle);
|
||||||
if (!mBuf->SetHandle(std::move(aHandle), ipc::SharedMemory::RightsReadOnly)) {
|
if (!mBufHandle) {
|
||||||
MOZ_CRASH("Invalid shared memory handle!");
|
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.
|
// We don't support unmapping for this surface, and we failed to map it.
|
||||||
NS_ABORT_OOM(len);
|
NS_ABORT_OOM(len);
|
||||||
} else {
|
} else {
|
||||||
mBuf->CloseHandle();
|
mBufHandle = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,15 +80,20 @@ void SourceSurfaceSharedDataWrapper::Init(SourceSurfaceSharedData* aSurface) {
|
|||||||
bool SourceSurfaceSharedDataWrapper::EnsureMapped(size_t aLength) {
|
bool SourceSurfaceSharedDataWrapper::EnsureMapped(size_t aLength) {
|
||||||
MOZ_ASSERT(!GetData());
|
MOZ_ASSERT(!GetData());
|
||||||
|
|
||||||
while (!mBuf->Map(aLength)) {
|
auto mapping = mBufHandle.Map();
|
||||||
|
while (!mapping) {
|
||||||
nsTArray<RefPtr<SourceSurfaceSharedDataWrapper>> expired;
|
nsTArray<RefPtr<SourceSurfaceSharedDataWrapper>> expired;
|
||||||
if (!SharedSurfacesParent::AgeOneGeneration(expired)) {
|
if (!SharedSurfacesParent::AgeOneGeneration(expired)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(!expired.Contains(this));
|
MOZ_ASSERT(!expired.Contains(this));
|
||||||
SharedSurfacesParent::ExpireMap(expired);
|
SharedSurfacesParent::ExpireMap(expired);
|
||||||
|
mapping = mBufHandle.Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mBuf = std::make_shared<ipc::MutableOrReadOnlySharedMemoryMapping>(
|
||||||
|
std::move(mapping));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +148,8 @@ void SourceSurfaceSharedDataWrapper::Unmap() {
|
|||||||
void SourceSurfaceSharedDataWrapper::ExpireMap() {
|
void SourceSurfaceSharedDataWrapper::ExpireMap() {
|
||||||
MutexAutoLock lock(*mHandleLock);
|
MutexAutoLock lock(*mHandleLock);
|
||||||
if (mMapCount == 0) {
|
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;
|
mFormat = aFormat;
|
||||||
|
|
||||||
size_t len = GetAlignedDataLength();
|
size_t len = GetAlignedDataLength();
|
||||||
mBuf = new SharedMemory();
|
mBufHandle = ipc::shared_memory::Create(len);
|
||||||
if (NS_WARN_IF(!mBuf->Create(len)) || NS_WARN_IF(!mBuf->Map(len))) {
|
mBuf = std::make_shared<ipc::MutableOrReadOnlySharedMemoryMapping>(
|
||||||
mBuf = nullptr;
|
mBufHandle.Map());
|
||||||
|
if (NS_WARN_IF(!mBufHandle) || NS_WARN_IF(!mBuf || !*mBuf)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,17 +194,23 @@ void SourceSurfaceSharedData::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
|
|||||||
uint8_t* SourceSurfaceSharedData::GetDataInternal() const {
|
uint8_t* SourceSurfaceSharedData::GetDataInternal() const {
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMutex.AssertCurrentThreadOwns();
|
||||||
|
|
||||||
|
// This class's mappings are always mutable, so we can safely cast away the
|
||||||
|
// const in the values returned here (see the comment above the `mBuf`
|
||||||
|
// declaration).
|
||||||
|
|
||||||
// If we have an old buffer lingering, it is because we get reallocated to
|
// If we have an old buffer lingering, it is because we get reallocated to
|
||||||
// get a new handle to share, but there were still active mappings.
|
// get a new handle to share, but there were still active mappings.
|
||||||
if (MOZ_UNLIKELY(mOldBuf)) {
|
if (MOZ_UNLIKELY(mOldBuf)) {
|
||||||
MOZ_ASSERT(mMapCount > 0);
|
MOZ_ASSERT(mMapCount > 0);
|
||||||
MOZ_ASSERT(mFinalized);
|
MOZ_ASSERT(mFinalized);
|
||||||
return static_cast<uint8_t*>(mOldBuf->Memory());
|
return const_cast<uint8_t*>(mOldBuf->DataAs<uint8_t>());
|
||||||
}
|
}
|
||||||
return static_cast<uint8_t*>(mBuf->Memory());
|
// Const cast to match `GetData()`.
|
||||||
|
return const_cast<uint8_t*>(mBuf->DataAs<uint8_t>());
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult SourceSurfaceSharedData::CloneHandle(SharedMemory::Handle& aHandle) {
|
nsresult SourceSurfaceSharedData::CloneHandle(
|
||||||
|
ipc::ReadOnlySharedMemoryHandle& aHandle) {
|
||||||
MutexAutoLock lock(mMutex);
|
MutexAutoLock lock(mMutex);
|
||||||
MOZ_ASSERT(mHandleCount > 0);
|
MOZ_ASSERT(mHandleCount > 0);
|
||||||
|
|
||||||
@@ -205,7 +218,7 @@ nsresult SourceSurfaceSharedData::CloneHandle(SharedMemory::Handle& aHandle) {
|
|||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
aHandle = mBuf->CloneHandle();
|
aHandle = mBufHandle.Clone().ToReadOnly();
|
||||||
if (MOZ_UNLIKELY(!aHandle)) {
|
if (MOZ_UNLIKELY(!aHandle)) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
@@ -223,7 +236,7 @@ void SourceSurfaceSharedData::CloseHandleInternal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mShared) {
|
if (mShared) {
|
||||||
mBuf->CloseHandle();
|
mBufHandle = nullptr;
|
||||||
mClosed = true;
|
mClosed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,21 +255,25 @@ bool SourceSurfaceSharedData::ReallocHandle() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t len = GetAlignedDataLength();
|
size_t len = GetAlignedDataLength();
|
||||||
RefPtr<SharedMemory> buf = new SharedMemory();
|
auto handle = ipc::shared_memory::Create(len);
|
||||||
if (NS_WARN_IF(!buf->Create(len)) || NS_WARN_IF(!buf->Map(len))) {
|
auto mapping = handle.Map();
|
||||||
|
if (NS_WARN_IF(!handle) || NS_WARN_IF(!mapping)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t copyLen = GetDataLength();
|
size_t copyLen = GetDataLength();
|
||||||
memcpy(buf->Memory(), mBuf->Memory(), copyLen);
|
memcpy(mapping.Address(), mBuf->Address(), copyLen);
|
||||||
#ifdef SHARED_SURFACE_PROTECT_FINALIZED
|
#ifdef SHARED_SURFACE_PROTECT_FINALIZED
|
||||||
buf->Protect(static_cast<char*>(buf->Memory()), len, RightsRead);
|
ipc::shared_memory::LocalProtect(mapping.DataAs<char>(), len,
|
||||||
|
ipc::shared_memory::AccessRead);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (mMapCount > 0 && !mOldBuf) {
|
if (mMapCount > 0 && !mOldBuf) {
|
||||||
mOldBuf = std::move(mBuf);
|
mOldBuf = std::move(mBuf);
|
||||||
}
|
}
|
||||||
mBuf = std::move(buf);
|
mBufHandle = std::move(handle);
|
||||||
|
mBuf = std::make_shared<ipc::MutableOrReadOnlySharedMemoryMapping>(
|
||||||
|
std::move(mapping));
|
||||||
mClosed = false;
|
mClosed = false;
|
||||||
mShared = false;
|
mShared = false;
|
||||||
return true;
|
return true;
|
||||||
@@ -268,7 +285,10 @@ void SourceSurfaceSharedData::Finalize() {
|
|||||||
|
|
||||||
#ifdef SHARED_SURFACE_PROTECT_FINALIZED
|
#ifdef SHARED_SURFACE_PROTECT_FINALIZED
|
||||||
size_t len = GetAlignedDataLength();
|
size_t len = GetAlignedDataLength();
|
||||||
mBuf->Protect(static_cast<char*>(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<char*>(mBuf->DataAs<char>()), len,
|
||||||
|
ipc::shared_memory::AccessRead);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mFinalized = true;
|
mFinalized = true;
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
#include "base/process.h"
|
#include "base/process.h"
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
#include "mozilla/Mutex.h"
|
#include "mozilla/Mutex.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
#include "nsExpirationTracker.h"
|
#include "nsExpirationTracker.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@@ -34,8 +35,6 @@ class SourceSurfaceSharedData;
|
|||||||
* mapped in the given shared memory handle as read only memory.
|
* mapped in the given shared memory handle as read only memory.
|
||||||
*/
|
*/
|
||||||
class SourceSurfaceSharedDataWrapper final : public DataSourceSurface {
|
class SourceSurfaceSharedDataWrapper final : public DataSourceSurface {
|
||||||
typedef mozilla::ipc::SharedMemory SharedMemory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceSharedDataWrapper,
|
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceSharedDataWrapper,
|
||||||
override)
|
override)
|
||||||
@@ -43,7 +42,8 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface {
|
|||||||
SourceSurfaceSharedDataWrapper() = default;
|
SourceSurfaceSharedDataWrapper() = default;
|
||||||
|
|
||||||
void Init(const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat,
|
void Init(const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat,
|
||||||
SharedMemory::Handle aHandle, base::ProcessId aCreatorPid);
|
mozilla::ipc::ReadOnlySharedMemoryHandle aHandle,
|
||||||
|
base::ProcessId aCreatorPid);
|
||||||
|
|
||||||
void Init(SourceSurfaceSharedData* aSurface);
|
void Init(SourceSurfaceSharedData* aSurface);
|
||||||
|
|
||||||
@@ -57,7 +57,11 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface {
|
|||||||
IntSize GetSize() const override { return mSize; }
|
IntSize GetSize() const override { return mSize; }
|
||||||
SurfaceFormat GetFormat() const override { return mFormat; }
|
SurfaceFormat GetFormat() const override { return mFormat; }
|
||||||
|
|
||||||
uint8_t* GetData() override { return static_cast<uint8_t*>(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<uint8_t*>(mBuf->DataAs<uint8_t>()) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool OnHeap() const override { return false; }
|
bool OnHeap() const override { return false; }
|
||||||
|
|
||||||
@@ -97,7 +101,7 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t GetAlignedDataLength() const {
|
size_t GetAlignedDataLength() const {
|
||||||
return mozilla::ipc::SharedMemory::PageAlignedSize(GetDataLength());
|
return mozilla::ipc::shared_memory::PageAlignedSize(GetDataLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EnsureMapped(size_t aLength);
|
bool EnsureMapped(size_t aLength);
|
||||||
@@ -108,7 +112,9 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface {
|
|||||||
int32_t mStride = 0;
|
int32_t mStride = 0;
|
||||||
uint32_t mConsumers = 1;
|
uint32_t mConsumers = 1;
|
||||||
IntSize mSize;
|
IntSize mSize;
|
||||||
RefPtr<SharedMemory> mBuf;
|
// This is only used to support EnsureMapped if we fail initially.
|
||||||
|
mozilla::ipc::ReadOnlySharedMemoryHandle mBufHandle;
|
||||||
|
std::shared_ptr<mozilla::ipc::MutableOrReadOnlySharedMemoryMapping> mBuf;
|
||||||
SurfaceFormat mFormat = SurfaceFormat::UNKNOWN;
|
SurfaceFormat mFormat = SurfaceFormat::UNKNOWN;
|
||||||
base::ProcessId mCreatorPid = 0;
|
base::ProcessId mCreatorPid = 0;
|
||||||
bool mCreatorRef = true;
|
bool mCreatorRef = true;
|
||||||
@@ -119,8 +125,6 @@ class SourceSurfaceSharedDataWrapper final : public DataSourceSurface {
|
|||||||
* source surface.
|
* source surface.
|
||||||
*/
|
*/
|
||||||
class SourceSurfaceSharedData : public DataSourceSurface {
|
class SourceSurfaceSharedData : public DataSourceSurface {
|
||||||
typedef mozilla::ipc::SharedMemory SharedMemory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceSharedData, override)
|
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceSharedData, override)
|
||||||
|
|
||||||
@@ -197,7 +201,7 @@ class SourceSurfaceSharedData : public DataSourceSurface {
|
|||||||
* NS_ERROR_NOT_AVAILABLE -- handle was closed, need to reallocate.
|
* NS_ERROR_NOT_AVAILABLE -- handle was closed, need to reallocate.
|
||||||
* NS_ERROR_FAILURE -- failed to create a handle to share.
|
* NS_ERROR_FAILURE -- failed to create a handle to share.
|
||||||
*/
|
*/
|
||||||
nsresult CloneHandle(SharedMemory::Handle& aHandle);
|
nsresult CloneHandle(mozilla::ipc::ReadOnlySharedMemoryHandle& aHandle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates the buffer is not expected to be shared with any more processes.
|
* Indicates the buffer is not expected to be shared with any more processes.
|
||||||
@@ -314,7 +318,7 @@ class SourceSurfaceSharedData : public DataSourceSurface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t GetAlignedDataLength() const {
|
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;
|
int32_t mHandleCount;
|
||||||
Maybe<IntRect> mDirtyRect;
|
Maybe<IntRect> mDirtyRect;
|
||||||
IntSize mSize;
|
IntSize mSize;
|
||||||
RefPtr<SharedMemory> mBuf;
|
mozilla::ipc::MutableSharedMemoryHandle mBufHandle;
|
||||||
RefPtr<SharedMemory> mOldBuf;
|
// 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<mozilla::ipc::MutableOrReadOnlySharedMemoryMapping> mBuf;
|
||||||
|
std::shared_ptr<mozilla::ipc::MutableOrReadOnlySharedMemoryMapping> mOldBuf;
|
||||||
SurfaceFormat mFormat;
|
SurfaceFormat mFormat;
|
||||||
bool mClosed : 1;
|
bool mClosed : 1;
|
||||||
bool mFinalized : 1;
|
bool mFinalized : 1;
|
||||||
|
|||||||
@@ -86,9 +86,8 @@
|
|||||||
#include "nsThreadUtils.h" // for NS_IsMainThread
|
#include "nsThreadUtils.h" // for NS_IsMainThread
|
||||||
#include "nsViewportInfo.h" // for ViewportMinScale(), ViewportMaxScale()
|
#include "nsViewportInfo.h" // for ViewportMinScale(), ViewportMaxScale()
|
||||||
#include "prsystem.h" // for PR_GetPhysicalMemorySize
|
#include "prsystem.h" // for PR_GetPhysicalMemorySize
|
||||||
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory
|
#include "ScrollSnap.h" // for ScrollSnapUtils
|
||||||
#include "ScrollSnap.h" // for ScrollSnapUtils
|
#include "ScrollAnimationPhysics.h" // for ComputeAcceleratedWheelDelta
|
||||||
#include "ScrollAnimationPhysics.h" // for ComputeAcceleratedWheelDelta
|
|
||||||
#include "SmoothMsdScrollAnimation.h"
|
#include "SmoothMsdScrollAnimation.h"
|
||||||
#include "SmoothScrollAnimation.h"
|
#include "SmoothScrollAnimation.h"
|
||||||
#include "WheelScrollAnimation.h"
|
#include "WheelScrollAnimation.h"
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
#include "mozilla/gfx/Logging.h" // for gfxDebug
|
#include "mozilla/gfx/Logging.h" // for gfxDebug
|
||||||
#include "mozilla/gfx/gfxVars.h"
|
#include "mozilla/gfx/gfxVars.h"
|
||||||
#include "mozilla/ipc/CrossProcessSemaphore.h"
|
#include "mozilla/ipc/CrossProcessSemaphore.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
|
|
||||||
#include "mozilla/layers/CanvasRenderer.h"
|
#include "mozilla/layers/CanvasRenderer.h"
|
||||||
#include "mozilla/layers/CompositableForwarder.h"
|
#include "mozilla/layers/CompositableForwarder.h"
|
||||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "mozilla/gfx/Point.h"
|
#include "mozilla/gfx/Point.h"
|
||||||
#include "mozilla/ipc/Endpoint.h"
|
#include "mozilla/ipc/Endpoint.h"
|
||||||
#include "mozilla/ipc/ProcessChild.h"
|
#include "mozilla/ipc/ProcessChild.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
#include "mozilla/layers/CanvasDrawEventRecorder.h"
|
#include "mozilla/layers/CanvasDrawEventRecorder.h"
|
||||||
#include "mozilla/layers/ImageDataSerializer.h"
|
#include "mozilla/layers/ImageDataSerializer.h"
|
||||||
#include "mozilla/layers/SourceSurfaceSharedData.h"
|
#include "mozilla/layers/SourceSurfaceSharedData.h"
|
||||||
@@ -39,27 +40,29 @@ class RecorderHelpers final : public CanvasDrawEventRecorder::Helpers {
|
|||||||
|
|
||||||
~RecorderHelpers() override = default;
|
~RecorderHelpers() override = default;
|
||||||
|
|
||||||
bool InitTranslator(TextureType aTextureType, TextureType aWebglTextureType,
|
bool InitTranslator(
|
||||||
gfx::BackendType aBackendType, Handle&& aReadHandle,
|
TextureType aTextureType, TextureType aWebglTextureType,
|
||||||
nsTArray<Handle>&& aBufferHandles, uint64_t aBufferSize,
|
gfx::BackendType aBackendType,
|
||||||
CrossProcessSemaphoreHandle&& aReaderSem,
|
ipc::MutableSharedMemoryHandle&& aReadHandle,
|
||||||
CrossProcessSemaphoreHandle&& aWriterSem) override {
|
nsTArray<ipc::ReadOnlySharedMemoryHandle>&& aBufferHandles,
|
||||||
|
CrossProcessSemaphoreHandle&& aReaderSem,
|
||||||
|
CrossProcessSemaphoreHandle&& aWriterSem) override {
|
||||||
NS_ASSERT_OWNINGTHREAD(RecorderHelpers);
|
NS_ASSERT_OWNINGTHREAD(RecorderHelpers);
|
||||||
if (NS_WARN_IF(!mCanvasChild)) {
|
if (NS_WARN_IF(!mCanvasChild)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return mCanvasChild->SendInitTranslator(
|
return mCanvasChild->SendInitTranslator(
|
||||||
aTextureType, aWebglTextureType, aBackendType, std::move(aReadHandle),
|
aTextureType, aWebglTextureType, aBackendType, std::move(aReadHandle),
|
||||||
std::move(aBufferHandles), aBufferSize, std::move(aReaderSem),
|
std::move(aBufferHandles), std::move(aReaderSem),
|
||||||
std::move(aWriterSem));
|
std::move(aWriterSem));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AddBuffer(Handle&& aBufferHandle, uint64_t aBufferSize) override {
|
bool AddBuffer(ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) override {
|
||||||
NS_ASSERT_OWNINGTHREAD(RecorderHelpers);
|
NS_ASSERT_OWNINGTHREAD(RecorderHelpers);
|
||||||
if (!mCanvasChild) {
|
if (!mCanvasChild) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return mCanvasChild->SendAddBuffer(std::move(aBufferHandle), aBufferSize);
|
return mCanvasChild->SendAddBuffer(std::move(aBufferHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReaderClosed() override {
|
bool ReaderClosed() override {
|
||||||
@@ -192,7 +195,9 @@ class SourceSurfaceCanvasRecording final : public gfx::SourceSurface {
|
|||||||
|
|
||||||
class CanvasDataShmemHolder {
|
class CanvasDataShmemHolder {
|
||||||
public:
|
public:
|
||||||
CanvasDataShmemHolder(ipc::SharedMemory* aShmem, CanvasChild* aCanvasChild)
|
CanvasDataShmemHolder(
|
||||||
|
const std::shared_ptr<ipc::ReadOnlySharedMemoryMapping>& aShmem,
|
||||||
|
CanvasChild* aCanvasChild)
|
||||||
: mMutex("CanvasChild::DataShmemHolder::mMutex"),
|
: mMutex("CanvasChild::DataShmemHolder::mMutex"),
|
||||||
mShmem(aShmem),
|
mShmem(aShmem),
|
||||||
mCanvasChild(aCanvasChild) {}
|
mCanvasChild(aCanvasChild) {}
|
||||||
@@ -259,7 +264,7 @@ class CanvasDataShmemHolder {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mCanvasChild->ReturnDataSurfaceShmem(mShmem.forget());
|
mCanvasChild->ReturnDataSurfaceShmem(std::move(mShmem));
|
||||||
mCanvasChild = nullptr;
|
mCanvasChild = nullptr;
|
||||||
mWorkerRef = nullptr;
|
mWorkerRef = nullptr;
|
||||||
}
|
}
|
||||||
@@ -276,7 +281,7 @@ class CanvasDataShmemHolder {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex mMutex;
|
Mutex mMutex;
|
||||||
RefPtr<ipc::SharedMemory> mShmem;
|
std::shared_ptr<ipc::ReadOnlySharedMemoryMapping> mShmem;
|
||||||
RefPtr<CanvasChild> mCanvasChild MOZ_GUARDED_BY(mMutex);
|
RefPtr<CanvasChild> mCanvasChild MOZ_GUARDED_BY(mMutex);
|
||||||
RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef MOZ_GUARDED_BY(mMutex);
|
RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef MOZ_GUARDED_BY(mMutex);
|
||||||
};
|
};
|
||||||
@@ -489,26 +494,26 @@ bool CanvasChild::EnsureDataSurfaceShmem(gfx::IntSize aSize,
|
|||||||
if (!sizeRequired) {
|
if (!sizeRequired) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
sizeRequired = ipc::SharedMemory::PageAlignedSize(sizeRequired);
|
sizeRequired = ipc::shared_memory::PageAlignedSize(sizeRequired);
|
||||||
|
|
||||||
if (!mDataSurfaceShmemAvailable || mDataSurfaceShmem->Size() < sizeRequired) {
|
if (!mDataSurfaceShmemAvailable || mDataSurfaceShmem->Size() < sizeRequired) {
|
||||||
RecordEvent(RecordedPauseTranslation());
|
RecordEvent(RecordedPauseTranslation());
|
||||||
auto dataSurfaceShmem = MakeRefPtr<ipc::SharedMemory>();
|
auto shmemHandle = ipc::shared_memory::Create(sizeRequired);
|
||||||
if (!dataSurfaceShmem->Create(sizeRequired) ||
|
|
||||||
!dataSurfaceShmem->Map(sizeRequired)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto shmemHandle = dataSurfaceShmem->TakeHandle();
|
|
||||||
if (!shmemHandle) {
|
if (!shmemHandle) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SendSetDataSurfaceBuffer(std::move(shmemHandle), sizeRequired)) {
|
auto roMapping = shmemHandle.AsReadOnly().Map();
|
||||||
|
if (!roMapping) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mDataSurfaceShmem = dataSurfaceShmem.forget();
|
if (!SendSetDataSurfaceBuffer(std::move(shmemHandle))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDataSurfaceShmem = std::make_shared<ipc::ReadOnlySharedMemoryMapping>(
|
||||||
|
std::move(roMapping));
|
||||||
mDataSurfaceShmemAvailable = true;
|
mDataSurfaceShmemAvailable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,8 +565,7 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
|
|||||||
// use that directly without having to allocate a new shmem for retrieval.
|
// use that directly without having to allocate a new shmem for retrieval.
|
||||||
auto it = mTextureInfo.find(aTextureOwnerId);
|
auto it = mTextureInfo.find(aTextureOwnerId);
|
||||||
if (it != mTextureInfo.end() && it->second.mSnapshotShmem) {
|
if (it != mTextureInfo.end() && it->second.mSnapshotShmem) {
|
||||||
const auto shmemPtr =
|
const auto* shmemPtr = it->second.mSnapshotShmem->DataAs<uint8_t>();
|
||||||
reinterpret_cast<uint8_t*>(it->second.mSnapshotShmem->Memory());
|
|
||||||
MOZ_ASSERT(shmemPtr);
|
MOZ_ASSERT(shmemPtr);
|
||||||
mRecorder->RecordEvent(RecordedPrepareShmem(aTextureOwnerId));
|
mRecorder->RecordEvent(RecordedPrepareShmem(aTextureOwnerId));
|
||||||
auto checkpoint = CreateCheckpoint();
|
auto checkpoint = CreateCheckpoint();
|
||||||
@@ -574,10 +578,12 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
|
|||||||
delete closure;
|
delete closure;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
// We can cast away the const of `shmemPtr` to match the call because the
|
||||||
|
// DataSourceSurface will not be written to.
|
||||||
RefPtr<gfx::DataSourceSurface> dataSurface =
|
RefPtr<gfx::DataSourceSurface> dataSurface =
|
||||||
gfx::Factory::CreateWrappingDataSourceSurface(
|
gfx::Factory::CreateWrappingDataSourceSurface(
|
||||||
shmemPtr, stride, ssSize, ssFormat, ReleaseDataShmemHolder,
|
const_cast<uint8_t*>(shmemPtr), stride, ssSize, ssFormat,
|
||||||
closure);
|
ReleaseDataShmemHolder, closure);
|
||||||
aMayInvalidate = true;
|
aMayInvalidate = true;
|
||||||
return dataSurface.forget();
|
return dataSurface.forget();
|
||||||
}
|
}
|
||||||
@@ -603,11 +609,14 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
|
|||||||
|
|
||||||
mDataSurfaceShmemAvailable = false;
|
mDataSurfaceShmemAvailable = false;
|
||||||
|
|
||||||
auto* data = static_cast<uint8_t*>(mDataSurfaceShmem->Memory());
|
const auto* data = mDataSurfaceShmem->DataAs<uint8_t>();
|
||||||
|
|
||||||
|
// We can cast away the const of `data` to match the call because the
|
||||||
|
// DataSourceSurface will not be written to.
|
||||||
RefPtr<gfx::DataSourceSurface> dataSurface =
|
RefPtr<gfx::DataSourceSurface> dataSurface =
|
||||||
gfx::Factory::CreateWrappingDataSourceSurface(
|
gfx::Factory::CreateWrappingDataSourceSurface(
|
||||||
data, stride, ssSize, ssFormat, ReleaseDataShmemHolder, closure);
|
const_cast<uint8_t*>(data), stride, ssSize, ssFormat,
|
||||||
|
ReleaseDataShmemHolder, closure);
|
||||||
aMayInvalidate = false;
|
aMayInvalidate = false;
|
||||||
return dataSurface.forget();
|
return dataSurface.forget();
|
||||||
}
|
}
|
||||||
@@ -631,10 +640,9 @@ already_AddRefed<gfx::SourceSurface> CanvasChild::WrapSurface(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CanvasChild::ReturnDataSurfaceShmem(
|
void CanvasChild::ReturnDataSurfaceShmem(
|
||||||
already_AddRefed<ipc::SharedMemory> aDataSurfaceShmem) {
|
std::shared_ptr<ipc::ReadOnlySharedMemoryMapping>&& aDataSurfaceShmem) {
|
||||||
RefPtr<ipc::SharedMemory> data = aDataSurfaceShmem;
|
|
||||||
// We can only reuse the latest data surface shmem.
|
// We can only reuse the latest data surface shmem.
|
||||||
if (data == mDataSurfaceShmem) {
|
if (aDataSurfaceShmem == mDataSurfaceShmem) {
|
||||||
MOZ_ASSERT(!mDataSurfaceShmemAvailable);
|
MOZ_ASSERT(!mDataSurfaceShmemAvailable);
|
||||||
mDataSurfaceShmemAvailable = true;
|
mDataSurfaceShmemAvailable = true;
|
||||||
}
|
}
|
||||||
@@ -680,17 +688,17 @@ bool CanvasChild::RequiresRefresh(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ipc::IPCResult CanvasChild::RecvSnapshotShmem(
|
ipc::IPCResult CanvasChild::RecvSnapshotShmem(
|
||||||
const RemoteTextureOwnerId aTextureOwnerId, Handle&& aShmemHandle,
|
const RemoteTextureOwnerId aTextureOwnerId,
|
||||||
uint32_t aShmemSize, SnapshotShmemResolver&& aResolve) {
|
ipc::ReadOnlySharedMemoryHandle&& aShmemHandle,
|
||||||
|
SnapshotShmemResolver&& aResolve) {
|
||||||
auto it = mTextureInfo.find(aTextureOwnerId);
|
auto it = mTextureInfo.find(aTextureOwnerId);
|
||||||
if (it != mTextureInfo.end()) {
|
if (it != mTextureInfo.end()) {
|
||||||
auto shmem = MakeRefPtr<ipc::SharedMemory>();
|
auto shmem = aShmemHandle.Map();
|
||||||
if (NS_WARN_IF(!shmem->SetHandle(std::move(aShmemHandle),
|
if (NS_WARN_IF(!shmem)) {
|
||||||
ipc::SharedMemory::RightsReadOnly)) ||
|
|
||||||
NS_WARN_IF(!shmem->Map(aShmemSize))) {
|
|
||||||
shmem = nullptr;
|
shmem = nullptr;
|
||||||
} else {
|
} else {
|
||||||
it->second.mSnapshotShmem = std::move(shmem);
|
it->second.mSnapshotShmem =
|
||||||
|
std::make_shared<ipc::ReadOnlySharedMemoryMapping>(std::move(shmem));
|
||||||
}
|
}
|
||||||
aResolve(true);
|
aResolve(true);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "mozilla/gfx/RecordedEvent.h"
|
#include "mozilla/gfx/RecordedEvent.h"
|
||||||
#include "mozilla/ipc/CrossProcessSemaphore.h"
|
#include "mozilla/ipc/CrossProcessSemaphore.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
#include "mozilla/layers/PCanvasChild.h"
|
#include "mozilla/layers/PCanvasChild.h"
|
||||||
#include "mozilla/layers/SourceSurfaceSharedData.h"
|
#include "mozilla/layers/SourceSurfaceSharedData.h"
|
||||||
#include "mozilla/WeakPtr.h"
|
#include "mozilla/WeakPtr.h"
|
||||||
@@ -56,9 +57,10 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
|
|||||||
ipc::IPCResult RecvNotifyRequiresRefresh(
|
ipc::IPCResult RecvNotifyRequiresRefresh(
|
||||||
const RemoteTextureOwnerId aTextureOwnerId);
|
const RemoteTextureOwnerId aTextureOwnerId);
|
||||||
|
|
||||||
ipc::IPCResult RecvSnapshotShmem(const RemoteTextureOwnerId aTextureOwnerId,
|
ipc::IPCResult RecvSnapshotShmem(
|
||||||
Handle&& aShmemHandle, uint32_t aShmemSize,
|
const RemoteTextureOwnerId aTextureOwnerId,
|
||||||
SnapshotShmemResolver&& aResolve);
|
ipc::ReadOnlySharedMemoryHandle&& aShmemHandle,
|
||||||
|
SnapshotShmemResolver&& aResolve);
|
||||||
|
|
||||||
ipc::IPCResult RecvNotifyTextureDestruction(
|
ipc::IPCResult RecvNotifyTextureDestruction(
|
||||||
const RemoteTextureOwnerId aTextureOwnerId);
|
const RemoteTextureOwnerId aTextureOwnerId);
|
||||||
@@ -162,7 +164,7 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
|
|||||||
bool RequiresRefresh(const RemoteTextureOwnerId aTextureOwnerId) const;
|
bool RequiresRefresh(const RemoteTextureOwnerId aTextureOwnerId) const;
|
||||||
|
|
||||||
void ReturnDataSurfaceShmem(
|
void ReturnDataSurfaceShmem(
|
||||||
already_AddRefed<ipc::SharedMemory> aDataSurfaceShmem);
|
std::shared_ptr<ipc::ReadOnlySharedMemoryMapping>&& aDataSurfaceShmem);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ActorDestroy(ActorDestroyReason aWhy) final;
|
void ActorDestroy(ActorDestroyReason aWhy) final;
|
||||||
@@ -185,12 +187,12 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
|
|||||||
RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef;
|
RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef;
|
||||||
RefPtr<CanvasDrawEventRecorder> mRecorder;
|
RefPtr<CanvasDrawEventRecorder> mRecorder;
|
||||||
|
|
||||||
RefPtr<ipc::SharedMemory> mDataSurfaceShmem;
|
std::shared_ptr<ipc::ReadOnlySharedMemoryMapping> mDataSurfaceShmem;
|
||||||
bool mDataSurfaceShmemAvailable = false;
|
bool mDataSurfaceShmemAvailable = false;
|
||||||
int64_t mLastWriteLockCheckpoint = 0;
|
int64_t mLastWriteLockCheckpoint = 0;
|
||||||
uint32_t mTransactionsSinceGetDataSurface = kCacheDataSurfaceThreshold;
|
uint32_t mTransactionsSinceGetDataSurface = kCacheDataSurfaceThreshold;
|
||||||
struct TextureInfo {
|
struct TextureInfo {
|
||||||
RefPtr<mozilla::ipc::SharedMemory> mSnapshotShmem;
|
std::shared_ptr<mozilla::ipc::ReadOnlySharedMemoryMapping> mSnapshotShmem;
|
||||||
bool mRequiresRefresh = false;
|
bool mRequiresRefresh = false;
|
||||||
};
|
};
|
||||||
std::unordered_map<RemoteTextureOwnerId, TextureInfo,
|
std::unordered_map<RemoteTextureOwnerId, TextureInfo,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "mozilla/gfx/GPUProcessManager.h"
|
#include "mozilla/gfx/GPUProcessManager.h"
|
||||||
#include "mozilla/gfx/Logging.h"
|
#include "mozilla/gfx/Logging.h"
|
||||||
#include "mozilla/ipc/Endpoint.h"
|
#include "mozilla/ipc/Endpoint.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
#include "mozilla/layers/BufferTexture.h"
|
#include "mozilla/layers/BufferTexture.h"
|
||||||
#include "mozilla/layers/CanvasTranslator.h"
|
#include "mozilla/layers/CanvasTranslator.h"
|
||||||
#include "mozilla/layers/ImageDataSerializer.h"
|
#include "mozilla/layers/ImageDataSerializer.h"
|
||||||
@@ -102,21 +103,6 @@ bool CanvasTranslator::IsInTaskQueue() const {
|
|||||||
return gfx::CanvasRenderThread::IsInCanvasRenderThread();
|
return gfx::CanvasRenderThread::IsInCanvasRenderThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CreateAndMapShmem(RefPtr<ipc::SharedMemory>& aShmem,
|
|
||||||
Handle&& aHandle,
|
|
||||||
ipc::SharedMemory::OpenRights aOpenRights,
|
|
||||||
size_t aSize) {
|
|
||||||
auto shmem = MakeRefPtr<ipc::SharedMemory>();
|
|
||||||
if (!shmem->SetHandle(std::move(aHandle), aOpenRights) ||
|
|
||||||
!shmem->Map(aSize)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
shmem->CloseHandle();
|
|
||||||
aShmem = shmem.forget();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
StaticRefPtr<gfx::SharedContextWebgl> CanvasTranslator::sSharedContext;
|
StaticRefPtr<gfx::SharedContextWebgl> CanvasTranslator::sSharedContext;
|
||||||
|
|
||||||
bool CanvasTranslator::EnsureSharedContextWebgl() {
|
bool CanvasTranslator::EnsureSharedContextWebgl() {
|
||||||
@@ -154,8 +140,8 @@ void CanvasTranslator::Shutdown() {
|
|||||||
|
|
||||||
mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
|
mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
|
||||||
TextureType aTextureType, TextureType aWebglTextureType,
|
TextureType aTextureType, TextureType aWebglTextureType,
|
||||||
gfx::BackendType aBackendType, Handle&& aReadHandle,
|
gfx::BackendType aBackendType, ipc::MutableSharedMemoryHandle&& aReadHandle,
|
||||||
nsTArray<Handle>&& aBufferHandles, uint64_t aBufferSize,
|
nsTArray<ipc::ReadOnlySharedMemoryHandle>&& aBufferHandles,
|
||||||
CrossProcessSemaphoreHandle&& aReaderSem,
|
CrossProcessSemaphoreHandle&& aReaderSem,
|
||||||
CrossProcessSemaphoreHandle&& aWriterSem) {
|
CrossProcessSemaphoreHandle&& aWriterSem) {
|
||||||
if (mHeaderShmem) {
|
if (mHeaderShmem) {
|
||||||
@@ -167,14 +153,13 @@ mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
|
|||||||
mBackendType = aBackendType;
|
mBackendType = aBackendType;
|
||||||
mOtherPid = OtherPid();
|
mOtherPid = OtherPid();
|
||||||
|
|
||||||
mHeaderShmem = MakeAndAddRef<ipc::SharedMemory>();
|
mHeaderShmem = aReadHandle.Map();
|
||||||
if (!CreateAndMapShmem(mHeaderShmem, std::move(aReadHandle),
|
if (!mHeaderShmem) {
|
||||||
ipc::SharedMemory::RightsReadWrite, sizeof(Header))) {
|
|
||||||
Deactivate();
|
Deactivate();
|
||||||
return IPC_FAIL(this, "Failed to map canvas header shared memory.");
|
return IPC_FAIL(this, "Failed to map canvas header shared memory.");
|
||||||
}
|
}
|
||||||
|
|
||||||
mHeader = static_cast<Header*>(mHeaderShmem->Memory());
|
mHeader = mHeaderShmem.DataAs<Header>();
|
||||||
|
|
||||||
mWriterSemaphore.reset(CrossProcessSemaphore::Create(std::move(aWriterSem)));
|
mWriterSemaphore.reset(CrossProcessSemaphore::Create(std::move(aWriterSem)));
|
||||||
mWriterSemaphore->CloseHandle();
|
mWriterSemaphore->CloseHandle();
|
||||||
@@ -193,10 +178,10 @@ mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use the first buffer as our current buffer.
|
// Use the first buffer as our current buffer.
|
||||||
mDefaultBufferSize = aBufferSize;
|
mDefaultBufferSize = aBufferHandles[0].Size();
|
||||||
auto handleIter = aBufferHandles.begin();
|
auto handleIter = aBufferHandles.begin();
|
||||||
if (!CreateAndMapShmem(mCurrentShmem.shmem, std::move(*handleIter),
|
mCurrentShmem.shmem = std::move(*handleIter).Map();
|
||||||
ipc::SharedMemory::RightsReadOnly, aBufferSize)) {
|
if (!mCurrentShmem.shmem) {
|
||||||
Deactivate();
|
Deactivate();
|
||||||
return IPC_FAIL(this, "Failed to map canvas buffer shared memory.");
|
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.
|
// Add all other buffers to our recycled CanvasShmems.
|
||||||
for (handleIter++; handleIter < aBufferHandles.end(); handleIter++) {
|
for (handleIter++; handleIter < aBufferHandles.end(); handleIter++) {
|
||||||
CanvasShmem newShmem;
|
CanvasShmem newShmem;
|
||||||
if (!CreateAndMapShmem(newShmem.shmem, std::move(*handleIter),
|
newShmem.shmem = std::move(*handleIter).Map();
|
||||||
ipc::SharedMemory::RightsReadOnly, aBufferSize)) {
|
if (!newShmem.shmem) {
|
||||||
Deactivate();
|
Deactivate();
|
||||||
return IPC_FAIL(this, "Failed to map canvas buffer shared memory.");
|
return IPC_FAIL(this, "Failed to map canvas buffer shared memory.");
|
||||||
}
|
}
|
||||||
@@ -247,7 +232,7 @@ ipc::IPCResult CanvasTranslator::RecvRestartTranslation() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ipc::IPCResult CanvasTranslator::RecvAddBuffer(
|
ipc::IPCResult CanvasTranslator::RecvAddBuffer(
|
||||||
ipc::SharedMemory::Handle&& aBufferHandle, uint64_t aBufferSize) {
|
ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) {
|
||||||
if (mDeactivated) {
|
if (mDeactivated) {
|
||||||
// The other side might have sent a resume message before we deactivated.
|
// The other side might have sent a resume message before we deactivated.
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
@@ -255,20 +240,20 @@ ipc::IPCResult CanvasTranslator::RecvAddBuffer(
|
|||||||
|
|
||||||
if (UsePendingCanvasTranslatorEvents()) {
|
if (UsePendingCanvasTranslatorEvents()) {
|
||||||
MutexAutoLock lock(mCanvasTranslatorEventsLock);
|
MutexAutoLock lock(mCanvasTranslatorEventsLock);
|
||||||
mPendingCanvasTranslatorEvents.push_back(CanvasTranslatorEvent::AddBuffer(
|
mPendingCanvasTranslatorEvents.push_back(
|
||||||
std::move(aBufferHandle), aBufferSize));
|
CanvasTranslatorEvent::AddBuffer(std::move(aBufferHandle)));
|
||||||
PostCanvasTranslatorEvents(lock);
|
PostCanvasTranslatorEvents(lock);
|
||||||
} else {
|
} else {
|
||||||
DispatchToTaskQueue(NewRunnableMethod<ipc::SharedMemory::Handle&&, size_t>(
|
DispatchToTaskQueue(NewRunnableMethod<ipc::ReadOnlySharedMemoryHandle&&>(
|
||||||
"CanvasTranslator::AddBuffer", this, &CanvasTranslator::AddBuffer,
|
"CanvasTranslator::AddBuffer", this, &CanvasTranslator::AddBuffer,
|
||||||
std::move(aBufferHandle), aBufferSize));
|
std::move(aBufferHandle)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanvasTranslator::AddBuffer(ipc::SharedMemory::Handle&& aBufferHandle,
|
bool CanvasTranslator::AddBuffer(
|
||||||
size_t aBufferSize) {
|
ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) {
|
||||||
MOZ_ASSERT(IsInTaskQueue());
|
MOZ_ASSERT(IsInTaskQueue());
|
||||||
if (mHeader->readerState == State::Failed) {
|
if (mHeader->readerState == State::Failed) {
|
||||||
// We failed before we got to the pause event.
|
// We failed before we got to the pause event.
|
||||||
@@ -297,8 +282,8 @@ bool CanvasTranslator::AddBuffer(ipc::SharedMemory::Handle&& aBufferHandle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CanvasShmem newShmem;
|
CanvasShmem newShmem;
|
||||||
if (!CreateAndMapShmem(newShmem.shmem, std::move(aBufferHandle),
|
newShmem.shmem = aBufferHandle.Map();
|
||||||
ipc::SharedMemory::RightsReadOnly, aBufferSize)) {
|
if (!newShmem.shmem) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +294,7 @@ bool CanvasTranslator::AddBuffer(ipc::SharedMemory::Handle&& aBufferHandle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ipc::IPCResult CanvasTranslator::RecvSetDataSurfaceBuffer(
|
ipc::IPCResult CanvasTranslator::RecvSetDataSurfaceBuffer(
|
||||||
ipc::SharedMemory::Handle&& aBufferHandle, uint64_t aBufferSize) {
|
ipc::MutableSharedMemoryHandle&& aBufferHandle) {
|
||||||
if (mDeactivated) {
|
if (mDeactivated) {
|
||||||
// The other side might have sent a resume message before we deactivated.
|
// The other side might have sent a resume message before we deactivated.
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
@@ -318,21 +303,19 @@ ipc::IPCResult CanvasTranslator::RecvSetDataSurfaceBuffer(
|
|||||||
if (UsePendingCanvasTranslatorEvents()) {
|
if (UsePendingCanvasTranslatorEvents()) {
|
||||||
MutexAutoLock lock(mCanvasTranslatorEventsLock);
|
MutexAutoLock lock(mCanvasTranslatorEventsLock);
|
||||||
mPendingCanvasTranslatorEvents.push_back(
|
mPendingCanvasTranslatorEvents.push_back(
|
||||||
CanvasTranslatorEvent::SetDataSurfaceBuffer(std::move(aBufferHandle),
|
CanvasTranslatorEvent::SetDataSurfaceBuffer(std::move(aBufferHandle)));
|
||||||
aBufferSize));
|
|
||||||
PostCanvasTranslatorEvents(lock);
|
PostCanvasTranslatorEvents(lock);
|
||||||
} else {
|
} else {
|
||||||
DispatchToTaskQueue(NewRunnableMethod<ipc::SharedMemory::Handle&&, size_t>(
|
DispatchToTaskQueue(NewRunnableMethod<ipc::MutableSharedMemoryHandle&&>(
|
||||||
"CanvasTranslator::SetDataSurfaceBuffer", this,
|
"CanvasTranslator::SetDataSurfaceBuffer", this,
|
||||||
&CanvasTranslator::SetDataSurfaceBuffer, std::move(aBufferHandle),
|
&CanvasTranslator::SetDataSurfaceBuffer, std::move(aBufferHandle)));
|
||||||
aBufferSize));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanvasTranslator::SetDataSurfaceBuffer(
|
bool CanvasTranslator::SetDataSurfaceBuffer(
|
||||||
ipc::SharedMemory::Handle&& aBufferHandle, size_t aBufferSize) {
|
ipc::MutableSharedMemoryHandle&& aBufferHandle) {
|
||||||
MOZ_ASSERT(IsInTaskQueue());
|
MOZ_ASSERT(IsInTaskQueue());
|
||||||
if (mHeader->readerState == State::Failed) {
|
if (mHeader->readerState == State::Failed) {
|
||||||
// We failed before we got to the pause event.
|
// We failed before we got to the pause event.
|
||||||
@@ -349,8 +332,8 @@ bool CanvasTranslator::SetDataSurfaceBuffer(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CreateAndMapShmem(mDataSurfaceShmem, std::move(aBufferHandle),
|
mDataSurfaceShmem = aBufferHandle.Map();
|
||||||
ipc::SharedMemory::RightsReadWrite, aBufferSize)) {
|
if (!mDataSurfaceShmem) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,11 +368,11 @@ void CanvasTranslator::GetDataSurface(uint64_t aSurfaceRef) {
|
|||||||
ImageDataSerializer::ComputeRGBStride(format, dstSize.width);
|
ImageDataSerializer::ComputeRGBStride(format, dstSize.width);
|
||||||
auto requiredSize =
|
auto requiredSize =
|
||||||
ImageDataSerializer::ComputeRGBBufferSize(dstSize, format);
|
ImageDataSerializer::ComputeRGBBufferSize(dstSize, format);
|
||||||
if (requiredSize <= 0 || size_t(requiredSize) > mDataSurfaceShmem->Size()) {
|
if (requiredSize <= 0 || size_t(requiredSize) > mDataSurfaceShmem.Size()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* dst = static_cast<uint8_t*>(mDataSurfaceShmem->Memory());
|
uint8_t* dst = mDataSurfaceShmem.DataAs<uint8_t>();
|
||||||
const uint8_t* src = map->GetData();
|
const uint8_t* src = map->GetData();
|
||||||
const uint8_t* endSrc = src + (srcSize.height * srcStride);
|
const uint8_t* endSrc = src + (srcSize.height * srcStride);
|
||||||
while (src < endSrc) {
|
while (src < endSrc) {
|
||||||
@@ -795,12 +778,11 @@ void CanvasTranslator::HandleCanvasTranslatorEvents() {
|
|||||||
dispatchTranslate = TranslateRecording();
|
dispatchTranslate = TranslateRecording();
|
||||||
break;
|
break;
|
||||||
case CanvasTranslatorEvent::Tag::AddBuffer:
|
case CanvasTranslatorEvent::Tag::AddBuffer:
|
||||||
dispatchTranslate =
|
dispatchTranslate = AddBuffer(event->TakeBufferHandle());
|
||||||
AddBuffer(event->TakeBufferHandle(), event->BufferSize());
|
|
||||||
break;
|
break;
|
||||||
case CanvasTranslatorEvent::Tag::SetDataSurfaceBuffer:
|
case CanvasTranslatorEvent::Tag::SetDataSurfaceBuffer:
|
||||||
dispatchTranslate = SetDataSurfaceBuffer(event->TakeBufferHandle(),
|
dispatchTranslate =
|
||||||
event->BufferSize());
|
SetDataSurfaceBuffer(event->TakeDataSurfaceBufferHandle());
|
||||||
break;
|
break;
|
||||||
case CanvasTranslatorEvent::Tag::ClearCachedResources:
|
case CanvasTranslatorEvent::Tag::ClearCachedResources:
|
||||||
ClearCachedResources();
|
ClearCachedResources();
|
||||||
@@ -1071,8 +1053,7 @@ void CanvasTranslator::CacheSnapshotShmem(
|
|||||||
nsCOMPtr<nsIThread> thread =
|
nsCOMPtr<nsIThread> thread =
|
||||||
gfx::CanvasRenderThread::GetCanvasRenderThread();
|
gfx::CanvasRenderThread::GetCanvasRenderThread();
|
||||||
RefPtr<CanvasTranslator> translator = this;
|
RefPtr<CanvasTranslator> translator = this;
|
||||||
SendSnapshotShmem(aTextureOwnerId, std::move(shmemHandle),
|
SendSnapshotShmem(aTextureOwnerId, std::move(shmemHandle))
|
||||||
webgl->GetShmemSize())
|
|
||||||
->Then(
|
->Then(
|
||||||
thread, __func__,
|
thread, __func__,
|
||||||
[=](bool) { translator->RemoveTexture(aTextureOwnerId); },
|
[=](bool) { translator->RemoveTexture(aTextureOwnerId); },
|
||||||
|
|||||||
@@ -15,13 +15,16 @@
|
|||||||
#include "mozilla/gfx/InlineTranslator.h"
|
#include "mozilla/gfx/InlineTranslator.h"
|
||||||
#include "mozilla/gfx/RecordedEvent.h"
|
#include "mozilla/gfx/RecordedEvent.h"
|
||||||
#include "CanvasChild.h"
|
#include "CanvasChild.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
#include "mozilla/layers/CanvasDrawEventRecorder.h"
|
#include "mozilla/layers/CanvasDrawEventRecorder.h"
|
||||||
#include "mozilla/layers/LayersSurfaces.h"
|
#include "mozilla/layers/LayersSurfaces.h"
|
||||||
#include "mozilla/layers/PCanvasParent.h"
|
#include "mozilla/layers/PCanvasParent.h"
|
||||||
#include "mozilla/layers/RemoteTextureMap.h"
|
#include "mozilla/layers/RemoteTextureMap.h"
|
||||||
#include "mozilla/ipc/CrossProcessSemaphore.h"
|
#include "mozilla/ipc/CrossProcessSemaphore.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
#include "mozilla/Monitor.h"
|
#include "mozilla/Monitor.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
|
#include "mozilla/Variant.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
@@ -81,14 +84,13 @@ class CanvasTranslator final : public gfx::InlineTranslator,
|
|||||||
* @param aReaderSem reading blocked semaphore for the CanvasEventRingBuffer
|
* @param aReaderSem reading blocked semaphore for the CanvasEventRingBuffer
|
||||||
* @param aWriterSem writing blocked semaphore for the CanvasEventRingBuffer
|
* @param aWriterSem writing blocked semaphore for the CanvasEventRingBuffer
|
||||||
*/
|
*/
|
||||||
ipc::IPCResult RecvInitTranslator(TextureType aTextureType,
|
ipc::IPCResult RecvInitTranslator(
|
||||||
TextureType aWebglTextureType,
|
TextureType aTextureType, TextureType aWebglTextureType,
|
||||||
gfx::BackendType aBackendType,
|
gfx::BackendType aBackendType,
|
||||||
Handle&& aReadHandle,
|
ipc::MutableSharedMemoryHandle&& aReadHandle,
|
||||||
nsTArray<Handle>&& aBufferHandles,
|
nsTArray<ipc::ReadOnlySharedMemoryHandle>&& aBufferHandles,
|
||||||
uint64_t aBufferSize,
|
CrossProcessSemaphoreHandle&& aReaderSem,
|
||||||
CrossProcessSemaphoreHandle&& aReaderSem,
|
CrossProcessSemaphoreHandle&& aWriterSem);
|
||||||
CrossProcessSemaphoreHandle&& aWriterSem);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restart the translation from a Stopped state.
|
* 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
|
* Adds a new buffer to be translated. The current buffer will be recycled if
|
||||||
* it is of the default size. The translation will then be restarted.
|
* it is of the default size. The translation will then be restarted.
|
||||||
*/
|
*/
|
||||||
ipc::IPCResult RecvAddBuffer(Handle&& aBufferHandle, uint64_t aBufferSize);
|
ipc::IPCResult RecvAddBuffer(ipc::ReadOnlySharedMemoryHandle&& aBufferHandle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the shared memory to be used for readback.
|
* Sets the shared memory to be used for readback.
|
||||||
*/
|
*/
|
||||||
ipc::IPCResult RecvSetDataSurfaceBuffer(Handle&& aBufferHandle,
|
ipc::IPCResult RecvSetDataSurfaceBuffer(
|
||||||
uint64_t aBufferSize);
|
ipc::MutableSharedMemoryHandle&& aBufferHandle);
|
||||||
|
|
||||||
ipc::IPCResult RecvClearCachedResources();
|
ipc::IPCResult RecvClearCachedResources();
|
||||||
|
|
||||||
@@ -316,23 +318,25 @@ class CanvasTranslator final : public gfx::InlineTranslator,
|
|||||||
const Tag mTag;
|
const Tag mTag;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ipc::SharedMemory::Handle mBufferHandle;
|
Variant<ipc::ReadOnlySharedMemoryHandle, ipc::MutableSharedMemoryHandle>
|
||||||
const size_t mBufferSize;
|
mBufferHandle;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CanvasTranslatorEvent(const Tag aTag)
|
explicit CanvasTranslatorEvent(const Tag aTag)
|
||||||
: mTag(aTag), mBufferSize(0) {
|
: mTag(aTag), mBufferHandle(ipc::ReadOnlySharedMemoryHandle()) {
|
||||||
MOZ_ASSERT(mTag == Tag::TranslateRecording ||
|
MOZ_ASSERT(mTag == Tag::TranslateRecording ||
|
||||||
mTag == Tag::ClearCachedResources ||
|
mTag == Tag::ClearCachedResources ||
|
||||||
mTag == Tag::DropFreeBuffersWhenDormant);
|
mTag == Tag::DropFreeBuffersWhenDormant);
|
||||||
}
|
}
|
||||||
CanvasTranslatorEvent(const Tag aTag,
|
CanvasTranslatorEvent(const Tag aTag,
|
||||||
ipc::SharedMemory::Handle&& aBufferHandle,
|
ipc::ReadOnlySharedMemoryHandle&& aBufferHandle)
|
||||||
size_t aBufferSize)
|
: mTag(aTag), mBufferHandle(std::move(aBufferHandle)) {
|
||||||
: mTag(aTag),
|
MOZ_ASSERT(mTag == Tag::AddBuffer);
|
||||||
mBufferHandle(std::move(aBufferHandle)),
|
}
|
||||||
mBufferSize(aBufferSize) {
|
CanvasTranslatorEvent(const Tag aTag,
|
||||||
MOZ_ASSERT(mTag == Tag::AddBuffer || mTag == Tag::SetDataSurfaceBuffer);
|
ipc::MutableSharedMemoryHandle&& aBufferHandle)
|
||||||
|
: mTag(aTag), mBufferHandle(std::move(aBufferHandle)) {
|
||||||
|
MOZ_ASSERT(mTag == Tag::SetDataSurfaceBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static UniquePtr<CanvasTranslatorEvent> TranslateRecording() {
|
static UniquePtr<CanvasTranslatorEvent> TranslateRecording() {
|
||||||
@@ -340,15 +344,15 @@ class CanvasTranslator final : public gfx::InlineTranslator,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static UniquePtr<CanvasTranslatorEvent> AddBuffer(
|
static UniquePtr<CanvasTranslatorEvent> AddBuffer(
|
||||||
ipc::SharedMemory::Handle&& aBufferHandle, size_t aBufferSize) {
|
ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) {
|
||||||
return MakeUnique<CanvasTranslatorEvent>(
|
return MakeUnique<CanvasTranslatorEvent>(Tag::AddBuffer,
|
||||||
Tag::AddBuffer, std::move(aBufferHandle), aBufferSize);
|
std::move(aBufferHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
static UniquePtr<CanvasTranslatorEvent> SetDataSurfaceBuffer(
|
static UniquePtr<CanvasTranslatorEvent> SetDataSurfaceBuffer(
|
||||||
ipc::SharedMemory::Handle&& aBufferHandle, size_t aBufferSize) {
|
ipc::MutableSharedMemoryHandle&& aBufferHandle) {
|
||||||
return MakeUnique<CanvasTranslatorEvent>(
|
return MakeUnique<CanvasTranslatorEvent>(Tag::SetDataSurfaceBuffer,
|
||||||
Tag::SetDataSurfaceBuffer, std::move(aBufferHandle), aBufferSize);
|
std::move(aBufferHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
static UniquePtr<CanvasTranslatorEvent> ClearCachedResources() {
|
static UniquePtr<CanvasTranslatorEvent> ClearCachedResources() {
|
||||||
@@ -359,20 +363,20 @@ class CanvasTranslator final : public gfx::InlineTranslator,
|
|||||||
return MakeUnique<CanvasTranslatorEvent>(Tag::DropFreeBuffersWhenDormant);
|
return MakeUnique<CanvasTranslatorEvent>(Tag::DropFreeBuffersWhenDormant);
|
||||||
}
|
}
|
||||||
|
|
||||||
ipc::SharedMemory::Handle TakeBufferHandle() {
|
ipc::ReadOnlySharedMemoryHandle TakeBufferHandle() {
|
||||||
if (mTag == Tag::AddBuffer || mTag == Tag::SetDataSurfaceBuffer) {
|
if (mTag == Tag::AddBuffer) {
|
||||||
return std::move(mBufferHandle);
|
return std::move(mBufferHandle).as<ipc::ReadOnlySharedMemoryHandle>();
|
||||||
}
|
}
|
||||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||||
return mozilla::ipc::SharedMemory::NULLHandle();
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t BufferSize() {
|
ipc::MutableSharedMemoryHandle TakeDataSurfaceBufferHandle() {
|
||||||
if (mTag == Tag::AddBuffer || mTag == Tag::SetDataSurfaceBuffer) {
|
if (mTag == Tag::SetDataSurfaceBuffer) {
|
||||||
return mBufferSize;
|
return std::move(mBufferHandle).as<ipc::MutableSharedMemoryHandle>();
|
||||||
}
|
}
|
||||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
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
|
* @returns true if next HandleCanvasTranslatorEvents() needs to call
|
||||||
* TranslateRecording().
|
* TranslateRecording().
|
||||||
*/
|
*/
|
||||||
bool AddBuffer(Handle&& aBufferHandle, size_t aBufferSize);
|
bool AddBuffer(ipc::ReadOnlySharedMemoryHandle&& aBufferHandle);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @returns true if next HandleCanvasTranslatorEvents() needs to call
|
* @returns true if next HandleCanvasTranslatorEvents() needs to call
|
||||||
* TranslateRecording().
|
* TranslateRecording().
|
||||||
*/
|
*/
|
||||||
bool SetDataSurfaceBuffer(Handle&& aBufferHandle, size_t aBufferSize);
|
bool SetDataSurfaceBuffer(ipc::MutableSharedMemoryHandle&& aBufferHandle);
|
||||||
|
|
||||||
bool ReadNextEvent(EventType& aEventType);
|
bool ReadNextEvent(EventType& aEventType);
|
||||||
|
|
||||||
@@ -470,7 +474,7 @@ class CanvasTranslator final : public gfx::InlineTranslator,
|
|||||||
using State = CanvasDrawEventRecorder::State;
|
using State = CanvasDrawEventRecorder::State;
|
||||||
using Header = CanvasDrawEventRecorder::Header;
|
using Header = CanvasDrawEventRecorder::Header;
|
||||||
|
|
||||||
RefPtr<ipc::SharedMemory> mHeaderShmem;
|
ipc::SharedMemoryMapping mHeaderShmem;
|
||||||
Header* mHeader = nullptr;
|
Header* mHeader = nullptr;
|
||||||
// Limit event processing to stop at the designated checkpoint, rather than
|
// Limit event processing to stop at the designated checkpoint, rather than
|
||||||
// proceed beyond it. This also forces processing to continue, even when it
|
// proceed beyond it. This also forces processing to continue, even when it
|
||||||
@@ -479,20 +483,20 @@ class CanvasTranslator final : public gfx::InlineTranslator,
|
|||||||
int64_t mFlushCheckpoint = 0;
|
int64_t mFlushCheckpoint = 0;
|
||||||
|
|
||||||
struct CanvasShmem {
|
struct CanvasShmem {
|
||||||
RefPtr<ipc::SharedMemory> shmem;
|
ipc::ReadOnlySharedMemoryMapping shmem;
|
||||||
bool IsValid() const { return !!shmem; }
|
bool IsValid() const { return shmem.IsValid(); }
|
||||||
auto Size() { return shmem ? shmem->Size() : 0; }
|
auto Size() { return shmem ? shmem.Size() : 0; }
|
||||||
gfx::MemReader CreateMemReader() {
|
gfx::MemReader CreateMemReader() {
|
||||||
if (!shmem) {
|
if (!shmem) {
|
||||||
return {nullptr, 0};
|
return {nullptr, 0};
|
||||||
}
|
}
|
||||||
return {static_cast<char*>(shmem->Memory()), Size()};
|
return {shmem.DataAs<char>(), Size()};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
std::queue<CanvasShmem> mCanvasShmems;
|
std::queue<CanvasShmem> mCanvasShmems;
|
||||||
CanvasShmem mCurrentShmem;
|
CanvasShmem mCurrentShmem;
|
||||||
gfx::MemReader mCurrentMemReader{0, 0};
|
gfx::MemReader mCurrentMemReader{0, 0};
|
||||||
RefPtr<ipc::SharedMemory> mDataSurfaceShmem;
|
ipc::SharedMemoryMapping mDataSurfaceShmem;
|
||||||
UniquePtr<CrossProcessSemaphore> mWriterSemaphore;
|
UniquePtr<CrossProcessSemaphore> mWriterSemaphore;
|
||||||
UniquePtr<CrossProcessSemaphore> mReaderSemaphore;
|
UniquePtr<CrossProcessSemaphore> mReaderSemaphore;
|
||||||
TextureType mTextureType = TextureType::Unknown;
|
TextureType mTextureType = TextureType::Unknown;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
#include "mozilla/TimeStamp.h" // for TimeStamp
|
#include "mozilla/TimeStamp.h" // for TimeStamp
|
||||||
#include "mozilla/gfx/Point.h" // for IntSize
|
#include "mozilla/gfx/Point.h" // for IntSize
|
||||||
#include "mozilla/ipc/ProtocolUtils.h"
|
#include "mozilla/ipc/ProtocolUtils.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
|
||||||
#include "mozilla/layers/CompositorController.h"
|
#include "mozilla/layers/CompositorController.h"
|
||||||
#include "mozilla/layers/CompositorVsyncSchedulerOwner.h"
|
#include "mozilla/layers/CompositorVsyncSchedulerOwner.h"
|
||||||
#include "mozilla/layers/FocusTarget.h"
|
#include "mozilla/layers/FocusTarget.h"
|
||||||
|
|||||||
@@ -11,8 +11,7 @@
|
|||||||
#include <stdint.h> // for uint32_t
|
#include <stdint.h> // for uint32_t
|
||||||
#include "gfxTypes.h"
|
#include "gfxTypes.h"
|
||||||
#include "mozilla/dom/ipc/IdType.h"
|
#include "mozilla/dom/ipc/IdType.h"
|
||||||
#include "mozilla/gfx/Point.h" // for IntSize
|
#include "mozilla/gfx/Point.h" // for IntSize
|
||||||
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
|
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "nsIMemoryReporter.h" // for nsIMemoryReporter
|
#include "nsIMemoryReporter.h" // for nsIMemoryReporter
|
||||||
#include "mozilla/Atomics.h" // for Atomic
|
#include "mozilla/Atomics.h" // for Atomic
|
||||||
|
|||||||
@@ -13,8 +13,7 @@
|
|||||||
|
|
||||||
#include "mozilla/Attributes.h" // for override
|
#include "mozilla/Attributes.h" // for override
|
||||||
#include "mozilla/Atomics.h"
|
#include "mozilla/Atomics.h"
|
||||||
#include "mozilla/RefPtr.h" // for already_AddRefed
|
#include "mozilla/RefPtr.h" // for already_AddRefed
|
||||||
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
|
|
||||||
#include "mozilla/layers/CompositableForwarder.h"
|
#include "mozilla/layers/CompositableForwarder.h"
|
||||||
#include "mozilla/layers/CompositorTypes.h"
|
#include "mozilla/layers/CompositorTypes.h"
|
||||||
#include "mozilla/layers/PImageBridgeChild.h"
|
#include "mozilla/layers/PImageBridgeChild.h"
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
#include "mozilla/Attributes.h" // for override
|
#include "mozilla/Attributes.h" // for override
|
||||||
#include "mozilla/dom/ipc/IdType.h"
|
#include "mozilla/dom/ipc/IdType.h"
|
||||||
#include "mozilla/ipc/ProtocolUtils.h"
|
#include "mozilla/ipc/ProtocolUtils.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
|
|
||||||
#include "mozilla/layers/CompositorThread.h"
|
#include "mozilla/layers/CompositorThread.h"
|
||||||
#include "mozilla/layers/PImageBridgeParent.h"
|
#include "mozilla/layers/PImageBridgeParent.h"
|
||||||
#include "nsISupportsImpl.h"
|
#include "nsISupportsImpl.h"
|
||||||
|
|||||||
@@ -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::Matrix4x4 from "mozilla/gfx/Matrix.h";
|
||||||
using mozilla::gfx::FenceInfo from "mozilla/gfx/FileHandleWrapper.h";
|
using mozilla::gfx::FenceInfo from "mozilla/gfx/FileHandleWrapper.h";
|
||||||
[RefCounted] using mozilla::gfx::FileHandleWrapper from "mozilla/gfx/FileHandleWrapper.h";
|
[RefCounted] using mozilla::gfx::FileHandleWrapper from "mozilla/gfx/FileHandleWrapper.h";
|
||||||
[MoveOnly] using mozilla::ipc::SharedMemory::Handle from "mozilla/ipc/SharedMemory.h";
|
|
||||||
using gfxImageFormat from "gfxTypes.h";
|
using gfxImageFormat from "gfxTypes.h";
|
||||||
using mozilla::layers::MaybeVideoBridgeSource from "mozilla/layers/VideoBridgeUtils.h";
|
using mozilla::layers::MaybeVideoBridgeSource from "mozilla/layers/VideoBridgeUtils.h";
|
||||||
using mozilla::layers::RemoteTextureId from "mozilla/layers/LayersTypes.h";
|
using mozilla::layers::RemoteTextureId from "mozilla/layers/LayersTypes.h";
|
||||||
@@ -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::ExternalImageSource from "mozilla/webrender/WebRenderTypes.h";
|
||||||
using mozilla::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h";
|
using mozilla::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h";
|
||||||
using mozilla::layers::SurfaceDescriptorRemoteDecoderId from "mozilla/layers/LayersTypes.h";
|
using mozilla::layers::SurfaceDescriptorRemoteDecoderId from "mozilla/layers/LayersTypes.h";
|
||||||
|
[MoveOnly] using mozilla::ipc::ReadOnlySharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h";
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
@@ -186,12 +186,12 @@ namespace layers {
|
|||||||
MemoryOrShmem data;
|
MemoryOrShmem data;
|
||||||
};
|
};
|
||||||
|
|
||||||
[Comparable] struct SurfaceDescriptorShared
|
struct SurfaceDescriptorShared
|
||||||
{
|
{
|
||||||
IntSize size;
|
IntSize size;
|
||||||
int32_t stride;
|
int32_t stride;
|
||||||
SurfaceFormat format;
|
SurfaceFormat format;
|
||||||
Handle handle;
|
ReadOnlySharedMemoryHandle handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
[Comparable] struct SurfaceDescriptorExternalImage
|
[Comparable] struct SurfaceDescriptorExternalImage
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ include "mozilla/layers/CanvasTranslator.h";
|
|||||||
[MoveOnly] using mozilla::CrossProcessSemaphoreHandle from "mozilla/ipc/CrossProcessSemaphore.h";
|
[MoveOnly] using mozilla::CrossProcessSemaphoreHandle from "mozilla/ipc/CrossProcessSemaphore.h";
|
||||||
using mozilla::layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h";
|
using mozilla::layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h";
|
||||||
using mozilla::layers::TextureType from "mozilla/layers/LayersTypes.h";
|
using mozilla::layers::TextureType from "mozilla/layers/LayersTypes.h";
|
||||||
[MoveOnly] using mozilla::ipc::SharedMemory::Handle from "mozilla/ipc/SharedMemory.h";
|
|
||||||
using mozilla::gfx::BackendType from "mozilla/gfx/Types.h";
|
using mozilla::gfx::BackendType from "mozilla/gfx/Types.h";
|
||||||
|
[MoveOnly] using mozilla::ipc::ReadOnlySharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h";
|
||||||
|
[MoveOnly] using mozilla::ipc::MutableSharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h";
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
@@ -34,8 +35,8 @@ parent:
|
|||||||
* are handles for the semaphores to handle waiting on either side.
|
* are handles for the semaphores to handle waiting on either side.
|
||||||
*/
|
*/
|
||||||
async InitTranslator(TextureType aTextureType, TextureType aWebglTextureType,
|
async InitTranslator(TextureType aTextureType, TextureType aWebglTextureType,
|
||||||
BackendType aBackendType, Handle aHeaderHandle,
|
BackendType aBackendType, MutableSharedMemoryHandle aHeaderHandle,
|
||||||
Handle[] aBufferHandles, uint64_t aBufferSize,
|
ReadOnlySharedMemoryHandle[] aBufferHandles,
|
||||||
CrossProcessSemaphoreHandle aReaderSem,
|
CrossProcessSemaphoreHandle aReaderSem,
|
||||||
CrossProcessSemaphoreHandle aWriterSem);
|
CrossProcessSemaphoreHandle aWriterSem);
|
||||||
|
|
||||||
@@ -48,12 +49,12 @@ parent:
|
|||||||
* Adds a new buffer to be translated. The current buffer will be recycled if
|
* Adds a new buffer to be translated. The current buffer will be recycled if
|
||||||
* it is of the default size. The translation will then be restarted.
|
* it is of the default size. The translation will then be restarted.
|
||||||
*/
|
*/
|
||||||
async AddBuffer(Handle aBufferHandle, uint64_t aBufferSize);
|
async AddBuffer(ReadOnlySharedMemoryHandle aBufferHandle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the shared memory to be used for readback.
|
* 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.
|
* Notify CanvasTranslator it is about to be minimized.
|
||||||
@@ -97,7 +98,7 @@ child:
|
|||||||
/**
|
/**
|
||||||
* Cache the shmem of the framebuffer for snapshotting.
|
* 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);
|
async NotifyTextureDestruction(RemoteTextureOwnerId aTextureOwnerId);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ include "mozilla/layers/WebRenderMessageUtils.h";
|
|||||||
using mozilla::TimeDuration from "mozilla/TimeStamp.h";
|
using mozilla::TimeDuration from "mozilla/TimeStamp.h";
|
||||||
using mozilla::CSSToLayoutDeviceScale from "Units.h";
|
using mozilla::CSSToLayoutDeviceScale from "Units.h";
|
||||||
using mozilla::gfx::IntSize from "mozilla/gfx/2D.h";
|
using mozilla::gfx::IntSize from "mozilla/gfx/2D.h";
|
||||||
[MoveOnly] using mozilla::ipc::SharedMemory::Handle from "mozilla/ipc/SharedMemory.h";
|
|
||||||
using mozilla::layers::CompositorOptions from "mozilla/layers/LayersMessageUtils.h";
|
using mozilla::layers::CompositorOptions from "mozilla/layers/LayersMessageUtils.h";
|
||||||
using mozilla::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h";
|
using mozilla::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h";
|
||||||
using mozilla::wr::MemoryReport from "mozilla/webrender/WebRenderTypes.h";
|
using mozilla::wr::MemoryReport from "mozilla/webrender/WebRenderTypes.h";
|
||||||
|
|||||||
@@ -5,13 +5,12 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "SharedPlanarYCbCrImage.h"
|
#include "SharedPlanarYCbCrImage.h"
|
||||||
#include <stddef.h> // for size_t
|
#include <stddef.h> // for size_t
|
||||||
#include <stdio.h> // for printf
|
#include <stdio.h> // for printf
|
||||||
#include "gfx2DGlue.h" // for Moz2D transition helpers
|
#include "gfx2DGlue.h" // for Moz2D transition helpers
|
||||||
#include "ISurfaceAllocator.h" // for ISurfaceAllocator, etc
|
#include "ISurfaceAllocator.h" // for ISurfaceAllocator, etc
|
||||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||||
#include "mozilla/gfx/Types.h" // for SurfaceFormat::SurfaceFormat::YUV
|
#include "mozilla/gfx/Types.h" // for SurfaceFormat::SurfaceFormat::YUV
|
||||||
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
|
|
||||||
#include "mozilla/layers/ImageClient.h" // for ImageClient
|
#include "mozilla/layers/ImageClient.h" // for ImageClient
|
||||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
|
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
|
||||||
#include "mozilla/layers/TextureClient.h"
|
#include "mozilla/layers/TextureClient.h"
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ nsresult SharedSurfacesChild::ShareInternal(SourceSurfaceSharedData* aSurface,
|
|||||||
// Attempt to share a handle with the GPU process. The handle may or may not
|
// Attempt to share a handle with the GPU process. The handle may or may not
|
||||||
// be available -- it will only be available if it is either not yet finalized
|
// be available -- it will only be available if it is either not yet finalized
|
||||||
// and/or if it has been finalized but never used for drawing in process.
|
// and/or if it has been finalized but never used for drawing in process.
|
||||||
ipc::SharedMemory::Handle handle = ipc::SharedMemory::NULLHandle();
|
ipc::ReadOnlySharedMemoryHandle handle;
|
||||||
nsresult rv = aSurface->CloneHandle(handle);
|
nsresult rv = aSurface->CloneHandle(handle);
|
||||||
if (rv == NS_ERROR_NOT_AVAILABLE) {
|
if (rv == NS_ERROR_NOT_AVAILABLE) {
|
||||||
// It is at least as expensive to copy the image to the GPU process if we
|
// It is at least as expensive to copy the image to the GPU process if we
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#include "mozilla/StaticMutex.h" // for StaticMutex
|
#include "mozilla/StaticMutex.h" // for StaticMutex
|
||||||
#include "mozilla/StaticPtr.h" // for StaticAutoPtr
|
#include "mozilla/StaticPtr.h" // for StaticAutoPtr
|
||||||
#include "mozilla/RefPtr.h" // for already_AddRefed
|
#include "mozilla/RefPtr.h" // for already_AddRefed
|
||||||
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
|
|
||||||
#include "mozilla/gfx/2D.h" // for SurfaceFormat
|
#include "mozilla/gfx/2D.h" // for SurfaceFormat
|
||||||
#include "mozilla/gfx/Point.h" // for IntSize
|
#include "mozilla/gfx/Point.h" // for IntSize
|
||||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptorShared
|
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptorShared
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
|
||||||
#include "mozilla/layers/PTextureChild.h"
|
#include "mozilla/layers/PTextureChild.h"
|
||||||
#include "mozilla/layers/WebRenderBridgeChild.h"
|
#include "mozilla/layers/WebRenderBridgeChild.h"
|
||||||
|
|
||||||
|
|||||||
@@ -14,15 +14,13 @@
|
|||||||
#include "nsXULAppAPI.h"
|
#include "nsXULAppAPI.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
|
|
||||||
// This is split out from SharedFontList.h because that header is included
|
// This is split out from SharedFontList.h because that header is included
|
||||||
// quite widely (via gfxPlatformFontList.h, gfxTextRun.h, etc), and other code
|
// quite widely (via gfxPlatformFontList.h, gfxTextRun.h, etc). This header,
|
||||||
// such as the generated DOM bindings code gets upset at (indirect) inclusion
|
// which defines the actual shared-memory FontList class, is included only by
|
||||||
// of <windows.h> via SharedMemory.h. So this header, which defines the actual
|
// the .cpp files that implement or directly interface with the font list, to
|
||||||
// shared-memory FontList class, is included only by the .cpp files that
|
// avoid polluting other headers.
|
||||||
// implement or directly interface with the font list, to avoid polluting other
|
|
||||||
// headers.
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace fontlist {
|
namespace fontlist {
|
||||||
@@ -243,14 +241,14 @@ class FontList {
|
|||||||
* list has changed/grown since the child was first initialized).
|
* list has changed/grown since the child was first initialized).
|
||||||
*/
|
*/
|
||||||
void ShareShmBlockToProcess(uint32_t aIndex, base::ProcessId aPid,
|
void ShareShmBlockToProcess(uint32_t aIndex, base::ProcessId aPid,
|
||||||
ipc::SharedMemory::Handle* aOut) {
|
ipc::ReadOnlySharedMemoryHandle* aOut) {
|
||||||
MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length());
|
MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length());
|
||||||
if (aIndex >= mReadOnlyShmems.Length()) {
|
if (aIndex >= mReadOnlyShmems.Length()) {
|
||||||
// Block index out of range
|
// Block index out of range
|
||||||
*aOut = ipc::SharedMemory::NULLHandle();
|
*aOut = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*aOut = mReadOnlyShmems[aIndex]->CloneHandle();
|
*aOut = mReadOnlyShmems[aIndex].Clone();
|
||||||
if (!*aOut) {
|
if (!*aOut) {
|
||||||
MOZ_CRASH("failed to share block");
|
MOZ_CRASH("failed to share block");
|
||||||
}
|
}
|
||||||
@@ -261,14 +259,14 @@ class FontList {
|
|||||||
* shared to the given process. This is used at child process startup
|
* shared to the given process. This is used at child process startup
|
||||||
* to pass the complete list at once.
|
* to pass the complete list at once.
|
||||||
*/
|
*/
|
||||||
void ShareBlocksToProcess(nsTArray<ipc::SharedMemory::Handle>* aBlocks,
|
void ShareBlocksToProcess(nsTArray<ipc::ReadOnlySharedMemoryHandle>* aBlocks,
|
||||||
base::ProcessId aPid);
|
base::ProcessId aPid);
|
||||||
|
|
||||||
ipc::SharedMemory::Handle ShareBlockToProcess(uint32_t aIndex,
|
ipc::ReadOnlySharedMemoryHandle ShareBlockToProcess(uint32_t aIndex,
|
||||||
base::ProcessId aPid);
|
base::ProcessId aPid);
|
||||||
|
|
||||||
void ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
|
void ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
|
||||||
ipc::SharedMemory::Handle aHandle);
|
ipc::ReadOnlySharedMemoryHandle aHandle);
|
||||||
/**
|
/**
|
||||||
* Support for memory reporter.
|
* Support for memory reporter.
|
||||||
*/
|
*/
|
||||||
@@ -298,13 +296,22 @@ class FontList {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
struct ShmBlock {
|
struct ShmBlock {
|
||||||
// Takes ownership of aShmem. Note that in a child process, aShmem will be
|
// Takes ownership of aShmem. In a child process, aShmem will be mapped as
|
||||||
// mapped as read-only.
|
// read-only.
|
||||||
explicit ShmBlock(RefPtr<ipc::SharedMemory>&& aShmem)
|
explicit ShmBlock(ipc::ReadOnlySharedMemoryMapping&& aShmem)
|
||||||
: mShmem(std::move(aShmem)) {}
|
: mShmem(std::move(aShmem)) {
|
||||||
|
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit ShmBlock(ipc::SharedMemoryMapping&& aShmem)
|
||||||
|
: mShmem(std::move(aShmem)) {
|
||||||
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
|
}
|
||||||
|
|
||||||
// Get pointer to the mapped memory.
|
// Get pointer to the mapped memory.
|
||||||
void* Memory() const { return mShmem->Memory(); }
|
void* Memory() const { return mShmem.Address(); }
|
||||||
|
|
||||||
|
void Clear() { mShmem = nullptr; }
|
||||||
|
|
||||||
// Only the parent process does allocation, so only it will update this
|
// Only the parent process does allocation, so only it will update this
|
||||||
// field. Content processes read the value when checking Pointer validity.
|
// field. Content processes read the value when checking Pointer validity.
|
||||||
@@ -326,7 +333,8 @@ class FontList {
|
|||||||
return static_cast<BlockHeader*>(Memory())->mBlockSize;
|
return static_cast<BlockHeader*>(Memory())->mBlockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<ipc::SharedMemory> mShmem;
|
private:
|
||||||
|
ipc::MutableOrReadOnlySharedMemoryMapping mShmem;
|
||||||
};
|
};
|
||||||
|
|
||||||
Header& GetHeader() const;
|
Header& GetHeader() const;
|
||||||
@@ -369,10 +377,10 @@ class FontList {
|
|||||||
nsTArray<mozilla::UniquePtr<ShmBlock>> mBlocks;
|
nsTArray<mozilla::UniquePtr<ShmBlock>> mBlocks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auxiliary array, used only in the parent process; holds read-only copies
|
* Auxiliary array, used only in the parent process; holds read-only handles
|
||||||
* of the shmem blocks; these are what will be shared to child processes.
|
* for the shmem blocks; these are what will be shared to child processes.
|
||||||
*/
|
*/
|
||||||
nsTArray<RefPtr<ipc::SharedMemory>> mReadOnlyShmems;
|
nsTArray<ipc::ReadOnlySharedMemoryHandle> mReadOnlyShmems;
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
// Bool array to track whether we have read face names from the name table.
|
// Bool array to track whether we have read face names from the name table.
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include "gfxPlatformFontList.h"
|
#include "gfxPlatformFontList.h"
|
||||||
#include "gfxFontUtils.h"
|
#include "gfxFontUtils.h"
|
||||||
#include "gfxFont.h"
|
#include "gfxFont.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
|
||||||
#include "nsReadableUtils.h"
|
#include "nsReadableUtils.h"
|
||||||
#include "prerror.h"
|
#include "prerror.h"
|
||||||
#include "mozilla/dom/ContentChild.h"
|
#include "mozilla/dom/ContentChild.h"
|
||||||
@@ -741,25 +740,21 @@ FontList::FontList(uint32_t aGeneration) {
|
|||||||
// SetXPCOMProcessAttributes.
|
// SetXPCOMProcessAttributes.
|
||||||
auto& blocks = dom::ContentChild::GetSingleton()->SharedFontListBlocks();
|
auto& blocks = dom::ContentChild::GetSingleton()->SharedFontListBlocks();
|
||||||
for (auto& handle : blocks) {
|
for (auto& handle : blocks) {
|
||||||
auto newShm = MakeRefPtr<ipc::SharedMemory>();
|
if (!handle) {
|
||||||
if (!newShm->IsHandleValid(handle)) {
|
|
||||||
// Bail out and let UpdateShmBlocks try to do its thing below.
|
// Bail out and let UpdateShmBlocks try to do its thing below.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!newShm->SetHandle(std::move(handle),
|
if (handle.Size() < SHM_BLOCK_SIZE) {
|
||||||
ipc::SharedMemory::OpenRights::RightsReadOnly)) {
|
|
||||||
MOZ_CRASH("failed to set shm handle");
|
|
||||||
}
|
|
||||||
if (!newShm->Map(SHM_BLOCK_SIZE) || !newShm->Memory()) {
|
|
||||||
MOZ_CRASH("failed to map shared memory");
|
MOZ_CRASH("failed to map shared memory");
|
||||||
}
|
}
|
||||||
uint32_t size = static_cast<BlockHeader*>(newShm->Memory())->mBlockSize;
|
auto newShm = handle.Map();
|
||||||
|
if (!newShm || !newShm.Address()) {
|
||||||
|
MOZ_CRASH("failed to map shared memory");
|
||||||
|
}
|
||||||
|
uint32_t size = newShm.DataAs<BlockHeader>()->mBlockSize;
|
||||||
MOZ_ASSERT(size >= SHM_BLOCK_SIZE);
|
MOZ_ASSERT(size >= SHM_BLOCK_SIZE);
|
||||||
if (size != SHM_BLOCK_SIZE) {
|
if (newShm.Size() < size) {
|
||||||
newShm->Unmap();
|
MOZ_CRASH("failed to map shared memory");
|
||||||
if (!newShm->Map(size) || !newShm->Memory()) {
|
|
||||||
MOZ_CRASH("failed to map shared memory");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mBlocks.AppendElement(new ShmBlock(std::move(newShm)));
|
mBlocks.AppendElement(new ShmBlock(std::move(newShm)));
|
||||||
}
|
}
|
||||||
@@ -804,17 +799,17 @@ FontList::Header& FontList::GetHeader() const MOZ_NO_THREAD_SAFETY_ANALYSIS {
|
|||||||
bool FontList::AppendShmBlock(uint32_t aSizeNeeded) {
|
bool FontList::AppendShmBlock(uint32_t aSizeNeeded) {
|
||||||
MOZ_ASSERT(XRE_IsParentProcess());
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
uint32_t size = std::max(aSizeNeeded, SHM_BLOCK_SIZE);
|
uint32_t size = std::max(aSizeNeeded, SHM_BLOCK_SIZE);
|
||||||
auto newShm = MakeRefPtr<ipc::SharedMemory>();
|
auto handle = ipc::shared_memory::CreateFreezable(size);
|
||||||
if (!newShm->CreateFreezable(size)) {
|
if (!handle) {
|
||||||
MOZ_CRASH("failed to create shared memory");
|
MOZ_CRASH("failed to create shared memory");
|
||||||
return false;
|
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");
|
MOZ_CRASH("failed to map shared memory");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto readOnly = MakeRefPtr<ipc::SharedMemory>();
|
if (!readOnly) {
|
||||||
if (!newShm->ReadOnlyCopy(readOnly.get())) {
|
|
||||||
MOZ_CRASH("failed to create read-only copy");
|
MOZ_CRASH("failed to create read-only copy");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -848,19 +843,13 @@ bool FontList::AppendShmBlock(uint32_t aSizeNeeded) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FontList::ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
|
void FontList::ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
|
||||||
ipc::SharedMemory::Handle aHandle) {
|
ipc::ReadOnlySharedMemoryHandle aHandle) {
|
||||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||||
MOZ_ASSERT(mBlocks.Length() > 0);
|
MOZ_ASSERT(mBlocks.Length() > 0);
|
||||||
|
|
||||||
auto newShm = MakeRefPtr<ipc::SharedMemory>();
|
if (!aHandle) {
|
||||||
if (!newShm->IsHandleValid(aHandle)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!newShm->SetHandle(std::move(aHandle),
|
|
||||||
ipc::SharedMemory::RightsReadOnly)) {
|
|
||||||
MOZ_CRASH("failed to set shm handle");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aIndex != mBlocks.Length()) {
|
if (aIndex != mBlocks.Length()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -868,17 +857,15 @@ void FontList::ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
|
|||||||
return;
|
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");
|
MOZ_CRASH("failed to map shared memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t size = static_cast<BlockHeader*>(newShm->Memory())->mBlockSize;
|
uint32_t size = newShm.DataAs<BlockHeader>()->mBlockSize;
|
||||||
MOZ_ASSERT(size >= SHM_BLOCK_SIZE);
|
MOZ_ASSERT(size >= SHM_BLOCK_SIZE);
|
||||||
if (size != SHM_BLOCK_SIZE) {
|
if (newShm.Size() < size) {
|
||||||
newShm->Unmap();
|
MOZ_CRASH("failed to map shared memory");
|
||||||
if (!newShm->Map(size) || !newShm->Memory()) {
|
|
||||||
MOZ_CRASH("failed to map shared memory");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mBlocks.AppendElement(new ShmBlock(std::move(newShm)));
|
mBlocks.AppendElement(new ShmBlock(std::move(newShm)));
|
||||||
@@ -886,7 +873,7 @@ void FontList::ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
|
|||||||
|
|
||||||
void FontList::DetachShmBlocks() {
|
void FontList::DetachShmBlocks() {
|
||||||
for (auto& i : mBlocks) {
|
for (auto& i : mBlocks) {
|
||||||
i->mShmem = nullptr;
|
i->Clear();
|
||||||
}
|
}
|
||||||
mBlocks.Clear();
|
mBlocks.Clear();
|
||||||
mReadOnlyShmems.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;
|
// If we have no existing blocks, we don't want a generation check yet;
|
||||||
// the header in the first block will define the generation of this list
|
// the header in the first block will define the generation of this list
|
||||||
uint32_t generation = aIndex == 0 ? 0 : GetGeneration();
|
uint32_t generation = aIndex == 0 ? 0 : GetGeneration();
|
||||||
ipc::SharedMemory::Handle handle = ipc::SharedMemory::NULLHandle();
|
ipc::ReadOnlySharedMemoryHandle handle;
|
||||||
if (!dom::ContentChild::GetSingleton()->SendGetFontListShmBlock(
|
if (!dom::ContentChild::GetSingleton()->SendGetFontListShmBlock(
|
||||||
generation, aIndex, &handle)) {
|
generation, aIndex, &handle)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto newShm = MakeRefPtr<ipc::SharedMemory>();
|
if (!handle) {
|
||||||
if (!newShm->IsHandleValid(handle)) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (!newShm->SetHandle(std::move(handle),
|
auto newShm = handle.Map();
|
||||||
ipc::SharedMemory::RightsReadOnly)) {
|
if (!newShm || !newShm.Address() || newShm.Size() < SHM_BLOCK_SIZE) {
|
||||||
MOZ_CRASH("failed to set shm handle");
|
|
||||||
}
|
|
||||||
if (!newShm->Map(SHM_BLOCK_SIZE) || !newShm->Memory()) {
|
|
||||||
MOZ_CRASH("failed to map shared memory");
|
MOZ_CRASH("failed to map shared memory");
|
||||||
}
|
}
|
||||||
uint32_t size = static_cast<BlockHeader*>(newShm->Memory())->mBlockSize;
|
uint32_t size = newShm.DataAs<BlockHeader>()->mBlockSize;
|
||||||
MOZ_ASSERT(size >= SHM_BLOCK_SIZE);
|
MOZ_ASSERT(size >= SHM_BLOCK_SIZE);
|
||||||
if (size != SHM_BLOCK_SIZE) {
|
if (newShm.Size() < size) {
|
||||||
newShm->Unmap();
|
MOZ_CRASH("failed to map shared memory");
|
||||||
if (!newShm->Map(size) || !newShm->Memory()) {
|
|
||||||
MOZ_CRASH("failed to map shared memory");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return new ShmBlock(std::move(newShm));
|
return new ShmBlock(std::move(newShm));
|
||||||
}
|
}
|
||||||
@@ -947,10 +927,10 @@ bool FontList::UpdateShmBlocks(bool aMustLock) MOZ_NO_THREAD_SAFETY_ANALYSIS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FontList::ShareBlocksToProcess(
|
void FontList::ShareBlocksToProcess(
|
||||||
nsTArray<ipc::SharedMemory::Handle>* aBlocks, base::ProcessId aPid) {
|
nsTArray<ipc::ReadOnlySharedMemoryHandle>* aBlocks, base::ProcessId aPid) {
|
||||||
MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length());
|
MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length());
|
||||||
for (auto& shmem : mReadOnlyShmems) {
|
for (auto& shmem : mReadOnlyShmems) {
|
||||||
auto handle = shmem->CloneHandle();
|
auto handle = shmem.Clone();
|
||||||
if (!handle) {
|
if (!handle) {
|
||||||
// If something went wrong here, we just bail out; the child will need to
|
// If something went wrong here, we just bail out; the child will need to
|
||||||
// request the blocks as needed, at some performance cost. (Although in
|
// request the blocks as needed, at some performance cost. (Although in
|
||||||
@@ -963,13 +943,13 @@ void FontList::ShareBlocksToProcess(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ipc::SharedMemory::Handle FontList::ShareBlockToProcess(uint32_t aIndex,
|
ipc::ReadOnlySharedMemoryHandle FontList::ShareBlockToProcess(
|
||||||
base::ProcessId aPid) {
|
uint32_t aIndex, base::ProcessId aPid) {
|
||||||
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
|
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
|
||||||
MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length());
|
MOZ_RELEASE_ASSERT(mReadOnlyShmems.Length() == mBlocks.Length());
|
||||||
MOZ_RELEASE_ASSERT(aIndex < mReadOnlyShmems.Length());
|
MOZ_RELEASE_ASSERT(aIndex < mReadOnlyShmems.Length());
|
||||||
|
|
||||||
return mReadOnlyShmems[aIndex]->CloneHandle();
|
return mReadOnlyShmems[aIndex].Clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointer FontList::Alloc(uint32_t aSize) {
|
Pointer FontList::Alloc(uint32_t aSize) {
|
||||||
@@ -1410,7 +1390,7 @@ size_t FontList::SizeOfExcludingThis(
|
|||||||
mozilla::MallocSizeOf aMallocSizeOf) const {
|
mozilla::MallocSizeOf aMallocSizeOf) const {
|
||||||
size_t result = mBlocks.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
size_t result = mBlocks.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||||
for (const auto& b : mBlocks) {
|
for (const auto& b : mBlocks) {
|
||||||
result += aMallocSizeOf(b.get()) + aMallocSizeOf(b->mShmem.get());
|
result += aMallocSizeOf(b.get());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
#include "mozilla/ipc/Shmem.h"
|
#include "mozilla/ipc/Shmem.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
|
||||||
|
|
||||||
#include "gfxASurface.h"
|
#include "gfxASurface.h"
|
||||||
#include "gfxImageSurface.h"
|
#include "gfxImageSurface.h"
|
||||||
@@ -33,7 +32,6 @@ extern const cairo_user_data_key_t SHM_KEY;
|
|||||||
|
|
||||||
template <typename Base, typename Sub>
|
template <typename Base, typename Sub>
|
||||||
class gfxBaseSharedMemorySurface : public Base {
|
class gfxBaseSharedMemorySurface : public Base {
|
||||||
typedef mozilla::ipc::SharedMemory SharedMemory;
|
|
||||||
typedef mozilla::ipc::Shmem Shmem;
|
typedef mozilla::ipc::Shmem Shmem;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -3111,7 +3111,7 @@ void gfxPlatformFontList::CancelInitOtherFamilyNamesTask() {
|
|||||||
|
|
||||||
void gfxPlatformFontList::ShareFontListShmBlockToProcess(
|
void gfxPlatformFontList::ShareFontListShmBlockToProcess(
|
||||||
uint32_t aGeneration, uint32_t aIndex, base::ProcessId aPid,
|
uint32_t aGeneration, uint32_t aIndex, base::ProcessId aPid,
|
||||||
mozilla::ipc::SharedMemory::Handle* aOut) {
|
mozilla::ipc::ReadOnlySharedMemoryHandle* aOut) {
|
||||||
auto list = SharedFontList();
|
auto list = SharedFontList();
|
||||||
if (!list) {
|
if (!list) {
|
||||||
return;
|
return;
|
||||||
@@ -3119,12 +3119,12 @@ void gfxPlatformFontList::ShareFontListShmBlockToProcess(
|
|||||||
if (!aGeneration || list->GetGeneration() == aGeneration) {
|
if (!aGeneration || list->GetGeneration() == aGeneration) {
|
||||||
list->ShareShmBlockToProcess(aIndex, aPid, aOut);
|
list->ShareShmBlockToProcess(aIndex, aPid, aOut);
|
||||||
} else {
|
} else {
|
||||||
*aOut = mozilla::ipc::SharedMemory::NULLHandle();
|
*aOut = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfxPlatformFontList::ShareFontListToProcess(
|
void gfxPlatformFontList::ShareFontListToProcess(
|
||||||
nsTArray<mozilla::ipc::SharedMemory::Handle>* aBlocks,
|
nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle>* aBlocks,
|
||||||
base::ProcessId aPid) {
|
base::ProcessId aPid) {
|
||||||
auto list = SharedFontList();
|
auto list = SharedFontList();
|
||||||
if (list) {
|
if (list) {
|
||||||
@@ -3132,15 +3132,16 @@ void gfxPlatformFontList::ShareFontListToProcess(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::SharedMemory::Handle gfxPlatformFontList::ShareShmBlockToProcess(
|
mozilla::ipc::ReadOnlySharedMemoryHandle
|
||||||
uint32_t aIndex, base::ProcessId aPid) {
|
gfxPlatformFontList::ShareShmBlockToProcess(uint32_t aIndex,
|
||||||
|
base::ProcessId aPid) {
|
||||||
MOZ_RELEASE_ASSERT(SharedFontList());
|
MOZ_RELEASE_ASSERT(SharedFontList());
|
||||||
return SharedFontList()->ShareBlockToProcess(aIndex, aPid);
|
return SharedFontList()->ShareBlockToProcess(aIndex, aPid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfxPlatformFontList::ShmBlockAdded(
|
void gfxPlatformFontList::ShmBlockAdded(
|
||||||
uint32_t aGeneration, uint32_t aIndex,
|
uint32_t aGeneration, uint32_t aIndex,
|
||||||
mozilla::ipc::SharedMemory::Handle aHandle) {
|
mozilla::ipc::ReadOnlySharedMemoryHandle aHandle) {
|
||||||
if (SharedFontList()) {
|
if (SharedFontList()) {
|
||||||
AutoLock lock(mLock);
|
AutoLock lock(mLock);
|
||||||
SharedFontList()->ShmBlockAdded(aGeneration, aIndex, std::move(aHandle));
|
SharedFontList()->ShmBlockAdded(aGeneration, aIndex, std::move(aHandle));
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/RangedArray.h"
|
#include "mozilla/RangedArray.h"
|
||||||
#include "mozilla/RecursiveMutex.h"
|
#include "mozilla/RecursiveMutex.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
#include "nsLanguageAtomService.h"
|
#include "nsLanguageAtomService.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@@ -353,20 +353,20 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
|
|||||||
|
|
||||||
// Create a handle for a single shmem block (identified by index) ready to
|
// Create a handle for a single shmem block (identified by index) ready to
|
||||||
// be shared to the given processId.
|
// be shared to the given processId.
|
||||||
void ShareFontListShmBlockToProcess(uint32_t aGeneration, uint32_t aIndex,
|
void ShareFontListShmBlockToProcess(
|
||||||
base::ProcessId aPid,
|
uint32_t aGeneration, uint32_t aIndex, base::ProcessId aPid,
|
||||||
mozilla::ipc::SharedMemory::Handle* aOut);
|
mozilla::ipc::ReadOnlySharedMemoryHandle* aOut);
|
||||||
|
|
||||||
// Populate the array aBlocks with the complete list of shmem handles ready
|
// Populate the array aBlocks with the complete list of shmem handles ready
|
||||||
// to be shared to the given processId.
|
// to be shared to the given processId.
|
||||||
void ShareFontListToProcess(
|
void ShareFontListToProcess(
|
||||||
nsTArray<mozilla::ipc::SharedMemory::Handle>* aBlocks,
|
nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle>* aBlocks,
|
||||||
base::ProcessId aPid);
|
base::ProcessId aPid);
|
||||||
|
|
||||||
void ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
|
void ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
|
||||||
mozilla::ipc::SharedMemory::Handle aHandle);
|
mozilla::ipc::ReadOnlySharedMemoryHandle aHandle);
|
||||||
|
|
||||||
mozilla::ipc::SharedMemory::Handle ShareShmBlockToProcess(
|
mozilla::ipc::ReadOnlySharedMemoryHandle ShareShmBlockToProcess(
|
||||||
uint32_t aIndex, base::ProcessId aPid);
|
uint32_t aIndex, base::ProcessId aPid);
|
||||||
|
|
||||||
void SetCharacterMap(uint32_t aGeneration, uint32_t aFamilyIndex, bool aAlias,
|
void SetCharacterMap(uint32_t aGeneration, uint32_t aFamilyIndex, bool aAlias,
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include "mozilla/dom/WebXRBinding.h"
|
#include "mozilla/dom/WebXRBinding.h"
|
||||||
#include "mozilla/dom/XRFrame.h"
|
#include "mozilla/dom/XRFrame.h"
|
||||||
#include "mozilla/gfx/PVRManagerChild.h"
|
#include "mozilla/gfx/PVRManagerChild.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
|
|
||||||
#include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator
|
#include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator
|
||||||
#include "mozilla/layers/LayersTypes.h" // for LayersBackend
|
#include "mozilla/layers/LayersTypes.h" // for LayersBackend
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "ImageMemoryReporter.h"
|
#include "ImageMemoryReporter.h"
|
||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
#include "base/process_util.h"
|
#include "base/process_util.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
#include "mozilla/layers/SharedSurfacesParent.h"
|
#include "mozilla/layers/SharedSurfacesParent.h"
|
||||||
#include "mozilla/StaticPrefs_image.h"
|
#include "mozilla/StaticPrefs_image.h"
|
||||||
#include "nsIMemoryReporter.h"
|
#include "nsIMemoryReporter.h"
|
||||||
@@ -113,7 +114,7 @@ void ImageMemoryReporter::ReportSharedSurface(
|
|||||||
path.AppendInt(aEntry.mCreatorRef);
|
path.AppendInt(aEntry.mCreatorRef);
|
||||||
path.AppendLiteral(")/decoded-");
|
path.AppendLiteral(")/decoded-");
|
||||||
|
|
||||||
size_t surfaceSize = mozilla::ipc::SharedMemory::PageAlignedSize(
|
size_t surfaceSize = mozilla::ipc::shared_memory::PageAlignedSize(
|
||||||
aEntry.mSize.height * aEntry.mStride);
|
aEntry.mSize.height * aEntry.mStride);
|
||||||
|
|
||||||
// If this memory has already been reported elsewhere (e.g. as part of our
|
// If this memory has already been reported elsewhere (e.g. as part of our
|
||||||
|
|||||||
@@ -331,11 +331,10 @@ void nsHyphenationManager::LoadAliases() {
|
|||||||
|
|
||||||
void nsHyphenationManager::ShareHyphDictToProcess(
|
void nsHyphenationManager::ShareHyphDictToProcess(
|
||||||
nsIURI* aURI, base::ProcessId aPid,
|
nsIURI* aURI, base::ProcessId aPid,
|
||||||
mozilla::ipc::SharedMemory::Handle* aOutHandle, uint32_t* aOutSize) {
|
mozilla::ipc::ReadOnlySharedMemoryHandle* aOutHandle) {
|
||||||
MOZ_ASSERT(XRE_IsParentProcess());
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
// aURI will be referring to an omnijar resource (otherwise just bail).
|
// aURI will be referring to an omnijar resource (otherwise just bail).
|
||||||
*aOutHandle = mozilla::ipc::SharedMemory::NULLHandle();
|
*aOutHandle = nullptr;
|
||||||
*aOutSize = 0;
|
|
||||||
|
|
||||||
// Extract the locale code from the URI, and get the corresponding
|
// Extract the locale code from the URI, and get the corresponding
|
||||||
// hyphenator (loading it into shared memory if necessary).
|
// hyphenator (loading it into shared memory if necessary).
|
||||||
@@ -358,7 +357,7 @@ void nsHyphenationManager::ShareHyphDictToProcess(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hyph->CloneHandle(aOutHandle, aOutSize);
|
*aOutHandle = hyph->CloneHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nsHyphenationManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) {
|
size_t nsHyphenationManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "base/process.h"
|
#include "base/process.h"
|
||||||
#include "mozilla/Omnijar.h"
|
#include "mozilla/Omnijar.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
#include "nsHashKeys.h"
|
#include "nsHashKeys.h"
|
||||||
#include "nsAtomHashKeys.h"
|
#include "nsAtomHashKeys.h"
|
||||||
#include "nsInterfaceHashtable.h"
|
#include "nsInterfaceHashtable.h"
|
||||||
@@ -27,9 +27,9 @@ class nsHyphenationManager : public nsIObserver {
|
|||||||
|
|
||||||
already_AddRefed<nsHyphenator> GetHyphenator(nsAtom* aLocale);
|
already_AddRefed<nsHyphenator> GetHyphenator(nsAtom* aLocale);
|
||||||
|
|
||||||
void ShareHyphDictToProcess(nsIURI* aURI, base::ProcessId aPid,
|
void ShareHyphDictToProcess(
|
||||||
mozilla::ipc::SharedMemory::Handle* aOutHandle,
|
nsIURI* aURI, base::ProcessId aPid,
|
||||||
uint32_t* aOutSize);
|
mozilla::ipc::ReadOnlySharedMemoryHandle* aOutHandle);
|
||||||
|
|
||||||
static nsHyphenationManager* Instance();
|
static nsHyphenationManager* Instance();
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include "mozilla/dom/ContentChild.h"
|
#include "mozilla/dom/ContentChild.h"
|
||||||
#include "mozilla/Omnijar.h"
|
#include "mozilla/Omnijar.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsIChannel.h"
|
#include "nsIChannel.h"
|
||||||
#include "nsIFile.h"
|
#include "nsIFile.h"
|
||||||
@@ -32,7 +34,7 @@ void DefaultDelete<const CompiledData>::operator()(
|
|||||||
mapped_hyph_free_compiled_data(const_cast<CompiledData*>(aData));
|
mapped_hyph_free_compiled_data(const_cast<CompiledData*>(aData));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const 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
|
// Try to get the jarfile's nsZipArchive, find the relevant item, and return
|
||||||
// a pointer to its data provided it is stored uncompressed.
|
// a pointer to its data provided it is stored uncompressed.
|
||||||
nsCOMPtr<nsIURI> jarFile;
|
nsCOMPtr<nsIURI> jarFile;
|
||||||
@@ -66,63 +68,53 @@ static const void* GetItemPtrFromJarURI(nsIJARURI* aJAR, uint32_t* aLength) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RefPtr<ipc::SharedMemory> GetHyphDictFromParent(nsIURI* aURI,
|
static ipc::ReadOnlySharedMemoryMapping GetHyphDictFromParent(nsIURI* aURI) {
|
||||||
uint32_t* aLength) {
|
|
||||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||||
ipc::SharedMemory::Handle handle = ipc::SharedMemory::NULLHandle();
|
ipc::ReadOnlySharedMemoryHandle handle;
|
||||||
uint32_t size;
|
|
||||||
MOZ_ASSERT(aURI);
|
MOZ_ASSERT(aURI);
|
||||||
if (!dom::ContentChild::GetSingleton()->SendGetHyphDict(aURI, &handle,
|
if (!dom::ContentChild::GetSingleton()->SendGetHyphDict(aURI, &handle)) {
|
||||||
&size)) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
RefPtr<ipc::SharedMemory> shm = MakeRefPtr<ipc::SharedMemory>();
|
if (!handle.IsValid()) {
|
||||||
if (!shm->IsHandleValid(handle)) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (!shm->SetHandle(std::move(handle), ipc::SharedMemory::RightsReadOnly)) {
|
auto map = handle.Map();
|
||||||
|
if (!map) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (!shm->Map(size)) {
|
if (!map.Address()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
char* addr = static_cast<char*>(shm->Memory());
|
return map;
|
||||||
if (!addr) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
*aLength = size;
|
|
||||||
return shm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RefPtr<ipc::SharedMemory> CopyToShmem(const CompiledData* aData) {
|
static ipc::ReadOnlySharedMemoryHandle CopyToShmem(const CompiledData* aData) {
|
||||||
MOZ_ASSERT(XRE_IsParentProcess());
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
|
|
||||||
// The shm-related calls here are not expected to fail, but if they do,
|
// The shm-related calls here are not expected to fail, but if they do,
|
||||||
// we'll just return null (as if the resource was unavailable) and proceed
|
// we'll just return null (as if the resource was unavailable) and proceed
|
||||||
// without hyphenation.
|
// without hyphenation.
|
||||||
uint32_t size = mapped_hyph_compiled_data_size(aData);
|
uint32_t size = mapped_hyph_compiled_data_size(aData);
|
||||||
RefPtr<ipc::SharedMemory> shm = MakeRefPtr<ipc::SharedMemory>();
|
auto handle = ipc::shared_memory::CreateFreezable(size);
|
||||||
if (!shm->CreateFreezable(size)) {
|
if (!handle) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (!shm->Map(size)) {
|
auto map = std::move(handle).Map();
|
||||||
|
if (!map) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
char* buffer = static_cast<char*>(shm->Memory());
|
char* buffer = map.DataAs<char>();
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(buffer, mapped_hyph_compiled_data_ptr(aData), size);
|
memcpy(buffer, mapped_hyph_compiled_data_ptr(aData), size);
|
||||||
if (!shm->Freeze()) {
|
auto [_, readOnlyHandle] = std::move(map).Freeze();
|
||||||
return nullptr;
|
return std::move(readOnlyHandle);
|
||||||
}
|
|
||||||
|
|
||||||
return shm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RefPtr<ipc::SharedMemory> LoadFromURI(nsIURI* aURI, uint32_t* aLength,
|
static ipc::ReadOnlySharedMemoryHandle LoadFromURI(nsIURI* aURI,
|
||||||
bool aPrecompiled) {
|
bool aPrecompiled) {
|
||||||
MOZ_ASSERT(XRE_IsParentProcess());
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
nsCOMPtr<nsIChannel> channel;
|
nsCOMPtr<nsIChannel> channel;
|
||||||
if (NS_FAILED(NS_NewChannel(
|
if (NS_FAILED(NS_NewChannel(
|
||||||
@@ -145,14 +137,15 @@ static RefPtr<ipc::SharedMemory> LoadFromURI(nsIURI* aURI, uint32_t* aLength,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (aPrecompiled) {
|
if (aPrecompiled) {
|
||||||
RefPtr<ipc::SharedMemory> shm = MakeRefPtr<ipc::SharedMemory>();
|
auto handle = ipc::shared_memory::CreateFreezable(available);
|
||||||
if (!shm->CreateFreezable(available)) {
|
if (!handle) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (!shm->Map(available)) {
|
auto map = std::move(handle).Map();
|
||||||
|
if (!map) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
char* buffer = static_cast<char*>(shm->Memory());
|
char* buffer = map.DataAs<char>();
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -168,12 +161,13 @@ static RefPtr<ipc::SharedMemory> LoadFromURI(nsIURI* aURI, uint32_t* aLength,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shm->Freeze()) {
|
auto [_, readOnlyHandle] = std::move(map).Freeze();
|
||||||
|
|
||||||
|
if (!readOnlyHandle) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
*aLength = bytesRead;
|
return std::move(readOnlyHandle);
|
||||||
return shm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read from the URI into a temporary buffer, compile it, then copy the
|
// Read from the URI into a temporary buffer, compile it, then copy the
|
||||||
@@ -188,7 +182,6 @@ static RefPtr<ipc::SharedMemory> LoadFromURI(nsIURI* aURI, uint32_t* aLength,
|
|||||||
UniquePtr<const CompiledData> data(mapped_hyph_compile_buffer(
|
UniquePtr<const CompiledData> data(mapped_hyph_compile_buffer(
|
||||||
reinterpret_cast<const uint8_t*>(buffer.get()), bytesRead, false));
|
reinterpret_cast<const uint8_t*>(buffer.get()), bytesRead, false));
|
||||||
if (data) {
|
if (data) {
|
||||||
*aLength = mapped_hyph_compiled_data_size(data.get());
|
|
||||||
return CopyToShmem(data.get());
|
return CopyToShmem(data.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,8 +189,7 @@ static RefPtr<ipc::SharedMemory> LoadFromURI(nsIURI* aURI, uint32_t* aLength,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized)
|
nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized)
|
||||||
: mDict(static_cast<const void*>(nullptr)),
|
: mDict(Span<const uint8_t>()),
|
||||||
mDictSize(0),
|
|
||||||
mHyphenateCapitalized(aHyphenateCapitalized) {
|
mHyphenateCapitalized(aHyphenateCapitalized) {
|
||||||
// Files with extension ".hyf" are expected to be precompiled mapped_hyph
|
// Files with extension ".hyf" are expected to be precompiled mapped_hyph
|
||||||
// tables; we also support uncompiled ".dic" files, but they are more
|
// tables; we also support uncompiled ".dic" files, but they are more
|
||||||
@@ -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
|
// them a compiled version of the resource, so that we only pay the cost of
|
||||||
// compilation once per language per session.
|
// compilation once per language per session.
|
||||||
if (!precompiled && !XRE_IsParentProcess()) {
|
if (!precompiled && !XRE_IsParentProcess()) {
|
||||||
uint32_t length;
|
auto shm = GetHyphDictFromParent(aURI);
|
||||||
RefPtr<ipc::SharedMemory> shm = GetHyphDictFromParent(aURI, &length);
|
|
||||||
if (shm) {
|
if (shm) {
|
||||||
// We don't need to validate mDict because the parent process
|
// We don't need to validate mDict because the parent process
|
||||||
// will have done so.
|
// will have done so.
|
||||||
mDictSize = length;
|
mDict.emplace<ipc::ReadOnlySharedMemoryMapping>(std::move(shm));
|
||||||
mDict = AsVariant(std::move(shm));
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -226,15 +216,13 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized)
|
|||||||
// This gives us a raw pointer into the omnijar's data (if uncompressed);
|
// This gives us a raw pointer into the omnijar's data (if uncompressed);
|
||||||
// we do not own it and must not attempt to free it!
|
// we do not own it and must not attempt to free it!
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
const void* ptr = GetItemPtrFromJarURI(jar, &length);
|
const uint8_t* ptr = GetItemPtrFromJarURI(jar, &length);
|
||||||
if (ptr) {
|
if (ptr) {
|
||||||
if (precompiled) {
|
if (precompiled) {
|
||||||
// The data should be directly usable by mapped_hyph; validate that it
|
// The data should be directly usable by mapped_hyph; validate that it
|
||||||
// looks correct, and save the pointer.
|
// looks correct, and save the pointer.
|
||||||
if (mapped_hyph_is_valid_hyphenator(static_cast<const uint8_t*>(ptr),
|
if (mapped_hyph_is_valid_hyphenator(ptr, length)) {
|
||||||
length)) {
|
mDict.emplace<Span<const uint8_t>>(ptr, length);
|
||||||
mDictSize = length;
|
|
||||||
mDict = AsVariant(ptr);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
// We then move it to shared memory so we can expose it to content
|
||||||
// processes.
|
// processes.
|
||||||
MOZ_ASSERT(XRE_IsParentProcess());
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
UniquePtr<const CompiledData> data(mapped_hyph_compile_buffer(
|
UniquePtr<const CompiledData> data(
|
||||||
static_cast<const uint8_t*>(ptr), length, false));
|
mapped_hyph_compile_buffer(ptr, length, false));
|
||||||
if (data) {
|
if (data) {
|
||||||
RefPtr<ipc::SharedMemory> shm = CopyToShmem(data.get());
|
auto shm = CopyToShmem(data.get());
|
||||||
if (shm) {
|
if (shm) {
|
||||||
mDictSize = mapped_hyph_compiled_data_size(data.get());
|
mDict.emplace<ipc::ReadOnlySharedMemoryHandle>(std::move(shm));
|
||||||
mDict = AsVariant(std::move(shm));
|
|
||||||
return;
|
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
|
// buffer; if we're a child, send a request to the parent for the
|
||||||
// shared-memory copy (which it will load if not already available).
|
// shared-memory copy (which it will load if not already available).
|
||||||
if (XRE_IsParentProcess()) {
|
if (XRE_IsParentProcess()) {
|
||||||
RefPtr<ipc::SharedMemory> shm = LoadFromURI(aURI, &length, precompiled);
|
auto shm = LoadFromURI(aURI, precompiled);
|
||||||
if (shm) {
|
if (shm) {
|
||||||
mDictSize = length;
|
mDict.emplace<ipc::ReadOnlySharedMemoryHandle>(std::move(shm));
|
||||||
mDict = AsVariant(std::move(shm));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
RefPtr<ipc::SharedMemory> shm = GetHyphDictFromParent(aURI, &length);
|
auto shm = GetHyphDictFromParent(aURI);
|
||||||
if (shm) {
|
if (shm) {
|
||||||
// We don't need to validate mDict because the parent process
|
// We don't need to validate mDict because the parent process
|
||||||
// will have done so.
|
// will have done so.
|
||||||
mDictSize = length;
|
mDict.emplace<ipc::ReadOnlySharedMemoryMapping>(std::move(shm));
|
||||||
mDict = AsVariant(std::move(shm));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -312,10 +297,9 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized)
|
|||||||
UniquePtr<const CompiledData> data(
|
UniquePtr<const CompiledData> data(
|
||||||
mapped_hyph_compile_file(path.get(), false));
|
mapped_hyph_compile_file(path.get(), false));
|
||||||
if (data) {
|
if (data) {
|
||||||
RefPtr<ipc::SharedMemory> shm = CopyToShmem(data.get());
|
auto shm = CopyToShmem(data.get());
|
||||||
if (shm) {
|
if (shm) {
|
||||||
mDictSize = mapped_hyph_compiled_data_size(data.get());
|
mDict.emplace<ipc::ReadOnlySharedMemoryHandle>(std::move(shm));
|
||||||
mDict = AsVariant(std::move(shm));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,8 +317,9 @@ nsHyphenator::nsHyphenator(nsIURI* aURI, bool aHyphenateCapitalized)
|
|||||||
|
|
||||||
bool nsHyphenator::IsValid() {
|
bool nsHyphenator::IsValid() {
|
||||||
return mDict.match(
|
return mDict.match(
|
||||||
[](const void*& ptr) { return ptr != nullptr; },
|
[](Span<const uint8_t>& span) { return span.data() != nullptr; },
|
||||||
[](RefPtr<ipc::SharedMemory>& shm) { return shm != nullptr; },
|
[](ipc::ReadOnlySharedMemoryHandle& shm) { return shm.IsValid(); },
|
||||||
|
[](ipc::ReadOnlySharedMemoryMapping& shm) { return shm.IsValid(); },
|
||||||
[](UniquePtr<const HyphDic>& hyph) { return hyph != nullptr; });
|
[](UniquePtr<const HyphDic>& hyph) { return hyph != nullptr; });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,16 +426,21 @@ void nsHyphenator::HyphenateWord(const nsAString& aString, uint32_t aStart,
|
|||||||
AutoTArray<uint8_t, 200> hyphenValues;
|
AutoTArray<uint8_t, 200> hyphenValues;
|
||||||
hyphenValues.SetLength(utf8.Length());
|
hyphenValues.SetLength(utf8.Length());
|
||||||
int32_t result = mDict.match(
|
int32_t result = mDict.match(
|
||||||
[&](const void*& ptr) {
|
[&](Span<const uint8_t>& span) {
|
||||||
return mapped_hyph_find_hyphen_values_raw(
|
return mapped_hyph_find_hyphen_values_raw(
|
||||||
static_cast<const uint8_t*>(ptr), mDictSize, utf8.BeginReading(),
|
span.data(), span.size(), utf8.BeginReading(), utf8.Length(),
|
||||||
utf8.Length(), hyphenValues.Elements(), hyphenValues.Length());
|
hyphenValues.Elements(), hyphenValues.Length());
|
||||||
},
|
},
|
||||||
[&](RefPtr<ipc::SharedMemory>& 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(
|
return mapped_hyph_find_hyphen_values_raw(
|
||||||
static_cast<const uint8_t*>(shm->Memory()), mDictSize,
|
shm.DataAs<uint8_t>(), shm.Size(), utf8.BeginReading(),
|
||||||
utf8.BeginReading(), utf8.Length(), hyphenValues.Elements(),
|
utf8.Length(), hyphenValues.Elements(), hyphenValues.Length());
|
||||||
hyphenValues.Length());
|
|
||||||
},
|
},
|
||||||
[&](UniquePtr<const HyphDic>& hyph) {
|
[&](UniquePtr<const HyphDic>& hyph) {
|
||||||
return mapped_hyph_find_hyphen_values_dic(
|
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,
|
ipc::ReadOnlySharedMemoryHandle nsHyphenator::CloneHandle() {
|
||||||
uint32_t* aOutSize) {
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
// 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
|
if (mDict.is<ipc::ReadOnlySharedMemoryHandle>()) {
|
||||||
// for this to be a fatal error.
|
return mDict.as<ipc::ReadOnlySharedMemoryHandle>().Clone();
|
||||||
if (!mDict.is<RefPtr<ipc::SharedMemory>>()) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
*aOutHandle = mDict.as<RefPtr<ipc::SharedMemory>>()->CloneHandle();
|
return nullptr;
|
||||||
*aOutSize = mDictSize;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,10 @@
|
|||||||
#ifndef nsHyphenator_h__
|
#ifndef nsHyphenator_h__
|
||||||
#define 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/RefPtr.h"
|
||||||
|
#include "mozilla/Span.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "mozilla/Variant.h"
|
#include "mozilla/Variant.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
@@ -42,8 +44,7 @@ class nsHyphenator {
|
|||||||
|
|
||||||
nsresult Hyphenate(const nsAString& aText, nsTArray<bool>& aHyphens);
|
nsresult Hyphenate(const nsAString& aText, nsTArray<bool>& aHyphens);
|
||||||
|
|
||||||
void CloneHandle(mozilla::ipc::SharedMemory::Handle* aOutHandle,
|
mozilla::ipc::ReadOnlySharedMemoryHandle CloneHandle();
|
||||||
uint32_t* aOutSize);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~nsHyphenator() = default;
|
~nsHyphenator() = default;
|
||||||
@@ -51,12 +52,13 @@ class nsHyphenator {
|
|||||||
void HyphenateWord(const nsAString& aString, uint32_t aStart, uint32_t aLimit,
|
void HyphenateWord(const nsAString& aString, uint32_t aStart, uint32_t aLimit,
|
||||||
nsTArray<bool>& aHyphens);
|
nsTArray<bool>& aHyphens);
|
||||||
|
|
||||||
mozilla::Variant<const void*, // raw pointer to uncompressed omnijar data
|
mozilla::Variant<
|
||||||
RefPtr<mozilla::ipc::SharedMemory>, // shmem block
|
mozilla::Span<const uint8_t>, // raw pointer to uncompressed omnijar data
|
||||||
mozilla::UniquePtr<const HyphDic> // loaded by mapped_hyph
|
mozilla::ipc::ReadOnlySharedMemoryHandle, // shmem handle, in the parent
|
||||||
>
|
mozilla::ipc::ReadOnlySharedMemoryMapping, // mapped shmem, in the child
|
||||||
|
mozilla::UniquePtr<const HyphDic> // loaded by mapped_hyph
|
||||||
|
>
|
||||||
mDict;
|
mDict;
|
||||||
uint32_t mDictSize; // size of mDict data (not used if type is HyphDic)
|
|
||||||
bool mHyphenateCapitalized;
|
bool mHyphenateCapitalized;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
%{C++
|
%{C++
|
||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
@@ -27,7 +27,7 @@ class ContentParent;
|
|||||||
%}
|
%}
|
||||||
|
|
||||||
[ptr] native ContentParent(mozilla::dom::ContentParent);
|
[ptr] native ContentParent(mozilla::dom::ContentParent);
|
||||||
[ref] native SharedMemoryHandle(mozilla::ipc::SharedMemoryHandle);
|
native ReadOnlySharedMemoryHandle(mozilla::ipc::ReadOnlySharedMemoryHandle&&);
|
||||||
native MallocSizeOf(mozilla::MallocSizeOf);
|
native MallocSizeOf(mozilla::MallocSizeOf);
|
||||||
|
|
||||||
[scriptable, builtinclass, uuid(D85A17C2-AA7C-11d2-9B8C-00805F8A16D9)]
|
[scriptable, builtinclass, uuid(D85A17C2-AA7C-11d2-9B8C-00805F8A16D9)]
|
||||||
@@ -104,6 +104,5 @@ interface nsIStringBundleService : nsISupports
|
|||||||
[notxpcom, nostdcall] void sendContentBundles(in ContentParent aContentParent);
|
[notxpcom, nostdcall] void sendContentBundles(in ContentParent aContentParent);
|
||||||
|
|
||||||
[notxpcom, nostdcall] void registerContentBundle(in ACString aBundleURL,
|
[notxpcom, nostdcall] void registerContentBundle(in ACString aBundleURL,
|
||||||
[const] in SharedMemoryHandle aMapHandle,
|
in ReadOnlySharedMemoryHandle aMapHandle);
|
||||||
in size_t aMapSize);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include "nsSimpleEnumerator.h"
|
#include "nsSimpleEnumerator.h"
|
||||||
#include "nsStringStream.h"
|
#include "nsStringStream.h"
|
||||||
#include "mozilla/dom/txXSLTMsgsURL.h"
|
#include "mozilla/dom/txXSLTMsgsURL.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
#include "mozilla/BinarySearch.h"
|
#include "mozilla/BinarySearch.h"
|
||||||
#include "mozilla/ClearOnShutdown.h"
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
#include "mozilla/ResultExtensions.h"
|
#include "mozilla/ResultExtensions.h"
|
||||||
@@ -93,12 +94,8 @@ static bool IsContentBundle(const nsCString& aUrl) {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#define STRINGBUNDLEPROXY_IID \
|
#define STRINGBUNDLEPROXY_IID \
|
||||||
{ \
|
{0x537cf21b, 0x99fc, 0x4002, {0x9e, 0xec, 0x97, 0xbe, 0x4d, 0xe0, 0xb3, 0xdc}}
|
||||||
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
|
* 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)
|
NS_IMPL_ISUPPORTS(StringBundleProxy, nsIStringBundle, StringBundleProxy)
|
||||||
|
|
||||||
#define SHAREDSTRINGBUNDLE_IID \
|
#define SHAREDSTRINGBUNDLE_IID \
|
||||||
{ \
|
{0x7a8df5f7, 0x9e50, 0x44f6, {0xbf, 0x89, 0xc7, 0xad, 0x6c, 0x17, 0xf8, 0x5f}}
|
||||||
0x7a8df5f7, 0x9e50, 0x44f6, { \
|
|
||||||
0xbf, 0x89, 0xc7, 0xad, 0x6c, 0x17, 0xf8, 0x5f \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A string bundle backed by a read-only, shared memory buffer. This should
|
* 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
|
* called in child processes, for bundles initially created in the parent
|
||||||
* process.
|
* process.
|
||||||
*/
|
*/
|
||||||
void SetMapFile(const mozilla::ipc::SharedMemoryHandle& aHandle,
|
void SetMapFile(mozilla::ipc::ReadOnlySharedMemoryHandle&& aHandle);
|
||||||
size_t aSize);
|
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
NS_DECLARE_STATIC_IID_ACCESSOR(SHAREDSTRINGBUNDLE_IID)
|
NS_DECLARE_STATIC_IID_ACCESSOR(SHAREDSTRINGBUNDLE_IID)
|
||||||
@@ -219,21 +211,21 @@ class SharedStringBundle final : public nsStringBundleBase {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a copy of the file descriptor pointing to the shared memory
|
* Returns a copy of the file descriptor pointing to the shared memory
|
||||||
* key-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
|
* parent process, and may be used to send shared string bundles to child
|
||||||
* processes.
|
* processes.
|
||||||
*/
|
*/
|
||||||
mozilla::ipc::SharedMemoryHandle CloneHandle() const {
|
mozilla::ipc::ReadOnlySharedMemoryHandle CloneHandle() const {
|
||||||
MOZ_ASSERT(XRE_IsParentProcess());
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
if (mMapHandle.isSome()) {
|
if (mMapHandle.isSome()) {
|
||||||
return mozilla::ipc::SharedMemory::CloneHandle(mMapHandle.ref());
|
return mMapHandle.ref().Clone();
|
||||||
}
|
}
|
||||||
return mStringMap->CloneHandle();
|
return mStringMap->CloneHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t MapSize() const {
|
size_t MapSize() const {
|
||||||
if (mMapHandle.isSome()) {
|
if (mMapHandle.isSome()) {
|
||||||
return mMapSize;
|
return mMapHandle->Size();
|
||||||
}
|
}
|
||||||
if (mStringMap) {
|
if (mStringMap) {
|
||||||
return mStringMap->MapSize();
|
return mStringMap->MapSize();
|
||||||
@@ -249,7 +241,6 @@ class SharedStringBundle final : public nsStringBundleBase {
|
|||||||
StringBundleDescriptor descriptor;
|
StringBundleDescriptor descriptor;
|
||||||
descriptor.bundleURL() = BundleURL();
|
descriptor.bundleURL() = BundleURL();
|
||||||
descriptor.mapHandle() = CloneHandle();
|
descriptor.mapHandle() = CloneHandle();
|
||||||
descriptor.mapSize() = MapSize();
|
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,8 +265,7 @@ class SharedStringBundle final : public nsStringBundleBase {
|
|||||||
private:
|
private:
|
||||||
RefPtr<SharedStringMap> mStringMap;
|
RefPtr<SharedStringMap> mStringMap;
|
||||||
|
|
||||||
Maybe<mozilla::ipc::SharedMemoryHandle> mMapHandle;
|
Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle> mMapHandle;
|
||||||
size_t mMapSize;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(SharedStringBundle, SHAREDSTRINGBUNDLE_IID)
|
NS_DEFINE_STATIC_IID_ACCESSOR(SharedStringBundle, SHAREDSTRINGBUNDLE_IID)
|
||||||
@@ -523,8 +513,7 @@ nsresult SharedStringBundle::LoadProperties() {
|
|||||||
if (mStringMap) return NS_OK;
|
if (mStringMap) return NS_OK;
|
||||||
|
|
||||||
if (mMapHandle.isSome()) {
|
if (mMapHandle.isSome()) {
|
||||||
mStringMap = new SharedStringMap(mMapHandle.ref(), mMapSize);
|
mStringMap = new SharedStringMap(mMapHandle.extract());
|
||||||
mMapHandle.reset();
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,11 +567,10 @@ nsresult SharedStringBundle::LoadProperties() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SharedStringBundle::SetMapFile(
|
void SharedStringBundle::SetMapFile(
|
||||||
const mozilla::ipc::SharedMemoryHandle& aHandle, size_t aSize) {
|
mozilla::ipc::ReadOnlySharedMemoryHandle&& aHandle) {
|
||||||
MOZ_ASSERT(XRE_IsContentProcess());
|
MOZ_ASSERT(XRE_IsContentProcess());
|
||||||
mStringMap = nullptr;
|
mStringMap = nullptr;
|
||||||
mMapHandle.emplace(mozilla::ipc::SharedMemory::CloneHandle(aHandle));
|
mMapHandle.emplace(std::move(aHandle));
|
||||||
mMapSize = aSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@@ -830,7 +818,7 @@ void nsStringBundleService::SendContentBundles(ContentParent* aContentParent) {
|
|||||||
|
|
||||||
void nsStringBundleService::RegisterContentBundle(
|
void nsStringBundleService::RegisterContentBundle(
|
||||||
const nsACString& aBundleURL,
|
const nsACString& aBundleURL,
|
||||||
const mozilla::ipc::SharedMemoryHandle& aMapHandle, size_t aMapSize) {
|
mozilla::ipc::ReadOnlySharedMemoryHandle&& aMapHandle) {
|
||||||
RefPtr<StringBundleProxy> proxy;
|
RefPtr<StringBundleProxy> proxy;
|
||||||
|
|
||||||
bundleCacheEntry_t* cacheEntry = mBundleMap.Get(aBundleURL);
|
bundleCacheEntry_t* cacheEntry = mBundleMap.Get(aBundleURL);
|
||||||
@@ -848,7 +836,7 @@ void nsStringBundleService::RegisterContentBundle(
|
|||||||
|
|
||||||
auto bundle = MakeBundleRefPtr<SharedStringBundle>(
|
auto bundle = MakeBundleRefPtr<SharedStringBundle>(
|
||||||
PromiseFlatCString(aBundleURL).get());
|
PromiseFlatCString(aBundleURL).get());
|
||||||
bundle->SetMapFile(aMapHandle, aMapSize);
|
bundle->SetMapFile(std::move(aMapHandle));
|
||||||
|
|
||||||
if (proxy) {
|
if (proxy) {
|
||||||
proxy->Retarget(bundle);
|
proxy->Retarget(bundle);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ MessageBufferReader::MessageBufferReader(MessageReader* reader,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (shmem_ok) {
|
if (shmem_ok) {
|
||||||
mozilla::ipc::shared_memory::Handle handle;
|
mozilla::ipc::shared_memory::MutableHandle handle;
|
||||||
if (!IPC::ReadParam(reader, &handle)) {
|
if (!IPC::ReadParam(reader, &handle)) {
|
||||||
reader->FatalError("failed to read shared memory handle");
|
reader->FatalError("failed to read shared memory handle");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "base/pickle.h"
|
#include "base/pickle.h"
|
||||||
#include "chrome/common/ipc_message.h"
|
#include "chrome/common/ipc_message.h"
|
||||||
#include "mozilla/CheckedInt.h"
|
#include "mozilla/CheckedInt.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
|
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
@@ -32,7 +33,6 @@ namespace mozilla::ipc {
|
|||||||
class IProtocol;
|
class IProtocol;
|
||||||
template <typename P>
|
template <typename P>
|
||||||
struct IPDLParamTraits;
|
struct IPDLParamTraits;
|
||||||
class SharedMemory;
|
|
||||||
namespace shared_memory {
|
namespace shared_memory {
|
||||||
class Cursor;
|
class Cursor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,16 +7,15 @@
|
|||||||
#include "mozilla/ipc/BigBuffer.h"
|
#include "mozilla/ipc/BigBuffer.h"
|
||||||
|
|
||||||
#include "chrome/common/ipc_message_utils.h"
|
#include "chrome/common/ipc_message_utils.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
|
||||||
#include "nsDebug.h"
|
#include "nsDebug.h"
|
||||||
|
|
||||||
namespace mozilla::ipc {
|
namespace mozilla::ipc {
|
||||||
|
|
||||||
BigBuffer::BigBuffer(Adopt, SharedMemory* aSharedMemory, size_t aSize)
|
BigBuffer::BigBuffer(Adopt, SharedMemoryMappingWithHandle&& aSharedMemory,
|
||||||
: mSize(aSize), mData(AsVariant(RefPtr{aSharedMemory})) {
|
size_t aSize)
|
||||||
MOZ_RELEASE_ASSERT(aSharedMemory && aSharedMemory->Memory(),
|
: mSize(aSize), mData(AsVariant(std::move(aSharedMemory))) {
|
||||||
"shared memory must be non-null and mapped");
|
MOZ_RELEASE_ASSERT(mData.as<1>(), "shared memory must be valid");
|
||||||
MOZ_RELEASE_ASSERT(mSize <= aSharedMemory->Size(),
|
MOZ_RELEASE_ASSERT(mSize <= mData.as<1>().Size(),
|
||||||
"shared memory region isn't large enough");
|
"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<uint8_t[]>{aData})) {}
|
: mSize(aSize), mData(AsVariant(UniqueFreePtr<uint8_t[]>{aData})) {}
|
||||||
|
|
||||||
uint8_t* BigBuffer::Data() {
|
uint8_t* BigBuffer::Data() {
|
||||||
return mData.is<0>() ? mData.as<0>().get()
|
return mData.is<0>() ? mData.as<0>().get() : mData.as<1>().DataAs<uint8_t>();
|
||||||
: reinterpret_cast<uint8_t*>(mData.as<1>()->Memory());
|
|
||||||
}
|
}
|
||||||
const uint8_t* BigBuffer::Data() const {
|
const uint8_t* BigBuffer::Data() const {
|
||||||
return mData.is<0>()
|
return mData.is<0>() ? mData.as<0>().get()
|
||||||
? mData.as<0>().get()
|
: mData.as<1>().DataAs<const uint8_t>();
|
||||||
: reinterpret_cast<const uint8_t*>(mData.as<1>()->Memory());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto BigBuffer::TryAllocBuffer(size_t aSize) -> Maybe<Storage> {
|
auto BigBuffer::TryAllocBuffer(size_t aSize) -> Maybe<Storage> {
|
||||||
@@ -41,12 +38,12 @@ auto BigBuffer::TryAllocBuffer(size_t aSize) -> Maybe<Storage> {
|
|||||||
return Some(AsVariant(std::move(mem)));
|
return Some(AsVariant(std::move(mem)));
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<SharedMemory> shmem = new SharedMemory();
|
size_t capacity = shared_memory::PageAlignedSize(aSize);
|
||||||
size_t capacity = SharedMemory::PageAlignedSize(aSize);
|
auto mapping = shared_memory::Create(capacity).MapWithHandle();
|
||||||
if (!shmem->Create(capacity) || !shmem->Map(capacity)) {
|
if (!mapping) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return Some(AsVariant(shmem));
|
return Some(AsVariant(std::move(mapping)));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla::ipc
|
} // namespace mozilla::ipc
|
||||||
@@ -62,8 +59,11 @@ void IPC::ParamTraits<mozilla::ipc::BigBuffer>::Write(MessageWriter* aWriter,
|
|||||||
WriteParam(aWriter, isShmem);
|
WriteParam(aWriter, isShmem);
|
||||||
|
|
||||||
if (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");
|
aWriter->FatalError("Failed to write data shmem");
|
||||||
|
} else {
|
||||||
|
WriteParam(aWriter, std::move(handle));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
aWriter->WriteBytes(data.as<0>().get(), size);
|
aWriter->WriteBytes(data.as<0>().get(), size);
|
||||||
@@ -81,13 +81,18 @@ bool IPC::ParamTraits<mozilla::ipc::BigBuffer>::Read(MessageReader* aReader,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isShmem) {
|
if (isShmem) {
|
||||||
RefPtr<SharedMemory> shmem = new SharedMemory();
|
MutableSharedMemoryHandle handle;
|
||||||
size_t capacity = SharedMemory::PageAlignedSize(size);
|
size_t expected_size = shared_memory::PageAlignedSize(size);
|
||||||
if (!shmem->ReadHandle(aReader) || !shmem->Map(capacity)) {
|
if (!ReadParam(aReader, &handle) || !handle) {
|
||||||
aReader->FatalError("Failed to read data shmem");
|
aReader->FatalError("Failed to read data shmem");
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,10 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/Span.h"
|
#include "mozilla/Span.h"
|
||||||
#include "mozilla/Variant.h"
|
#include "mozilla/Variant.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
|
|
||||||
namespace mozilla::ipc {
|
namespace mozilla::ipc {
|
||||||
|
|
||||||
@@ -62,8 +63,8 @@ class BigBuffer {
|
|||||||
|
|
||||||
// Create a new BigBuffer from an existing shared memory region, taking
|
// Create a new BigBuffer from an existing shared memory region, taking
|
||||||
// ownership of that shared memory region. The shared memory region must be
|
// ownership of that shared memory region. The shared memory region must be
|
||||||
// non-null, mapped, and large enough to fit aSize bytes.
|
// valid and large enough to fit aSize bytes.
|
||||||
BigBuffer(Adopt, SharedMemory* aSharedMemory, size_t aSize);
|
BigBuffer(Adopt, SharedMemoryMappingWithHandle&& aSharedMemory, size_t aSize);
|
||||||
|
|
||||||
// Create a new BigBuffer from an existing memory buffer, taking ownership of
|
// Create a new BigBuffer from an existing memory buffer, taking ownership of
|
||||||
// that memory region. The region will be freed using `free()` when it is no
|
// that memory region. The region will be freed using `free()` when it is no
|
||||||
@@ -87,14 +88,16 @@ class BigBuffer {
|
|||||||
|
|
||||||
// If the BigBuffer is backed by shared memory, returns a pointer to the
|
// If the BigBuffer is backed by shared memory, returns a pointer to the
|
||||||
// backing SharedMemory region.
|
// backing SharedMemory region.
|
||||||
SharedMemory* GetSharedMemory() const {
|
// This is only meant to be used in tests.
|
||||||
return mData.is<1>() ? mData.as<1>().get() : nullptr;
|
const SharedMemoryMappingWithHandle* GetSharedMemory() const {
|
||||||
|
return mData.is<1>() ? &mData.as<1>() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct IPC::ParamTraits<mozilla::ipc::BigBuffer>;
|
friend struct IPC::ParamTraits<mozilla::ipc::BigBuffer>;
|
||||||
|
|
||||||
using Storage = Variant<UniqueFreePtr<uint8_t[]>, RefPtr<SharedMemory>>;
|
using Storage =
|
||||||
|
Variant<UniqueFreePtr<uint8_t[]>, SharedMemoryMappingWithHandle>;
|
||||||
|
|
||||||
// Empty storage which holds no data.
|
// Empty storage which holds no data.
|
||||||
static Storage NoData() { return AsVariant(UniqueFreePtr<uint8_t[]>{}); }
|
static Storage NoData() { return AsVariant(UniqueFreePtr<uint8_t[]>{}); }
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#if !defined(XP_WIN) && !defined(XP_NETBSD) && !defined(XP_OPENBSD)
|
#if !defined(XP_WIN) && !defined(XP_NETBSD) && !defined(XP_OPENBSD)
|
||||||
# include <pthread.h>
|
# include <pthread.h>
|
||||||
# include "mozilla/ipc/SharedMemory.h"
|
# include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
# include "mozilla/Atomics.h"
|
# include "mozilla/Atomics.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ namespace mozilla {
|
|||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
typedef mozilla::UniqueFileHandle CrossProcessMutexHandle;
|
typedef mozilla::UniqueFileHandle CrossProcessMutexHandle;
|
||||||
#elif !defined(XP_NETBSD) && !defined(XP_OPENBSD)
|
#elif !defined(XP_NETBSD) && !defined(XP_OPENBSD)
|
||||||
typedef mozilla::ipc::SharedMemory::Handle CrossProcessMutexHandle;
|
typedef mozilla::ipc::MutableSharedMemoryHandle CrossProcessMutexHandle;
|
||||||
#else
|
#else
|
||||||
// Stub for other platforms. We can't use uintptr_t here since different
|
// Stub for other platforms. We can't use uintptr_t here since different
|
||||||
// processes could disagree on its size.
|
// processes could disagree on its size.
|
||||||
@@ -104,7 +104,7 @@ class CrossProcessMutex {
|
|||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
HANDLE mMutex;
|
HANDLE mMutex;
|
||||||
#elif !defined(XP_NETBSD) && !defined(XP_OPENBSD)
|
#elif !defined(XP_NETBSD) && !defined(XP_OPENBSD)
|
||||||
RefPtr<mozilla::ipc::SharedMemory> mSharedBuffer;
|
mozilla::ipc::SharedMemoryMappingWithHandle mSharedBuffer;
|
||||||
pthread_mutex_t* mMutex;
|
pthread_mutex_t* mMutex;
|
||||||
mozilla::Atomic<int32_t>* mCount;
|
mozilla::Atomic<int32_t>* mCount;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "CrossProcessMutex.h"
|
#include "CrossProcessMutex.h"
|
||||||
#include "mozilla/Unused.h"
|
#include "mozilla/Unused.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
#include "nsDebug.h"
|
#include "nsDebug.h"
|
||||||
#include "nsISupportsImpl.h"
|
#include "nsISupportsImpl.h"
|
||||||
|
|
||||||
@@ -43,16 +44,12 @@ CrossProcessMutex::CrossProcessMutex(const char*)
|
|||||||
// they specifically are not on Linux.
|
// they specifically are not on Linux.
|
||||||
MOZ_RELEASE_ASSERT(false);
|
MOZ_RELEASE_ASSERT(false);
|
||||||
#endif
|
#endif
|
||||||
mSharedBuffer = new ipc::SharedMemory;
|
mSharedBuffer = ipc::shared_memory::Create(sizeof(MutexData)).MapWithHandle();
|
||||||
if (!mSharedBuffer->Create(sizeof(MutexData))) {
|
if (!mSharedBuffer) {
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mSharedBuffer->Map(sizeof(MutexData))) {
|
MutexData* data = mSharedBuffer.DataAs<MutexData>();
|
||||||
MOZ_CRASH();
|
|
||||||
}
|
|
||||||
|
|
||||||
MutexData* data = static_cast<MutexData*>(mSharedBuffer->Memory());
|
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
@@ -69,22 +66,12 @@ CrossProcessMutex::CrossProcessMutex(const char*)
|
|||||||
|
|
||||||
CrossProcessMutex::CrossProcessMutex(CrossProcessMutexHandle aHandle)
|
CrossProcessMutex::CrossProcessMutex(CrossProcessMutexHandle aHandle)
|
||||||
: mMutex(nullptr), mCount(nullptr) {
|
: mMutex(nullptr), mCount(nullptr) {
|
||||||
mSharedBuffer = new ipc::SharedMemory;
|
mSharedBuffer = std::move(aHandle).MapWithHandle();
|
||||||
|
if (!mSharedBuffer) {
|
||||||
if (!mSharedBuffer->IsHandleValid(aHandle)) {
|
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mSharedBuffer->SetHandle(std::move(aHandle),
|
MutexData* data = mSharedBuffer.DataAs<MutexData>();
|
||||||
ipc::SharedMemory::RightsReadWrite)) {
|
|
||||||
MOZ_CRASH();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mSharedBuffer->Map(sizeof(MutexData))) {
|
|
||||||
MOZ_CRASH();
|
|
||||||
}
|
|
||||||
|
|
||||||
MutexData* data = static_cast<MutexData*>(mSharedBuffer->Memory());
|
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
@@ -125,16 +112,14 @@ void CrossProcessMutex::Unlock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CrossProcessMutexHandle CrossProcessMutex::CloneHandle() {
|
CrossProcessMutexHandle CrossProcessMutex::CloneHandle() {
|
||||||
CrossProcessMutexHandle result = ipc::SharedMemory::NULLHandle();
|
|
||||||
|
|
||||||
if (mSharedBuffer) {
|
if (mSharedBuffer) {
|
||||||
result = mSharedBuffer->CloneHandle();
|
auto handle = mSharedBuffer.Handle().Clone();
|
||||||
if (!result) {
|
if (!handle) {
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
}
|
}
|
||||||
|
return handle;
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
#else
|
#else
|
||||||
# include <pthread.h>
|
# include <pthread.h>
|
||||||
# include <semaphore.h>
|
# include <semaphore.h>
|
||||||
# include "mozilla/ipc/SharedMemory.h"
|
# include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
# include "mozilla/Atomics.h"
|
# include "mozilla/Atomics.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -41,13 +41,7 @@ typedef mozilla::UniqueFileHandle CrossProcessSemaphoreHandle;
|
|||||||
#elif defined(XP_DARWIN)
|
#elif defined(XP_DARWIN)
|
||||||
typedef mozilla::UniqueMachSendRight CrossProcessSemaphoreHandle;
|
typedef mozilla::UniqueMachSendRight CrossProcessSemaphoreHandle;
|
||||||
#else
|
#else
|
||||||
typedef mozilla::ipc::SharedMemory::Handle CrossProcessSemaphoreHandle;
|
typedef mozilla::ipc::MutableSharedMemoryHandle CrossProcessSemaphoreHandle;
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool IsHandleValid<CrossProcessSemaphoreHandle>(
|
|
||||||
const CrossProcessSemaphoreHandle& handle) {
|
|
||||||
return !(handle == mozilla::ipc::SharedMemory::NULLHandle());
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class CrossProcessSemaphore {
|
class CrossProcessSemaphore {
|
||||||
@@ -108,7 +102,8 @@ class CrossProcessSemaphore {
|
|||||||
|
|
||||||
CrossProcessSemaphoreHandle mSemaphore;
|
CrossProcessSemaphoreHandle mSemaphore;
|
||||||
#else
|
#else
|
||||||
RefPtr<mozilla::ipc::SharedMemory> mSharedBuffer;
|
mozilla::ipc::MutableSharedMemoryHandle mHandle;
|
||||||
|
mozilla::ipc::SharedMemoryMapping mSharedBuffer;
|
||||||
sem_t* mSemaphore;
|
sem_t* mSemaphore;
|
||||||
mozilla::Atomic<int32_t>* mRefCount;
|
mozilla::Atomic<int32_t>* mRefCount;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -28,16 +28,17 @@ namespace mozilla {
|
|||||||
/* static */
|
/* static */
|
||||||
CrossProcessSemaphore* CrossProcessSemaphore::Create(const char*,
|
CrossProcessSemaphore* CrossProcessSemaphore::Create(const char*,
|
||||||
uint32_t aInitialValue) {
|
uint32_t aInitialValue) {
|
||||||
RefPtr<ipc::SharedMemory> sharedBuffer = new ipc::SharedMemory;
|
auto handle = ipc::shared_memory::Create(sizeof(SemaphoreData));
|
||||||
if (!sharedBuffer->Create(sizeof(SemaphoreData))) {
|
if (!handle) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sharedBuffer->Map(sizeof(SemaphoreData))) {
|
auto mapping = handle.Map();
|
||||||
|
if (!mapping) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SemaphoreData* data = static_cast<SemaphoreData*>(sharedBuffer->Memory());
|
SemaphoreData* data = mapping.DataAs<SemaphoreData>();
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -48,7 +49,8 @@ CrossProcessSemaphore* CrossProcessSemaphore::Create(const char*,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CrossProcessSemaphore* sem = new CrossProcessSemaphore;
|
CrossProcessSemaphore* sem = new CrossProcessSemaphore;
|
||||||
sem->mSharedBuffer = sharedBuffer;
|
sem->mHandle = std::move(handle);
|
||||||
|
sem->mSharedBuffer = std::move(mapping);
|
||||||
sem->mSemaphore = &data->mSemaphore;
|
sem->mSemaphore = &data->mSemaphore;
|
||||||
sem->mRefCount = &data->mRefCount;
|
sem->mRefCount = &data->mRefCount;
|
||||||
*sem->mRefCount = 1;
|
*sem->mRefCount = 1;
|
||||||
@@ -61,24 +63,14 @@ CrossProcessSemaphore* CrossProcessSemaphore::Create(const char*,
|
|||||||
/* static */
|
/* static */
|
||||||
CrossProcessSemaphore* CrossProcessSemaphore::Create(
|
CrossProcessSemaphore* CrossProcessSemaphore::Create(
|
||||||
CrossProcessSemaphoreHandle aHandle) {
|
CrossProcessSemaphoreHandle aHandle) {
|
||||||
RefPtr<ipc::SharedMemory> sharedBuffer = new ipc::SharedMemory;
|
auto mapping = aHandle.Map();
|
||||||
|
if (!mapping) {
|
||||||
if (!sharedBuffer->IsHandleValid(aHandle)) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sharedBuffer->SetHandle(std::move(aHandle),
|
aHandle = nullptr;
|
||||||
ipc::SharedMemory::RightsReadWrite)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sharedBuffer->Map(sizeof(SemaphoreData))) {
|
SemaphoreData* data = mapping.DataAs<SemaphoreData>();
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
sharedBuffer->CloseHandle();
|
|
||||||
|
|
||||||
SemaphoreData* data = static_cast<SemaphoreData*>(sharedBuffer->Memory());
|
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -95,7 +87,7 @@ CrossProcessSemaphore* CrossProcessSemaphore::Create(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CrossProcessSemaphore* sem = new CrossProcessSemaphore;
|
CrossProcessSemaphore* sem = new CrossProcessSemaphore;
|
||||||
sem->mSharedBuffer = sharedBuffer;
|
sem->mSharedBuffer = std::move(mapping);
|
||||||
sem->mSemaphore = &data->mSemaphore;
|
sem->mSemaphore = &data->mSemaphore;
|
||||||
sem->mRefCount = &data->mRefCount;
|
sem->mRefCount = &data->mRefCount;
|
||||||
return sem;
|
return sem;
|
||||||
@@ -147,18 +139,16 @@ void CrossProcessSemaphore::Signal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CrossProcessSemaphoreHandle CrossProcessSemaphore::CloneHandle() {
|
CrossProcessSemaphoreHandle CrossProcessSemaphore::CloneHandle() {
|
||||||
CrossProcessSemaphoreHandle result = ipc::SharedMemory::NULLHandle();
|
|
||||||
|
|
||||||
if (mSharedBuffer) {
|
if (mSharedBuffer) {
|
||||||
result = mSharedBuffer->CloneHandle();
|
auto handle = mHandle.Clone();
|
||||||
if (!result) {
|
if (!handle) {
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
}
|
}
|
||||||
|
return handle;
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrossProcessSemaphore::CloseHandle() { mSharedBuffer->CloseHandle(); }
|
void CrossProcessSemaphore::CloseHandle() { mHandle = nullptr; }
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|||||||
@@ -71,9 +71,10 @@ static void DoNotifyOnUnlock(DataPipeAutoLock& aLock,
|
|||||||
class DataPipeLink : public NodeController::PortObserver {
|
class DataPipeLink : public NodeController::PortObserver {
|
||||||
public:
|
public:
|
||||||
DataPipeLink(bool aReceiverSide, std::shared_ptr<Mutex> aMutex,
|
DataPipeLink(bool aReceiverSide, std::shared_ptr<Mutex> aMutex,
|
||||||
ScopedPort aPort, SharedMemory::Handle aShmemHandle,
|
ScopedPort aPort, MutableSharedMemoryHandle&& aShmemHandle,
|
||||||
SharedMemory* aShmem, uint32_t aCapacity, nsresult aPeerStatus,
|
const std::shared_ptr<SharedMemoryMapping> aShmem,
|
||||||
uint32_t aOffset, uint32_t aAvailable)
|
uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset,
|
||||||
|
uint32_t aAvailable)
|
||||||
: mMutex(std::move(aMutex)),
|
: mMutex(std::move(aMutex)),
|
||||||
mPort(std::move(aPort)),
|
mPort(std::move(aPort)),
|
||||||
mShmemHandle(std::move(aShmemHandle)),
|
mShmemHandle(std::move(aShmemHandle)),
|
||||||
@@ -165,8 +166,8 @@ class DataPipeLink : public NodeController::PortObserver {
|
|||||||
std::shared_ptr<Mutex> mMutex;
|
std::shared_ptr<Mutex> mMutex;
|
||||||
|
|
||||||
ScopedPort mPort MOZ_GUARDED_BY(*mMutex);
|
ScopedPort mPort MOZ_GUARDED_BY(*mMutex);
|
||||||
SharedMemory::Handle mShmemHandle MOZ_GUARDED_BY(*mMutex);
|
MutableSharedMemoryHandle mShmemHandle MOZ_GUARDED_BY(*mMutex);
|
||||||
const RefPtr<SharedMemory> mShmem;
|
const std::shared_ptr<SharedMemoryMapping> mShmem;
|
||||||
const uint32_t mCapacity;
|
const uint32_t mCapacity;
|
||||||
const bool mReceiverSide;
|
const bool mReceiverSide;
|
||||||
|
|
||||||
@@ -245,10 +246,10 @@ DataPipeBase::DataPipeBase(bool aReceiverSide, nsresult aError)
|
|||||||
mStatus(NS_SUCCEEDED(aError) ? NS_BASE_STREAM_CLOSED : aError) {}
|
mStatus(NS_SUCCEEDED(aError) ? NS_BASE_STREAM_CLOSED : aError) {}
|
||||||
|
|
||||||
DataPipeBase::DataPipeBase(bool aReceiverSide, ScopedPort aPort,
|
DataPipeBase::DataPipeBase(bool aReceiverSide, ScopedPort aPort,
|
||||||
SharedMemory::Handle aShmemHandle,
|
MutableSharedMemoryHandle&& aShmemHandle,
|
||||||
SharedMemory* aShmem, uint32_t aCapacity,
|
const std::shared_ptr<SharedMemoryMapping>& aShmem,
|
||||||
nsresult aPeerStatus, uint32_t aOffset,
|
uint32_t aCapacity, nsresult aPeerStatus,
|
||||||
uint32_t aAvailable)
|
uint32_t aOffset, uint32_t aAvailable)
|
||||||
: mMutex(std::make_shared<Mutex>(aReceiverSide ? "DataPipeReceiver"
|
: mMutex(std::make_shared<Mutex>(aReceiverSide ? "DataPipeReceiver"
|
||||||
: "DataPipeSender")),
|
: "DataPipeSender")),
|
||||||
mStatus(NS_OK),
|
mStatus(NS_OK),
|
||||||
@@ -318,7 +319,7 @@ nsresult DataPipeBase::ProcessSegmentsInternal(
|
|||||||
|
|
||||||
// Extract an iterator over the next contiguous region of the shared memory
|
// Extract an iterator over the next contiguous region of the shared memory
|
||||||
// buffer which will be used .
|
// buffer which will be used .
|
||||||
char* start = static_cast<char*>(link->mShmem->Memory()) + link->mOffset;
|
char* start = link->mShmem->DataAs<char>() + link->mOffset;
|
||||||
char* iter = start;
|
char* iter = start;
|
||||||
char* end = start + std::min({aCount - *aProcessedCount, link->mAvailable,
|
char* end = start + std::min({aCount - *aProcessedCount, link->mAvailable,
|
||||||
link->mCapacity - link->mOffset});
|
link->mCapacity - link->mOffset});
|
||||||
@@ -480,21 +481,17 @@ bool DataPipeRead(IPC::MessageReader* aReader, RefPtr<T>* aResult) {
|
|||||||
aReader->FatalError("failed to read DataPipe port");
|
aReader->FatalError("failed to read DataPipe port");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SharedMemory::Handle shmemHandle;
|
MutableSharedMemoryHandle shmemHandle;
|
||||||
if (!ReadParam(aReader, &shmemHandle)) {
|
if (!ReadParam(aReader, &shmemHandle)) {
|
||||||
aReader->FatalError("failed to read DataPipe shmem");
|
aReader->FatalError("failed to read DataPipe shmem");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Due to the awkward shared memory API provided by SharedMemory, we need to
|
|
||||||
// transfer ownership into the `shmem` here, then steal it back later in the
|
if (!shmemHandle) {
|
||||||
// function. Bug 1797039 tracks potential changes to the RawShmem API which
|
aReader->FatalError("failed to create DataPipe shmem handle");
|
||||||
// could improve this situation.
|
|
||||||
RefPtr shmem = new SharedMemory();
|
|
||||||
if (!shmem->SetHandle(std::move(shmemHandle),
|
|
||||||
SharedMemory::RightsReadWrite)) {
|
|
||||||
aReader->FatalError("failed to create DataPipe shmem from handle");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t capacity = 0;
|
uint32_t capacity = 0;
|
||||||
nsresult peerStatus = NS_OK;
|
nsresult peerStatus = NS_OK;
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
@@ -508,12 +505,14 @@ bool DataPipeRead(IPC::MessageReader* aReader, RefPtr<T>* aResult) {
|
|||||||
aReader->FatalError("received DataPipe state values are inconsistent");
|
aReader->FatalError("received DataPipe state values are inconsistent");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!shmem->Map(SharedMemory::PageAlignedSize(capacity))) {
|
auto mapping = std::make_shared<SharedMemoryMapping>(shmemHandle.Map());
|
||||||
|
if (!*mapping ||
|
||||||
|
mapping->Size() != shared_memory::PageAlignedSize(capacity)) {
|
||||||
aReader->FatalError("failed to map DataPipe shared memory region");
|
aReader->FatalError("failed to map DataPipe shared memory region");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*aResult = new T(std::move(port), shmem->TakeHandle(), shmem, capacity,
|
*aResult = new T(std::move(port), std::move(shmemHandle), mapping, capacity,
|
||||||
peerStatus, offset, available);
|
peerStatus, offset, available);
|
||||||
if (MOZ_LOG_TEST(gDataPipeLog, LogLevel::Debug)) {
|
if (MOZ_LOG_TEST(gDataPipeLog, LogLevel::Debug)) {
|
||||||
DataPipeAutoLock lock(*(*aResult)->mMutex);
|
DataPipeAutoLock lock(*(*aResult)->mMutex);
|
||||||
@@ -588,7 +587,7 @@ NS_IMETHODIMP DataPipeSender::AsyncWait(nsIOutputStreamCallback* aCallback,
|
|||||||
nsIEventTarget* aTarget) {
|
nsIEventTarget* aTarget) {
|
||||||
AsyncWaitInternal(
|
AsyncWaitInternal(
|
||||||
aCallback ? NS_NewCancelableRunnableFunction(
|
aCallback ? NS_NewCancelableRunnableFunction(
|
||||||
"DataPipeReceiver::AsyncWait",
|
"DataPipeSender::AsyncWait",
|
||||||
[self = RefPtr{this}, callback = RefPtr{aCallback}] {
|
[self = RefPtr{this}, callback = RefPtr{aCallback}] {
|
||||||
MOZ_LOG(gDataPipeLog, LogLevel::Debug,
|
MOZ_LOG(gDataPipeLog, LogLevel::Debug,
|
||||||
("Calling OnOutputStreamReady(%p, %p)",
|
("Calling OnOutputStreamReady(%p, %p)",
|
||||||
@@ -717,27 +716,31 @@ nsresult NewDataPipe(uint32_t aCapacity, DataPipeSender** aSender,
|
|||||||
auto [senderPort, receiverPort] = controller->CreatePortPair();
|
auto [senderPort, receiverPort] = controller->CreatePortPair();
|
||||||
|
|
||||||
// Create and allocate the shared memory region.
|
// Create and allocate the shared memory region.
|
||||||
auto shmem = MakeRefPtr<SharedMemory>();
|
size_t alignedCapacity = shared_memory::PageAlignedSize(aCapacity);
|
||||||
size_t alignedCapacity = SharedMemory::PageAlignedSize(aCapacity);
|
auto handle = shared_memory::Create(alignedCapacity);
|
||||||
if (!shmem->Create(alignedCapacity) || !shmem->Map(alignedCapacity)) {
|
if (!handle) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
auto mapping = std::make_shared<SharedMemoryMapping>(handle.Map());
|
||||||
|
if (!*mapping) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll first clone then take the handle from the region so that the sender &
|
// We'll first clone then take the handle from the region so that the sender &
|
||||||
// receiver each have a handle. This avoids the need to duplicate the handle
|
// receiver each have a handle. This avoids the need to duplicate the handle
|
||||||
// when serializing, when errors are non-recoverable.
|
// when serializing, when errors are non-recoverable.
|
||||||
SharedMemory::Handle senderShmemHandle = shmem->CloneHandle();
|
auto senderShmemHandle = handle.Clone();
|
||||||
SharedMemory::Handle receiverShmemHandle = shmem->TakeHandle();
|
auto receiverShmemHandle = std::move(handle);
|
||||||
if (!senderShmemHandle || !receiverShmemHandle) {
|
if (!senderShmemHandle || !receiverShmemHandle) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr sender =
|
RefPtr sender =
|
||||||
new DataPipeSender(std::move(senderPort), std::move(senderShmemHandle),
|
new DataPipeSender(std::move(senderPort), std::move(senderShmemHandle),
|
||||||
shmem, aCapacity, NS_OK, 0, aCapacity);
|
mapping, aCapacity, NS_OK, 0, aCapacity);
|
||||||
RefPtr receiver = new DataPipeReceiver(std::move(receiverPort),
|
RefPtr receiver = new DataPipeReceiver(std::move(receiverPort),
|
||||||
std::move(receiverShmemHandle), shmem,
|
std::move(receiverShmemHandle),
|
||||||
aCapacity, NS_OK, 0, 0);
|
mapping, aCapacity, NS_OK, 0, 0);
|
||||||
sender.forget(aSender);
|
sender.forget(aSender);
|
||||||
receiver.forget(aReceiver);
|
receiver.forget(aReceiver);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|||||||
@@ -7,12 +7,14 @@
|
|||||||
#ifndef mozilla_ipc_DataPipe_h
|
#ifndef mozilla_ipc_DataPipe_h
|
||||||
#define 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 "mozilla/ipc/NodeController.h"
|
||||||
#include "nsIAsyncInputStream.h"
|
#include "nsIAsyncInputStream.h"
|
||||||
#include "nsIAsyncOutputStream.h"
|
#include "nsIAsyncOutputStream.h"
|
||||||
#include "nsIIPCSerializableInputStream.h"
|
#include "nsIIPCSerializableInputStream.h"
|
||||||
#include "nsISupports.h"
|
#include "nsISupports.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
@@ -30,7 +32,8 @@ class DataPipeBase {
|
|||||||
protected:
|
protected:
|
||||||
explicit DataPipeBase(bool aReceiverSide, nsresult aError);
|
explicit DataPipeBase(bool aReceiverSide, nsresult aError);
|
||||||
DataPipeBase(bool aReceiverSide, ScopedPort aPort,
|
DataPipeBase(bool aReceiverSide, ScopedPort aPort,
|
||||||
SharedMemory::Handle aShmemHandle, SharedMemory* aShmem,
|
MutableSharedMemoryHandle&& aShmemHandle,
|
||||||
|
const std::shared_ptr<SharedMemoryMapping>& aShmem,
|
||||||
uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset,
|
uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset,
|
||||||
uint32_t aAvailable);
|
uint32_t aAvailable);
|
||||||
|
|
||||||
@@ -78,12 +81,8 @@ bool DataPipeRead(IPC::MessageReader* aReader, RefPtr<T>* aResult);
|
|||||||
class DataPipeSender;
|
class DataPipeSender;
|
||||||
class DataPipeReceiver;
|
class DataPipeReceiver;
|
||||||
|
|
||||||
#define NS_DATAPIPESENDER_IID \
|
#define NS_DATAPIPESENDER_IID \
|
||||||
{ \
|
{0x6698ed77, 0x9fff, 0x425d, {0xb0, 0xa6, 0x1d, 0x30, 0x66, 0xee, 0xb8, 0x16}}
|
||||||
0x6698ed77, 0x9fff, 0x425d, { \
|
|
||||||
0xb0, 0xa6, 0x1d, 0x30, 0x66, 0xee, 0xb8, 0x16 \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper class for streaming data to another process.
|
// Helper class for streaming data to another process.
|
||||||
class DataPipeSender final : public nsIAsyncOutputStream,
|
class DataPipeSender final : public nsIAsyncOutputStream,
|
||||||
@@ -103,9 +102,10 @@ class DataPipeSender final : public nsIAsyncOutputStream,
|
|||||||
|
|
||||||
explicit DataPipeSender(nsresult aError)
|
explicit DataPipeSender(nsresult aError)
|
||||||
: data_pipe_detail::DataPipeBase(/* aReceiverSide */ false, aError) {}
|
: data_pipe_detail::DataPipeBase(/* aReceiverSide */ false, aError) {}
|
||||||
DataPipeSender(ScopedPort aPort, SharedMemory::Handle aShmemHandle,
|
DataPipeSender(ScopedPort aPort, MutableSharedMemoryHandle&& aShmemHandle,
|
||||||
SharedMemory* aShmem, uint32_t aCapacity, nsresult aPeerStatus,
|
const std::shared_ptr<SharedMemoryMapping>& aShmem,
|
||||||
uint32_t aOffset, uint32_t aAvailable)
|
uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset,
|
||||||
|
uint32_t aAvailable)
|
||||||
: data_pipe_detail::DataPipeBase(
|
: data_pipe_detail::DataPipeBase(
|
||||||
/* aReceiverSide */ false, std::move(aPort),
|
/* aReceiverSide */ false, std::move(aPort),
|
||||||
std::move(aShmemHandle), aShmem, aCapacity, aPeerStatus, aOffset,
|
std::move(aShmemHandle), aShmem, aCapacity, aPeerStatus, aOffset,
|
||||||
@@ -116,12 +116,8 @@ class DataPipeSender final : public nsIAsyncOutputStream,
|
|||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(DataPipeSender, NS_DATAPIPESENDER_IID)
|
NS_DEFINE_STATIC_IID_ACCESSOR(DataPipeSender, NS_DATAPIPESENDER_IID)
|
||||||
|
|
||||||
#define NS_DATAPIPERECEIVER_IID \
|
#define NS_DATAPIPERECEIVER_IID \
|
||||||
{ \
|
{0x0a185f83, 0x499e, 0x450c, {0x95, 0x82, 0x27, 0x67, 0xad, 0x6d, 0x64, 0xb5}}
|
||||||
0x0a185f83, 0x499e, 0x450c, { \
|
|
||||||
0x95, 0x82, 0x27, 0x67, 0xad, 0x6d, 0x64, 0xb5 \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper class for streaming data from another process.
|
// Helper class for streaming data from another process.
|
||||||
class DataPipeReceiver final : public nsIAsyncInputStream,
|
class DataPipeReceiver final : public nsIAsyncInputStream,
|
||||||
@@ -143,9 +139,10 @@ class DataPipeReceiver final : public nsIAsyncInputStream,
|
|||||||
|
|
||||||
explicit DataPipeReceiver(nsresult aError)
|
explicit DataPipeReceiver(nsresult aError)
|
||||||
: data_pipe_detail::DataPipeBase(/* aReceiverSide */ true, aError) {}
|
: data_pipe_detail::DataPipeBase(/* aReceiverSide */ true, aError) {}
|
||||||
DataPipeReceiver(ScopedPort aPort, SharedMemory::Handle aShmemHandle,
|
DataPipeReceiver(ScopedPort aPort, MutableSharedMemoryHandle&& aShmemHandle,
|
||||||
SharedMemory* aShmem, uint32_t aCapacity,
|
const std::shared_ptr<SharedMemoryMapping>& aShmem,
|
||||||
nsresult aPeerStatus, uint32_t aOffset, uint32_t aAvailable)
|
uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset,
|
||||||
|
uint32_t aAvailable)
|
||||||
: data_pipe_detail::DataPipeBase(
|
: data_pipe_detail::DataPipeBase(
|
||||||
/* aReceiverSide */ true, std::move(aPort), std::move(aShmemHandle),
|
/* aReceiverSide */ true, std::move(aPort), std::move(aShmemHandle),
|
||||||
aShmem, aCapacity, aPeerStatus, aOffset, aAvailable) {}
|
aShmem, aCapacity, aPeerStatus, aOffset, aAvailable) {}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include "chrome/common/process_watcher.h"
|
#include "chrome/common/process_watcher.h"
|
||||||
#ifdef XP_DARWIN
|
#ifdef XP_DARWIN
|
||||||
# include <mach/mach_traps.h>
|
# include <mach/mach_traps.h>
|
||||||
# include "SharedMemory.h"
|
|
||||||
# include "base/rand_util.h"
|
# include "base/rand_util.h"
|
||||||
# include "chrome/common/mach_ipc_mac.h"
|
# include "chrome/common/mach_ipc_mac.h"
|
||||||
# include "mozilla/StaticPrefs_media.h"
|
# include "mozilla/StaticPrefs_media.h"
|
||||||
|
|||||||
@@ -29,18 +29,16 @@ void IdleSchedulerChild::Init(IdlePeriodState* aIdlePeriodState) {
|
|||||||
mIdlePeriodState = aIdlePeriodState;
|
mIdlePeriodState = aIdlePeriodState;
|
||||||
|
|
||||||
RefPtr<IdleSchedulerChild> scheduler = this;
|
RefPtr<IdleSchedulerChild> scheduler = this;
|
||||||
auto resolve =
|
auto resolve = [&](std::tuple<mozilla::Maybe<MutableSharedMemoryHandle>,
|
||||||
[&](std::tuple<mozilla::Maybe<SharedMemoryHandle>, uint32_t>&& aResult) {
|
uint32_t>&& aResult) {
|
||||||
if (std::get<0>(aResult)) {
|
if (auto& handle = std::get<0>(aResult)) {
|
||||||
mActiveCounter->SetHandle(std::move(*std::get<0>(aResult)),
|
mActiveCounter = handle->Map();
|
||||||
SharedMemory::RightsReadWrite);
|
mChildId = std::get<1>(aResult);
|
||||||
mActiveCounter->Map(sizeof(int32_t));
|
if (mChildId && mIdlePeriodState && mIdlePeriodState->IsActive()) {
|
||||||
mChildId = std::get<1>(aResult);
|
SetActive();
|
||||||
if (mChildId && mIdlePeriodState && mIdlePeriodState->IsActive()) {
|
}
|
||||||
SetActive();
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto reject = [&](ResponseRejectReason) {};
|
auto reject = [&](ResponseRejectReason) {};
|
||||||
SendInitForIdleUse(std::move(resolve), std::move(reject));
|
SendInitForIdleUse(std::move(resolve), std::move(reject));
|
||||||
@@ -54,23 +52,21 @@ IPCResult IdleSchedulerChild::RecvIdleTime(uint64_t aId, TimeDuration aBudget) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IdleSchedulerChild::SetActive() {
|
void IdleSchedulerChild::SetActive() {
|
||||||
if (mChildId && CanSend() && mActiveCounter->Memory()) {
|
if (mChildId && CanSend() && mActiveCounter) {
|
||||||
++(static_cast<Atomic<int32_t>*>(
|
auto counters = mActiveCounter.DataAsSpan<Atomic<int32_t>>();
|
||||||
mActiveCounter->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]);
|
++counters[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER];
|
||||||
++(static_cast<Atomic<int32_t>*>(mActiveCounter->Memory())[mChildId]);
|
++counters[mChildId];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IdleSchedulerChild::SetPaused() {
|
bool IdleSchedulerChild::SetPaused() {
|
||||||
if (mChildId && CanSend() && mActiveCounter->Memory()) {
|
if (mChildId && CanSend() && mActiveCounter) {
|
||||||
--(static_cast<Atomic<int32_t>*>(mActiveCounter->Memory())[mChildId]);
|
auto counters = mActiveCounter.DataAsSpan<Atomic<int32_t>>();
|
||||||
|
--counters[mChildId];
|
||||||
// The following expression reduces the global activity count and checks if
|
// The following expression reduces the global activity count and checks if
|
||||||
// it drops below the cpu counter limit.
|
// it drops below the cpu counter limit.
|
||||||
return (static_cast<Atomic<int32_t>*>(mActiveCounter->Memory())
|
return counters[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]-- ==
|
||||||
[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER])-- ==
|
counters[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER];
|
||||||
static_cast<Atomic<int32_t>*>(
|
|
||||||
mActiveCounter
|
|
||||||
->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "mozilla/ipc/PIdleSchedulerChild.h"
|
#include "mozilla/ipc/PIdleSchedulerChild.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
|
|
||||||
class nsIIdlePeriod;
|
class nsIIdlePeriod;
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ class IdleSchedulerChild final : public PIdleSchedulerChild {
|
|||||||
friend class BackgroundChildImpl;
|
friend class BackgroundChildImpl;
|
||||||
|
|
||||||
// See IdleScheduleParent::sActiveChildCounter
|
// See IdleScheduleParent::sActiveChildCounter
|
||||||
RefPtr<SharedMemory> mActiveCounter = MakeRefPtr<SharedMemory>();
|
SharedMemoryMapping mActiveCounter;
|
||||||
|
|
||||||
IdlePeriodState* mIdlePeriodState = nullptr;
|
IdlePeriodState* mIdlePeriodState = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,10 @@
|
|||||||
#include "mozilla/Unused.h"
|
#include "mozilla/Unused.h"
|
||||||
#include "mozilla/ipc/IdleSchedulerParent.h"
|
#include "mozilla/ipc/IdleSchedulerParent.h"
|
||||||
#include "mozilla/AppShutdown.h"
|
#include "mozilla/AppShutdown.h"
|
||||||
|
#include "mozilla/NeverDestroyed.h"
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
#include "nsSystemInfo.h"
|
#include "nsSystemInfo.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "nsITimer.h"
|
#include "nsITimer.h"
|
||||||
@@ -17,8 +20,18 @@
|
|||||||
|
|
||||||
namespace mozilla::ipc {
|
namespace mozilla::ipc {
|
||||||
|
|
||||||
MOZ_RUNINIT RefPtr<SharedMemory> IdleSchedulerParent::sActiveChildCounter =
|
// Shared memory for counting how many child processes are running
|
||||||
nullptr;
|
// 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<SharedMemoryMappingWithHandle> mapping;
|
||||||
|
return *mapping;
|
||||||
|
}
|
||||||
|
|
||||||
std::bitset<NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT>
|
std::bitset<NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT>
|
||||||
IdleSchedulerParent::sInUseChildCounters;
|
IdleSchedulerParent::sInUseChildCounters;
|
||||||
MOZ_RUNINIT LinkedList<IdleSchedulerParent>
|
MOZ_RUNINIT LinkedList<IdleSchedulerParent>
|
||||||
@@ -108,9 +121,9 @@ void IdleSchedulerParent::CalculateNumIdleTasks() {
|
|||||||
sMaxConcurrentGCs = std::clamp(sNumCPUs / sPrefConcurrentGCsCPUDivisor, 1u,
|
sMaxConcurrentGCs = std::clamp(sNumCPUs / sPrefConcurrentGCsCPUDivisor, 1u,
|
||||||
sPrefConcurrentGCsMax);
|
sPrefConcurrentGCsMax);
|
||||||
|
|
||||||
if (sActiveChildCounter && sActiveChildCounter->Memory()) {
|
if (sActiveChildCounter()) {
|
||||||
static_cast<Atomic<int32_t>*>(
|
sActiveChildCounter()
|
||||||
sActiveChildCounter->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] =
|
.DataAsSpan<Atomic<int32_t>>()[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] =
|
||||||
static_cast<int32_t>(sMaxConcurrentIdleTasksInChildProcesses);
|
static_cast<int32_t>(sMaxConcurrentIdleTasksInChildProcesses);
|
||||||
}
|
}
|
||||||
IdleSchedulerParent::Schedule(nullptr);
|
IdleSchedulerParent::Schedule(nullptr);
|
||||||
@@ -121,14 +134,12 @@ IdleSchedulerParent::~IdleSchedulerParent() {
|
|||||||
// that is the case.
|
// that is the case.
|
||||||
if (mChildId) {
|
if (mChildId) {
|
||||||
sInUseChildCounters[mChildId] = false;
|
sInUseChildCounters[mChildId] = false;
|
||||||
if (sActiveChildCounter && sActiveChildCounter->Memory() &&
|
if (sActiveChildCounter()) {
|
||||||
static_cast<Atomic<int32_t>*>(
|
auto counters = sActiveChildCounter().DataAsSpan<Atomic<int32_t>>();
|
||||||
sActiveChildCounter->Memory())[mChildId]) {
|
if (counters[mChildId]) {
|
||||||
--static_cast<Atomic<int32_t>*>(
|
--counters[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER];
|
||||||
sActiveChildCounter
|
counters[mChildId] = 0;
|
||||||
->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER];
|
}
|
||||||
static_cast<Atomic<int32_t>*>(sActiveChildCounter->Memory())[mChildId] =
|
|
||||||
0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +166,7 @@ IdleSchedulerParent::~IdleSchedulerParent() {
|
|||||||
sChildProcessesAlive--;
|
sChildProcessesAlive--;
|
||||||
if (sChildProcessesAlive == 0) {
|
if (sChildProcessesAlive == 0) {
|
||||||
MOZ_ASSERT(sIdleAndGCRequests.isEmpty());
|
MOZ_ASSERT(sIdleAndGCRequests.isEmpty());
|
||||||
sActiveChildCounter = nullptr;
|
sActiveChildCounter() = nullptr;
|
||||||
|
|
||||||
if (sStarvationPreventer) {
|
if (sStarvationPreventer) {
|
||||||
sStarvationPreventer->Cancel();
|
sStarvationPreventer->Cancel();
|
||||||
@@ -177,27 +188,22 @@ IPCResult IdleSchedulerParent::RecvInitForIdleUse(
|
|||||||
|
|
||||||
// Create a shared memory object which is shared across all the relevant
|
// Create a shared memory object which is shared across all the relevant
|
||||||
// processes.
|
// processes.
|
||||||
if (!sActiveChildCounter) {
|
if (!sActiveChildCounter()) {
|
||||||
sActiveChildCounter = MakeRefPtr<SharedMemory>();
|
|
||||||
size_t shmemSize = NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT * sizeof(int32_t);
|
size_t shmemSize = NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT * sizeof(int32_t);
|
||||||
if (sActiveChildCounter->Create(shmemSize) &&
|
sActiveChildCounter() = shared_memory::Create(shmemSize).MapWithHandle();
|
||||||
sActiveChildCounter->Map(shmemSize)) {
|
if (sActiveChildCounter()) {
|
||||||
memset(sActiveChildCounter->Memory(), 0, shmemSize);
|
memset(sActiveChildCounter().Address(), 0, shmemSize);
|
||||||
sInUseChildCounters[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER] = true;
|
sInUseChildCounters[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER] = true;
|
||||||
sInUseChildCounters[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] = true;
|
sInUseChildCounters[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] = true;
|
||||||
static_cast<Atomic<int32_t>*>(
|
sActiveChildCounter().DataAsSpan<Atomic<int32_t>>()
|
||||||
sActiveChildCounter
|
[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] =
|
||||||
->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER] =
|
|
||||||
static_cast<int32_t>(sMaxConcurrentIdleTasksInChildProcesses);
|
static_cast<int32_t>(sMaxConcurrentIdleTasksInChildProcesses);
|
||||||
} else {
|
} else {
|
||||||
sActiveChildCounter = nullptr;
|
sActiveChildCounter() = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Maybe<SharedMemory::Handle> activeCounter;
|
MutableSharedMemoryHandle activeCounter =
|
||||||
if (SharedMemory::Handle handle =
|
sActiveChildCounter() ? sActiveChildCounter().Handle().Clone() : nullptr;
|
||||||
sActiveChildCounter ? sActiveChildCounter->CloneHandle() : nullptr) {
|
|
||||||
activeCounter.emplace(std::move(handle));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t unusedId = 0;
|
uint32_t unusedId = 0;
|
||||||
for (uint32_t i = 0; i < NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT; ++i) {
|
for (uint32_t i = 0; i < NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT; ++i) {
|
||||||
@@ -211,8 +217,9 @@ IPCResult IdleSchedulerParent::RecvInitForIdleUse(
|
|||||||
// If there wasn't an empty item, we'll fallback to 0.
|
// If there wasn't an empty item, we'll fallback to 0.
|
||||||
mChildId = unusedId;
|
mChildId = unusedId;
|
||||||
|
|
||||||
aResolve(std::tuple<mozilla::Maybe<SharedMemory::Handle>&&, const uint32_t&>(
|
aResolve(
|
||||||
std::move(activeCounter), mChildId));
|
std::tuple<mozilla::Maybe<MutableSharedMemoryHandle>&&, const uint32_t&>(
|
||||||
|
Some(std::move(activeCounter)), mChildId));
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,10 +325,9 @@ IPCResult IdleSchedulerParent::RecvDoneGC() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t IdleSchedulerParent::ActiveCount() {
|
int32_t IdleSchedulerParent::ActiveCount() {
|
||||||
if (sActiveChildCounter) {
|
if (sActiveChildCounter()) {
|
||||||
return (static_cast<Atomic<int32_t>*>(
|
return sActiveChildCounter().DataAsSpan<Atomic<int32_t>>()
|
||||||
sActiveChildCounter
|
[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER];
|
||||||
->Memory())[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include "mozilla/LinkedList.h"
|
#include "mozilla/LinkedList.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "mozilla/ipc/PIdleSchedulerParent.h"
|
#include "mozilla/ipc/PIdleSchedulerParent.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
|
||||||
#define NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT 1024
|
#define NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT 1024
|
||||||
@@ -82,14 +82,6 @@ class IdleSchedulerParent final
|
|||||||
bool IsDoingIdleTask() const { return !isInList() && mRequestedIdleBudget; }
|
bool IsDoingIdleTask() const { return !isInList() && mRequestedIdleBudget; }
|
||||||
bool IsNotDoingIdleTask() const { return !mRequestedIdleBudget; }
|
bool IsNotDoingIdleTask() const { return !mRequestedIdleBudget; }
|
||||||
|
|
||||||
// Shared memory for counting how many child processes are running
|
|
||||||
// tasks. This memory is shared across all the child processes.
|
|
||||||
// The [0] is used for counting all the processes and
|
|
||||||
// [childId] is for counting per process activity.
|
|
||||||
// This way the global activity can be checked in a fast way by just looking
|
|
||||||
// at [0] value.
|
|
||||||
// [1] is used for cpu count for child processes.
|
|
||||||
static RefPtr<SharedMemory> sActiveChildCounter;
|
|
||||||
// A bit is set if there is a child with child Id as the offset.
|
// A bit is set if there is a child with child Id as the offset.
|
||||||
// The bit is used to check per child specific activity counters in
|
// The bit is used to check per child specific activity counters in
|
||||||
// sActiveChildCounter.
|
// sActiveChildCounter.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
include protocol PBackground;
|
include protocol PBackground;
|
||||||
using mozilla::TimeDuration from "mozilla/TimeStamp.h";
|
using mozilla::TimeDuration from "mozilla/TimeStamp.h";
|
||||||
[MoveOnly] using mozilla::ipc::SharedMemoryHandle from "mozilla/ipc/SharedMemory.h";
|
[MoveOnly] using mozilla::ipc::MutableSharedMemoryHandle from "mozilla/ipc/SharedMemoryHandle.h";
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ child:
|
|||||||
async IdleTime(uint64_t id, TimeDuration budget);
|
async IdleTime(uint64_t id, TimeDuration budget);
|
||||||
|
|
||||||
parent:
|
parent:
|
||||||
async InitForIdleUse() returns (SharedMemoryHandle? state, uint32_t childId);
|
async InitForIdleUse() returns (MutableSharedMemoryHandle? state, uint32_t childId);
|
||||||
async RequestIdleTime(uint64_t id, TimeDuration budget);
|
async RequestIdleTime(uint64_t id, TimeDuration budget);
|
||||||
async IdleTimeUsed(uint64_t id);
|
async IdleTimeUsed(uint64_t id);
|
||||||
|
|
||||||
|
|||||||
@@ -55,22 +55,18 @@ void ProcessChild::AddPlatformBuildID(geckoargs::ChildProcessArgs& aExtraArgs) {
|
|||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
bool ProcessChild::InitPrefs(int aArgc, char* aArgv[]) {
|
bool ProcessChild::InitPrefs(int aArgc, char* aArgv[]) {
|
||||||
Maybe<SharedMemoryHandle> prefsHandle =
|
Maybe<ReadOnlySharedMemoryHandle> prefsHandle =
|
||||||
geckoargs::sPrefsHandle.Get(aArgc, aArgv);
|
geckoargs::sPrefsHandle.Get(aArgc, aArgv);
|
||||||
Maybe<SharedMemoryHandle> prefMapHandle =
|
Maybe<ReadOnlySharedMemoryHandle> prefMapHandle =
|
||||||
geckoargs::sPrefMapHandle.Get(aArgc, aArgv);
|
geckoargs::sPrefMapHandle.Get(aArgc, aArgv);
|
||||||
Maybe<uint64_t> prefsLen = geckoargs::sPrefsLen.Get(aArgc, aArgv);
|
|
||||||
Maybe<uint64_t> prefMapSize = geckoargs::sPrefMapSize.Get(aArgc, aArgv);
|
|
||||||
|
|
||||||
if (prefsLen.isNothing() || prefMapSize.isNothing() ||
|
if (prefsHandle.isNothing() || prefMapHandle.isNothing()) {
|
||||||
prefsHandle.isNothing() || prefMapHandle.isNothing()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPreferenceDeserializer deserializer;
|
SharedPreferenceDeserializer deserializer;
|
||||||
return deserializer.DeserializeFromSharedMemory(std::move(*prefsHandle),
|
return deserializer.DeserializeFromSharedMemory(std::move(*prefsHandle),
|
||||||
std::move(*prefMapHandle),
|
std::move(*prefMapHandle));
|
||||||
*prefsLen, *prefMapSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_TESTS
|
#ifdef ENABLE_TESTS
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
|
|
||||||
#include "mozilla/GeckoArgs.h"
|
#include "mozilla/GeckoArgs.h"
|
||||||
#include "mozilla/ipc/FileDescriptor.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/Maybe.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
@@ -36,22 +37,21 @@ class SharedPreferenceSerializer final {
|
|||||||
bool SerializeToSharedMemory(const GeckoProcessType aDestinationProcessType,
|
bool SerializeToSharedMemory(const GeckoProcessType aDestinationProcessType,
|
||||||
const nsACString& aDestinationRemoteType);
|
const nsACString& aDestinationRemoteType);
|
||||||
|
|
||||||
size_t GetPrefMapSize() const { return mPrefMapSize; }
|
const ReadOnlySharedMemoryHandle& GetPrefsHandle() const {
|
||||||
size_t GetPrefsLength() const { return mPrefsLength; }
|
return mPrefsHandle;
|
||||||
|
}
|
||||||
|
|
||||||
const SharedMemoryHandle& GetPrefsHandle() const { return mPrefsHandle; }
|
const ReadOnlySharedMemoryHandle& GetPrefMapHandle() const {
|
||||||
|
return mPrefMapHandle;
|
||||||
const SharedMemoryHandle& GetPrefMapHandle() const { return mPrefMapHandle; }
|
}
|
||||||
|
|
||||||
void AddSharedPrefCmdLineArgs(GeckoChildProcessHost& procHost,
|
void AddSharedPrefCmdLineArgs(GeckoChildProcessHost& procHost,
|
||||||
geckoargs::ChildProcessArgs& aExtraOpts) const;
|
geckoargs::ChildProcessArgs& aExtraOpts) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(SharedPreferenceSerializer);
|
DISALLOW_COPY_AND_ASSIGN(SharedPreferenceSerializer);
|
||||||
size_t mPrefMapSize;
|
ReadOnlySharedMemoryHandle mPrefMapHandle;
|
||||||
size_t mPrefsLength;
|
ReadOnlySharedMemoryHandle mPrefsHandle;
|
||||||
SharedMemoryHandle mPrefMapHandle;
|
|
||||||
SharedMemoryHandle mPrefsHandle;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SharedPreferenceDeserializer final {
|
class SharedPreferenceDeserializer final {
|
||||||
@@ -59,18 +59,13 @@ class SharedPreferenceDeserializer final {
|
|||||||
SharedPreferenceDeserializer();
|
SharedPreferenceDeserializer();
|
||||||
~SharedPreferenceDeserializer();
|
~SharedPreferenceDeserializer();
|
||||||
|
|
||||||
bool DeserializeFromSharedMemory(SharedMemoryHandle aPrefsHandle,
|
bool DeserializeFromSharedMemory(ReadOnlySharedMemoryHandle&& aPrefsHandle,
|
||||||
SharedMemoryHandle aPrefMapHandle,
|
ReadOnlySharedMemoryHandle&& aPrefMapHandle);
|
||||||
uint64_t aPrefsLen, uint64_t aPrefMapSize);
|
|
||||||
|
|
||||||
const SharedMemoryHandle& GetPrefMapHandle() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(SharedPreferenceDeserializer);
|
DISALLOW_COPY_AND_ASSIGN(SharedPreferenceDeserializer);
|
||||||
Maybe<SharedMemoryHandle> mPrefMapHandle;
|
ReadOnlySharedMemoryHandle mPrefMapHandle;
|
||||||
Maybe<size_t> mPrefsLen;
|
ReadOnlySharedMemoryMapping mShmem;
|
||||||
Maybe<size_t> mPrefMapSize;
|
|
||||||
RefPtr<SharedMemory> mShmem = MakeRefPtr<SharedMemory>();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generate command line argument to spawn a child process. If the shared memory
|
// Generate command line argument to spawn a child process. If the shared memory
|
||||||
@@ -80,7 +75,7 @@ void ExportSharedJSInit(GeckoChildProcessHost& procHost,
|
|||||||
|
|
||||||
// Initialize the content used by the JS engine during the initialization of a
|
// Initialize the content used by the JS engine during the initialization of a
|
||||||
// JS::Runtime.
|
// JS::Runtime.
|
||||||
bool ImportSharedJSInit(SharedMemoryHandle aJsInitHandle, uint64_t aJsInitLen);
|
bool ImportSharedJSInit(ReadOnlySharedMemoryHandle&& aJsInitHandle);
|
||||||
|
|
||||||
} // namespace ipc
|
} // namespace ipc
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
|
||||||
SharedPreferenceSerializer::SharedPreferenceSerializer()
|
SharedPreferenceSerializer::SharedPreferenceSerializer() {
|
||||||
: mPrefMapSize(0), mPrefsLength(0) {
|
|
||||||
MOZ_COUNT_CTOR(SharedPreferenceSerializer);
|
MOZ_COUNT_CTOR(SharedPreferenceSerializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,9 +29,7 @@ SharedPreferenceSerializer::~SharedPreferenceSerializer() {
|
|||||||
|
|
||||||
SharedPreferenceSerializer::SharedPreferenceSerializer(
|
SharedPreferenceSerializer::SharedPreferenceSerializer(
|
||||||
SharedPreferenceSerializer&& aOther)
|
SharedPreferenceSerializer&& aOther)
|
||||||
: mPrefMapSize(aOther.mPrefMapSize),
|
: mPrefMapHandle(std::move(aOther.mPrefMapHandle)),
|
||||||
mPrefsLength(aOther.mPrefsLength),
|
|
||||||
mPrefMapHandle(std::move(aOther.mPrefMapHandle)),
|
|
||||||
mPrefsHandle(std::move(aOther.mPrefsHandle)) {
|
mPrefsHandle(std::move(aOther.mPrefsHandle)) {
|
||||||
MOZ_COUNT_CTOR(SharedPreferenceSerializer);
|
MOZ_COUNT_CTOR(SharedPreferenceSerializer);
|
||||||
}
|
}
|
||||||
@@ -40,7 +37,7 @@ SharedPreferenceSerializer::SharedPreferenceSerializer(
|
|||||||
bool SharedPreferenceSerializer::SerializeToSharedMemory(
|
bool SharedPreferenceSerializer::SerializeToSharedMemory(
|
||||||
const GeckoProcessType aDestinationProcessType,
|
const GeckoProcessType aDestinationProcessType,
|
||||||
const nsACString& aDestinationRemoteType) {
|
const nsACString& aDestinationRemoteType) {
|
||||||
mPrefMapHandle = Preferences::EnsureSnapshot(&mPrefMapSize);
|
mPrefMapHandle = Preferences::EnsureSnapshot();
|
||||||
|
|
||||||
bool destIsWebContent =
|
bool destIsWebContent =
|
||||||
aDestinationProcessType == GeckoProcessType_Content &&
|
aDestinationProcessType == GeckoProcessType_Content &&
|
||||||
@@ -50,40 +47,38 @@ bool SharedPreferenceSerializer::SerializeToSharedMemory(
|
|||||||
// Serialize the early prefs.
|
// Serialize the early prefs.
|
||||||
nsAutoCStringN<1024> prefs;
|
nsAutoCStringN<1024> prefs;
|
||||||
Preferences::SerializePreferences(prefs, destIsWebContent);
|
Preferences::SerializePreferences(prefs, destIsWebContent);
|
||||||
mPrefsLength = prefs.Length();
|
auto prefsLength = prefs.Length();
|
||||||
|
|
||||||
RefPtr<SharedMemory> shm = MakeRefPtr<SharedMemory>();
|
|
||||||
// Set up the shared memory.
|
// 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");
|
NS_ERROR("failed to create shared memory in the parent");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!shm->Map(prefs.Length())) {
|
auto mapping = handle.Map();
|
||||||
|
if (!mapping) {
|
||||||
NS_ERROR("failed to map shared memory in the parent");
|
NS_ERROR("failed to map shared memory in the parent");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the serialized prefs into the shared memory.
|
// Copy the serialized prefs into the shared memory.
|
||||||
memcpy(static_cast<char*>(shm->Memory()), prefs.get(), mPrefsLength);
|
memcpy(mapping.DataAs<char>(), prefs.get(), prefsLength);
|
||||||
|
|
||||||
mPrefsHandle = shm->TakeHandleAndUnmap();
|
mPrefsHandle = std::move(handle).ToReadOnly();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedPreferenceSerializer::AddSharedPrefCmdLineArgs(
|
void SharedPreferenceSerializer::AddSharedPrefCmdLineArgs(
|
||||||
mozilla::ipc::GeckoChildProcessHost& procHost,
|
mozilla::ipc::GeckoChildProcessHost& procHost,
|
||||||
geckoargs::ChildProcessArgs& aExtraOpts) const {
|
geckoargs::ChildProcessArgs& aExtraOpts) const {
|
||||||
SharedMemoryHandle prefsHandle = SharedMemory::CloneHandle(GetPrefsHandle());
|
auto prefsHandle = GetPrefsHandle().Clone();
|
||||||
MOZ_RELEASE_ASSERT(prefsHandle, "failed to duplicate prefs handle");
|
MOZ_RELEASE_ASSERT(prefsHandle, "failed to clone prefs handle");
|
||||||
SharedMemoryHandle prefMapHandle =
|
auto prefMapHandle = GetPrefMapHandle().Clone();
|
||||||
SharedMemory::CloneHandle(GetPrefMapHandle());
|
MOZ_RELEASE_ASSERT(prefMapHandle, "failed to clone pref map handle");
|
||||||
MOZ_RELEASE_ASSERT(prefMapHandle, "failed to duplicate 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::sPrefsHandle.Put(std::move(prefsHandle), aExtraOpts);
|
||||||
geckoargs::sPrefsLen.Put((uintptr_t)(GetPrefsLength()), aExtraOpts);
|
|
||||||
geckoargs::sPrefMapHandle.Put(std::move(prefMapHandle), aExtraOpts);
|
geckoargs::sPrefMapHandle.Put(std::move(prefMapHandle), aExtraOpts);
|
||||||
geckoargs::sPrefMapSize.Put((uintptr_t)(GetPrefMapSize()), aExtraOpts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPreferenceDeserializer::SharedPreferenceDeserializer() {
|
SharedPreferenceDeserializer::SharedPreferenceDeserializer() {
|
||||||
@@ -95,79 +90,56 @@ SharedPreferenceDeserializer::~SharedPreferenceDeserializer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SharedPreferenceDeserializer::DeserializeFromSharedMemory(
|
bool SharedPreferenceDeserializer::DeserializeFromSharedMemory(
|
||||||
SharedMemoryHandle aPrefsHandle, SharedMemoryHandle aPrefMapHandle,
|
ReadOnlySharedMemoryHandle&& aPrefsHandle,
|
||||||
uint64_t aPrefsLen, uint64_t aPrefMapSize) {
|
ReadOnlySharedMemoryHandle&& aPrefMapHandle) {
|
||||||
if (!aPrefsHandle || !aPrefMapHandle || !aPrefsLen || !aPrefMapSize) {
|
if (!aPrefsHandle || !aPrefMapHandle) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mPrefMapHandle.emplace(std::move(aPrefMapHandle));
|
mPrefMapHandle = std::move(aPrefMapHandle);
|
||||||
|
|
||||||
mPrefsLen = Some((uintptr_t)(aPrefsLen));
|
|
||||||
|
|
||||||
mPrefMapSize = Some((uintptr_t)(aPrefMapSize));
|
|
||||||
|
|
||||||
// Init the shared-memory base preference mapping first, so that only changed
|
// Init the shared-memory base preference mapping first, so that only changed
|
||||||
// preferences wind up in heap memory.
|
// preferences wind up in heap memory.
|
||||||
Preferences::InitSnapshot(mPrefMapHandle.ref(), *mPrefMapSize);
|
Preferences::InitSnapshot(mPrefMapHandle);
|
||||||
|
|
||||||
// Set up early prefs from the shared memory.
|
// Set up early prefs from the shared memory.
|
||||||
if (!mShmem->SetHandle(std::move(aPrefsHandle),
|
mShmem = aPrefsHandle.Map();
|
||||||
SharedMemory::RightsReadOnly)) {
|
if (!mShmem) {
|
||||||
NS_ERROR("failed to open shared memory in the child");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!mShmem->Map(*mPrefsLen)) {
|
|
||||||
NS_ERROR("failed to map shared memory in the child");
|
NS_ERROR("failed to map shared memory in the child");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Preferences::DeserializePreferences(static_cast<char*>(mShmem->Memory()),
|
Preferences::DeserializePreferences(mShmem.DataAs<char>(), mShmem.Size());
|
||||||
*mPrefsLen);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SharedMemoryHandle& SharedPreferenceDeserializer::GetPrefMapHandle()
|
|
||||||
const {
|
|
||||||
MOZ_ASSERT(mPrefMapHandle.isSome());
|
|
||||||
|
|
||||||
return mPrefMapHandle.ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExportSharedJSInit(mozilla::ipc::GeckoChildProcessHost& procHost,
|
void ExportSharedJSInit(mozilla::ipc::GeckoChildProcessHost& procHost,
|
||||||
geckoargs::ChildProcessArgs& aExtraOpts) {
|
geckoargs::ChildProcessArgs& aExtraOpts) {
|
||||||
auto& shmem = xpc::SelfHostedShmem::GetSingleton();
|
auto& shmem = xpc::SelfHostedShmem::GetSingleton();
|
||||||
SharedMemoryHandle handle = SharedMemory::CloneHandle(shmem.Handle());
|
auto handle = shmem.Handle().Clone();
|
||||||
size_t len = shmem.Content().Length();
|
|
||||||
|
|
||||||
// If the file is not found or the content is empty, then we would start the
|
// If the file is not found or the content is empty, then we would start the
|
||||||
// content process without this optimization.
|
// content process without this optimization.
|
||||||
if (!SharedMemory::IsHandleValid(handle) || !len) {
|
if (!handle) {
|
||||||
NS_ERROR("Can't use SelfHosted shared memory handle.");
|
NS_ERROR("Can't use SelfHosted shared memory handle.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// command line: -jsInitHandle handle -jsInitLen length
|
// command line: -jsInitHandle handle
|
||||||
geckoargs::sJsInitHandle.Put(std::move(handle), aExtraOpts);
|
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
|
// This is an optimization, and as such we can safely recover if the command
|
||||||
// line argument are not provided.
|
// line argument are not provided.
|
||||||
if (!aJsInitLen || !aJsInitHandle) {
|
if (!aJsInitHandle) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len = (uintptr_t)(aJsInitLen);
|
|
||||||
if (!len) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the shared memory with the file handle and size of the content
|
// Initialize the shared memory with the file handle and size of the content
|
||||||
// of the self-hosted Xdr.
|
// of the self-hosted Xdr.
|
||||||
auto& shmem = xpc::SelfHostedShmem::GetSingleton();
|
auto& shmem = xpc::SelfHostedShmem::GetSingleton();
|
||||||
if (!shmem.InitFromChild(std::move(aJsInitHandle), len)) {
|
if (!shmem.InitFromChild(std::move(aJsInitHandle))) {
|
||||||
NS_ERROR("failed to open shared memory in the child");
|
NS_ERROR("failed to open shared memory in the child");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "mozilla/ipc/MessageChannel.h"
|
#include "mozilla/ipc/MessageChannel.h"
|
||||||
#include "mozilla/ipc/MessageLink.h"
|
#include "mozilla/ipc/MessageLink.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
|
||||||
#include "mozilla/ipc/Shmem.h"
|
#include "mozilla/ipc/Shmem.h"
|
||||||
#include "nsPrintfCString.h"
|
#include "nsPrintfCString.h"
|
||||||
#include "nsTHashMap.h"
|
#include "nsTHashMap.h"
|
||||||
|
|||||||
@@ -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 <utility>
|
|
||||||
|
|
||||||
#include "chrome/common/ipc_message_utils.h"
|
|
||||||
#include "mozilla/Atomics.h"
|
|
||||||
#include "nsIMemoryReporter.h"
|
|
||||||
|
|
||||||
#ifdef FUZZING
|
|
||||||
# include "mozilla/ipc/SharedMemoryFuzzer.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace mozilla::ipc {
|
|
||||||
|
|
||||||
static Atomic<size_t> gShmemAllocated;
|
|
||||||
static Atomic<size_t> gShmemMapped;
|
|
||||||
|
|
||||||
class ShmemReporter final : public nsIMemoryReporter {
|
|
||||||
~ShmemReporter() = default;
|
|
||||||
|
|
||||||
public:
|
|
||||||
NS_DECL_THREADSAFE_ISUPPORTS
|
|
||||||
|
|
||||||
NS_IMETHOD
|
|
||||||
CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
|
|
||||||
bool aAnonymize) override {
|
|
||||||
MOZ_COLLECT_REPORT(
|
|
||||||
"shmem-allocated", KIND_OTHER, UNITS_BYTES, gShmemAllocated,
|
|
||||||
"Memory shared with other processes that is accessible (but not "
|
|
||||||
"necessarily mapped).");
|
|
||||||
|
|
||||||
MOZ_COLLECT_REPORT(
|
|
||||||
"shmem-mapped", KIND_OTHER, UNITS_BYTES, gShmemMapped,
|
|
||||||
"Memory shared with other processes that is mapped into the address "
|
|
||||||
"space.");
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(ShmemReporter, nsIMemoryReporter)
|
|
||||||
|
|
||||||
SharedMemory::SharedMemory() : mAllocSize(0), mMappedSize(0) {
|
|
||||||
static Atomic<bool> registered;
|
|
||||||
if (registered.compareExchange(false, true)) {
|
|
||||||
RegisterStrongMemoryReporter(new ShmemReporter());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedMemory::~SharedMemory() {
|
|
||||||
Unmap();
|
|
||||||
CloseHandle();
|
|
||||||
ResetImpl();
|
|
||||||
|
|
||||||
MOZ_ASSERT(gShmemAllocated >= mAllocSize,
|
|
||||||
"Can't destroy more than allocated");
|
|
||||||
gShmemAllocated -= mAllocSize;
|
|
||||||
mAllocSize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemory::Create(size_t aNBytes, bool freezable) {
|
|
||||||
MOZ_ASSERT(!IsValid(), "already initialized");
|
|
||||||
bool ok = CreateImpl(aNBytes, freezable);
|
|
||||||
if (ok) {
|
|
||||||
mAllocSize = aNBytes;
|
|
||||||
mFreezable = freezable;
|
|
||||||
mReadOnly = false;
|
|
||||||
mExternalHandle = false;
|
|
||||||
gShmemAllocated += mAllocSize;
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemory::Map(size_t aNBytes, void* fixedAddress) {
|
|
||||||
if (!mHandle) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
MOZ_ASSERT(!mMemory, "can't map memory when a mapping already exists");
|
|
||||||
auto address = MapImpl(aNBytes, fixedAddress);
|
|
||||||
if (address) {
|
|
||||||
mMappedSize = aNBytes;
|
|
||||||
mMemory = UniqueMapping(*address, MappingDeleter(mMappedSize));
|
|
||||||
gShmemMapped += mMappedSize;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedMemory::Unmap() {
|
|
||||||
if (!mMemory) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MOZ_ASSERT(gShmemMapped >= mMappedSize, "Can't unmap more than mapped");
|
|
||||||
mMemory = nullptr;
|
|
||||||
gShmemMapped -= std::exchange(mMappedSize, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* SharedMemory::Memory() const {
|
|
||||||
#ifdef FUZZING
|
|
||||||
return SharedMemoryFuzzer::MutateSharedMemory(mMemory.get(), mAllocSize);
|
|
||||||
#else
|
|
||||||
return mMemory.get();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
Span<uint8_t> SharedMemory::TakeMapping() {
|
|
||||||
// NOTE: this doesn't reduce gShmemMapped since it _is_ still mapped memory
|
|
||||||
// (and will be until the process terminates).
|
|
||||||
return {static_cast<uint8_t*>(mMemory.release()),
|
|
||||||
std::exchange(mMappedSize, 0)};
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedMemory::Handle SharedMemory::TakeHandle() {
|
|
||||||
gShmemAllocated -= mAllocSize;
|
|
||||||
mAllocSize = 0;
|
|
||||||
return std::move(mHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemory::SetHandle(Handle aHandle, OpenRights aRights) {
|
|
||||||
MOZ_ASSERT(!IsValid(),
|
|
||||||
"SetHandle cannot be called when a valid handle is already held");
|
|
||||||
ResetImpl();
|
|
||||||
mHandle = std::move(aHandle);
|
|
||||||
mAllocSize = 0;
|
|
||||||
mMappedSize = 0;
|
|
||||||
mFreezable = false;
|
|
||||||
mReadOnly = aRights == OpenRights::RightsReadOnly;
|
|
||||||
mExternalHandle = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemory::ReadOnlyCopy(SharedMemory* ro_out) {
|
|
||||||
MOZ_ASSERT(mHandle);
|
|
||||||
MOZ_ASSERT(!mReadOnly);
|
|
||||||
MOZ_ASSERT(mFreezable);
|
|
||||||
if (ro_out == this) {
|
|
||||||
MOZ_ASSERT(
|
|
||||||
!mMemory,
|
|
||||||
"Memory cannot be mapped when creating a read-only copy of this.");
|
|
||||||
}
|
|
||||||
auto handle = ReadOnlyCopyImpl();
|
|
||||||
auto allocSize = mAllocSize;
|
|
||||||
TakeHandle();
|
|
||||||
if (!handle) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mFreezable = false;
|
|
||||||
|
|
||||||
// Reset ro_out (unmapping, etc).
|
|
||||||
ro_out->~SharedMemory();
|
|
||||||
|
|
||||||
ro_out->mHandle = std::move(*handle);
|
|
||||||
ro_out->mAllocSize = allocSize;
|
|
||||||
gShmemAllocated += ro_out->mAllocSize;
|
|
||||||
ro_out->mReadOnly = true;
|
|
||||||
ro_out->mFreezable = false;
|
|
||||||
ro_out->mExternalHandle = mExternalHandle;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemory::WriteHandle(IPC::MessageWriter* aWriter) {
|
|
||||||
Handle handle = CloneHandle(mHandle);
|
|
||||||
if (!handle) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IPC::WriteParam(aWriter, std::move(handle));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemory::ReadHandle(IPC::MessageReader* aReader) {
|
|
||||||
Handle handle;
|
|
||||||
return IPC::ReadParam(aReader, &handle) && IsHandleValid(handle) &&
|
|
||||||
SetHandle(std::move(handle), RightsReadWrite);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedMemory::Protect(char* aAddr, size_t aSize, int aRights) {
|
|
||||||
// Don't allow altering of rights on freezable shared memory handles.
|
|
||||||
MOZ_ASSERT(!mFreezable);
|
|
||||||
|
|
||||||
char* memStart = reinterpret_cast<char*>(Memory());
|
|
||||||
if (!memStart) MOZ_CRASH("SharedMemory region points at NULL!");
|
|
||||||
char* memEnd = memStart + Size();
|
|
||||||
|
|
||||||
char* protStart = aAddr;
|
|
||||||
if (!protStart) MOZ_CRASH("trying to Protect() a NULL region!");
|
|
||||||
char* protEnd = protStart + aSize;
|
|
||||||
|
|
||||||
if (!(memStart <= protStart && protEnd <= memEnd)) {
|
|
||||||
MOZ_CRASH("attempt to Protect() a region outside this SharedMemory");
|
|
||||||
}
|
|
||||||
|
|
||||||
// checks alignment etc.
|
|
||||||
SystemProtect(aAddr, aSize, aRights);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t SharedMemory::PageAlignedSize(size_t aSize) {
|
|
||||||
size_t pageSize = SystemPageSize();
|
|
||||||
size_t nPagesNeeded = size_t(ceil(double(aSize) / double(pageSize)));
|
|
||||||
return pageSize * nPagesNeeded;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mozilla::ipc
|
|
||||||
@@ -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 <cstddef>
|
|
||||||
|
|
||||||
#include "mozilla/Maybe.h"
|
|
||||||
#include "mozilla/UniquePtrExtensions.h"
|
|
||||||
#include "nsISupportsImpl.h" // NS_INLINE_DECL_REFCOUNTING
|
|
||||||
|
|
||||||
#if !(defined(XP_DARWIN) || defined(XP_WIN))
|
|
||||||
# include <string>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace IPC {
|
|
||||||
class MessageWriter;
|
|
||||||
class MessageReader;
|
|
||||||
} // namespace IPC
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
enum Rights { RightsNone = 0, RightsRead = 1 << 0, RightsWrite = 1 << 1 };
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace mozilla::ipc {
|
|
||||||
|
|
||||||
// Rust Bindgen code doesn't actually use these types, but `UniqueFileHandle`
|
|
||||||
// and `UniqueMachSendRight` aren't defined and some headers need to type check,
|
|
||||||
// so we define a dummy type.
|
|
||||||
#if defined(RUST_BINDGEN)
|
|
||||||
using SharedMemoryHandle = void*;
|
|
||||||
#elif defined(XP_DARWIN)
|
|
||||||
using SharedMemoryHandle = mozilla::UniqueMachSendRight;
|
|
||||||
#else
|
|
||||||
using SharedMemoryHandle = mozilla::UniqueFileHandle;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class SharedMemory {
|
|
||||||
~SharedMemory();
|
|
||||||
|
|
||||||
/// # Provided methods
|
|
||||||
public:
|
|
||||||
using Handle = SharedMemoryHandle;
|
|
||||||
|
|
||||||
enum OpenRights {
|
|
||||||
RightsReadOnly = RightsRead,
|
|
||||||
RightsReadWrite = RightsRead | RightsWrite,
|
|
||||||
};
|
|
||||||
|
|
||||||
SharedMemory();
|
|
||||||
|
|
||||||
// bug 1168843, compositor thread may create shared memory instances that are
|
|
||||||
// destroyed by main thread on shutdown, so this must use thread-safe RC to
|
|
||||||
// avoid hitting assertion
|
|
||||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedMemory)
|
|
||||||
|
|
||||||
size_t Size() const { return mMappedSize; }
|
|
||||||
size_t MaxSize() const { return mAllocSize; }
|
|
||||||
|
|
||||||
bool Create(size_t nBytes, bool freezable = false);
|
|
||||||
bool Map(size_t nBytes, void* fixedAddress = nullptr);
|
|
||||||
void Unmap();
|
|
||||||
void* Memory() const;
|
|
||||||
/// Take the mapping memory.
|
|
||||||
///
|
|
||||||
/// This prevents unmapping the memory.
|
|
||||||
Span<uint8_t> TakeMapping();
|
|
||||||
|
|
||||||
Handle TakeHandleAndUnmap() {
|
|
||||||
auto handle = TakeHandle();
|
|
||||||
Unmap();
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
Handle TakeHandle();
|
|
||||||
Handle CloneHandle() {
|
|
||||||
mFreezable = false;
|
|
||||||
return SharedMemory::CloneHandle(mHandle);
|
|
||||||
}
|
|
||||||
void CloseHandle() { TakeHandle(); }
|
|
||||||
bool SetHandle(Handle aHandle, OpenRights aRights);
|
|
||||||
bool IsValid() const { return IsHandleValid(mHandle); }
|
|
||||||
static bool IsHandleValid(const Handle& aHandle) {
|
|
||||||
// `operator!=` had ambiguous overload resolution with the windows Handle
|
|
||||||
// (mozilla::UniqueFileHandle), so invert `operator==` instead.
|
|
||||||
return !(aHandle == NULLHandle());
|
|
||||||
}
|
|
||||||
static Handle NULLHandle() { return nullptr; }
|
|
||||||
|
|
||||||
bool CreateFreezable(size_t nBytes) { return Create(nBytes, true); }
|
|
||||||
|
|
||||||
[[nodiscard]] bool Freeze() {
|
|
||||||
Unmap();
|
|
||||||
return ReadOnlyCopy(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WriteHandle(IPC::MessageWriter* aWriter);
|
|
||||||
bool ReadHandle(IPC::MessageReader* aReader);
|
|
||||||
void Protect(char* aAddr, size_t aSize, int aRights);
|
|
||||||
|
|
||||||
static size_t PageAlignedSize(size_t aSize);
|
|
||||||
|
|
||||||
/// Public methods which should be defined as part of each implementation.
|
|
||||||
public:
|
|
||||||
[[nodiscard]] bool ReadOnlyCopy(SharedMemory* ro_out);
|
|
||||||
|
|
||||||
static void SystemProtect(char* aAddr, size_t aSize, int aRights);
|
|
||||||
[[nodiscard]] static bool SystemProtectFallible(char* aAddr, size_t aSize,
|
|
||||||
int aRights);
|
|
||||||
static Handle CloneHandle(const Handle& aHandle);
|
|
||||||
static size_t SystemPageSize();
|
|
||||||
static void* FindFreeAddressSpace(size_t size);
|
|
||||||
|
|
||||||
/// Private methods which should be defined as part of each implementation.
|
|
||||||
private:
|
|
||||||
bool CreateImpl(size_t size, bool freezable);
|
|
||||||
Maybe<void*> MapImpl(size_t nBytes, void* fixedAddress);
|
|
||||||
static void UnmapImpl(size_t nBytes, void* address);
|
|
||||||
Maybe<Handle> ReadOnlyCopyImpl();
|
|
||||||
void ResetImpl();
|
|
||||||
|
|
||||||
/// Common members
|
|
||||||
private:
|
|
||||||
struct MappingDeleter {
|
|
||||||
size_t mMappedSize = 0;
|
|
||||||
explicit MappingDeleter(size_t size) : mMappedSize(size) {}
|
|
||||||
MappingDeleter() = default;
|
|
||||||
void operator()(void* ptr) {
|
|
||||||
MOZ_ASSERT(mMappedSize != 0);
|
|
||||||
UnmapImpl(mMappedSize, ptr);
|
|
||||||
// Guard against multiple calls of the same deleter, which shouldn't
|
|
||||||
// happen (but could, if `UniquePtr::reset` were used). Calling
|
|
||||||
// `munmap` with an incorrect non-zero length would be bad.
|
|
||||||
mMappedSize = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#ifndef RUST_BINDGEN
|
|
||||||
using UniqueMapping = mozilla::UniquePtr<void, MappingDeleter>;
|
|
||||||
#else
|
|
||||||
using UniqueMapping = void*;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The held handle, if any.
|
|
||||||
Handle mHandle = NULLHandle();
|
|
||||||
// The size of the shmem region requested in Create(), if
|
|
||||||
// successful. SharedMemory instances that are opened from a
|
|
||||||
// foreign handle have an alloc size of 0, even though they have
|
|
||||||
// access to the alloc-size information.
|
|
||||||
size_t mAllocSize;
|
|
||||||
// The memory mapping, if any.
|
|
||||||
UniqueMapping mMemory;
|
|
||||||
// The size of the region mapped in Map(), if successful. All
|
|
||||||
// SharedMemorys that are mapped have a non-zero mapped size.
|
|
||||||
size_t mMappedSize;
|
|
||||||
// Whether the handle held is freezable.
|
|
||||||
bool mFreezable = false;
|
|
||||||
// Whether the handle held is read-only.
|
|
||||||
bool mReadOnly = false;
|
|
||||||
// Whether the handle held is external (set with `SetHandle`).
|
|
||||||
bool mExternalHandle = false;
|
|
||||||
|
|
||||||
#if !defined(XP_DARWIN) && !defined(XP_WIN)
|
|
||||||
/// # Unix/POSIX-specific methods and members.
|
|
||||||
public:
|
|
||||||
// If named POSIX shm is being used, append the prefix (including
|
|
||||||
// the leading '/') that would be used by a process with the given
|
|
||||||
// pid to the given string and return true. If not, return false.
|
|
||||||
// (This is public so that the Linux sandboxing code can use it.)
|
|
||||||
static bool AppendPosixShmPrefix(std::string* str, pid_t pid);
|
|
||||||
|
|
||||||
// Similar, but simply returns whether POSIX shm is in use.
|
|
||||||
static bool UsingPosixShm();
|
|
||||||
|
|
||||||
# if !defined(ANDROID) && !defined(RUST_BINDGEN)
|
|
||||||
private:
|
|
||||||
mozilla::UniqueFileHandle mFrozenFile;
|
|
||||||
bool mIsMemfd = false;
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mozilla::ipc
|
|
||||||
|
|
||||||
#endif // ifndef mozilla_ipc_SharedMemory_h
|
|
||||||
@@ -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 <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "mozilla/Ashmem.h"
|
|
||||||
|
|
||||||
#ifdef MOZ_VALGRIND
|
|
||||||
# include <valgrind/valgrind.h>
|
|
||||||
#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<void*> 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::Handle> 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
|
|
||||||
@@ -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 <utility>
|
|
||||||
|
|
||||||
#include <mach/vm_map.h>
|
|
||||||
#include <mach/mach_port.h>
|
|
||||||
#if defined(XP_IOS)
|
|
||||||
# include <mach/vm_map.h>
|
|
||||||
# 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 <mach/mach_vm.h>
|
|
||||||
#endif
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <sys/mman.h> // mprotect
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#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<void*>(static_cast<uintptr_t>(address));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline mach_vm_address_t toVMAddress(void* pointer) {
|
|
||||||
return static_cast<mach_vm_address_t>(reinterpret_cast<uintptr_t>(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<void*> 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<void*> 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::Handle> 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<memory_object_offset_t>(reinterpret_cast<uintptr_t>(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<size_t> 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
|
|
||||||
@@ -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 <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#ifdef XP_LINUX
|
|
||||||
# include "base/linux_memfd_defs.h"
|
|
||||||
#endif
|
|
||||||
#ifdef MOZ_WIDGET_GTK
|
|
||||||
# include "mozilla/WidgetUtilsGtk.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
|
||||||
# include <sys/capsicum.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MOZ_VALGRIND
|
|
||||||
# include <valgrind/valgrind.h>
|
|
||||||
#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<void*> 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<unsigned> HaveMemfd() {
|
|
||||||
#ifdef USE_MEMFD_CREATE
|
|
||||||
static const Maybe<unsigned> kHave = []() -> Maybe<unsigned> {
|
|
||||||
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<int>(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<size_t> 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<int> 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<off_t>(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<off_t>(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::Handle> 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
|
|
||||||
@@ -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 <windows.h>
|
|
||||||
|
|
||||||
#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<NtQuerySectionType>(
|
|
||||||
::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), "NtQuerySection"));
|
|
||||||
DCHECK(nt_query_section_func);
|
|
||||||
|
|
||||||
// The handle must have SECTION_QUERY access for this to succeed.
|
|
||||||
SECTION_BASIC_INFORMATION basic_information = {};
|
|
||||||
ULONG status =
|
|
||||||
nt_query_section_func(handle, SectionBasicInformation, &basic_information,
|
|
||||||
sizeof(basic_information), nullptr);
|
|
||||||
if (status) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (basic_information.Attributes & SEC_IMAGE) != SEC_IMAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // 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<void*> 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 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<DWORD>(size), nullptr));
|
|
||||||
return (bool)mHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
Maybe<SharedMemory::Handle> 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
|
|
||||||
@@ -55,7 +55,6 @@ EXPORTS.mozilla.ipc += [
|
|||||||
"RustMessageUtils.h",
|
"RustMessageUtils.h",
|
||||||
"ScopedPort.h",
|
"ScopedPort.h",
|
||||||
"SerializedStructuredCloneBuffer.h",
|
"SerializedStructuredCloneBuffer.h",
|
||||||
"SharedMemory.h",
|
|
||||||
"SharedMemoryCursor.h",
|
"SharedMemoryCursor.h",
|
||||||
"SharedMemoryHandle.h",
|
"SharedMemoryHandle.h",
|
||||||
"SharedMemoryMapping.h",
|
"SharedMemoryMapping.h",
|
||||||
@@ -108,19 +107,14 @@ else:
|
|||||||
"CrossProcessSemaphore_posix.cpp",
|
"CrossProcessSemaphore_posix.cpp",
|
||||||
]
|
]
|
||||||
|
|
||||||
# TODO change to UNIFIED_SOURCES when old shared memory impl removed
|
|
||||||
if CONFIG["OS_ARCH"] == "Darwin":
|
if CONFIG["OS_ARCH"] == "Darwin":
|
||||||
SOURCES += ["SharedMemory_mach.cpp"]
|
UNIFIED_SOURCES += ["SharedMemoryPlatform_mach.cpp"]
|
||||||
SOURCES += ["SharedMemoryPlatform_mach.cpp"]
|
|
||||||
elif CONFIG["OS_ARCH"] == "WINNT":
|
elif CONFIG["OS_ARCH"] == "WINNT":
|
||||||
SOURCES += ["SharedMemory_windows.cpp"]
|
UNIFIED_SOURCES += ["SharedMemoryPlatform_windows.cpp"]
|
||||||
SOURCES += ["SharedMemoryPlatform_windows.cpp"]
|
|
||||||
elif CONFIG["OS_TARGET"] == "Android":
|
elif CONFIG["OS_TARGET"] == "Android":
|
||||||
SOURCES += ["SharedMemory_android.cpp"]
|
UNIFIED_SOURCES += ["SharedMemoryPlatform_android.cpp"]
|
||||||
SOURCES += ["SharedMemoryPlatform_android.cpp"]
|
|
||||||
else:
|
else:
|
||||||
SOURCES += ["SharedMemory_posix.cpp"]
|
UNIFIED_SOURCES += ["SharedMemoryPlatform_posix.cpp"]
|
||||||
SOURCES += ["SharedMemoryPlatform_posix.cpp"]
|
|
||||||
|
|
||||||
|
|
||||||
if CONFIG["OS_ARCH"] == "Linux":
|
if CONFIG["OS_ARCH"] == "Linux":
|
||||||
@@ -195,7 +189,9 @@ UNIFIED_SOURCES += [
|
|||||||
"RandomAccessStreamUtils.cpp",
|
"RandomAccessStreamUtils.cpp",
|
||||||
"ScopedPort.cpp",
|
"ScopedPort.cpp",
|
||||||
"SerializedStructuredCloneBuffer.cpp",
|
"SerializedStructuredCloneBuffer.cpp",
|
||||||
"SharedMemory.cpp",
|
"SharedMemoryCursor.cpp",
|
||||||
|
"SharedMemoryHandle.cpp",
|
||||||
|
"SharedMemoryMapping.cpp",
|
||||||
"Shmem.cpp",
|
"Shmem.cpp",
|
||||||
"StringUtil.cpp",
|
"StringUtil.cpp",
|
||||||
"TransportSecurityInfoUtils.cpp",
|
"TransportSecurityInfoUtils.cpp",
|
||||||
@@ -214,10 +210,6 @@ UNIFIED_SOURCES += [
|
|||||||
SOURCES += [
|
SOURCES += [
|
||||||
"BackgroundChildImpl.cpp",
|
"BackgroundChildImpl.cpp",
|
||||||
"BackgroundParentImpl.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":
|
if CONFIG["OS_ARCH"] == "Darwin":
|
||||||
|
|||||||
@@ -3378,7 +3378,6 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||||||
Typedef(Type("IPC::Message"), "Message"),
|
Typedef(Type("IPC::Message"), "Message"),
|
||||||
Typedef(Type("base::ProcessHandle"), "ProcessHandle"),
|
Typedef(Type("base::ProcessHandle"), "ProcessHandle"),
|
||||||
Typedef(Type("mozilla::ipc::MessageChannel"), "MessageChannel"),
|
Typedef(Type("mozilla::ipc::MessageChannel"), "MessageChannel"),
|
||||||
Typedef(Type("mozilla::ipc::SharedMemory"), "SharedMemory"),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def visitTranslationUnit(self, tu):
|
def visitTranslationUnit(self, tu):
|
||||||
|
|||||||
@@ -66,12 +66,18 @@ class OutputBuffer {
|
|||||||
|
|
||||||
class InputBuffer {
|
class InputBuffer {
|
||||||
public:
|
public:
|
||||||
explicit InputBuffer(const Range<uint8_t>& buffer) : data(buffer) {}
|
explicit InputBuffer(const Range<const uint8_t>& 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 <typename T>
|
||||||
|
explicit InputBuffer(T) = delete;
|
||||||
|
|
||||||
const uint8_t* read(size_t size) {
|
const uint8_t* read(size_t size) {
|
||||||
MOZ_ASSERT(checkCapacity(size));
|
MOZ_ASSERT(checkCapacity(size));
|
||||||
|
|
||||||
auto buf = &data[cursor_];
|
const auto* buf = &data[cursor_];
|
||||||
cursor_ += size;
|
cursor_ += size;
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
@@ -138,7 +144,7 @@ class InputBuffer {
|
|||||||
bool error_ = false;
|
bool error_ = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const Range<uint8_t>& data;
|
const Range<const uint8_t>& data;
|
||||||
size_t cursor_ = 0;
|
size_t cursor_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -558,7 +558,7 @@ Result<Ok, nsresult> ScriptPreloader::InitCacheInternal(
|
|||||||
|
|
||||||
LinkedList<CachedStencil> scripts;
|
LinkedList<CachedStencil> scripts;
|
||||||
|
|
||||||
Range<uint8_t> header(data, data + headerSize);
|
Range<const uint8_t> header(data, data + headerSize);
|
||||||
data += headerSize;
|
data += headerSize;
|
||||||
|
|
||||||
// Reconstruct alignment padding if required.
|
// Reconstruct alignment padding if required.
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ Result<Ok, nsresult> URLPreloader::ReadCache(
|
|||||||
mCachedURLs.Clear();
|
mCachedURLs.Clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
Range<uint8_t> header(data, data + headerSize);
|
Range<const uint8_t> header(data, data + headerSize);
|
||||||
data += headerSize;
|
data += headerSize;
|
||||||
|
|
||||||
InputBuffer buf(header);
|
InputBuffer buf(header);
|
||||||
|
|||||||
@@ -40,64 +40,45 @@ void xpc::SelfHostedShmem::Shutdown() {
|
|||||||
void xpc::SelfHostedShmem::InitFromParent(ContentType aXdr) {
|
void xpc::SelfHostedShmem::InitFromParent(ContentType aXdr) {
|
||||||
MOZ_ASSERT(XRE_IsParentProcess());
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
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();
|
size_t len = aXdr.Length();
|
||||||
auto shm = mozilla::MakeRefPtr<mozilla::ipc::SharedMemory>();
|
auto handle = mozilla::ipc::shared_memory::CreateFreezable(len);
|
||||||
if (NS_WARN_IF(!shm->CreateFreezable(len))) {
|
if (NS_WARN_IF(!handle)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NS_WARN_IF(!shm->Map(len))) {
|
auto mapping = std::move(handle).Map();
|
||||||
|
if (NS_WARN_IF(!mapping)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* address = shm->Memory();
|
void* address = mapping.Address();
|
||||||
memcpy(address, aXdr.Elements(), aXdr.LengthBytes());
|
memcpy(address, aXdr.Elements(), aXdr.LengthBytes());
|
||||||
|
|
||||||
RefPtr<mozilla::ipc::SharedMemory> roCopy =
|
std::tie(std::ignore, mHandle) = std::move(mapping).Freeze();
|
||||||
mozilla::MakeRefPtr<mozilla::ipc::SharedMemory>();
|
mMem = mHandle.Map();
|
||||||
if (NS_WARN_IF(!shm->ReadOnlyCopy(&*roCopy))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mMem = std::move(shm);
|
|
||||||
mHandle = roCopy->TakeHandleAndUnmap();
|
|
||||||
mLen = len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool xpc::SelfHostedShmem::InitFromChild(
|
bool xpc::SelfHostedShmem::InitFromChild(
|
||||||
mozilla::ipc::SharedMemoryHandle aHandle, size_t aLen) {
|
mozilla::ipc::ReadOnlySharedMemoryHandle aHandle) {
|
||||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
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<mozilla::ipc::SharedMemory>();
|
mMem = aHandle.Map();
|
||||||
if (NS_WARN_IF(!shm->SetHandle(std::move(aHandle),
|
return mMem.IsValid();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
xpc::SelfHostedShmem::ContentType xpc::SelfHostedShmem::Content() const {
|
xpc::SelfHostedShmem::ContentType xpc::SelfHostedShmem::Content() const {
|
||||||
if (!mMem) {
|
if (!mMem) {
|
||||||
MOZ_ASSERT(mLen == 0);
|
|
||||||
return ContentType();
|
return ContentType();
|
||||||
}
|
}
|
||||||
return ContentType(reinterpret_cast<uint8_t*>(mMem->Memory()), mLen);
|
return mMem.DataAsSpan<uint8_t>();
|
||||||
}
|
}
|
||||||
|
|
||||||
const mozilla::ipc::SharedMemoryHandle& xpc::SelfHostedShmem::Handle() const {
|
const mozilla::ipc::ReadOnlySharedMemoryHandle& xpc::SelfHostedShmem::Handle()
|
||||||
|
const {
|
||||||
return mHandle;
|
return mHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +91,7 @@ xpc::SelfHostedShmem::CollectReports(nsIHandleReportCallback* aHandleReport,
|
|||||||
// This does not exactly report the amount of data mapped by the system,
|
// This does not exactly report the amount of data mapped by the system,
|
||||||
// but the space requested when creating the handle.
|
// but the space requested when creating the handle.
|
||||||
MOZ_COLLECT_REPORT("explicit/js-non-window/shared-memory/self-hosted-xdr",
|
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 "
|
"Memory used to initialize the JS engine with the "
|
||||||
"self-hosted code encoded by the parent process.");
|
"self-hosted code encoded by the parent process.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "mozilla/Span.h"
|
#include "mozilla/Span.h"
|
||||||
#include "mozilla/StaticPtr.h"
|
#include "mozilla/StaticPtr.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
#include "nsIMemoryReporter.h"
|
#include "nsIMemoryReporter.h"
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
#include "nsIThread.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
|
// This function is not thread-safe and should be call at most once and from
|
||||||
// the main thread.
|
// the main thread.
|
||||||
[[nodiscard]] bool InitFromChild(mozilla::ipc::SharedMemoryHandle aHandle,
|
[[nodiscard]] bool InitFromChild(
|
||||||
size_t aLen);
|
mozilla::ipc::ReadOnlySharedMemoryHandle aHandle);
|
||||||
|
|
||||||
// Return a span over the read-only XDR content of the self-hosted stencil.
|
// Return a span over the read-only XDR content of the self-hosted stencil.
|
||||||
ContentType Content() const;
|
ContentType Content() const;
|
||||||
|
|
||||||
// Return the file handle which is under which the content is mapped.
|
// 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.
|
// Register this class to the memory reporter service.
|
||||||
void InitMemoryReporter();
|
void InitMemoryReporter();
|
||||||
@@ -74,15 +75,9 @@ class SelfHostedShmem final : public nsIMemoryReporter {
|
|||||||
|
|
||||||
static mozilla::StaticRefPtr<SelfHostedShmem> sSelfHostedXdr;
|
static mozilla::StaticRefPtr<SelfHostedShmem> sSelfHostedXdr;
|
||||||
|
|
||||||
// read-only file Handle used to transfer from the parent process to content
|
// Read-only shared memory used by JS runtime initialization.
|
||||||
// processes.
|
mozilla::ipc::ReadOnlySharedMemoryHandle mHandle;
|
||||||
mozilla::ipc::SharedMemoryHandle mHandle;
|
mozilla::ipc::ReadOnlySharedMemoryMapping mMem;
|
||||||
|
|
||||||
// Shared memory used by JS runtime initialization.
|
|
||||||
RefPtr<mozilla::ipc::SharedMemory> mMem;
|
|
||||||
|
|
||||||
// Length of the content within the shared memory.
|
|
||||||
size_t mLen = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xpc
|
} // namespace xpc
|
||||||
|
|||||||
@@ -17,7 +17,8 @@
|
|||||||
#include "mozilla/css/Loader.h"
|
#include "mozilla/css/Loader.h"
|
||||||
#include "mozilla/dom/ReferrerInfo.h"
|
#include "mozilla/dom/ReferrerInfo.h"
|
||||||
#include "mozilla/dom/SRIMetadata.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 "MainThreadUtils.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsIConsoleService.h"
|
#include "nsIConsoleService.h"
|
||||||
@@ -105,8 +106,8 @@ namespace mozilla {
|
|||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace css;
|
using namespace css;
|
||||||
|
|
||||||
mozilla::ipc::SharedMemoryHandle& sSharedMemoryHandle() {
|
mozilla::ipc::ReadOnlySharedMemoryHandle& sSharedMemoryHandle() {
|
||||||
static NeverDestroyed<mozilla::ipc::SharedMemoryHandle> handle;
|
static NeverDestroyed<mozilla::ipc::ReadOnlySharedMemoryHandle> handle;
|
||||||
return *handle;
|
return *handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +266,8 @@ GlobalStyleSheetCache::GlobalStyleSheetCache() {
|
|||||||
// non-shared sheets in the mFooSheet fields. In a content process, we'll
|
// non-shared sheets in the mFooSheet fields. In a content process, we'll
|
||||||
// lazily load our own copies of the sheets later.
|
// lazily load our own copies of the sheets later.
|
||||||
if (!sSharedMemory.IsEmpty()) {
|
if (!sSharedMemory.IsEmpty()) {
|
||||||
if (auto* header = reinterpret_cast<Header*>(sSharedMemory.data())) {
|
if (const auto* header =
|
||||||
|
reinterpret_cast<const Header*>(sSharedMemory.data())) {
|
||||||
MOZ_RELEASE_ASSERT(header->mMagic == Header::kMagic);
|
MOZ_RELEASE_ASSERT(header->mMagic == Header::kMagic);
|
||||||
|
|
||||||
#define STYLE_SHEET(identifier_, url_, shared_) \
|
#define STYLE_SHEET(identifier_, url_, shared_) \
|
||||||
@@ -282,7 +284,7 @@ GlobalStyleSheetCache::GlobalStyleSheetCache() {
|
|||||||
|
|
||||||
void GlobalStyleSheetCache::LoadSheetFromSharedMemory(
|
void GlobalStyleSheetCache::LoadSheetFromSharedMemory(
|
||||||
const char* aURL, RefPtr<StyleSheet>* aSheet, SheetParsingMode aParsingMode,
|
const char* aURL, RefPtr<StyleSheet>* aSheet, SheetParsingMode aParsingMode,
|
||||||
Header* aHeader, UserAgentStyleSheetID aSheetID) {
|
const Header* aHeader, UserAgentStyleSheetID aSheetID) {
|
||||||
auto i = size_t(aSheetID);
|
auto i = size_t(aSheetID);
|
||||||
|
|
||||||
auto sheet =
|
auto sheet =
|
||||||
@@ -307,8 +309,8 @@ void GlobalStyleSheetCache::InitSharedSheetsInParent() {
|
|||||||
MOZ_ASSERT(XRE_IsParentProcess());
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
MOZ_RELEASE_ASSERT(sSharedMemory.IsEmpty());
|
MOZ_RELEASE_ASSERT(sSharedMemory.IsEmpty());
|
||||||
|
|
||||||
auto shm = MakeRefPtr<ipc::SharedMemory>();
|
auto handle = ipc::shared_memory::CreateFreezable(kSharedMemorySize);
|
||||||
if (NS_WARN_IF(!shm->CreateFreezable(kSharedMemorySize))) {
|
if (NS_WARN_IF(!handle)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,19 +342,22 @@ void GlobalStyleSheetCache::InitSharedSheetsInParent() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void* address = nullptr;
|
void* address = nullptr;
|
||||||
if (void* p = ipc::SharedMemory::FindFreeAddressSpace(2 * kOffset)) {
|
if (void* p = ipc::shared_memory::FindFreeAddressSpace(2 * kOffset)) {
|
||||||
address = reinterpret_cast<void*>(uintptr_t(p) + kOffset);
|
address = reinterpret_cast<void*>(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
|
// 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
|
// to just allocating at a location of the OS's choosing, and hope that
|
||||||
// it works in the content process.
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
address = shm->Memory();
|
address = mapping.Address();
|
||||||
|
|
||||||
auto* header = static_cast<Header*>(address);
|
auto* header = static_cast<Header*>(address);
|
||||||
header->mMagic = Header::kMagic;
|
header->mMagic = Header::kMagic;
|
||||||
@@ -388,16 +393,12 @@ void GlobalStyleSheetCache::InitSharedSheetsInParent() {
|
|||||||
|
|
||||||
// Finished writing into the shared memory. Freeze it, so that a process
|
// Finished writing into the shared memory. Freeze it, so that a process
|
||||||
// can't confuse other processes by changing the UA style sheet contents.
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Freeze() call unmaps the shared memory. Re-map it again as read only.
|
auto roMapping = readOnlyHandle.Map(address);
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Record how must of the shared memory we have used, for memory reporting
|
// 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
|
// 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
|
// 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
|
// shared memory with SEC_RESERVE so that the pages are reserved but not
|
||||||
// committed.
|
// committed.
|
||||||
size_t pageSize = ipc::SharedMemory::SystemPageSize();
|
size_t pageSize = ipc::shared_memory::SystemPageSize();
|
||||||
sUsedSharedMemory =
|
sUsedSharedMemory =
|
||||||
(Servo_SharedMemoryBuilder_GetLength(builder.get()) + pageSize - 1) &
|
(Servo_SharedMemoryBuilder_GetLength(builder.get()) + pageSize - 1) &
|
||||||
~(pageSize - 1);
|
~(pageSize - 1);
|
||||||
|
|
||||||
sSharedMemory = shm->TakeMapping();
|
sSharedMemory = std::move(roMapping).Release();
|
||||||
sSharedMemoryHandle() = shm->TakeHandle();
|
sSharedMemoryHandle() = std::move(readOnlyHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalStyleSheetCache::~GlobalStyleSheetCache() {
|
GlobalStyleSheetCache::~GlobalStyleSheetCache() {
|
||||||
@@ -539,26 +540,24 @@ RefPtr<StyleSheet> GlobalStyleSheetCache::LoadSheet(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void GlobalStyleSheetCache::SetSharedMemory(
|
/* static */ void GlobalStyleSheetCache::SetSharedMemory(
|
||||||
ipc::SharedMemory::Handle aHandle, uintptr_t aAddress) {
|
ipc::ReadOnlySharedMemoryHandle aHandle, uintptr_t aAddress) {
|
||||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||||
MOZ_ASSERT(!gStyleCache, "Too late, GlobalStyleSheetCache already created!");
|
MOZ_ASSERT(!gStyleCache, "Too late, GlobalStyleSheetCache already created!");
|
||||||
MOZ_ASSERT(sSharedMemory.IsEmpty(), "Shouldn't call this more than once");
|
MOZ_ASSERT(sSharedMemory.IsEmpty(), "Shouldn't call this more than once");
|
||||||
|
|
||||||
auto shm = MakeRefPtr<ipc::SharedMemory>();
|
auto mapping = aHandle.Map(reinterpret_cast<void*>(aAddress));
|
||||||
if (!shm->SetHandle(std::move(aHandle), ipc::SharedMemory::RightsReadOnly)) {
|
if (!mapping) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shm->Map(kSharedMemorySize, reinterpret_cast<void*>(aAddress))) {
|
sSharedMemory = std::move(mapping).Release();
|
||||||
sSharedMemory = shm->TakeMapping();
|
sSharedMemoryHandle() = std::move(aHandle);
|
||||||
sSharedMemoryHandle() = shm->TakeHandle();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ipc::SharedMemoryHandle GlobalStyleSheetCache::CloneHandle() {
|
ipc::ReadOnlySharedMemoryHandle GlobalStyleSheetCache::CloneHandle() {
|
||||||
MOZ_ASSERT(XRE_IsParentProcess());
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
if (ipc::SharedMemory::IsHandleValid(sSharedMemoryHandle())) {
|
if (sSharedMemoryHandle().IsValid()) {
|
||||||
return ipc::SharedMemory::CloneHandle(sSharedMemoryHandle());
|
return sSharedMemoryHandle().Clone();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -567,7 +566,7 @@ StaticRefPtr<GlobalStyleSheetCache> GlobalStyleSheetCache::gStyleCache;
|
|||||||
StaticRefPtr<css::Loader> GlobalStyleSheetCache::gCSSLoader;
|
StaticRefPtr<css::Loader> GlobalStyleSheetCache::gCSSLoader;
|
||||||
StaticRefPtr<nsIURI> GlobalStyleSheetCache::gUserContentSheetURL;
|
StaticRefPtr<nsIURI> GlobalStyleSheetCache::gUserContentSheetURL;
|
||||||
|
|
||||||
Span<uint8_t> GlobalStyleSheetCache::sSharedMemory;
|
ipc::shared_memory::LeakedReadOnlyMapping GlobalStyleSheetCache::sSharedMemory;
|
||||||
size_t GlobalStyleSheetCache::sUsedSharedMemory;
|
size_t GlobalStyleSheetCache::sUsedSharedMemory;
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
#include "mozilla/StaticPtr.h"
|
#include "mozilla/StaticPtr.h"
|
||||||
#include "mozilla/UserAgentStyleSheetID.h"
|
#include "mozilla/UserAgentStyleSheetID.h"
|
||||||
#include "mozilla/css/Loader.h"
|
#include "mozilla/css/Loader.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryMapping.h"
|
||||||
|
|
||||||
class nsIFile;
|
class nsIFile;
|
||||||
class nsIURI;
|
class nsIURI;
|
||||||
@@ -60,13 +61,13 @@ class GlobalStyleSheetCache final : public nsIObserver,
|
|||||||
// Called early on in a content process' life from
|
// Called early on in a content process' life from
|
||||||
// ContentChild::InitSharedUASheets, before the GlobalStyleSheetCache
|
// ContentChild::InitSharedUASheets, before the GlobalStyleSheetCache
|
||||||
// singleton has been created.
|
// singleton has been created.
|
||||||
static void SetSharedMemory(mozilla::ipc::SharedMemory::Handle aHandle,
|
static void SetSharedMemory(mozilla::ipc::ReadOnlySharedMemoryHandle aHandle,
|
||||||
uintptr_t aAddress);
|
uintptr_t aAddress);
|
||||||
|
|
||||||
// Obtain a shared memory handle for the shared UA sheets to pass into a
|
// Obtain a shared memory handle for the shared UA sheets to pass into a
|
||||||
// content process. Called by ContentParent::InitInternal shortly after
|
// content process. Called by ContentParent::InitInternal shortly after
|
||||||
// a content process has been created.
|
// 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
|
// Returns the address of the shared memory segment that holds the shared UA
|
||||||
// sheets.
|
// sheets.
|
||||||
@@ -104,7 +105,7 @@ class GlobalStyleSheetCache final : public nsIObserver,
|
|||||||
RefPtr<StyleSheet> LoadSheet(nsIURI* aURI, css::SheetParsingMode aParsingMode,
|
RefPtr<StyleSheet> LoadSheet(nsIURI* aURI, css::SheetParsingMode aParsingMode,
|
||||||
css::FailureAction aFailureAction);
|
css::FailureAction aFailureAction);
|
||||||
void LoadSheetFromSharedMemory(const char* aURL, RefPtr<StyleSheet>* aSheet,
|
void LoadSheetFromSharedMemory(const char* aURL, RefPtr<StyleSheet>* aSheet,
|
||||||
css::SheetParsingMode, Header*,
|
css::SheetParsingMode, const Header*,
|
||||||
UserAgentStyleSheetID);
|
UserAgentStyleSheetID);
|
||||||
|
|
||||||
static StaticRefPtr<GlobalStyleSheetCache> gStyleCache;
|
static StaticRefPtr<GlobalStyleSheetCache> gStyleCache;
|
||||||
@@ -120,7 +121,7 @@ class GlobalStyleSheetCache final : public nsIObserver,
|
|||||||
RefPtr<StyleSheet> mUserContentSheet;
|
RefPtr<StyleSheet> mUserContentSheet;
|
||||||
|
|
||||||
// Shared memory segment storing shared style sheets.
|
// Shared memory segment storing shared style sheets.
|
||||||
static Span<uint8_t> sSharedMemory;
|
static mozilla::ipc::shared_memory::LeakedReadOnlyMapping sSharedMemory;
|
||||||
|
|
||||||
// How much of the shared memory buffer we ended up using. Used for memory
|
// How much of the shared memory buffer we ended up using. Used for memory
|
||||||
// reporting in the parent process.
|
// reporting in the parent process.
|
||||||
|
|||||||
@@ -176,9 +176,9 @@ static void SerializeAndAppendString(const nsCString& aChars, nsCString& aStr) {
|
|||||||
aStr.Append(aChars);
|
aStr.Append(aChars);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* DeserializeString(char* aChars, nsCString& aStr) {
|
static const char* DeserializeString(const char* aChars, nsCString& aStr) {
|
||||||
char* p = aChars;
|
const char* p = aChars;
|
||||||
uint32_t length = strtol(p, &p, 10);
|
uint32_t length = strtol(p, const_cast<char**>(&p), 10);
|
||||||
MOZ_ASSERT(p[0] == '/');
|
MOZ_ASSERT(p[0] == '/');
|
||||||
p++; // move past the '/'
|
p++; // move past the '/'
|
||||||
aStr.Assign(p, length);
|
aStr.Assign(p, length);
|
||||||
@@ -332,9 +332,9 @@ union PrefValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* Deserialize(PrefType aType, char* aStr,
|
static const char* Deserialize(PrefType aType, const char* aStr,
|
||||||
Maybe<dom::PrefValue>* aDomValue) {
|
Maybe<dom::PrefValue>* aDomValue) {
|
||||||
char* p = aStr;
|
const char* p = aStr;
|
||||||
|
|
||||||
switch (aType) {
|
switch (aType) {
|
||||||
case PrefType::Bool:
|
case PrefType::Bool:
|
||||||
@@ -350,7 +350,7 @@ union PrefValue {
|
|||||||
return p;
|
return p;
|
||||||
|
|
||||||
case PrefType::Int: {
|
case PrefType::Int: {
|
||||||
*aDomValue = Some(int32_t(strtol(p, &p, 10)));
|
*aDomValue = Some(int32_t(strtol(p, const_cast<char**>(&p), 10)));
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -981,8 +981,8 @@ class Pref {
|
|||||||
aStr.Append('\n');
|
aStr.Append('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* Deserialize(char* aStr, dom::Pref* aDomPref) {
|
static const char* Deserialize(const char* aStr, dom::Pref* aDomPref) {
|
||||||
char* p = aStr;
|
const char* p = aStr;
|
||||||
|
|
||||||
// The type.
|
// The type.
|
||||||
PrefType type;
|
PrefType type;
|
||||||
@@ -3796,13 +3796,13 @@ void Preferences::SerializePreferences(nsCString& aStr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
void Preferences::DeserializePreferences(char* aStr, size_t aPrefsLen) {
|
void Preferences::DeserializePreferences(const char* aStr, size_t aPrefsLen) {
|
||||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||||
|
|
||||||
MOZ_ASSERT(!gChangedDomPrefs);
|
MOZ_ASSERT(!gChangedDomPrefs);
|
||||||
gChangedDomPrefs = new nsTArray<dom::Pref>();
|
gChangedDomPrefs = new nsTArray<dom::Pref>();
|
||||||
|
|
||||||
char* p = aStr;
|
const char* p = aStr;
|
||||||
while (*p != '\0') {
|
while (*p != '\0') {
|
||||||
dom::Pref pref;
|
dom::Pref pref;
|
||||||
p = Pref::Deserialize(p, &pref);
|
p = Pref::Deserialize(p, &pref);
|
||||||
@@ -3818,7 +3818,7 @@ void Preferences::DeserializePreferences(char* aStr, size_t aPrefsLen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
mozilla::ipc::SharedMemoryHandle Preferences::EnsureSnapshot(size_t* aSize) {
|
mozilla::ipc::ReadOnlySharedMemoryHandle Preferences::EnsureSnapshot() {
|
||||||
MOZ_ASSERT(XRE_IsParentProcess());
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
@@ -3867,17 +3867,16 @@ mozilla::ipc::SharedMemoryHandle Preferences::EnsureSnapshot(size_t* aSize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*aSize = gSharedMap->MapSize();
|
|
||||||
return gSharedMap->CloneHandle();
|
return gSharedMap->CloneHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
void Preferences::InitSnapshot(const mozilla::ipc::SharedMemoryHandle& aHandle,
|
void Preferences::InitSnapshot(
|
||||||
size_t aSize) {
|
const mozilla::ipc::ReadOnlySharedMemoryHandle& aHandle) {
|
||||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||||
MOZ_ASSERT(!gSharedMap);
|
MOZ_ASSERT(!gSharedMap);
|
||||||
|
|
||||||
gSharedMap = new SharedPrefMap(aHandle, aSize);
|
gSharedMap = new SharedPrefMap(aHandle);
|
||||||
|
|
||||||
StaticPrefs::InitStaticPrefsFromShared();
|
StaticPrefs::InitStaticPrefsFromShared();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/MozPromise.h"
|
#include "mozilla/MozPromise.h"
|
||||||
#include "mozilla/StaticPtr.h"
|
#include "mozilla/StaticPtr.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
#include "nsIPrefBranch.h"
|
#include "nsIPrefBranch.h"
|
||||||
@@ -408,13 +408,10 @@ class Preferences final : public nsIPrefService,
|
|||||||
// prefs in bulk from the parent process, via shared memory.
|
// prefs in bulk from the parent process, via shared memory.
|
||||||
static void SerializePreferences(nsCString& aStr,
|
static void SerializePreferences(nsCString& aStr,
|
||||||
bool aIsDestinationWebContentProcess);
|
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::ReadOnlySharedMemoryHandle EnsureSnapshot();
|
||||||
static mozilla::ipc::SharedMemoryHandle EnsureSnapshot(size_t* aSize);
|
static void InitSnapshot(const mozilla::ipc::ReadOnlySharedMemoryHandle&);
|
||||||
static void InitSnapshot(const mozilla::ipc::SharedMemoryHandle&,
|
|
||||||
size_t aSize);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// When a single pref is changed in the parent process, these methods are
|
// When a single pref is changed in the parent process, these methods are
|
||||||
// used to pass the update to content processes.
|
// used to pass the update to content processes.
|
||||||
|
|||||||
@@ -22,38 +22,31 @@ static inline size_t GetAlignmentOffset(size_t aOffset, size_t aAlign) {
|
|||||||
return mod ? aAlign - mod : 0;
|
return mod ? aAlign - mod : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPrefMap::SharedPrefMap(const SharedMemoryHandle& aMapHandle,
|
SharedPrefMap::SharedPrefMap(const ReadOnlySharedMemoryHandle& aMapHandle) {
|
||||||
size_t aMapSize) {
|
auto map = aMapHandle.Map();
|
||||||
auto map = MakeRefPtr<SharedMemory>();
|
MOZ_RELEASE_ASSERT(map);
|
||||||
{
|
|
||||||
auto result = map->SetHandle(SharedMemory::CloneHandle(aMapHandle),
|
|
||||||
SharedMemory::OpenRights::RightsReadOnly);
|
|
||||||
MOZ_RELEASE_ASSERT(result);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = map->Map(aMapSize);
|
|
||||||
MOZ_RELEASE_ASSERT(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
mHandle = aMapHandle.Clone();
|
||||||
// We return literal nsCStrings pointing to the mapped data for preference
|
// We return literal nsCStrings pointing to the mapped data for preference
|
||||||
// names and string values, which means that we may still have references to
|
// 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
|
// 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.
|
// need to keep the mapping alive until process shutdown, in order to be safe.
|
||||||
mMappedMemory = map->TakeMapping();
|
mMappedMemory = std::move(map).Release();
|
||||||
mHandle = map->TakeHandle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPrefMap::SharedPrefMap(SharedPrefMapBuilder&& aBuilder) {
|
SharedPrefMap::SharedPrefMap(SharedPrefMapBuilder&& aBuilder) {
|
||||||
RefPtr<SharedMemory> map;
|
ReadOnlySharedMemoryMappingWithHandle mapWithHandle;
|
||||||
auto result = aBuilder.Finalize(map);
|
auto result = aBuilder.Finalize();
|
||||||
MOZ_RELEASE_ASSERT(result.isOk() && map);
|
MOZ_RELEASE_ASSERT(result.isOk());
|
||||||
|
mHandle = result.unwrap();
|
||||||
mMappedMemory = map->TakeMapping();
|
auto map = mHandle.Map();
|
||||||
mHandle = map->TakeHandle();
|
MOZ_RELEASE_ASSERT(map.IsValid());
|
||||||
|
mMappedMemory = std::move(map).Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::SharedMemoryHandle SharedPrefMap::CloneHandle() const {
|
mozilla::ipc::ReadOnlySharedMemoryHandle SharedPrefMap::CloneHandle() const {
|
||||||
return SharedMemory::CloneHandle(mHandle);
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
|
return mHandle.Clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SharedPrefMap::Has(const char* aKey) const {
|
bool SharedPrefMap::Has(const char* aKey) const {
|
||||||
@@ -148,8 +141,7 @@ void SharedPrefMapBuilder::Add(const nsCString& aKey, const Flags& aFlags,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Ok, nsresult> SharedPrefMapBuilder::Finalize(
|
Result<ReadOnlySharedMemoryHandle, nsresult> SharedPrefMapBuilder::Finalize() {
|
||||||
RefPtr<SharedMemory>& aMap) {
|
|
||||||
using Header = SharedPrefMap::Header;
|
using Header = SharedPrefMap::Header;
|
||||||
|
|
||||||
// Create an array of entry pointers for the entry array, and sort it by
|
// Create an array of entry pointers for the entry array, and sort it by
|
||||||
@@ -244,7 +236,7 @@ Result<Ok, nsresult> SharedPrefMapBuilder::Finalize(
|
|||||||
mStringValueTable.Clear();
|
mStringValueTable.Clear();
|
||||||
mEntries.Clear();
|
mEntries.Clear();
|
||||||
|
|
||||||
return mem.Finalize(aMap);
|
return mem.Finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/Result.h"
|
#include "mozilla/Result.h"
|
||||||
#include "mozilla/dom/ipc/StringTable.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"
|
#include "nsTHashMap.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@@ -419,7 +420,7 @@ class SharedPrefMap {
|
|||||||
|
|
||||||
// Note: These constructors are infallible, because the preference database is
|
// Note: These constructors are infallible, because the preference database is
|
||||||
// critical to platform functionality, and we cannot operate without it.
|
// 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&&);
|
explicit SharedPrefMap(SharedPrefMapBuilder&&);
|
||||||
|
|
||||||
// Searches for the given preference in the map, and returns true if it
|
// 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
|
// 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
|
// used to construct new instances of SharedPrefMap with the same data as this
|
||||||
// instance.
|
// 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
|
// Returns the size of the mapped memory region. This size must be passed to
|
||||||
// the constructor when mapping the shared region in another process.
|
// the constructor when mapping the shared region in another process.
|
||||||
@@ -528,8 +529,8 @@ class SharedPrefMap {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
RangedPtr<const T> GetBlock(const DataBlock& aBlock) const {
|
RangedPtr<const T> GetBlock(const DataBlock& aBlock) const {
|
||||||
return RangedPtr<uint8_t>(&mMappedMemory.data()[aBlock.mOffset],
|
return RangedPtr<const uint8_t>(&mMappedMemory.data()[aBlock.mOffset],
|
||||||
aBlock.mSize)
|
aBlock.mSize)
|
||||||
.ReinterpretCast<const T>();
|
.ReinterpretCast<const T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -549,19 +550,19 @@ class SharedPrefMap {
|
|||||||
|
|
||||||
StringTable<nsCString> KeyTable() const {
|
StringTable<nsCString> KeyTable() const {
|
||||||
auto& block = GetHeader().mKeyStrings;
|
auto& block = GetHeader().mKeyStrings;
|
||||||
return {{&mMappedMemory.data()[block.mOffset], block.mSize}};
|
return {{(uint8_t*)&mMappedMemory.data()[block.mOffset], block.mSize}};
|
||||||
}
|
}
|
||||||
|
|
||||||
StringTable<nsCString> ValueTable() const {
|
StringTable<nsCString> ValueTable() const {
|
||||||
auto& block = GetHeader().mValueStrings;
|
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
|
// This is a leaked shared memory mapping (see the constructor definition for
|
||||||
// an explanation). It replaces AutoMemMap::setPersistent behavior as part of
|
// an explanation). It replaces AutoMemMap::setPersistent behavior as part of
|
||||||
// bug 1454816.
|
// bug 1454816.
|
||||||
Span<uint8_t> mMappedMemory;
|
mozilla::ipc::shared_memory::LeakedReadOnlyMapping mMappedMemory;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A helper class which builds the contiguous look-up table used by
|
// 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);
|
const nsCString& aDefaultValue, const nsCString& aUserValue);
|
||||||
|
|
||||||
// Finalizes the binary representation of the map, writes it to a shared
|
// Finalizes the binary representation of the map, writes it to a shared
|
||||||
// memory region, and then initializes the given SharedMemory with a reference
|
// memory region, and then initializes the given ReadOnlySharedMemoryMapping
|
||||||
// to the read-only copy of it.
|
// with a reference to the read-only copy of it.
|
||||||
//
|
//
|
||||||
// This should generally not be used directly by callers. The
|
// This should generally not be used directly by callers. The
|
||||||
// SharedPrefMapBuilder instance should instead be passed to the SharedPrefMap
|
// SharedPrefMapBuilder instance should instead be passed to the SharedPrefMap
|
||||||
// constructor as a move reference.
|
// constructor as a move reference.
|
||||||
Result<Ok, nsresult> Finalize(RefPtr<mozilla::ipc::SharedMemory>& aMap);
|
Result<mozilla::ipc::ReadOnlySharedMemoryHandle, nsresult> Finalize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using StringTableEntry = mozilla::dom::ipc::StringTableEntry;
|
using StringTableEntry = mozilla::dom::ipc::StringTableEntry;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#include "mozilla/StaticMutex.h"
|
#include "mozilla/StaticMutex.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "mozilla/UniquePtrExtensions.h"
|
#include "mozilla/UniquePtrExtensions.h"
|
||||||
#include "mozilla/ipc/SharedMemory.h"
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
#include "nsComponentManagerUtils.h"
|
#include "nsComponentManagerUtils.h"
|
||||||
#include "nsPrintfCString.h"
|
#include "nsPrintfCString.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
@@ -320,7 +320,7 @@ static void AddLdLibraryEnvPaths(SandboxBroker::Policy* aPolicy) {
|
|||||||
|
|
||||||
static void AddSharedMemoryPaths(SandboxBroker::Policy* aPolicy, pid_t aPid) {
|
static void AddSharedMemoryPaths(SandboxBroker::Policy* aPolicy, pid_t aPid) {
|
||||||
std::string shmPath("/dev/shm");
|
std::string shmPath("/dev/shm");
|
||||||
if (ipc::SharedMemory::AppendPosixShmPrefix(&shmPath, aPid)) {
|
if (ipc::shared_memory::AppendPosixShmPrefix(&shmPath, aPid)) {
|
||||||
aPolicy->AddPrefix(rdwrcr, shmPath.c_str());
|
aPolicy->AddPrefix(rdwrcr, shmPath.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ Result<Ok, nsresult> StartupCache::LoadArchive() {
|
|||||||
return Err(NS_ERROR_UNEXPECTED);
|
return Err(NS_ERROR_UNEXPECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
Range<uint8_t> header(data, data + headerSize);
|
Range<const uint8_t> header(data, data + headerSize);
|
||||||
data += headerSize;
|
data += headerSize;
|
||||||
|
|
||||||
mCacheEntriesBaseOffset = sizeof(MAGIC) + sizeof(headerSize) + headerSize;
|
mCacheEntriesBaseOffset = sizeof(MAGIC) + sizeof(headerSize) + headerSize;
|
||||||
|
|||||||
@@ -210,15 +210,12 @@ static CommandLineArg<const char*> sProfile{"-profile", "profile"};
|
|||||||
|
|
||||||
static CommandLineArg<UniqueFileHandle> sIPCHandle{"-ipcHandle", "ipchandle"};
|
static CommandLineArg<UniqueFileHandle> sIPCHandle{"-ipcHandle", "ipchandle"};
|
||||||
|
|
||||||
static CommandLineArg<mozilla::ipc::SharedMemoryHandle> sJsInitHandle{
|
static CommandLineArg<mozilla::ipc::ReadOnlySharedMemoryHandle> sJsInitHandle{
|
||||||
"-jsInitHandle", "jsinithandle"};
|
"-jsInitHandle", "jsinithandle"};
|
||||||
static CommandLineArg<uint64_t> sJsInitLen{"-jsInitLen", "jsinitlen"};
|
static CommandLineArg<mozilla::ipc::ReadOnlySharedMemoryHandle> sPrefsHandle{
|
||||||
static CommandLineArg<mozilla::ipc::SharedMemoryHandle> sPrefsHandle{
|
|
||||||
"-prefsHandle", "prefshandle"};
|
"-prefsHandle", "prefshandle"};
|
||||||
static CommandLineArg<uint64_t> sPrefsLen{"-prefsLen", "prefslen"};
|
static CommandLineArg<mozilla::ipc::ReadOnlySharedMemoryHandle> sPrefMapHandle{
|
||||||
static CommandLineArg<mozilla::ipc::SharedMemoryHandle> sPrefMapHandle{
|
|
||||||
"-prefMapHandle", "prefmaphandle"};
|
"-prefMapHandle", "prefmaphandle"};
|
||||||
static CommandLineArg<uint64_t> sPrefMapSize{"-prefMapSize", "prefmapsize"};
|
|
||||||
|
|
||||||
static CommandLineArg<uint64_t> sSandboxingKind{"-sandboxingKind",
|
static CommandLineArg<uint64_t> sSandboxingKind{"-sandboxingKind",
|
||||||
"sandboxingkind"};
|
"sandboxingkind"};
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "gfxPlatform.h"
|
#include "gfxPlatform.h"
|
||||||
#include "mozilla/WidgetUtilsGtk.h"
|
#include "mozilla/WidgetUtilsGtk.h"
|
||||||
#include "mozilla/gfx/Tools.h"
|
#include "mozilla/gfx/Tools.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryHandle.h"
|
||||||
#include "nsGtkUtils.h"
|
#include "nsGtkUtils.h"
|
||||||
#include "nsPrintfCString.h"
|
#include "nsPrintfCString.h"
|
||||||
#include "prenv.h" // For PR_GetEnv
|
#include "prenv.h" // For PR_GetEnv
|
||||||
@@ -54,15 +55,16 @@ RefPtr<WaylandShmPool> WaylandShmPool::Create(nsWaylandDisplay* aWaylandDisplay,
|
|||||||
|
|
||||||
RefPtr<WaylandShmPool> shmPool = new WaylandShmPool();
|
RefPtr<WaylandShmPool> shmPool = new WaylandShmPool();
|
||||||
|
|
||||||
shmPool->mShm = MakeRefPtr<ipc::SharedMemory>();
|
auto handle = ipc::shared_memory::Create(aSize);
|
||||||
if (!shmPool->mShm->Create(aSize)) {
|
if (!handle) {
|
||||||
NS_WARNING("WaylandShmPool: Unable to allocate shared memory!");
|
NS_WARNING("WaylandShmPool: Unable to allocate shared memory!");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
shmPool->mSize = aSize;
|
shmPool->mShmHandle = handle.Clone();
|
||||||
shmPool->mShmPool = wl_shm_create_pool(
|
shmPool->mShmPool =
|
||||||
aWaylandDisplay->GetShm(), shmPool->mShm->CloneHandle().get(), aSize);
|
wl_shm_create_pool(aWaylandDisplay->GetShm(),
|
||||||
|
handle.Clone().TakePlatformHandle().get(), aSize);
|
||||||
if (!shmPool->mShmPool) {
|
if (!shmPool->mShmPool) {
|
||||||
NS_WARNING("WaylandShmPool: Unable to allocate shared memory pool!");
|
NS_WARNING("WaylandShmPool: Unable to allocate shared memory pool!");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -72,15 +74,14 @@ RefPtr<WaylandShmPool> WaylandShmPool::Create(nsWaylandDisplay* aWaylandDisplay,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* WaylandShmPool::GetImageData() {
|
void* WaylandShmPool::GetImageData() {
|
||||||
if (mImageData) {
|
if (!mShm) {
|
||||||
return mImageData;
|
mShm = mShmHandle.Map();
|
||||||
|
if (!mShm) {
|
||||||
|
NS_WARNING("WaylandShmPool: Failed to map Shm!");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!mShm->Map(mSize)) {
|
return mShm.Address();
|
||||||
NS_WARNING("WaylandShmPool: Failed to map Shm!");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
mImageData = mShm->Memory();
|
|
||||||
return mImageData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WaylandShmPool::~WaylandShmPool() {
|
WaylandShmPool::~WaylandShmPool() {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user