1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: sw=2 ts=8 et :
3 : */
4 : /* ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is Mozilla IPC.
18 : *
19 : * The Initial Developer of the Original Code is
20 : * The Mozilla Foundation
21 : * Portions created by the Initial Developer are Copyright (C) 2009
22 : * the Initial Developer. All Rights Reserved.
23 : *
24 : * Contributor(s):
25 : * Chris Jones <jones.chris.g@gmail.com>
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either the GNU General Public License Version 2 or later (the "GPL"), or
29 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : #include "Shmem.h"
42 :
43 : #include "ProtocolUtils.h"
44 : #include "SharedMemoryBasic.h"
45 : #include "SharedMemorySysV.h"
46 :
47 : #include "nsAutoPtr.h"
48 : #include "mozilla/unused.h"
49 :
50 :
51 : namespace mozilla {
52 : namespace ipc {
53 :
54 : class ShmemCreated : public IPC::Message
55 0 : {
56 : private:
57 : typedef Shmem::id_t id_t;
58 :
59 : public:
60 0 : ShmemCreated(int32 routingId,
61 : const id_t& aIPDLId,
62 : const size_t& aSize,
63 : const SharedMemoryBasic::Handle& aHandle) :
64 0 : IPC::Message(routingId, SHMEM_CREATED_MESSAGE_TYPE, PRIORITY_NORMAL)
65 : {
66 0 : IPC::WriteParam(this, aIPDLId);
67 0 : IPC::WriteParam(this, aSize);
68 0 : IPC::WriteParam(this, int32(SharedMemory::TYPE_BASIC)),
69 0 : IPC::WriteParam(this, aHandle);
70 0 : }
71 :
72 : // Instead of a single Read() function, we have ReadInfo() and
73 : // ReadHandle(). The reason is that the handle type is specific to
74 : // the shmem type. These functions should only be called in the
75 : // order ReadInfo(); ReadHandle();, and only once each.
76 :
77 : static bool
78 0 : ReadInfo(const Message* msg, void** iter,
79 : id_t* aIPDLId,
80 : size_t* aSize,
81 : SharedMemory::SharedMemoryType* aType)
82 : {
83 0 : if (!IPC::ReadParam(msg, iter, aIPDLId) ||
84 0 : !IPC::ReadParam(msg, iter, aSize) ||
85 0 : !IPC::ReadParam(msg, iter, reinterpret_cast<int32*>(aType)))
86 0 : return false;
87 0 : return true;
88 : }
89 :
90 : static bool
91 0 : ReadHandle(const Message* msg, void** iter,
92 : SharedMemoryBasic::Handle* aHandle)
93 : {
94 0 : if (!IPC::ReadParam(msg, iter, aHandle))
95 0 : return false;
96 0 : msg->EndRead(*iter);
97 0 : return true;
98 : }
99 :
100 : #ifdef MOZ_HAVE_SHAREDMEMORYSYSV
101 0 : ShmemCreated(int32 routingId,
102 : const id_t& aIPDLId,
103 : const size_t& aSize,
104 : const SharedMemorySysV::Handle& aHandle) :
105 0 : IPC::Message(routingId, SHMEM_CREATED_MESSAGE_TYPE, PRIORITY_NORMAL)
106 : {
107 0 : IPC::WriteParam(this, aIPDLId);
108 0 : IPC::WriteParam(this, aSize);
109 0 : IPC::WriteParam(this, int32(SharedMemory::TYPE_SYSV)),
110 0 : IPC::WriteParam(this, aHandle);
111 0 : }
112 :
113 : static bool
114 0 : ReadHandle(const Message* msg, void** iter,
115 : SharedMemorySysV::Handle* aHandle)
116 : {
117 0 : if (!IPC::ReadParam(msg, iter, aHandle))
118 0 : return false;
119 0 : msg->EndRead(*iter);
120 0 : return true;
121 : }
122 : #endif
123 :
124 : void Log(const std::string& aPrefix,
125 : FILE* aOutf) const
126 : {
127 : fputs("(special ShmemCreated msg)", aOutf);
128 : }
129 : };
130 :
131 : class ShmemDestroyed : public IPC::Message
132 0 : {
133 : private:
134 : typedef Shmem::id_t id_t;
135 :
136 : public:
137 0 : ShmemDestroyed(int32 routingId,
138 : const id_t& aIPDLId) :
139 0 : IPC::Message(routingId, SHMEM_DESTROYED_MESSAGE_TYPE, PRIORITY_NORMAL)
140 : {
141 0 : IPC::WriteParam(this, aIPDLId);
142 0 : }
143 : };
144 :
145 :
146 : #ifdef MOZ_HAVE_SHAREDMEMORYSYSV
147 : static Shmem::SharedMemory*
148 0 : CreateSegment(size_t aNBytes, SharedMemorySysV::Handle aHandle)
149 : {
150 0 : nsAutoPtr<SharedMemory> segment;
151 :
152 0 : if (SharedMemorySysV::IsHandleValid(aHandle)) {
153 0 : segment = new SharedMemorySysV(aHandle);
154 : }
155 : else {
156 0 : segment = new SharedMemorySysV();
157 :
158 0 : if (!segment->Create(aNBytes))
159 0 : return 0;
160 : }
161 0 : if (!segment->Map(aNBytes))
162 0 : return 0;
163 :
164 0 : segment->AddRef();
165 0 : return segment.forget();
166 : }
167 : #endif
168 :
169 : static Shmem::SharedMemory*
170 0 : CreateSegment(size_t aNBytes, SharedMemoryBasic::Handle aHandle)
171 : {
172 0 : nsAutoPtr<SharedMemory> segment;
173 :
174 0 : if (SharedMemoryBasic::IsHandleValid(aHandle)) {
175 0 : segment = new SharedMemoryBasic(aHandle);
176 : }
177 : else {
178 0 : segment = new SharedMemoryBasic();
179 :
180 0 : if (!segment->Create(aNBytes))
181 0 : return 0;
182 : }
183 0 : if (!segment->Map(aNBytes))
184 0 : return 0;
185 :
186 0 : segment->AddRef();
187 0 : return segment.forget();
188 : }
189 :
190 : static void
191 0 : DestroySegment(SharedMemory* aSegment)
192 : {
193 : // the SharedMemory dtor closes and unmaps the actual OS shmem segment
194 0 : if (aSegment)
195 0 : aSegment->Release();
196 0 : }
197 :
198 :
199 : #if defined(DEBUG)
200 :
201 : static const char sMagic[] =
202 : "This little piggy went to market.\n"
203 : "This little piggy stayed at home.\n"
204 : "This little piggy has roast beef,\n"
205 : "This little piggy had none.\n"
206 : "And this little piggy cried \"Wee! Wee! Wee!\" all the way home";
207 :
208 :
209 : struct Header {
210 : // Don't use size_t or bool here because their size depends on the
211 : // architecture.
212 : uint32 mSize;
213 : uint32 mUnsafe;
214 : char mMagic[sizeof(sMagic)];
215 : };
216 :
217 : static void
218 0 : GetSections(Shmem::SharedMemory* aSegment,
219 : Header** aHeader,
220 : char** aFrontSentinel,
221 : char** aData,
222 : char** aBackSentinel)
223 : {
224 0 : NS_ABORT_IF_FALSE(aSegment && aFrontSentinel && aData && aBackSentinel,
225 : "NULL param(s)");
226 :
227 0 : *aFrontSentinel = reinterpret_cast<char*>(aSegment->memory());
228 0 : NS_ABORT_IF_FALSE(*aFrontSentinel, "NULL memory()");
229 :
230 0 : *aHeader = reinterpret_cast<Header*>(*aFrontSentinel);
231 :
232 0 : size_t pageSize = Shmem::SharedMemory::SystemPageSize();
233 0 : *aData = *aFrontSentinel + pageSize;
234 :
235 0 : *aBackSentinel = *aFrontSentinel + aSegment->Size() - pageSize;
236 0 : }
237 :
238 : static Header*
239 0 : GetHeader(Shmem::SharedMemory* aSegment)
240 : {
241 : Header* header;
242 : char* dontcare;
243 0 : GetSections(aSegment, &header, &dontcare, &dontcare, &dontcare);
244 0 : return header;
245 : }
246 :
247 : static void
248 0 : Protect(SharedMemory* aSegment)
249 : {
250 0 : NS_ABORT_IF_FALSE(aSegment, "NULL segment");
251 0 : aSegment->Protect(reinterpret_cast<char*>(aSegment->memory()),
252 : aSegment->Size(),
253 0 : RightsNone);
254 0 : }
255 :
256 : static void
257 0 : Unprotect(SharedMemory* aSegment)
258 : {
259 0 : NS_ABORT_IF_FALSE(aSegment, "NULL segment");
260 0 : aSegment->Protect(reinterpret_cast<char*>(aSegment->memory()),
261 : aSegment->Size(),
262 0 : RightsRead | RightsWrite);
263 0 : }
264 :
265 : //
266 : // In debug builds, we specially allocate shmem segments. The layout
267 : // is as follows
268 : //
269 : // Page 0: "front sentinel"
270 : // size of mapping
271 : // magic bytes
272 : // Page 1 through n-1:
273 : // user data
274 : // Page n: "back sentinel"
275 : // [nothing]
276 : //
277 : // The mapping can be in one of the following states, wrt to the
278 : // current process.
279 : //
280 : // State "unmapped": all pages are mapped with no access rights.
281 : //
282 : // State "mapping": all pages are mapped with read/write access.
283 : //
284 : // State "mapped": the front and back sentinels are mapped with no
285 : // access rights, and all the other pages are mapped with
286 : // read/write access.
287 : //
288 : // When a SharedMemory segment is first allocated, it starts out in
289 : // the "mapping" state for the process that allocates the segment, and
290 : // in the "unmapped" state for the other process. The allocating
291 : // process will then create a Shmem, which takes the segment into the
292 : // "mapped" state, where it can be accessed by clients.
293 : //
294 : // When a Shmem is sent to another process in an IPDL message, the
295 : // segment transitions into the "unmapped" state for the sending
296 : // process, and into the "mapping" state for the receiving process.
297 : // The receiving process will then create a Shmem from the underlying
298 : // segment, and take the segment into the "mapped" state.
299 : //
300 : // In the "mapping" state, we use the front sentinel to verify the
301 : // integrity of the shmem segment. If valid, it has a size_t
302 : // containing the number of bytes the user allocated followed by the
303 : // magic bytes above.
304 : //
305 : // In the "mapped" state, the front and back sentinels have no access
306 : // rights. They act as guards against buffer overflows and underflows
307 : // in client code; if clients touch a sentinel, they die with SIGSEGV.
308 : //
309 : // The "unmapped" state is used to enforce single-owner semantics of
310 : // the shmem segment. If a process other than the current owner tries
311 : // to touch the segment, it dies with SIGSEGV.
312 : //
313 :
314 0 : Shmem::Shmem(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
315 : SharedMemory* aSegment, id_t aId) :
316 : mSegment(aSegment),
317 : mData(0),
318 0 : mSize(0)
319 : {
320 0 : NS_ABORT_IF_FALSE(mSegment, "NULL segment");
321 0 : NS_ABORT_IF_FALSE(aId != 0, "invalid ID");
322 :
323 0 : Unprotect(mSegment);
324 :
325 : Header* header;
326 : char* frontSentinel;
327 : char* data;
328 : char* backSentinel;
329 0 : GetSections(aSegment, &header, &frontSentinel, &data, &backSentinel);
330 :
331 : // do a quick validity check to avoid weird-looking crashes in libc
332 0 : char check = *frontSentinel;
333 : (void)check;
334 :
335 0 : NS_ABORT_IF_FALSE(!strncmp(header->mMagic, sMagic, sizeof(sMagic)),
336 : "invalid segment");
337 0 : mSize = static_cast<size_t>(header->mSize);
338 :
339 0 : size_t pageSize = SharedMemory::SystemPageSize();
340 : // transition into the "mapped" state by protecting the front and
341 : // back sentinels (which guard against buffer under/overflows)
342 0 : mSegment->Protect(frontSentinel, pageSize, RightsNone);
343 0 : mSegment->Protect(backSentinel, pageSize, RightsNone);
344 :
345 : // don't set these until we know they're valid
346 0 : mData = data;
347 0 : mId = aId;
348 0 : }
349 :
350 : void
351 0 : Shmem::AssertInvariants() const
352 : {
353 0 : NS_ABORT_IF_FALSE(mSegment, "NULL segment");
354 0 : NS_ABORT_IF_FALSE(mData, "NULL data pointer");
355 0 : NS_ABORT_IF_FALSE(mSize > 0, "invalid size");
356 : // if the segment isn't owned by the current process, these will
357 : // trigger SIGSEGV
358 0 : char checkMappingFront = *reinterpret_cast<char*>(mData);
359 0 : char checkMappingBack = *(reinterpret_cast<char*>(mData) + mSize - 1);
360 :
361 : // avoid "unused" warnings for these variables:
362 0 : unused << checkMappingFront;
363 0 : unused << checkMappingBack;
364 0 : }
365 :
366 : void
367 0 : Shmem::RevokeRights(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead)
368 : {
369 0 : AssertInvariants();
370 :
371 0 : size_t pageSize = SharedMemory::SystemPageSize();
372 0 : Header* header = GetHeader(mSegment);
373 :
374 : // Open this up for reading temporarily
375 0 : mSegment->Protect(reinterpret_cast<char*>(header), pageSize, RightsRead);
376 :
377 0 : if (!header->mUnsafe) {
378 0 : Protect(mSegment);
379 : } else {
380 0 : mSegment->Protect(reinterpret_cast<char*>(header), pageSize, RightsNone);
381 : }
382 0 : }
383 :
384 : // static
385 : Shmem::SharedMemory*
386 0 : Shmem::Alloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
387 : size_t aNBytes,
388 : SharedMemoryType aType,
389 : bool aUnsafe,
390 : bool aProtect)
391 : {
392 : NS_ASSERTION(aNBytes <= PR_UINT32_MAX, "Will truncate shmem segment size!");
393 0 : NS_ABORT_IF_FALSE(!aProtect || !aUnsafe, "protect => !unsafe");
394 :
395 0 : size_t pageSize = SharedMemory::SystemPageSize();
396 0 : SharedMemory* segment = nsnull;
397 : // |2*pageSize| is for the front and back sentinel
398 0 : size_t segmentSize = SharedMemory::PageAlignedSize(aNBytes + 2*pageSize);
399 :
400 0 : if (aType == SharedMemory::TYPE_BASIC)
401 0 : segment = CreateSegment(segmentSize, SharedMemoryBasic::NULLHandle());
402 : #ifdef MOZ_HAVE_SHAREDMEMORYSYSV
403 0 : else if (aType == SharedMemory::TYPE_SYSV)
404 0 : segment = CreateSegment(segmentSize, SharedMemorySysV::NULLHandle());
405 : #endif
406 : else
407 0 : NS_RUNTIMEABORT("unknown shmem type");
408 :
409 0 : if (!segment)
410 0 : return 0;
411 :
412 : Header* header;
413 : char *frontSentinel;
414 : char *data;
415 : char *backSentinel;
416 0 : GetSections(segment, &header, &frontSentinel, &data, &backSentinel);
417 :
418 : // initialize the segment with Shmem-internal information
419 :
420 : // NB: this can't be a static assert because technically pageSize
421 : // isn't known at compile time, event though in practice it's always
422 : // going to be 4KiB
423 0 : NS_ABORT_IF_FALSE(sizeof(Header) <= pageSize,
424 : "Shmem::Header has gotten too big");
425 0 : memcpy(header->mMagic, sMagic, sizeof(sMagic));
426 0 : header->mSize = static_cast<uint32>(aNBytes);
427 0 : header->mUnsafe = aUnsafe;
428 :
429 0 : if (aProtect)
430 0 : Protect(segment);
431 :
432 0 : return segment;
433 : }
434 :
435 : // static
436 : Shmem::SharedMemory*
437 0 : Shmem::OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
438 : const IPC::Message& aDescriptor,
439 : id_t* aId,
440 : bool aProtect)
441 : {
442 0 : if (SHMEM_CREATED_MESSAGE_TYPE != aDescriptor.type())
443 0 : NS_RUNTIMEABORT("expected 'shmem created' message");
444 :
445 0 : void* iter = 0;
446 : SharedMemory::SharedMemoryType type;
447 : size_t size;
448 0 : if (!ShmemCreated::ReadInfo(&aDescriptor, &iter, aId, &size, &type))
449 0 : return 0;
450 :
451 0 : SharedMemory* segment = 0;
452 0 : size_t pageSize = SharedMemory::SystemPageSize();
453 : // |2*pageSize| is for the front and back sentinels
454 0 : size_t segmentSize = SharedMemory::PageAlignedSize(size + 2*pageSize);
455 :
456 0 : if (SharedMemory::TYPE_BASIC == type) {
457 0 : SharedMemoryBasic::Handle handle;
458 0 : if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle))
459 0 : return 0;
460 :
461 0 : if (!SharedMemoryBasic::IsHandleValid(handle))
462 0 : NS_RUNTIMEABORT("trying to open invalid handle");
463 0 : segment = CreateSegment(segmentSize, handle);
464 : }
465 : #ifdef MOZ_HAVE_SHAREDMEMORYSYSV
466 0 : else if (SharedMemory::TYPE_SYSV == type) {
467 : SharedMemorySysV::Handle handle;
468 0 : if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle))
469 0 : return 0;
470 :
471 0 : if (!SharedMemorySysV::IsHandleValid(handle))
472 0 : NS_RUNTIMEABORT("trying to open invalid handle");
473 0 : segment = CreateSegment(segmentSize, handle);
474 : }
475 : #endif
476 : else {
477 0 : NS_RUNTIMEABORT("unknown shmem type");
478 : }
479 :
480 0 : if (!segment)
481 0 : return 0;
482 :
483 : // The caller of this function may not know whether the segment is
484 : // unsafe or not
485 0 : Header* header = GetHeader(segment);
486 0 : if (!header->mUnsafe && aProtect)
487 0 : Protect(segment);
488 :
489 0 : return segment;
490 : }
491 :
492 : // static
493 : void
494 0 : Shmem::Dealloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
495 : SharedMemory* aSegment)
496 : {
497 0 : if (!aSegment)
498 0 : return;
499 :
500 0 : size_t pageSize = SharedMemory::SystemPageSize();
501 : Header* header;
502 : char *frontSentinel;
503 : char *data;
504 : char *backSentinel;
505 0 : GetSections(aSegment, &header, &frontSentinel, &data, &backSentinel);
506 :
507 0 : aSegment->Protect(frontSentinel, pageSize, RightsWrite | RightsRead);
508 0 : memset(header->mMagic, 0, sizeof(sMagic));
509 0 : header->mSize = 0;
510 0 : header->mUnsafe = false; // make it "safe" so as to catch errors
511 :
512 0 : DestroySegment(aSegment);
513 : }
514 :
515 :
516 : #else // !defined(DEBUG)
517 :
518 : // static
519 : Shmem::SharedMemory*
520 : Shmem::Alloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
521 : size_t aNBytes,
522 : SharedMemoryType aType,
523 : bool /*unused*/,
524 : bool /*unused*/)
525 : {
526 : SharedMemory *segment = nsnull;
527 :
528 : if (aType == SharedMemory::TYPE_BASIC)
529 : segment = CreateSegment(SharedMemory::PageAlignedSize(aNBytes + sizeof(uint32)),
530 : SharedMemoryBasic::NULLHandle());
531 : #ifdef MOZ_HAVE_SHAREDMEMORYSYSV
532 : else if (aType == SharedMemory::TYPE_SYSV)
533 : segment = CreateSegment(SharedMemory::PageAlignedSize(aNBytes + sizeof(uint32)),
534 : SharedMemorySysV::NULLHandle());
535 : #endif
536 : else
537 : // Unhandled!!
538 : NS_ABORT();
539 :
540 : if (!segment)
541 : return 0;
542 :
543 : *PtrToSize(segment) = static_cast<uint32>(aNBytes);
544 :
545 : return segment;
546 : }
547 :
548 : // static
549 : Shmem::SharedMemory*
550 : Shmem::OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
551 : const IPC::Message& aDescriptor,
552 : id_t* aId,
553 : bool /*unused*/)
554 : {
555 : if (SHMEM_CREATED_MESSAGE_TYPE != aDescriptor.type())
556 : NS_RUNTIMEABORT("expected 'shmem created' message");
557 :
558 : SharedMemory::SharedMemoryType type;
559 : void* iter = 0;
560 : size_t size;
561 : if (!ShmemCreated::ReadInfo(&aDescriptor, &iter, aId, &size, &type))
562 : return 0;
563 :
564 : SharedMemory* segment = 0;
565 : size_t segmentSize = SharedMemory::PageAlignedSize(size + sizeof(uint32));
566 :
567 : if (SharedMemory::TYPE_BASIC == type) {
568 : SharedMemoryBasic::Handle handle;
569 : if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle))
570 : return 0;
571 :
572 : if (!SharedMemoryBasic::IsHandleValid(handle))
573 : NS_RUNTIMEABORT("trying to open invalid handle");
574 :
575 : segment = CreateSegment(segmentSize, handle);
576 : }
577 : #ifdef MOZ_HAVE_SHAREDMEMORYSYSV
578 : else if (SharedMemory::TYPE_SYSV == type) {
579 : SharedMemorySysV::Handle handle;
580 : if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle))
581 : return 0;
582 :
583 : if (!SharedMemorySysV::IsHandleValid(handle))
584 : NS_RUNTIMEABORT("trying to open invalid handle");
585 : segment = CreateSegment(segmentSize, handle);
586 : }
587 : #endif
588 : else {
589 : NS_RUNTIMEABORT("unknown shmem type");
590 : }
591 :
592 : if (!segment)
593 : return 0;
594 :
595 : // this is the only validity check done OPT builds
596 : if (size != static_cast<size_t>(*PtrToSize(segment)))
597 : NS_RUNTIMEABORT("Alloc() segment size disagrees with OpenExisting()'s");
598 :
599 : return segment;
600 : }
601 :
602 : // static
603 : void
604 : Shmem::Dealloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
605 : SharedMemory* aSegment)
606 : {
607 : DestroySegment(aSegment);
608 : }
609 :
610 : #endif // if defined(DEBUG)
611 :
612 : int
613 0 : Shmem::GetSysVID() const
614 : {
615 : #ifdef MOZ_HAVE_SHAREDMEMORYSYSV
616 0 : AssertInvariants();
617 :
618 0 : if (mSegment->Type() != SharedMemory::TYPE_SYSV)
619 0 : NS_RUNTIMEABORT("Can't call GetSysVID() on a non-SysV Shmem!");
620 :
621 0 : SharedMemorySysV* seg = static_cast<SharedMemorySysV*>(mSegment);
622 0 : return seg->GetHandle();
623 : #else
624 : NS_RUNTIMEABORT("Can't call GetSysVID() with no support for SysV shared memory!");
625 : return -1; // not reached
626 : #endif
627 : }
628 :
629 : IPC::Message*
630 0 : Shmem::ShareTo(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
631 : base::ProcessHandle aProcess,
632 : int32 routingId)
633 : {
634 0 : AssertInvariants();
635 :
636 0 : if (SharedMemory::TYPE_BASIC == mSegment->Type()) {
637 0 : SharedMemoryBasic* seg = static_cast<SharedMemoryBasic*>(mSegment);
638 0 : SharedMemoryBasic::Handle handle;
639 0 : if (!seg->ShareToProcess(aProcess, &handle))
640 0 : return 0;
641 :
642 0 : return new ShmemCreated(routingId, mId, mSize, handle);
643 : }
644 : #ifdef MOZ_HAVE_SHAREDMEMORYSYSV
645 0 : else if (SharedMemory::TYPE_SYSV == mSegment->Type()) {
646 0 : SharedMemorySysV* seg = static_cast<SharedMemorySysV*>(mSegment);
647 0 : return new ShmemCreated(routingId, mId, mSize, seg->GetHandle());
648 : }
649 : #endif
650 : else {
651 0 : NS_RUNTIMEABORT("unknown shmem type (here?!)");
652 : }
653 :
654 0 : return 0;
655 : }
656 :
657 : IPC::Message*
658 0 : Shmem::UnshareFrom(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
659 : base::ProcessHandle aProcess,
660 : int32 routingId)
661 : {
662 0 : AssertInvariants();
663 0 : return new ShmemDestroyed(routingId, mId);
664 : }
665 :
666 : } // namespace ipc
667 : } // namespace mozilla
|