1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/glue/Shmem.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,658 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * vim: sw=2 ts=8 et : 1.6 + */ 1.7 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.10 + 1.11 +#include "Shmem.h" 1.12 + 1.13 +#include "ProtocolUtils.h" 1.14 +#include "SharedMemoryBasic.h" 1.15 +#include "SharedMemorySysV.h" 1.16 + 1.17 +#include "nsAutoPtr.h" 1.18 +#include "mozilla/unused.h" 1.19 + 1.20 + 1.21 +namespace mozilla { 1.22 +namespace ipc { 1.23 + 1.24 +class ShmemCreated : public IPC::Message 1.25 +{ 1.26 +private: 1.27 + typedef Shmem::id_t id_t; 1.28 + 1.29 +public: 1.30 + ShmemCreated(int32_t routingId, 1.31 + const id_t& aIPDLId, 1.32 + const size_t& aSize, 1.33 + const SharedMemoryBasic::Handle& aHandle) : 1.34 + IPC::Message(routingId, SHMEM_CREATED_MESSAGE_TYPE, PRIORITY_NORMAL) 1.35 + { 1.36 + IPC::WriteParam(this, aIPDLId); 1.37 + IPC::WriteParam(this, aSize); 1.38 + IPC::WriteParam(this, int32_t(SharedMemory::TYPE_BASIC)), 1.39 + IPC::WriteParam(this, aHandle); 1.40 + } 1.41 + 1.42 + // Instead of a single Read() function, we have ReadInfo() and 1.43 + // ReadHandle(). The reason is that the handle type is specific to 1.44 + // the shmem type. These functions should only be called in the 1.45 + // order ReadInfo(); ReadHandle();, and only once each. 1.46 + 1.47 + static bool 1.48 + ReadInfo(const Message* msg, void** iter, 1.49 + id_t* aIPDLId, 1.50 + size_t* aSize, 1.51 + SharedMemory::SharedMemoryType* aType) 1.52 + { 1.53 + if (!IPC::ReadParam(msg, iter, aIPDLId) || 1.54 + !IPC::ReadParam(msg, iter, aSize) || 1.55 + !IPC::ReadParam(msg, iter, reinterpret_cast<int32_t*>(aType))) 1.56 + return false; 1.57 + return true; 1.58 + } 1.59 + 1.60 + static bool 1.61 + ReadHandle(const Message* msg, void** iter, 1.62 + SharedMemoryBasic::Handle* aHandle) 1.63 + { 1.64 + if (!IPC::ReadParam(msg, iter, aHandle)) 1.65 + return false; 1.66 + msg->EndRead(*iter); 1.67 + return true; 1.68 + } 1.69 + 1.70 +#ifdef MOZ_HAVE_SHAREDMEMORYSYSV 1.71 + ShmemCreated(int32_t routingId, 1.72 + const id_t& aIPDLId, 1.73 + const size_t& aSize, 1.74 + const SharedMemorySysV::Handle& aHandle) : 1.75 + IPC::Message(routingId, SHMEM_CREATED_MESSAGE_TYPE, PRIORITY_NORMAL) 1.76 + { 1.77 + IPC::WriteParam(this, aIPDLId); 1.78 + IPC::WriteParam(this, aSize); 1.79 + IPC::WriteParam(this, int32_t(SharedMemory::TYPE_SYSV)), 1.80 + IPC::WriteParam(this, aHandle); 1.81 + } 1.82 + 1.83 + static bool 1.84 + ReadHandle(const Message* msg, void** iter, 1.85 + SharedMemorySysV::Handle* aHandle) 1.86 + { 1.87 + if (!IPC::ReadParam(msg, iter, aHandle)) 1.88 + return false; 1.89 + msg->EndRead(*iter); 1.90 + return true; 1.91 + } 1.92 +#endif 1.93 + 1.94 + void Log(const std::string& aPrefix, 1.95 + FILE* aOutf) const 1.96 + { 1.97 + fputs("(special ShmemCreated msg)", aOutf); 1.98 + } 1.99 +}; 1.100 + 1.101 +class ShmemDestroyed : public IPC::Message 1.102 +{ 1.103 +private: 1.104 + typedef Shmem::id_t id_t; 1.105 + 1.106 +public: 1.107 + ShmemDestroyed(int32_t routingId, 1.108 + const id_t& aIPDLId) : 1.109 + IPC::Message(routingId, SHMEM_DESTROYED_MESSAGE_TYPE, PRIORITY_NORMAL) 1.110 + { 1.111 + IPC::WriteParam(this, aIPDLId); 1.112 + } 1.113 +}; 1.114 + 1.115 + 1.116 +#ifdef MOZ_HAVE_SHAREDMEMORYSYSV 1.117 +static Shmem::SharedMemory* 1.118 +CreateSegment(size_t aNBytes, SharedMemorySysV::Handle aHandle) 1.119 +{ 1.120 + nsAutoPtr<SharedMemory> segment; 1.121 + 1.122 + if (SharedMemorySysV::IsHandleValid(aHandle)) { 1.123 + segment = new SharedMemorySysV(aHandle); 1.124 + } 1.125 + else { 1.126 + segment = new SharedMemorySysV(); 1.127 + 1.128 + if (!segment->Create(aNBytes)) 1.129 + return 0; 1.130 + } 1.131 + if (!segment->Map(aNBytes)) 1.132 + return 0; 1.133 + 1.134 + segment->AddRef(); 1.135 + return segment.forget(); 1.136 +} 1.137 +#endif 1.138 + 1.139 +static Shmem::SharedMemory* 1.140 +CreateSegment(size_t aNBytes, SharedMemoryBasic::Handle aHandle) 1.141 +{ 1.142 + nsAutoPtr<SharedMemory> segment; 1.143 + 1.144 + if (SharedMemoryBasic::IsHandleValid(aHandle)) { 1.145 + segment = new SharedMemoryBasic(aHandle); 1.146 + } 1.147 + else { 1.148 + segment = new SharedMemoryBasic(); 1.149 + 1.150 + if (!segment->Create(aNBytes)) 1.151 + return 0; 1.152 + } 1.153 + if (!segment->Map(aNBytes)) 1.154 + return 0; 1.155 + 1.156 + segment->AddRef(); 1.157 + return segment.forget(); 1.158 +} 1.159 + 1.160 +static void 1.161 +DestroySegment(SharedMemory* aSegment) 1.162 +{ 1.163 + // the SharedMemory dtor closes and unmaps the actual OS shmem segment 1.164 + if (aSegment) 1.165 + aSegment->Release(); 1.166 +} 1.167 + 1.168 + 1.169 +#if defined(DEBUG) 1.170 + 1.171 +static const char sMagic[] = 1.172 + "This little piggy went to market.\n" 1.173 + "This little piggy stayed at home.\n" 1.174 + "This little piggy has roast beef,\n" 1.175 + "This little piggy had none.\n" 1.176 + "And this little piggy cried \"Wee! Wee! Wee!\" all the way home"; 1.177 + 1.178 + 1.179 +struct Header { 1.180 + // Don't use size_t or bool here because their size depends on the 1.181 + // architecture. 1.182 + uint32_t mSize; 1.183 + uint32_t mUnsafe; 1.184 + char mMagic[sizeof(sMagic)]; 1.185 +}; 1.186 + 1.187 +static void 1.188 +GetSections(Shmem::SharedMemory* aSegment, 1.189 + Header** aHeader, 1.190 + char** aFrontSentinel, 1.191 + char** aData, 1.192 + char** aBackSentinel) 1.193 +{ 1.194 + NS_ABORT_IF_FALSE(aSegment && aFrontSentinel && aData && aBackSentinel, 1.195 + "NULL param(s)"); 1.196 + 1.197 + *aFrontSentinel = reinterpret_cast<char*>(aSegment->memory()); 1.198 + NS_ABORT_IF_FALSE(*aFrontSentinel, "NULL memory()"); 1.199 + 1.200 + *aHeader = reinterpret_cast<Header*>(*aFrontSentinel); 1.201 + 1.202 + size_t pageSize = Shmem::SharedMemory::SystemPageSize(); 1.203 + *aData = *aFrontSentinel + pageSize; 1.204 + 1.205 + *aBackSentinel = *aFrontSentinel + aSegment->Size() - pageSize; 1.206 +} 1.207 + 1.208 +static Header* 1.209 +GetHeader(Shmem::SharedMemory* aSegment) 1.210 +{ 1.211 + Header* header; 1.212 + char* dontcare; 1.213 + GetSections(aSegment, &header, &dontcare, &dontcare, &dontcare); 1.214 + return header; 1.215 +} 1.216 + 1.217 +static void 1.218 +Protect(SharedMemory* aSegment) 1.219 +{ 1.220 + NS_ABORT_IF_FALSE(aSegment, "NULL segment"); 1.221 + aSegment->Protect(reinterpret_cast<char*>(aSegment->memory()), 1.222 + aSegment->Size(), 1.223 + RightsNone); 1.224 +} 1.225 + 1.226 +static void 1.227 +Unprotect(SharedMemory* aSegment) 1.228 +{ 1.229 + NS_ABORT_IF_FALSE(aSegment, "NULL segment"); 1.230 + aSegment->Protect(reinterpret_cast<char*>(aSegment->memory()), 1.231 + aSegment->Size(), 1.232 + RightsRead | RightsWrite); 1.233 +} 1.234 + 1.235 +// 1.236 +// In debug builds, we specially allocate shmem segments. The layout 1.237 +// is as follows 1.238 +// 1.239 +// Page 0: "front sentinel" 1.240 +// size of mapping 1.241 +// magic bytes 1.242 +// Page 1 through n-1: 1.243 +// user data 1.244 +// Page n: "back sentinel" 1.245 +// [nothing] 1.246 +// 1.247 +// The mapping can be in one of the following states, wrt to the 1.248 +// current process. 1.249 +// 1.250 +// State "unmapped": all pages are mapped with no access rights. 1.251 +// 1.252 +// State "mapping": all pages are mapped with read/write access. 1.253 +// 1.254 +// State "mapped": the front and back sentinels are mapped with no 1.255 +// access rights, and all the other pages are mapped with 1.256 +// read/write access. 1.257 +// 1.258 +// When a SharedMemory segment is first allocated, it starts out in 1.259 +// the "mapping" state for the process that allocates the segment, and 1.260 +// in the "unmapped" state for the other process. The allocating 1.261 +// process will then create a Shmem, which takes the segment into the 1.262 +// "mapped" state, where it can be accessed by clients. 1.263 +// 1.264 +// When a Shmem is sent to another process in an IPDL message, the 1.265 +// segment transitions into the "unmapped" state for the sending 1.266 +// process, and into the "mapping" state for the receiving process. 1.267 +// The receiving process will then create a Shmem from the underlying 1.268 +// segment, and take the segment into the "mapped" state. 1.269 +// 1.270 +// In the "mapping" state, we use the front sentinel to verify the 1.271 +// integrity of the shmem segment. If valid, it has a size_t 1.272 +// containing the number of bytes the user allocated followed by the 1.273 +// magic bytes above. 1.274 +// 1.275 +// In the "mapped" state, the front and back sentinels have no access 1.276 +// rights. They act as guards against buffer overflows and underflows 1.277 +// in client code; if clients touch a sentinel, they die with SIGSEGV. 1.278 +// 1.279 +// The "unmapped" state is used to enforce single-owner semantics of 1.280 +// the shmem segment. If a process other than the current owner tries 1.281 +// to touch the segment, it dies with SIGSEGV. 1.282 +// 1.283 + 1.284 +Shmem::Shmem(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, 1.285 + SharedMemory* aSegment, id_t aId) : 1.286 + mSegment(aSegment), 1.287 + mData(0), 1.288 + mSize(0) 1.289 +{ 1.290 + NS_ABORT_IF_FALSE(mSegment, "NULL segment"); 1.291 + NS_ABORT_IF_FALSE(aId != 0, "invalid ID"); 1.292 + 1.293 + Unprotect(mSegment); 1.294 + 1.295 + Header* header; 1.296 + char* frontSentinel; 1.297 + char* data; 1.298 + char* backSentinel; 1.299 + GetSections(aSegment, &header, &frontSentinel, &data, &backSentinel); 1.300 + 1.301 + // do a quick validity check to avoid weird-looking crashes in libc 1.302 + char check = *frontSentinel; 1.303 + (void)check; 1.304 + 1.305 + NS_ABORT_IF_FALSE(!strncmp(header->mMagic, sMagic, sizeof(sMagic)), 1.306 + "invalid segment"); 1.307 + mSize = static_cast<size_t>(header->mSize); 1.308 + 1.309 + size_t pageSize = SharedMemory::SystemPageSize(); 1.310 + // transition into the "mapped" state by protecting the front and 1.311 + // back sentinels (which guard against buffer under/overflows) 1.312 + mSegment->Protect(frontSentinel, pageSize, RightsNone); 1.313 + mSegment->Protect(backSentinel, pageSize, RightsNone); 1.314 + 1.315 + // don't set these until we know they're valid 1.316 + mData = data; 1.317 + mId = aId; 1.318 +} 1.319 + 1.320 +void 1.321 +Shmem::AssertInvariants() const 1.322 +{ 1.323 + NS_ABORT_IF_FALSE(mSegment, "NULL segment"); 1.324 + NS_ABORT_IF_FALSE(mData, "NULL data pointer"); 1.325 + NS_ABORT_IF_FALSE(mSize > 0, "invalid size"); 1.326 + // if the segment isn't owned by the current process, these will 1.327 + // trigger SIGSEGV 1.328 + char checkMappingFront = *reinterpret_cast<char*>(mData); 1.329 + char checkMappingBack = *(reinterpret_cast<char*>(mData) + mSize - 1); 1.330 + 1.331 + // avoid "unused" warnings for these variables: 1.332 + unused << checkMappingFront; 1.333 + unused << checkMappingBack; 1.334 +} 1.335 + 1.336 +void 1.337 +Shmem::RevokeRights(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead) 1.338 +{ 1.339 + AssertInvariants(); 1.340 + 1.341 + size_t pageSize = SharedMemory::SystemPageSize(); 1.342 + Header* header = GetHeader(mSegment); 1.343 + 1.344 + // Open this up for reading temporarily 1.345 + mSegment->Protect(reinterpret_cast<char*>(header), pageSize, RightsRead); 1.346 + 1.347 + if (!header->mUnsafe) { 1.348 + Protect(mSegment); 1.349 + } else { 1.350 + mSegment->Protect(reinterpret_cast<char*>(header), pageSize, RightsNone); 1.351 + } 1.352 +} 1.353 + 1.354 +// static 1.355 +Shmem::SharedMemory* 1.356 +Shmem::Alloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, 1.357 + size_t aNBytes, 1.358 + SharedMemoryType aType, 1.359 + bool aUnsafe, 1.360 + bool aProtect) 1.361 +{ 1.362 + NS_ASSERTION(aNBytes <= UINT32_MAX, "Will truncate shmem segment size!"); 1.363 + NS_ABORT_IF_FALSE(!aProtect || !aUnsafe, "protect => !unsafe"); 1.364 + 1.365 + size_t pageSize = SharedMemory::SystemPageSize(); 1.366 + SharedMemory* segment = nullptr; 1.367 + // |2*pageSize| is for the front and back sentinel 1.368 + size_t segmentSize = SharedMemory::PageAlignedSize(aNBytes + 2*pageSize); 1.369 + 1.370 + if (aType == SharedMemory::TYPE_BASIC) 1.371 + segment = CreateSegment(segmentSize, SharedMemoryBasic::NULLHandle()); 1.372 +#ifdef MOZ_HAVE_SHAREDMEMORYSYSV 1.373 + else if (aType == SharedMemory::TYPE_SYSV) 1.374 + segment = CreateSegment(segmentSize, SharedMemorySysV::NULLHandle()); 1.375 +#endif 1.376 + else { 1.377 + NS_ERROR("unknown shmem type"); 1.378 + return nullptr; 1.379 + } 1.380 + 1.381 + if (!segment) 1.382 + return 0; 1.383 + 1.384 + Header* header; 1.385 + char *frontSentinel; 1.386 + char *data; 1.387 + char *backSentinel; 1.388 + GetSections(segment, &header, &frontSentinel, &data, &backSentinel); 1.389 + 1.390 + // initialize the segment with Shmem-internal information 1.391 + 1.392 + // NB: this can't be a static assert because technically pageSize 1.393 + // isn't known at compile time, event though in practice it's always 1.394 + // going to be 4KiB 1.395 + NS_ABORT_IF_FALSE(sizeof(Header) <= pageSize, 1.396 + "Shmem::Header has gotten too big"); 1.397 + memcpy(header->mMagic, sMagic, sizeof(sMagic)); 1.398 + header->mSize = static_cast<uint32_t>(aNBytes); 1.399 + header->mUnsafe = aUnsafe; 1.400 + 1.401 + if (aProtect) 1.402 + Protect(segment); 1.403 + 1.404 + return segment; 1.405 +} 1.406 + 1.407 +// static 1.408 +Shmem::SharedMemory* 1.409 +Shmem::OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, 1.410 + const IPC::Message& aDescriptor, 1.411 + id_t* aId, 1.412 + bool aProtect) 1.413 +{ 1.414 + if (SHMEM_CREATED_MESSAGE_TYPE != aDescriptor.type()) { 1.415 + NS_ERROR("expected 'shmem created' message"); 1.416 + return nullptr; 1.417 + } 1.418 + 1.419 + void* iter = 0; 1.420 + SharedMemory::SharedMemoryType type; 1.421 + size_t size; 1.422 + if (!ShmemCreated::ReadInfo(&aDescriptor, &iter, aId, &size, &type)) 1.423 + return 0; 1.424 + 1.425 + SharedMemory* segment = 0; 1.426 + size_t pageSize = SharedMemory::SystemPageSize(); 1.427 + // |2*pageSize| is for the front and back sentinels 1.428 + size_t segmentSize = SharedMemory::PageAlignedSize(size + 2*pageSize); 1.429 + 1.430 + if (SharedMemory::TYPE_BASIC == type) { 1.431 + SharedMemoryBasic::Handle handle; 1.432 + if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle)) 1.433 + return 0; 1.434 + 1.435 + if (!SharedMemoryBasic::IsHandleValid(handle)) { 1.436 + NS_ERROR("trying to open invalid handle"); 1.437 + return nullptr; 1.438 + } 1.439 + segment = CreateSegment(segmentSize, handle); 1.440 + } 1.441 +#ifdef MOZ_HAVE_SHAREDMEMORYSYSV 1.442 + else if (SharedMemory::TYPE_SYSV == type) { 1.443 + SharedMemorySysV::Handle handle; 1.444 + if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle)) 1.445 + return 0; 1.446 + 1.447 + if (!SharedMemorySysV::IsHandleValid(handle)) { 1.448 + NS_ERROR("trying to open invalid handle"); 1.449 + return nullptr; 1.450 + } 1.451 + segment = CreateSegment(segmentSize, handle); 1.452 + } 1.453 +#endif 1.454 + else { 1.455 + NS_ERROR("unknown shmem type"); 1.456 + return nullptr; 1.457 + } 1.458 + 1.459 + if (!segment) 1.460 + return 0; 1.461 + 1.462 + Header* header = GetHeader(segment); 1.463 + 1.464 + if (size != header->mSize) { 1.465 + NS_ERROR("Wrong size for this Shmem!"); 1.466 + delete segment; 1.467 + return nullptr; 1.468 + } 1.469 + 1.470 + // The caller of this function may not know whether the segment is 1.471 + // unsafe or not 1.472 + if (!header->mUnsafe && aProtect) 1.473 + Protect(segment); 1.474 + 1.475 + return segment; 1.476 +} 1.477 + 1.478 +// static 1.479 +void 1.480 +Shmem::Dealloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, 1.481 + SharedMemory* aSegment) 1.482 +{ 1.483 + if (!aSegment) 1.484 + return; 1.485 + 1.486 + size_t pageSize = SharedMemory::SystemPageSize(); 1.487 + Header* header; 1.488 + char *frontSentinel; 1.489 + char *data; 1.490 + char *backSentinel; 1.491 + GetSections(aSegment, &header, &frontSentinel, &data, &backSentinel); 1.492 + 1.493 + aSegment->Protect(frontSentinel, pageSize, RightsWrite | RightsRead); 1.494 + memset(header->mMagic, 0, sizeof(sMagic)); 1.495 + header->mSize = 0; 1.496 + header->mUnsafe = false; // make it "safe" so as to catch errors 1.497 + 1.498 + DestroySegment(aSegment); 1.499 +} 1.500 + 1.501 + 1.502 +#else // !defined(DEBUG) 1.503 + 1.504 +// static 1.505 +Shmem::SharedMemory* 1.506 +Shmem::Alloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, 1.507 + size_t aNBytes, 1.508 + SharedMemoryType aType, 1.509 + bool /*unused*/, 1.510 + bool /*unused*/) 1.511 +{ 1.512 + SharedMemory *segment = nullptr; 1.513 + 1.514 + if (aType == SharedMemory::TYPE_BASIC) 1.515 + segment = CreateSegment(SharedMemory::PageAlignedSize(aNBytes + sizeof(uint32_t)), 1.516 + SharedMemoryBasic::NULLHandle()); 1.517 +#ifdef MOZ_HAVE_SHAREDMEMORYSYSV 1.518 + else if (aType == SharedMemory::TYPE_SYSV) 1.519 + segment = CreateSegment(SharedMemory::PageAlignedSize(aNBytes + sizeof(uint32_t)), 1.520 + SharedMemorySysV::NULLHandle()); 1.521 +#endif 1.522 + else { 1.523 + return nullptr; 1.524 + } 1.525 + 1.526 + if (!segment) 1.527 + return 0; 1.528 + 1.529 + *PtrToSize(segment) = static_cast<uint32_t>(aNBytes); 1.530 + 1.531 + return segment; 1.532 +} 1.533 + 1.534 +// static 1.535 +Shmem::SharedMemory* 1.536 +Shmem::OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, 1.537 + const IPC::Message& aDescriptor, 1.538 + id_t* aId, 1.539 + bool /*unused*/) 1.540 +{ 1.541 + if (SHMEM_CREATED_MESSAGE_TYPE != aDescriptor.type()) { 1.542 + return nullptr; 1.543 + } 1.544 + 1.545 + SharedMemory::SharedMemoryType type; 1.546 + void* iter = 0; 1.547 + size_t size; 1.548 + if (!ShmemCreated::ReadInfo(&aDescriptor, &iter, aId, &size, &type)) 1.549 + return 0; 1.550 + 1.551 + SharedMemory* segment = 0; 1.552 + size_t segmentSize = SharedMemory::PageAlignedSize(size + sizeof(uint32_t)); 1.553 + 1.554 + if (SharedMemory::TYPE_BASIC == type) { 1.555 + SharedMemoryBasic::Handle handle; 1.556 + if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle)) 1.557 + return 0; 1.558 + 1.559 + if (!SharedMemoryBasic::IsHandleValid(handle)) { 1.560 + return nullptr; 1.561 + } 1.562 + 1.563 + segment = CreateSegment(segmentSize, handle); 1.564 + } 1.565 +#ifdef MOZ_HAVE_SHAREDMEMORYSYSV 1.566 + else if (SharedMemory::TYPE_SYSV == type) { 1.567 + SharedMemorySysV::Handle handle; 1.568 + if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle)) 1.569 + return 0; 1.570 + 1.571 + if (!SharedMemorySysV::IsHandleValid(handle)) { 1.572 + return nullptr; 1.573 + } 1.574 + segment = CreateSegment(segmentSize, handle); 1.575 + } 1.576 +#endif 1.577 + else { 1.578 + return nullptr; 1.579 + } 1.580 + 1.581 + if (!segment) 1.582 + return 0; 1.583 + 1.584 + // this is the only validity check done in non-DEBUG builds 1.585 + if (size != static_cast<size_t>(*PtrToSize(segment))) { 1.586 + delete segment; 1.587 + return nullptr; 1.588 + } 1.589 + 1.590 + return segment; 1.591 +} 1.592 + 1.593 +// static 1.594 +void 1.595 +Shmem::Dealloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, 1.596 + SharedMemory* aSegment) 1.597 +{ 1.598 + DestroySegment(aSegment); 1.599 +} 1.600 + 1.601 +#endif // if defined(DEBUG) 1.602 + 1.603 +int 1.604 +Shmem::GetSysVID() const 1.605 +{ 1.606 +#ifdef MOZ_HAVE_SHAREDMEMORYSYSV 1.607 + AssertInvariants(); 1.608 + 1.609 + if (mSegment->Type() != SharedMemory::TYPE_SYSV) { 1.610 + NS_ERROR("Can't call GetSysVID() on a non-SysV Shmem!"); 1.611 + return -1; 1.612 + } 1.613 + 1.614 + SharedMemorySysV* seg = static_cast<SharedMemorySysV*>(mSegment); 1.615 + return seg->GetHandle(); 1.616 +#else 1.617 + NS_ERROR("Can't call GetSysVID() with no support for SysV shared memory!"); 1.618 + return -1; // not reached 1.619 +#endif 1.620 +} 1.621 + 1.622 +IPC::Message* 1.623 +Shmem::ShareTo(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, 1.624 + base::ProcessHandle aProcess, 1.625 + int32_t routingId) 1.626 +{ 1.627 + AssertInvariants(); 1.628 + 1.629 + if (SharedMemory::TYPE_BASIC == mSegment->Type()) { 1.630 + SharedMemoryBasic* seg = static_cast<SharedMemoryBasic*>(mSegment); 1.631 + SharedMemoryBasic::Handle handle; 1.632 + if (!seg->ShareToProcess(aProcess, &handle)) 1.633 + return 0; 1.634 + 1.635 + return new ShmemCreated(routingId, mId, mSize, handle); 1.636 + } 1.637 +#ifdef MOZ_HAVE_SHAREDMEMORYSYSV 1.638 + else if (SharedMemory::TYPE_SYSV == mSegment->Type()) { 1.639 + SharedMemorySysV* seg = static_cast<SharedMemorySysV*>(mSegment); 1.640 + return new ShmemCreated(routingId, mId, mSize, seg->GetHandle()); 1.641 + } 1.642 +#endif 1.643 + else { 1.644 + NS_ABORT_IF_FALSE(false, "unknown shmem type (here?!)"); 1.645 + return nullptr; 1.646 + } 1.647 + 1.648 + return 0; 1.649 +} 1.650 + 1.651 +IPC::Message* 1.652 +Shmem::UnshareFrom(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, 1.653 + base::ProcessHandle aProcess, 1.654 + int32_t routingId) 1.655 +{ 1.656 + AssertInvariants(); 1.657 + return new ShmemDestroyed(routingId, mId); 1.658 +} 1.659 + 1.660 +} // namespace ipc 1.661 +} // namespace mozilla