michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * vim: sw=2 ts=8 et : michael@0: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "Shmem.h" michael@0: michael@0: #include "ProtocolUtils.h" michael@0: #include "SharedMemoryBasic.h" michael@0: #include "SharedMemorySysV.h" michael@0: michael@0: #include "nsAutoPtr.h" michael@0: #include "mozilla/unused.h" michael@0: michael@0: michael@0: namespace mozilla { michael@0: namespace ipc { michael@0: michael@0: class ShmemCreated : public IPC::Message michael@0: { michael@0: private: michael@0: typedef Shmem::id_t id_t; michael@0: michael@0: public: michael@0: ShmemCreated(int32_t routingId, michael@0: const id_t& aIPDLId, michael@0: const size_t& aSize, michael@0: const SharedMemoryBasic::Handle& aHandle) : michael@0: IPC::Message(routingId, SHMEM_CREATED_MESSAGE_TYPE, PRIORITY_NORMAL) michael@0: { michael@0: IPC::WriteParam(this, aIPDLId); michael@0: IPC::WriteParam(this, aSize); michael@0: IPC::WriteParam(this, int32_t(SharedMemory::TYPE_BASIC)), michael@0: IPC::WriteParam(this, aHandle); michael@0: } michael@0: michael@0: // Instead of a single Read() function, we have ReadInfo() and michael@0: // ReadHandle(). The reason is that the handle type is specific to michael@0: // the shmem type. These functions should only be called in the michael@0: // order ReadInfo(); ReadHandle();, and only once each. michael@0: michael@0: static bool michael@0: ReadInfo(const Message* msg, void** iter, michael@0: id_t* aIPDLId, michael@0: size_t* aSize, michael@0: SharedMemory::SharedMemoryType* aType) michael@0: { michael@0: if (!IPC::ReadParam(msg, iter, aIPDLId) || michael@0: !IPC::ReadParam(msg, iter, aSize) || michael@0: !IPC::ReadParam(msg, iter, reinterpret_cast(aType))) michael@0: return false; michael@0: return true; michael@0: } michael@0: michael@0: static bool michael@0: ReadHandle(const Message* msg, void** iter, michael@0: SharedMemoryBasic::Handle* aHandle) michael@0: { michael@0: if (!IPC::ReadParam(msg, iter, aHandle)) michael@0: return false; michael@0: msg->EndRead(*iter); michael@0: return true; michael@0: } michael@0: michael@0: #ifdef MOZ_HAVE_SHAREDMEMORYSYSV michael@0: ShmemCreated(int32_t routingId, michael@0: const id_t& aIPDLId, michael@0: const size_t& aSize, michael@0: const SharedMemorySysV::Handle& aHandle) : michael@0: IPC::Message(routingId, SHMEM_CREATED_MESSAGE_TYPE, PRIORITY_NORMAL) michael@0: { michael@0: IPC::WriteParam(this, aIPDLId); michael@0: IPC::WriteParam(this, aSize); michael@0: IPC::WriteParam(this, int32_t(SharedMemory::TYPE_SYSV)), michael@0: IPC::WriteParam(this, aHandle); michael@0: } michael@0: michael@0: static bool michael@0: ReadHandle(const Message* msg, void** iter, michael@0: SharedMemorySysV::Handle* aHandle) michael@0: { michael@0: if (!IPC::ReadParam(msg, iter, aHandle)) michael@0: return false; michael@0: msg->EndRead(*iter); michael@0: return true; michael@0: } michael@0: #endif michael@0: michael@0: void Log(const std::string& aPrefix, michael@0: FILE* aOutf) const michael@0: { michael@0: fputs("(special ShmemCreated msg)", aOutf); michael@0: } michael@0: }; michael@0: michael@0: class ShmemDestroyed : public IPC::Message michael@0: { michael@0: private: michael@0: typedef Shmem::id_t id_t; michael@0: michael@0: public: michael@0: ShmemDestroyed(int32_t routingId, michael@0: const id_t& aIPDLId) : michael@0: IPC::Message(routingId, SHMEM_DESTROYED_MESSAGE_TYPE, PRIORITY_NORMAL) michael@0: { michael@0: IPC::WriteParam(this, aIPDLId); michael@0: } michael@0: }; michael@0: michael@0: michael@0: #ifdef MOZ_HAVE_SHAREDMEMORYSYSV michael@0: static Shmem::SharedMemory* michael@0: CreateSegment(size_t aNBytes, SharedMemorySysV::Handle aHandle) michael@0: { michael@0: nsAutoPtr segment; michael@0: michael@0: if (SharedMemorySysV::IsHandleValid(aHandle)) { michael@0: segment = new SharedMemorySysV(aHandle); michael@0: } michael@0: else { michael@0: segment = new SharedMemorySysV(); michael@0: michael@0: if (!segment->Create(aNBytes)) michael@0: return 0; michael@0: } michael@0: if (!segment->Map(aNBytes)) michael@0: return 0; michael@0: michael@0: segment->AddRef(); michael@0: return segment.forget(); michael@0: } michael@0: #endif michael@0: michael@0: static Shmem::SharedMemory* michael@0: CreateSegment(size_t aNBytes, SharedMemoryBasic::Handle aHandle) michael@0: { michael@0: nsAutoPtr segment; michael@0: michael@0: if (SharedMemoryBasic::IsHandleValid(aHandle)) { michael@0: segment = new SharedMemoryBasic(aHandle); michael@0: } michael@0: else { michael@0: segment = new SharedMemoryBasic(); michael@0: michael@0: if (!segment->Create(aNBytes)) michael@0: return 0; michael@0: } michael@0: if (!segment->Map(aNBytes)) michael@0: return 0; michael@0: michael@0: segment->AddRef(); michael@0: return segment.forget(); michael@0: } michael@0: michael@0: static void michael@0: DestroySegment(SharedMemory* aSegment) michael@0: { michael@0: // the SharedMemory dtor closes and unmaps the actual OS shmem segment michael@0: if (aSegment) michael@0: aSegment->Release(); michael@0: } michael@0: michael@0: michael@0: #if defined(DEBUG) michael@0: michael@0: static const char sMagic[] = michael@0: "This little piggy went to market.\n" michael@0: "This little piggy stayed at home.\n" michael@0: "This little piggy has roast beef,\n" michael@0: "This little piggy had none.\n" michael@0: "And this little piggy cried \"Wee! Wee! Wee!\" all the way home"; michael@0: michael@0: michael@0: struct Header { michael@0: // Don't use size_t or bool here because their size depends on the michael@0: // architecture. michael@0: uint32_t mSize; michael@0: uint32_t mUnsafe; michael@0: char mMagic[sizeof(sMagic)]; michael@0: }; michael@0: michael@0: static void michael@0: GetSections(Shmem::SharedMemory* aSegment, michael@0: Header** aHeader, michael@0: char** aFrontSentinel, michael@0: char** aData, michael@0: char** aBackSentinel) michael@0: { michael@0: NS_ABORT_IF_FALSE(aSegment && aFrontSentinel && aData && aBackSentinel, michael@0: "NULL param(s)"); michael@0: michael@0: *aFrontSentinel = reinterpret_cast(aSegment->memory()); michael@0: NS_ABORT_IF_FALSE(*aFrontSentinel, "NULL memory()"); michael@0: michael@0: *aHeader = reinterpret_cast(*aFrontSentinel); michael@0: michael@0: size_t pageSize = Shmem::SharedMemory::SystemPageSize(); michael@0: *aData = *aFrontSentinel + pageSize; michael@0: michael@0: *aBackSentinel = *aFrontSentinel + aSegment->Size() - pageSize; michael@0: } michael@0: michael@0: static Header* michael@0: GetHeader(Shmem::SharedMemory* aSegment) michael@0: { michael@0: Header* header; michael@0: char* dontcare; michael@0: GetSections(aSegment, &header, &dontcare, &dontcare, &dontcare); michael@0: return header; michael@0: } michael@0: michael@0: static void michael@0: Protect(SharedMemory* aSegment) michael@0: { michael@0: NS_ABORT_IF_FALSE(aSegment, "NULL segment"); michael@0: aSegment->Protect(reinterpret_cast(aSegment->memory()), michael@0: aSegment->Size(), michael@0: RightsNone); michael@0: } michael@0: michael@0: static void michael@0: Unprotect(SharedMemory* aSegment) michael@0: { michael@0: NS_ABORT_IF_FALSE(aSegment, "NULL segment"); michael@0: aSegment->Protect(reinterpret_cast(aSegment->memory()), michael@0: aSegment->Size(), michael@0: RightsRead | RightsWrite); michael@0: } michael@0: michael@0: // michael@0: // In debug builds, we specially allocate shmem segments. The layout michael@0: // is as follows michael@0: // michael@0: // Page 0: "front sentinel" michael@0: // size of mapping michael@0: // magic bytes michael@0: // Page 1 through n-1: michael@0: // user data michael@0: // Page n: "back sentinel" michael@0: // [nothing] michael@0: // michael@0: // The mapping can be in one of the following states, wrt to the michael@0: // current process. michael@0: // michael@0: // State "unmapped": all pages are mapped with no access rights. michael@0: // michael@0: // State "mapping": all pages are mapped with read/write access. michael@0: // michael@0: // State "mapped": the front and back sentinels are mapped with no michael@0: // access rights, and all the other pages are mapped with michael@0: // read/write access. michael@0: // michael@0: // When a SharedMemory segment is first allocated, it starts out in michael@0: // the "mapping" state for the process that allocates the segment, and michael@0: // in the "unmapped" state for the other process. The allocating michael@0: // process will then create a Shmem, which takes the segment into the michael@0: // "mapped" state, where it can be accessed by clients. michael@0: // michael@0: // When a Shmem is sent to another process in an IPDL message, the michael@0: // segment transitions into the "unmapped" state for the sending michael@0: // process, and into the "mapping" state for the receiving process. michael@0: // The receiving process will then create a Shmem from the underlying michael@0: // segment, and take the segment into the "mapped" state. michael@0: // michael@0: // In the "mapping" state, we use the front sentinel to verify the michael@0: // integrity of the shmem segment. If valid, it has a size_t michael@0: // containing the number of bytes the user allocated followed by the michael@0: // magic bytes above. michael@0: // michael@0: // In the "mapped" state, the front and back sentinels have no access michael@0: // rights. They act as guards against buffer overflows and underflows michael@0: // in client code; if clients touch a sentinel, they die with SIGSEGV. michael@0: // michael@0: // The "unmapped" state is used to enforce single-owner semantics of michael@0: // the shmem segment. If a process other than the current owner tries michael@0: // to touch the segment, it dies with SIGSEGV. michael@0: // michael@0: michael@0: Shmem::Shmem(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, michael@0: SharedMemory* aSegment, id_t aId) : michael@0: mSegment(aSegment), michael@0: mData(0), michael@0: mSize(0) michael@0: { michael@0: NS_ABORT_IF_FALSE(mSegment, "NULL segment"); michael@0: NS_ABORT_IF_FALSE(aId != 0, "invalid ID"); michael@0: michael@0: Unprotect(mSegment); michael@0: michael@0: Header* header; michael@0: char* frontSentinel; michael@0: char* data; michael@0: char* backSentinel; michael@0: GetSections(aSegment, &header, &frontSentinel, &data, &backSentinel); michael@0: michael@0: // do a quick validity check to avoid weird-looking crashes in libc michael@0: char check = *frontSentinel; michael@0: (void)check; michael@0: michael@0: NS_ABORT_IF_FALSE(!strncmp(header->mMagic, sMagic, sizeof(sMagic)), michael@0: "invalid segment"); michael@0: mSize = static_cast(header->mSize); michael@0: michael@0: size_t pageSize = SharedMemory::SystemPageSize(); michael@0: // transition into the "mapped" state by protecting the front and michael@0: // back sentinels (which guard against buffer under/overflows) michael@0: mSegment->Protect(frontSentinel, pageSize, RightsNone); michael@0: mSegment->Protect(backSentinel, pageSize, RightsNone); michael@0: michael@0: // don't set these until we know they're valid michael@0: mData = data; michael@0: mId = aId; michael@0: } michael@0: michael@0: void michael@0: Shmem::AssertInvariants() const michael@0: { michael@0: NS_ABORT_IF_FALSE(mSegment, "NULL segment"); michael@0: NS_ABORT_IF_FALSE(mData, "NULL data pointer"); michael@0: NS_ABORT_IF_FALSE(mSize > 0, "invalid size"); michael@0: // if the segment isn't owned by the current process, these will michael@0: // trigger SIGSEGV michael@0: char checkMappingFront = *reinterpret_cast(mData); michael@0: char checkMappingBack = *(reinterpret_cast(mData) + mSize - 1); michael@0: michael@0: // avoid "unused" warnings for these variables: michael@0: unused << checkMappingFront; michael@0: unused << checkMappingBack; michael@0: } michael@0: michael@0: void michael@0: Shmem::RevokeRights(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead) michael@0: { michael@0: AssertInvariants(); michael@0: michael@0: size_t pageSize = SharedMemory::SystemPageSize(); michael@0: Header* header = GetHeader(mSegment); michael@0: michael@0: // Open this up for reading temporarily michael@0: mSegment->Protect(reinterpret_cast(header), pageSize, RightsRead); michael@0: michael@0: if (!header->mUnsafe) { michael@0: Protect(mSegment); michael@0: } else { michael@0: mSegment->Protect(reinterpret_cast(header), pageSize, RightsNone); michael@0: } michael@0: } michael@0: michael@0: // static michael@0: Shmem::SharedMemory* michael@0: Shmem::Alloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, michael@0: size_t aNBytes, michael@0: SharedMemoryType aType, michael@0: bool aUnsafe, michael@0: bool aProtect) michael@0: { michael@0: NS_ASSERTION(aNBytes <= UINT32_MAX, "Will truncate shmem segment size!"); michael@0: NS_ABORT_IF_FALSE(!aProtect || !aUnsafe, "protect => !unsafe"); michael@0: michael@0: size_t pageSize = SharedMemory::SystemPageSize(); michael@0: SharedMemory* segment = nullptr; michael@0: // |2*pageSize| is for the front and back sentinel michael@0: size_t segmentSize = SharedMemory::PageAlignedSize(aNBytes + 2*pageSize); michael@0: michael@0: if (aType == SharedMemory::TYPE_BASIC) michael@0: segment = CreateSegment(segmentSize, SharedMemoryBasic::NULLHandle()); michael@0: #ifdef MOZ_HAVE_SHAREDMEMORYSYSV michael@0: else if (aType == SharedMemory::TYPE_SYSV) michael@0: segment = CreateSegment(segmentSize, SharedMemorySysV::NULLHandle()); michael@0: #endif michael@0: else { michael@0: NS_ERROR("unknown shmem type"); michael@0: return nullptr; michael@0: } michael@0: michael@0: if (!segment) michael@0: return 0; michael@0: michael@0: Header* header; michael@0: char *frontSentinel; michael@0: char *data; michael@0: char *backSentinel; michael@0: GetSections(segment, &header, &frontSentinel, &data, &backSentinel); michael@0: michael@0: // initialize the segment with Shmem-internal information michael@0: michael@0: // NB: this can't be a static assert because technically pageSize michael@0: // isn't known at compile time, event though in practice it's always michael@0: // going to be 4KiB michael@0: NS_ABORT_IF_FALSE(sizeof(Header) <= pageSize, michael@0: "Shmem::Header has gotten too big"); michael@0: memcpy(header->mMagic, sMagic, sizeof(sMagic)); michael@0: header->mSize = static_cast(aNBytes); michael@0: header->mUnsafe = aUnsafe; michael@0: michael@0: if (aProtect) michael@0: Protect(segment); michael@0: michael@0: return segment; michael@0: } michael@0: michael@0: // static michael@0: Shmem::SharedMemory* michael@0: Shmem::OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, michael@0: const IPC::Message& aDescriptor, michael@0: id_t* aId, michael@0: bool aProtect) michael@0: { michael@0: if (SHMEM_CREATED_MESSAGE_TYPE != aDescriptor.type()) { michael@0: NS_ERROR("expected 'shmem created' message"); michael@0: return nullptr; michael@0: } michael@0: michael@0: void* iter = 0; michael@0: SharedMemory::SharedMemoryType type; michael@0: size_t size; michael@0: if (!ShmemCreated::ReadInfo(&aDescriptor, &iter, aId, &size, &type)) michael@0: return 0; michael@0: michael@0: SharedMemory* segment = 0; michael@0: size_t pageSize = SharedMemory::SystemPageSize(); michael@0: // |2*pageSize| is for the front and back sentinels michael@0: size_t segmentSize = SharedMemory::PageAlignedSize(size + 2*pageSize); michael@0: michael@0: if (SharedMemory::TYPE_BASIC == type) { michael@0: SharedMemoryBasic::Handle handle; michael@0: if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle)) michael@0: return 0; michael@0: michael@0: if (!SharedMemoryBasic::IsHandleValid(handle)) { michael@0: NS_ERROR("trying to open invalid handle"); michael@0: return nullptr; michael@0: } michael@0: segment = CreateSegment(segmentSize, handle); michael@0: } michael@0: #ifdef MOZ_HAVE_SHAREDMEMORYSYSV michael@0: else if (SharedMemory::TYPE_SYSV == type) { michael@0: SharedMemorySysV::Handle handle; michael@0: if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle)) michael@0: return 0; michael@0: michael@0: if (!SharedMemorySysV::IsHandleValid(handle)) { michael@0: NS_ERROR("trying to open invalid handle"); michael@0: return nullptr; michael@0: } michael@0: segment = CreateSegment(segmentSize, handle); michael@0: } michael@0: #endif michael@0: else { michael@0: NS_ERROR("unknown shmem type"); michael@0: return nullptr; michael@0: } michael@0: michael@0: if (!segment) michael@0: return 0; michael@0: michael@0: Header* header = GetHeader(segment); michael@0: michael@0: if (size != header->mSize) { michael@0: NS_ERROR("Wrong size for this Shmem!"); michael@0: delete segment; michael@0: return nullptr; michael@0: } michael@0: michael@0: // The caller of this function may not know whether the segment is michael@0: // unsafe or not michael@0: if (!header->mUnsafe && aProtect) michael@0: Protect(segment); michael@0: michael@0: return segment; michael@0: } michael@0: michael@0: // static michael@0: void michael@0: Shmem::Dealloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, michael@0: SharedMemory* aSegment) michael@0: { michael@0: if (!aSegment) michael@0: return; michael@0: michael@0: size_t pageSize = SharedMemory::SystemPageSize(); michael@0: Header* header; michael@0: char *frontSentinel; michael@0: char *data; michael@0: char *backSentinel; michael@0: GetSections(aSegment, &header, &frontSentinel, &data, &backSentinel); michael@0: michael@0: aSegment->Protect(frontSentinel, pageSize, RightsWrite | RightsRead); michael@0: memset(header->mMagic, 0, sizeof(sMagic)); michael@0: header->mSize = 0; michael@0: header->mUnsafe = false; // make it "safe" so as to catch errors michael@0: michael@0: DestroySegment(aSegment); michael@0: } michael@0: michael@0: michael@0: #else // !defined(DEBUG) michael@0: michael@0: // static michael@0: Shmem::SharedMemory* michael@0: Shmem::Alloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, michael@0: size_t aNBytes, michael@0: SharedMemoryType aType, michael@0: bool /*unused*/, michael@0: bool /*unused*/) michael@0: { michael@0: SharedMemory *segment = nullptr; michael@0: michael@0: if (aType == SharedMemory::TYPE_BASIC) michael@0: segment = CreateSegment(SharedMemory::PageAlignedSize(aNBytes + sizeof(uint32_t)), michael@0: SharedMemoryBasic::NULLHandle()); michael@0: #ifdef MOZ_HAVE_SHAREDMEMORYSYSV michael@0: else if (aType == SharedMemory::TYPE_SYSV) michael@0: segment = CreateSegment(SharedMemory::PageAlignedSize(aNBytes + sizeof(uint32_t)), michael@0: SharedMemorySysV::NULLHandle()); michael@0: #endif michael@0: else { michael@0: return nullptr; michael@0: } michael@0: michael@0: if (!segment) michael@0: return 0; michael@0: michael@0: *PtrToSize(segment) = static_cast(aNBytes); michael@0: michael@0: return segment; michael@0: } michael@0: michael@0: // static michael@0: Shmem::SharedMemory* michael@0: Shmem::OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, michael@0: const IPC::Message& aDescriptor, michael@0: id_t* aId, michael@0: bool /*unused*/) michael@0: { michael@0: if (SHMEM_CREATED_MESSAGE_TYPE != aDescriptor.type()) { michael@0: return nullptr; michael@0: } michael@0: michael@0: SharedMemory::SharedMemoryType type; michael@0: void* iter = 0; michael@0: size_t size; michael@0: if (!ShmemCreated::ReadInfo(&aDescriptor, &iter, aId, &size, &type)) michael@0: return 0; michael@0: michael@0: SharedMemory* segment = 0; michael@0: size_t segmentSize = SharedMemory::PageAlignedSize(size + sizeof(uint32_t)); michael@0: michael@0: if (SharedMemory::TYPE_BASIC == type) { michael@0: SharedMemoryBasic::Handle handle; michael@0: if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle)) michael@0: return 0; michael@0: michael@0: if (!SharedMemoryBasic::IsHandleValid(handle)) { michael@0: return nullptr; michael@0: } michael@0: michael@0: segment = CreateSegment(segmentSize, handle); michael@0: } michael@0: #ifdef MOZ_HAVE_SHAREDMEMORYSYSV michael@0: else if (SharedMemory::TYPE_SYSV == type) { michael@0: SharedMemorySysV::Handle handle; michael@0: if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle)) michael@0: return 0; michael@0: michael@0: if (!SharedMemorySysV::IsHandleValid(handle)) { michael@0: return nullptr; michael@0: } michael@0: segment = CreateSegment(segmentSize, handle); michael@0: } michael@0: #endif michael@0: else { michael@0: return nullptr; michael@0: } michael@0: michael@0: if (!segment) michael@0: return 0; michael@0: michael@0: // this is the only validity check done in non-DEBUG builds michael@0: if (size != static_cast(*PtrToSize(segment))) { michael@0: delete segment; michael@0: return nullptr; michael@0: } michael@0: michael@0: return segment; michael@0: } michael@0: michael@0: // static michael@0: void michael@0: Shmem::Dealloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, michael@0: SharedMemory* aSegment) michael@0: { michael@0: DestroySegment(aSegment); michael@0: } michael@0: michael@0: #endif // if defined(DEBUG) michael@0: michael@0: int michael@0: Shmem::GetSysVID() const michael@0: { michael@0: #ifdef MOZ_HAVE_SHAREDMEMORYSYSV michael@0: AssertInvariants(); michael@0: michael@0: if (mSegment->Type() != SharedMemory::TYPE_SYSV) { michael@0: NS_ERROR("Can't call GetSysVID() on a non-SysV Shmem!"); michael@0: return -1; michael@0: } michael@0: michael@0: SharedMemorySysV* seg = static_cast(mSegment); michael@0: return seg->GetHandle(); michael@0: #else michael@0: NS_ERROR("Can't call GetSysVID() with no support for SysV shared memory!"); michael@0: return -1; // not reached michael@0: #endif michael@0: } michael@0: michael@0: IPC::Message* michael@0: Shmem::ShareTo(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, michael@0: base::ProcessHandle aProcess, michael@0: int32_t routingId) michael@0: { michael@0: AssertInvariants(); michael@0: michael@0: if (SharedMemory::TYPE_BASIC == mSegment->Type()) { michael@0: SharedMemoryBasic* seg = static_cast(mSegment); michael@0: SharedMemoryBasic::Handle handle; michael@0: if (!seg->ShareToProcess(aProcess, &handle)) michael@0: return 0; michael@0: michael@0: return new ShmemCreated(routingId, mId, mSize, handle); michael@0: } michael@0: #ifdef MOZ_HAVE_SHAREDMEMORYSYSV michael@0: else if (SharedMemory::TYPE_SYSV == mSegment->Type()) { michael@0: SharedMemorySysV* seg = static_cast(mSegment); michael@0: return new ShmemCreated(routingId, mId, mSize, seg->GetHandle()); michael@0: } michael@0: #endif michael@0: else { michael@0: NS_ABORT_IF_FALSE(false, "unknown shmem type (here?!)"); michael@0: return nullptr; michael@0: } michael@0: michael@0: return 0; michael@0: } michael@0: michael@0: IPC::Message* michael@0: Shmem::UnshareFrom(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, michael@0: base::ProcessHandle aProcess, michael@0: int32_t routingId) michael@0: { michael@0: AssertInvariants(); michael@0: return new ShmemDestroyed(routingId, mId); michael@0: } michael@0: michael@0: } // namespace ipc michael@0: } // namespace mozilla